Fix the event handling model

This commit is contained in:
Hajime Hoshi 2013-12-03 22:14:51 +09:00
parent f9e5e754b2
commit 79c74273f5
4 changed files with 53 additions and 81 deletions

View File

@ -62,8 +62,8 @@ func main() {
drawing := make(chan *graphics.LazyCanvas) drawing := make(chan *graphics.LazyCanvas)
go func() { go func() {
inputStateUpdated := u.ObserveInputStateUpdated() inputStateUpdated := u.InputStateUpdated()
screenSizeUpdated := u.ObserveScreenSizeUpdated() screenSizeUpdated := u.ScreenSizeUpdated()
frameTime := time.Duration(int64(time.Second) / int64(fps)) frameTime := time.Duration(int64(time.Second) / int64(fps))
tick := time.Tick(frameTime) tick := time.Tick(frameTime)
@ -78,8 +78,9 @@ func main() {
if game2, ok := game.(Handler); ok { if game2, ok := game.(Handler); ok {
game2.OnInputStateUpdated(e) game2.OnInputStateUpdated(e)
} }
} else {
inputStateUpdated = nil
} }
inputStateUpdated = u.ObserveInputStateUpdated()
case e, ok := <-screenSizeUpdated: case e, ok := <-screenSizeUpdated:
if ok { if ok {
type Handler interface { type Handler interface {
@ -88,8 +89,9 @@ func main() {
if game2, ok := game.(Handler); ok { if game2, ok := game.(Handler); ok {
game2.OnScreenSizeUpdated(e) game2.OnScreenSizeUpdated(e)
} }
} else {
screenSizeUpdated = nil
} }
screenSizeUpdated = u.ObserveScreenSizeUpdated()
case <-tick: case <-tick:
game.Update() game.Update()
case canvas := <-drawing: case canvas := <-drawing:

View File

@ -4,6 +4,7 @@ import (
"image" "image"
) )
// TODO: Remove this?
type TextureFactory interface { type TextureFactory interface {
CreateRenderTarget(width, height int) (RenderTargetId, error) CreateRenderTarget(width, height int) (RenderTargetId, error)
CreateTextureFromImage(img image.Image) (TextureId, error) CreateTextureFromImage(img image.Image) (TextureId, error)

View File

@ -34,10 +34,8 @@ type UI struct {
graphicsDevice *opengl.Device graphicsDevice *opengl.Device
window unsafe.Pointer window unsafe.Pointer
initialEventSent bool initialEventSent bool
inputStateUpdatedChs chan chan ui.InputStateUpdatedEvent screenSizeUpdated chan ui.ScreenSizeUpdatedEvent // initialized lazily
inputStateUpdatedNotified chan ui.InputStateUpdatedEvent inputStateUpdated chan ui.InputStateUpdatedEvent // initialized lazily
screenSizeUpdatedChs chan chan ui.ScreenSizeUpdatedEvent
screenSizeUpdatedNotified chan ui.ScreenSizeUpdatedEvent
} }
var currentUI *UI var currentUI *UI
@ -51,10 +49,6 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
screenHeight: screenHeight, screenHeight: screenHeight,
screenScale: screenScale, screenScale: screenScale,
initialEventSent: false, initialEventSent: false,
inputStateUpdatedChs: make(chan chan ui.InputStateUpdatedEvent),
inputStateUpdatedNotified: make(chan ui.InputStateUpdatedEvent),
screenSizeUpdatedChs: make(chan chan ui.ScreenSizeUpdatedEvent),
screenSizeUpdatedNotified: make(chan ui.ScreenSizeUpdatedEvent),
} }
cTitle := C.CString(title) cTitle := C.CString(title)
@ -75,45 +69,9 @@ func New(screenWidth, screenHeight, screenScale int, title string) *UI {
context) context)
currentUI = u currentUI = u
u.eventLoop()
return u return u
} }
func (u *UI) eventLoop() {
go func() {
inputStateUpdated := []chan ui.InputStateUpdatedEvent{}
for {
select {
case ch := <-u.inputStateUpdatedChs:
inputStateUpdated = append(inputStateUpdated, ch)
case e := <-u.inputStateUpdatedNotified:
for _, ch := range inputStateUpdated {
ch <- e
close(ch)
}
inputStateUpdated = inputStateUpdated[0:0]
}
}
}()
go func() {
screenSizeUpdated := []chan ui.ScreenSizeUpdatedEvent{}
for {
select {
case ch := <-u.screenSizeUpdatedChs:
screenSizeUpdated = append(screenSizeUpdated, ch)
case e := <-u.screenSizeUpdatedNotified:
for _, ch := range screenSizeUpdated {
ch <- e
close(ch)
}
screenSizeUpdated = []chan ui.ScreenSizeUpdatedEvent{}
}
}
}()
}
func (u *UI) PollEvents() { func (u *UI) PollEvents() {
C.PollEvents() C.PollEvents()
if !u.initialEventSent { if !u.initialEventSent {
@ -123,6 +81,10 @@ func (u *UI) PollEvents() {
} }
} }
func (u *UI) LoadTextures(map[int]string) {
// TODO: Implement
}
func (u *UI) LoadResources(f func(graphics.TextureFactory)) { func (u *UI) LoadResources(f func(graphics.TextureFactory)) {
C.BeginDrawing(u.window) C.BeginDrawing(u.window)
f(u.graphicsDevice.TextureFactory()) f(u.graphicsDevice.TextureFactory())
@ -135,31 +97,37 @@ func (u *UI) Draw(f func(graphics.Canvas)) {
C.EndDrawing(u.window) C.EndDrawing(u.window)
} }
func (u *UI) ObserveInputStateUpdated() <-chan ui.InputStateUpdatedEvent { func (u *UI) ScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent {
ch := make(chan ui.InputStateUpdatedEvent) if u.screenSizeUpdated != nil {
go func() { return u.screenSizeUpdated
u.inputStateUpdatedChs <- ch }
}() u.screenSizeUpdated = make(chan ui.ScreenSizeUpdatedEvent)
return ch return u.screenSizeUpdated
}
func (u *UI) notifyInputStateUpdated(e ui.InputStateUpdatedEvent) {
go func() {
u.inputStateUpdatedNotified <- e
}()
}
func (u *UI) ObserveScreenSizeUpdated() <-chan ui.ScreenSizeUpdatedEvent {
ch := make(chan ui.ScreenSizeUpdatedEvent)
go func() {
u.screenSizeUpdatedChs <- ch
}()
return ch
} }
func (u *UI) notifyScreenSizeUpdated(e ui.ScreenSizeUpdatedEvent) { func (u *UI) notifyScreenSizeUpdated(e ui.ScreenSizeUpdatedEvent) {
if u.screenSizeUpdated == nil {
return
}
go func() { go func() {
u.screenSizeUpdatedNotified <- e u.screenSizeUpdated <- e
}()
}
func (u *UI) InputStateUpdated() <-chan ui.InputStateUpdatedEvent {
if u.inputStateUpdated != nil {
return u.inputStateUpdated
}
u.inputStateUpdated = make(chan ui.InputStateUpdatedEvent)
return u.inputStateUpdated
}
func (u *UI) notifyInputStateUpdated(e ui.InputStateUpdatedEvent) {
if u.inputStateUpdated == nil {
return
}
go func() {
u.inputStateUpdated <- e
}() }()
} }

View File

@ -15,13 +15,14 @@ type InputStateUpdatedEvent struct {
} }
type UIEvents interface { type UIEvents interface {
ObserveScreenSizeUpdated() <-chan ScreenSizeUpdatedEvent ScreenSizeUpdated() <-chan ScreenSizeUpdatedEvent
ObserveInputStateUpdated() <-chan InputStateUpdatedEvent InputStateUpdated() <-chan InputStateUpdatedEvent
} }
type UI interface { type UI interface {
PollEvents() PollEvents()
LoadResources(func(graphics.TextureFactory)) LoadResources(func(graphics.TextureFactory))
LoadTextures(map[int]string)
Draw(func(graphics.Canvas)) Draw(func(graphics.Canvas))
UIEvents UIEvents
} }