Bug fix: can't call canvas.use recursively

This commit is contained in:
Hajime Hoshi 2014-12-09 01:08:47 +09:00
parent 0d78f9937f
commit 60e4d6f6ff
7 changed files with 111 additions and 37 deletions

View File

@ -29,7 +29,7 @@ func main() {
u := new(glfw.UI) u := new(glfw.UI)
game := NewGame() game := NewGame()
if err := ui.Run(u, game, ScreenWidth, ScreenHeight, 2, "Ebiten Demo", 60); err != nil { if err := ui.Run(u, game, ScreenWidth, ScreenHeight, 2, "Blocks (Ebiten Demo)", 60); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }

View File

@ -21,7 +21,7 @@ type TexturePart struct {
// A Drawer is the interface that draws itself. // A Drawer is the interface that draws itself.
type Drawer interface { type Drawer interface {
Draw(parts []TexturePart, geometryMatrix matrix.Geometry, colorMatrix matrix.Color) Draw(parts []TexturePart, geo matrix.Geometry, color matrix.Color)
} }
// DrawWhole draws the whole texture. // DrawWhole draws the whole texture.

View File

@ -4,19 +4,14 @@ import (
"github.com/go-gl/gl" "github.com/go-gl/gl"
"github.com/hajimehoshi/ebiten/graphics" "github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/matrix" "github.com/hajimehoshi/ebiten/graphics/matrix"
"github.com/hajimehoshi/ebiten/ui"
) )
type ContextUpdater struct { func Initialize(screenWidth, screenHeight, screenScale int) (*Context, error) {
context *context
}
func Initialize(screenWidth, screenHeight, screenScale int) (*ContextUpdater, error) {
gl.Init() gl.Init()
gl.Enable(gl.TEXTURE_2D) gl.Enable(gl.TEXTURE_2D)
gl.Enable(gl.BLEND) gl.Enable(gl.BLEND)
c := &context{ c := &Context{
screenWidth: screenWidth, screenWidth: screenWidth,
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
@ -37,14 +32,10 @@ func Initialize(screenWidth, screenHeight, screenScale int) (*ContextUpdater, er
c.ResetOffscreen() c.ResetOffscreen()
c.Clear() c.Clear()
return &ContextUpdater{c}, nil return c, nil
} }
func (u *ContextUpdater) Update(drawer ui.Drawer) error { type Context struct {
return u.context.update(drawer)
}
type context struct {
screenId graphics.RenderTargetID screenId graphics.RenderTargetID
defaultId graphics.RenderTargetID defaultId graphics.RenderTargetID
currentId graphics.RenderTargetID currentId graphics.RenderTargetID
@ -53,43 +44,41 @@ type context struct {
screenScale int screenScale int
} }
func (c *context) dispose() { func (c *Context) dispose() {
// NOTE: Now this method is not used anywhere. // NOTE: Now this method is not used anywhere.
idsInstance.deleteRenderTarget(c.screenId) idsInstance.deleteRenderTarget(c.screenId)
} }
func (c *context) Clear() { func (c *Context) Clear() {
c.Fill(0, 0, 0) c.Fill(0, 0, 0)
} }
func (c *context) Fill(r, g, b uint8) { func (c *Context) Fill(r, g, b uint8) {
idsInstance.fillRenderTarget(c.currentId, r, g, b) idsInstance.fillRenderTarget(c.currentId, r, g, b)
} }
func (c *context) Texture(id graphics.TextureID) graphics.Drawer { func (c *Context) Texture(id graphics.TextureID) graphics.Drawer {
return &textureWithContext{id, c} return &textureWithContext{id, c}
} }
func (c *context) RenderTarget(id graphics.RenderTargetID) graphics.Drawer { func (c *Context) RenderTarget(id graphics.RenderTargetID) graphics.Drawer {
return &textureWithContext{idsInstance.toTexture(id), c} return &textureWithContext{idsInstance.toTexture(id), c}
} }
func (c *context) ResetOffscreen() { func (c *Context) ResetOffscreen() {
c.currentId = c.screenId c.currentId = c.screenId
} }
func (c *context) SetOffscreen(renderTargetId graphics.RenderTargetID) { func (c *Context) SetOffscreen(renderTargetId graphics.RenderTargetID) {
c.currentId = renderTargetId c.currentId = renderTargetId
} }
func (c *context) update(drawer ui.Drawer) error { func (c *Context) PreUpdate() {
c.ResetOffscreen() c.ResetOffscreen()
c.Clear() c.Clear()
}
if err := drawer.Draw(c); err != nil { func (c *Context) PostUpdate() {
return err
}
c.SetOffscreen(c.defaultId) c.SetOffscreen(c.defaultId)
c.Clear() c.Clear()
@ -99,12 +88,11 @@ func (c *context) update(drawer ui.Drawer) error {
graphics.DrawWhole(c.RenderTarget(c.screenId), c.screenWidth, c.screenHeight, geo, matrix.ColorI()) graphics.DrawWhole(c.RenderTarget(c.screenId), c.screenWidth, c.screenHeight, geo, matrix.ColorI())
gl.Flush() gl.Flush()
return nil
} }
type textureWithContext struct { type textureWithContext struct {
id graphics.TextureID id graphics.TextureID
context *context context *Context
} }
func (t *textureWithContext) Draw(parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) { func (t *textureWithContext) Draw(parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) {

View File

@ -16,11 +16,21 @@ const (
// TextureID represents an ID of a texture. // TextureID represents an ID of a texture.
type TextureID int type TextureID int
// IsNil returns true if the texture is nil.
func (i TextureID) IsNil() bool {
return i == 0
}
// RenderTargetID represents an ID of a render target. // RenderTargetID represents an ID of a render target.
// A render target is essentially same as a texture, but it is assumed that the // A render target is essentially same as a texture, but it is assumed that the
// all alpha of a render target is maximum. // all alpha of a render target is maximum.
type RenderTargetID int type RenderTargetID int
// IsNil returns true if the render target is nil.
func (i RenderTargetID) IsNil() bool {
return i == 0
}
var currentTextureFactory TextureFactory var currentTextureFactory TextureFactory
// A TextureFactory is the interface that creates a render target or a texture. // A TextureFactory is the interface that creates a render target or a texture.

View File

@ -11,7 +11,7 @@ import (
type canvas struct { type canvas struct {
window *glfw.Window window *glfw.Window
contextUpdater *opengl.ContextUpdater context *opengl.Context
keyboard keyboard keyboard keyboard
mouse mouse mouse mouse
funcs chan func() funcs chan func()
@ -20,7 +20,13 @@ type canvas struct {
func (c *canvas) Draw(d ui.Drawer) (err error) { func (c *canvas) Draw(d ui.Drawer) (err error) {
c.use(func() { c.use(func() {
err = c.contextUpdater.Update(d) c.context.PreUpdate()
})
if err = d.Draw(&context{c}); err != nil {
return
}
c.use(func() {
c.context.PostUpdate()
c.window.SwapBuffers() c.window.SwapBuffers()
}) })
return return
@ -54,6 +60,7 @@ func (c *canvas) run(width, height, scale int) {
c.window.MakeContextCurrent() c.window.MakeContextCurrent()
glfw.SwapInterval(1) glfw.SwapInterval(1)
for { for {
f := <-c.funcs f := <-c.funcs
f() f()
c.funcsDone <- struct{}{} c.funcsDone <- struct{}{}

69
ui/glfw/context.go Normal file
View File

@ -0,0 +1,69 @@
package glfw
import (
"github.com/hajimehoshi/ebiten/graphics"
"github.com/hajimehoshi/ebiten/graphics/matrix"
)
type context struct {
canvas *canvas
}
var _ graphics.Context = new(context)
func (c *context) Clear() {
c.canvas.use(func() {
c.canvas.context.Clear()
})
}
func (c *context) Fill(r, g, b uint8) {
c.canvas.use(func() {
c.canvas.context.Fill(r, g, b)
})
}
func (c *context) Texture(id graphics.TextureID) (d graphics.Drawer) {
c.canvas.use(func() {
d = &drawer{
canvas: c.canvas,
innerDrawer: c.canvas.context.Texture(id),
}
})
return
}
func (c *context) RenderTarget(id graphics.RenderTargetID) (d graphics.Drawer) {
c.canvas.use(func() {
d = &drawer{
canvas: c.canvas,
innerDrawer: c.canvas.context.RenderTarget(id),
}
})
return
}
func (c *context) ResetOffscreen() {
c.canvas.use(func() {
c.canvas.context.ResetOffscreen()
})
}
func (c *context) SetOffscreen(id graphics.RenderTargetID) {
c.canvas.use(func() {
c.canvas.context.SetOffscreen(id)
})
}
type drawer struct {
canvas *canvas
innerDrawer graphics.Drawer
}
var _ graphics.Drawer = new(drawer)
func (d *drawer) Draw(parts []graphics.TexturePart, geo matrix.Geometry, color matrix.Color) {
d.canvas.use(func() {
d.innerDrawer.Draw(parts, geo, color)
})
}

View File

@ -45,7 +45,7 @@ func (u *UI) Start(width, height, scale int, title string) (ui.Canvas, error) {
windowWidth, _ := window.GetFramebufferSize() windowWidth, _ := window.GetFramebufferSize()
realScale := windowWidth / width realScale := windowWidth / width
c.use(func() { c.use(func() {
c.contextUpdater, err = opengl.Initialize(width, height, realScale) c.context, err = opengl.Initialize(width, height, realScale)
}) })
if err != nil { if err != nil {
return nil, err return nil, err