Remove canvas

This commit is contained in:
Hajime Hoshi 2014-12-14 18:57:29 +09:00
parent 60aad4326e
commit 3190609f07
7 changed files with 113 additions and 162 deletions

112
canvas.go
View File

@ -1,112 +0,0 @@
/*
Copyright 2014 Hajime Hoshi
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ebiten
import (
glfw "github.com/go-gl/glfw3"
"image"
"runtime"
)
type canvas struct {
window *glfw.Window
scale int
graphicsContext *graphicsContext
input input
funcs chan func()
funcsDone chan struct{}
}
func newCanvas(window *glfw.Window, width, height, scale int) (*canvas, error) {
c := &canvas{
window: window,
scale: scale,
funcs: make(chan func()),
funcsDone: make(chan struct{}),
}
c.run(width, height, scale)
// For retina displays, recalculate the scale with the framebuffer size.
windowWidth, _ := window.GetFramebufferSize()
realScale := windowWidth / width
var err error
c.use(func() {
c.graphicsContext, err = newGraphicsContext(width, height, realScale)
})
if err != nil {
return nil, err
}
return c, nil
}
func (c *canvas) draw(game Game) (err error) {
c.use(func() {
c.graphicsContext.PreUpdate()
})
if err = game.Draw(&syncGraphicsContext{c}); err != nil {
return
}
c.use(func() {
c.graphicsContext.PostUpdate()
c.window.SwapBuffers()
})
return
}
func (c *canvas) isClosed() bool {
return c.window.ShouldClose()
}
func (c *canvas) newTextureID(img image.Image, filter int) (TextureID, error) {
var id TextureID
var err error
c.use(func() {
id, err = newTextureID(img, filter)
})
return id, err
}
func (c *canvas) newRenderTargetID(width, height int, filter int) (RenderTargetID, error) {
var id RenderTargetID
var err error
c.use(func() {
id, err = newRenderTargetID(width, height, filter)
})
return id, err
}
func (c *canvas) run(width, height, scale int) {
go func() {
runtime.LockOSThread()
c.window.MakeContextCurrent()
glfw.SwapInterval(1)
for {
(<-c.funcs)()
c.funcsDone <- struct{}{}
}
}()
}
func (c *canvas) use(f func()) {
c.funcs <- f
<-c.funcsDone
}
func (c *canvas) update() {
c.input.update(c.window, c.scale)
}

View File

@ -22,15 +22,15 @@ import (
)
func IsKeyPressed(key Key) bool {
return currentUI.canvas.input.isKeyPressed(key)
return currentUI.input.isKeyPressed(key)
}
func CursorPosition() (x, y int) {
return currentUI.canvas.input.cursorPosition()
return currentUI.input.cursorPosition()
}
func IsMouseButtonPressed(mouseButton MouseButton) bool {
return currentUI.canvas.input.isMouseButtonPressed(mouseButton)
return currentUI.input.isMouseButtonPressed(mouseButton)
}
func glFilter(f Filter) int {
@ -45,9 +45,9 @@ func glFilter(f Filter) int {
}
func NewRenderTargetID(width, height int, filter Filter) (RenderTargetID, error) {
return currentUI.canvas.newRenderTargetID(width, height, glFilter(filter))
return currentUI.newRenderTargetID(width, height, glFilter(filter))
}
func NewTextureID(img image.Image, filter Filter) (TextureID, error) {
return currentUI.canvas.newTextureID(img, glFilter(filter))
return currentUI.newTextureID(img, glFilter(filter))
}

View File

@ -89,13 +89,13 @@ func (c *graphicsContext) PopRenderTarget() {
c.currentIDs = c.currentIDs[:len(c.currentIDs)-1]
}
func (c *graphicsContext) PreUpdate() {
func (c *graphicsContext) preUpdate() {
c.currentIDs = []RenderTargetID{c.defaultID}
c.PushRenderTarget(c.screenID)
c.Clear()
}
func (c *graphicsContext) PostUpdate() {
func (c *graphicsContext) postUpdate() {
c.PopRenderTarget()
c.Clear()

8
ids.go
View File

@ -41,14 +41,6 @@ var idsInstance = &ids{
currentRenderTargetId: -1,
}
func newRenderTargetID(width, height int, filter int) (RenderTargetID, error) {
return idsInstance.createRenderTarget(width, height, filter)
}
func newTextureID(img image.Image, filter int) (TextureID, error) {
return idsInstance.createTexture(img, filter)
}
func (i *ids) textureAt(id TextureID) *opengl.Texture {
i.RLock()
defer i.RUnlock()

11
run.go
View File

@ -32,18 +32,17 @@ var currentUI *ui
// Run runs the game.
func Run(game Game, width, height, scale int, title string, fps int) error {
ui := new(ui)
ui, err := newUI(game, width, height, scale, title)
if err != nil {
return err
}
defer ui.terminate()
currentUI = ui
defer func() {
currentUI = nil
}()
if err := ui.start(game, width, height, scale, title); err != nil {
return err
}
defer ui.terminate()
frameTime := time.Duration(int64(time.Second) / int64(fps))
tick := time.Tick(frameTime)
sigterm := make(chan os.Signal, 1)

View File

@ -17,64 +17,64 @@ limitations under the License.
package ebiten
type syncGraphicsContext struct {
canvas *canvas
ui *ui
}
var _ GraphicsContext = new(syncGraphicsContext)
func (c *syncGraphicsContext) Clear() {
c.canvas.use(func() {
c.canvas.graphicsContext.Clear()
c.ui.use(func() {
c.ui.graphicsContext.Clear()
})
}
func (c *syncGraphicsContext) Fill(r, g, b uint8) {
c.canvas.use(func() {
c.canvas.graphicsContext.Fill(r, g, b)
c.ui.use(func() {
c.ui.graphicsContext.Fill(r, g, b)
})
}
func (c *syncGraphicsContext) Texture(id TextureID) (d Drawer) {
c.canvas.use(func() {
c.ui.use(func() {
d = &drawer{
canvas: c.canvas,
innerDrawer: c.canvas.graphicsContext.Texture(id),
ui: c.ui,
innerDrawer: c.ui.graphicsContext.Texture(id),
}
})
return
}
func (c *syncGraphicsContext) RenderTarget(id RenderTargetID) (d Drawer) {
c.canvas.use(func() {
c.ui.use(func() {
d = &drawer{
canvas: c.canvas,
innerDrawer: c.canvas.graphicsContext.RenderTarget(id),
ui: c.ui,
innerDrawer: c.ui.graphicsContext.RenderTarget(id),
}
})
return
}
func (c *syncGraphicsContext) PopRenderTarget() {
c.canvas.use(func() {
c.canvas.graphicsContext.PopRenderTarget()
c.ui.use(func() {
c.ui.graphicsContext.PopRenderTarget()
})
}
func (c *syncGraphicsContext) PushRenderTarget(id RenderTargetID) {
c.canvas.use(func() {
c.canvas.graphicsContext.PushRenderTarget(id)
c.ui.use(func() {
c.ui.graphicsContext.PushRenderTarget(id)
})
}
type drawer struct {
canvas *canvas
ui *ui
innerDrawer Drawer
}
var _ Drawer = new(drawer)
func (d *drawer) Draw(parts []TexturePart, geo GeometryMatrix, color ColorMatrix) {
d.canvas.use(func() {
d.ui.use(func() {
d.innerDrawer.Draw(parts, geo, color)
})
}

96
ui.go
View File

@ -20,6 +20,8 @@ import (
"errors"
"fmt"
glfw "github.com/go-gl/glfw3"
"image"
"runtime"
)
func init() {
@ -29,31 +31,48 @@ func init() {
}
type ui struct {
canvas *canvas
window *glfw.Window
scale int
graphicsContext *graphicsContext
input input
funcs chan func()
funcsDone chan struct{}
}
func (u *ui) start(game Game, width, height, scale int, title string) error {
func newUI(game Game, width, height, scale int, title string) (*ui, error) {
if !glfw.Init() {
return errors.New("glfw.Init() fails")
return nil, errors.New("glfw.Init() fails")
}
glfw.WindowHint(glfw.Resizable, glfw.False)
window, err := glfw.CreateWindow(width*scale, height*scale, title, nil, nil)
if err != nil {
return err
return nil, err
}
c, err := newCanvas(window, width, height, scale)
u := &ui{
window: window,
scale: scale,
funcs: make(chan func()),
funcsDone: make(chan struct{}),
}
u.run(width, height, scale)
// For retina displays, recalculate the scale with the framebuffer size.
windowWidth, _ := window.GetFramebufferSize()
realScale := windowWidth / width
u.use(func() {
u.graphicsContext, err = newGraphicsContext(width, height, realScale)
})
if err != nil {
return err
return nil, err
}
u.canvas = c
return nil
return u, nil
}
func (u *ui) doEvents() {
glfw.PollEvents()
u.canvas.update()
u.update()
}
func (u *ui) terminate() {
@ -61,9 +80,62 @@ func (u *ui) terminate() {
}
func (u *ui) isClosed() bool {
return u.canvas.isClosed()
return u.window.ShouldClose()
}
func (u *ui) drawGame(game Game) error {
return u.canvas.draw(game)
return u.draw(game)
}
func (u *ui) draw(game Game) (err error) {
u.use(func() {
u.graphicsContext.preUpdate()
})
if err = game.Draw(&syncGraphicsContext{u}); err != nil {
return
}
u.use(func() {
u.graphicsContext.postUpdate()
u.window.SwapBuffers()
})
return
}
func (u *ui) newTextureID(img image.Image, filter int) (TextureID, error) {
var id TextureID
var err error
u.use(func() {
id, err = idsInstance.createTexture(img, filter)
})
return id, err
}
func (u *ui) newRenderTargetID(width, height int, filter int) (RenderTargetID, error) {
var id RenderTargetID
var err error
u.use(func() {
id, err = idsInstance.createRenderTarget(width, height, filter)
})
return id, err
}
func (u *ui) run(width, height, scale int) {
go func() {
runtime.LockOSThread()
u.window.MakeContextCurrent()
glfw.SwapInterval(1)
for {
(<-u.funcs)()
u.funcsDone <- struct{}{}
}
}()
}
func (u *ui) use(f func()) {
u.funcs <- f
<-u.funcsDone
}
func (u *ui) update() {
u.input.update(u.window, u.scale)
}