Refactoring event handling

This commit is contained in:
Hajime Hoshi 2013-12-16 09:39:49 +09:00
parent aeab5f3437
commit 94ecfbba9c
9 changed files with 56 additions and 160 deletions

View File

@ -60,22 +60,21 @@ func NewGame() *Game {
} }
} }
func (game *Game) OnTextureCreated(e graphics.TextureCreatedEvent) { func (game *Game) HandleEvent(e interface{}) {
if e.Error != nil { switch e := e.(type) {
panic(e.Error) case graphics.TextureCreatedEvent:
if e.Error != nil {
panic(e.Error)
}
game.textures[e.Tag.(string)] = e.Id
case graphics.RenderTargetCreatedEvent:
if e.Error != nil {
panic(e.Error)
}
game.renderTargets[e.Tag.(string)] = e.Id
case ui.MouseStateUpdatedEvent:
game.mouseX, game.mouseY = e.X, e.Y
} }
game.textures[e.Tag.(string)] = e.Id
}
func (game *Game) OnRenderTargetCreated(e graphics.RenderTargetCreatedEvent) {
if e.Error != nil {
panic(e.Error)
}
game.renderTargets[e.Tag.(string)] = e.Id
}
func (game *Game) OnMouseStateUpdated(e ui.MouseStateUpdatedEvent) {
game.mouseX, game.mouseY = e.X, e.Y
} }
func (game *Game) isInitialized() bool { func (game *Game) isInitialized() bool {

View File

@ -2,6 +2,7 @@ package main
import ( import (
"github.com/hajimehoshi/go-ebiten/graphics" "github.com/hajimehoshi/go-ebiten/graphics"
"github.com/hajimehoshi/go-ebiten/ui"
"github.com/hajimehoshi/go-ebiten/ui/cocoa" "github.com/hajimehoshi/go-ebiten/ui/cocoa"
"image" "image"
_ "image/png" _ "image/png"
@ -35,12 +36,11 @@ func main() {
const fps = 60 const fps = 60
const title = "Ebiten Demo" const title = "Ebiten Demo"
ui := cocoa.UI() u := cocoa.UI()
textureFactory := cocoa.TextureFactory() textureFactory := cocoa.TextureFactory()
window := ui.CreateWindow(screenWidth, screenHeight, screenScale, title) window := u.CreateWindow(screenWidth, screenHeight, screenScale, title)
textureCreated := textureFactory.TextureCreated() textureFactoryEvents := textureFactory.Events()
renderTargetCreated := textureFactory.RenderTargetCreated()
for tag, path := range TexturePaths { for tag, path := range TexturePaths {
tag := tag tag := tag
@ -67,26 +67,19 @@ func main() {
go func() { go func() {
defer close(quit) defer close(quit)
mouseStateUpdated := window.MouseStateUpdated() windowEvents := window.Events()
screenSizeUpdated := window.ScreenSizeUpdated()
windowClosed := window.WindowClosed()
game := NewGame() game := NewGame()
frameTime := time.Duration(int64(time.Second) / int64(fps)) frameTime := time.Duration(int64(time.Second) / int64(fps))
tick := time.Tick(frameTime) tick := time.Tick(frameTime)
for { for {
select { select {
case e := <-textureCreated: case e := <-textureFactoryEvents:
game.OnTextureCreated(e) game.HandleEvent(e)
case e := <-renderTargetCreated: case e := <-windowEvents:
game.OnRenderTargetCreated(e) if _, ok := e.(ui.WindowClosedEvent); ok {
case e := <-mouseStateUpdated: return
game.OnMouseStateUpdated(e)
case _, ok := <-screenSizeUpdated:
if !ok {
screenSizeUpdated = nil
} }
case <-windowClosed: game.HandleEvent(e)
return
case <-tick: case <-tick:
game.Update() game.Update()
case context := <-drawing: case context := <-drawing:
@ -97,7 +90,7 @@ func main() {
}() }()
for { for {
ui.PollEvents() u.PollEvents()
select { select {
default: default:
drawing <- graphics.NewLazyContext() drawing <- graphics.NewLazyContext()
@ -107,7 +100,7 @@ func main() {
context.Flush(actualContext) context.Flush(actualContext)
}) })
after := time.After(time.Duration(int64(time.Second) / 120)) after := time.After(time.Duration(int64(time.Second) / 120))
ui.PollEvents() u.PollEvents()
<-after <-after
case <-quit: case <-quit:
return return

View File

@ -16,13 +16,8 @@ type RenderTargetCreatedEvent struct {
Error error Error error
} }
type TextureFactoryEvents interface {
TextureCreated() <-chan TextureCreatedEvent
RenderTargetCreated() <-chan RenderTargetCreatedEvent
}
type TextureFactory interface { type TextureFactory interface {
CreateRenderTarget(tag interface{}, width, height int) CreateRenderTarget(tag interface{}, width, height int)
CreateTexture(tag interface{}, img image.Image) CreateTexture(tag interface{}, img image.Image)
TextureFactoryEvents Events() <-chan interface{}
} }

View File

@ -14,7 +14,6 @@ type textureFactory struct {
sharedContext unsafe.Pointer sharedContext unsafe.Pointer
funcs chan func() funcs chan func()
funcsDone chan struct{} funcsDone chan struct{}
textureFactoryEvents
} }
func runTextureFactory() *textureFactory { func runTextureFactory() *textureFactory {

View File

@ -1,44 +0,0 @@
package cocoa
import (
"github.com/hajimehoshi/go-ebiten/graphics"
)
type textureFactoryEvents struct {
textureCreated chan graphics.TextureCreatedEvent
renderTargetCreated chan graphics.RenderTargetCreatedEvent
}
func (t *textureFactoryEvents) TextureCreated() <-chan graphics.TextureCreatedEvent {
if t.textureCreated != nil {
return t.textureCreated
}
t.textureCreated = make(chan graphics.TextureCreatedEvent)
return t.textureCreated
}
func (t *textureFactoryEvents) notifyTextureCreated(e graphics.TextureCreatedEvent) {
if t.textureCreated == nil {
return
}
go func() {
t.textureCreated <- e
}()
}
func (t *textureFactoryEvents) RenderTargetCreated() <-chan graphics.RenderTargetCreatedEvent {
if t.renderTargetCreated != nil {
return t.renderTargetCreated
}
t.renderTargetCreated = make(chan graphics.RenderTargetCreatedEvent)
return t.renderTargetCreated
}
func (t *textureFactoryEvents) notifyRenderTargetCreated(e graphics.RenderTargetCreatedEvent) {
if t.renderTargetCreated == nil {
return
}
go func() {
t.renderTargetCreated <- e
}()
}

View File

@ -16,6 +16,7 @@ import (
type cocoaUI struct { type cocoaUI struct {
textureFactory *textureFactory textureFactory *textureFactory
textureFactoryEvents chan interface{}
graphicsDevice *opengl.Device graphicsDevice *opengl.Device
} }
@ -54,12 +55,12 @@ func (u *cocoaUI) PollEvents() {
C.PollEvents() C.PollEvents()
} }
func (u *cocoaUI) TextureCreated() <-chan graphics.TextureCreatedEvent { func (u *cocoaUI) Events() <-chan interface{} {
return u.textureFactory.TextureCreated() if u.textureFactoryEvents != nil {
} return u.textureFactoryEvents
}
func (u *cocoaUI) RenderTargetCreated() <-chan graphics.RenderTargetCreatedEvent { u.textureFactoryEvents = make(chan interface{})
return u.textureFactory.RenderTargetCreated() return u.textureFactoryEvents
} }
func (u *cocoaUI) CreateTexture(tag interface{}, img image.Image) { func (u *cocoaUI) CreateTexture(tag interface{}, img image.Image) {
@ -74,7 +75,7 @@ func (u *cocoaUI) CreateTexture(tag interface{}, img image.Image) {
Id: id, Id: id,
Error: err, Error: err,
} }
u.textureFactory.notifyTextureCreated(e) u.textureFactoryEvents <- e
}() }()
} }
@ -90,6 +91,6 @@ func (u *cocoaUI) CreateRenderTarget(tag interface{}, width, height int) {
Id: id, Id: id,
Error: err, Error: err,
} }
u.textureFactory.notifyRenderTargetCreated(e) u.textureFactoryEvents <- e
}() }()
} }

View File

@ -31,7 +31,7 @@ type Window struct {
context *opengl.Context context *opengl.Context
funcs chan func() funcs chan func()
funcsDone chan struct{} funcsDone chan struct{}
windowEvents events chan interface{}
} }
var windows = map[unsafe.Pointer]*Window{} var windows = map[unsafe.Pointer]*Window{}
@ -97,6 +97,23 @@ func (w *Window) useGLContext(f func()) {
<-w.funcsDone <-w.funcsDone
} }
func (w *Window) Events() <-chan interface{} {
if w.events != nil {
return w.events
}
w.events = make(chan interface{})
return w.events
}
func (w *Window) notify(e interface{}) {
if w.events == nil {
return
}
go func() {
w.events <- e
}()
}
/*//export ebiten_ScreenSizeUpdated /*//export ebiten_ScreenSizeUpdated
func ebiten_ScreenSizeUpdated(nativeWindow unsafe.Pointer, width, height int) { func ebiten_ScreenSizeUpdated(nativeWindow unsafe.Pointer, width, height int) {
u := currentUI u := currentUI

View File

@ -1,58 +0,0 @@
package cocoa
import (
"github.com/hajimehoshi/go-ebiten/ui"
)
type windowEvents struct {
screenSizeUpdated chan ui.ScreenSizeUpdatedEvent // initialized lazily
mouseStateUpdated chan ui.MouseStateUpdatedEvent // initialized lazily
windowClosed chan ui.WindowClosedEvent // initialized lazily
}
func (w *windowEvents) notify(e interface{}) {
go func() {
w.doNotify(e)
}()
}
func (w *windowEvents) doNotify(e interface{}) {
switch e := e.(type) {
case ui.ScreenSizeUpdatedEvent:
if w.screenSizeUpdated != nil {
w.screenSizeUpdated <- e
}
case ui.MouseStateUpdatedEvent:
if w.mouseStateUpdated != nil {
w.mouseStateUpdated <- e
}
case ui.WindowClosedEvent:
if w.windowClosed != nil {
w.windowClosed <- e
}
}
}
func (w *windowEvents) ScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent {
if w.screenSizeUpdated != nil {
return w.screenSizeUpdated
}
w.screenSizeUpdated = make(chan ui.ScreenSizeUpdatedEvent)
return w.screenSizeUpdated
}
func (w *windowEvents) MouseStateUpdated() <-chan ui.MouseStateUpdatedEvent {
if w.mouseStateUpdated != nil {
return w.mouseStateUpdated
}
w.mouseStateUpdated = make(chan ui.MouseStateUpdatedEvent)
return w.mouseStateUpdated
}
func (w *windowEvents) WindowClosed() <-chan ui.WindowClosedEvent {
if w.windowClosed != nil {
return w.windowClosed
}
w.windowClosed = make(chan ui.WindowClosedEvent)
return w.windowClosed
}

View File

@ -35,13 +35,7 @@ type UI interface {
CreateWindow(screenWidth, screenHeight, screenScale int, title string) Window CreateWindow(screenWidth, screenHeight, screenScale int, title string) Window
} }
type WindowEvents interface {
ScreenSizeUpdated() <-chan ScreenSizeUpdatedEvent
MouseStateUpdated() <-chan MouseStateUpdatedEvent
WindowClosed() <-chan WindowClosedEvent
}
type Window interface { type Window interface {
Draw(func(graphics.Context)) Draw(func(graphics.Context))
WindowEvents Events() <-chan interface{}
} }