ui: Refactoring: Remove events

This commit is contained in:
Hajime Hoshi 2016-09-02 00:53:05 +09:00
parent b95d714eed
commit 6da16aa1a0
6 changed files with 70 additions and 120 deletions

View File

@ -86,10 +86,17 @@ type GraphicsContext interface {
UpdateAndDraw(context *opengl.Context, updateCount int) error UpdateAndDraw(context *opengl.Context, updateCount int) error
} }
type regularTermination struct{} type loopGraphicsContext struct {
runContext *runContext
graphicsContext GraphicsContext
}
func (e regularTermination) Error() string { func (g *loopGraphicsContext) SetSize(width, height int, scale float64) error {
return "regular termination" return g.graphicsContext.SetSize(width, height, scale)
}
func (g *loopGraphicsContext) Update() error {
return g.runContext.render(g.graphicsContext)
} }
func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) (err error) { func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) (err error) {
@ -114,10 +121,8 @@ func Run(g GraphicsContext, width, height int, scale float64, title string, fps
currentRunContext.lastUpdated = n currentRunContext.lastUpdated = n
currentRunContext.lastFPSUpdated = n currentRunContext.lastFPSUpdated = n
if err := ui.CurrentUI().AnimationFrameLoop(func() error { if err := ui.CurrentUI().AnimationFrameLoop(&loopGraphicsContext{currentRunContext, g}); err != nil {
return currentRunContext.update(g) if _, ok := err.(*ui.RegularTermination); ok {
}); err != nil {
if err == (regularTermination{}) {
return nil return nil
} }
return err return err
@ -125,31 +130,6 @@ func Run(g GraphicsContext, width, height int, scale float64, title string, fps
return nil return nil
} }
func (c *runContext) update(g GraphicsContext) error {
e, err := ui.CurrentUI().Update()
if err != nil {
return err
}
switch e := e.(type) {
case ui.NopEvent:
case ui.ScreenSizeEvent:
if err := g.SetSize(e.Width, e.Height, e.ActualScale); err != nil {
return err
}
e.Done <- struct{}{}
case ui.CloseEvent:
return regularTermination{}
case ui.RenderEvent:
if err := currentRunContext.render(g); err != nil {
return err
}
e.Done <- struct{}{}
default:
panic("not reach")
}
return nil
}
func (c *runContext) render(g GraphicsContext) error { func (c *runContext) render(g GraphicsContext) error {
fps := c.fps fps := c.fps
n := now() n := now()

View File

@ -1,32 +0,0 @@
// Copyright 2016 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 ui
type NopEvent struct {
}
type CloseEvent struct {
}
type ScreenSizeEvent struct {
Width int
Height int
ActualScale float64
Done chan struct{}
}
type RenderEvent struct {
Done chan struct{}
}

View File

@ -14,12 +14,23 @@
package ui package ui
type GraphicsContext interface {
SetSize(width, height int, scale float64) error
Update() error
}
type UserInterface interface { type UserInterface interface {
Start(width, height int, scale float64, title string) error Start(width, height int, scale float64, title string) error
Update() (interface{}, error)
Terminate() error Terminate() error
AnimationFrameLoop(f func() error) error AnimationFrameLoop(g GraphicsContext) error
ScreenScale() float64 ScreenScale() float64
SetScreenSize(width, height int) (bool, error) SetScreenSize(width, height int) (bool, error)
SetScreenScale(scale float64) (bool, error) SetScreenScale(scale float64) (bool, error)
} }
type RegularTermination struct {
}
func (*RegularTermination) Error() string {
return "regular termination"
}

View File

@ -192,32 +192,29 @@ func (u *userInterface) pollEvents() error {
return currentInput.update(u.window, u.scale*glfwScale()) return currentInput.update(u.window, u.scale*glfwScale())
} }
func (u *userInterface) Update() (interface{}, error) { func (u *userInterface) update(g GraphicsContext) error {
shouldClose := false shouldClose := false
_ = u.runOnMainThread(func() error { _ = u.runOnMainThread(func() error {
shouldClose = u.window.ShouldClose() shouldClose = u.window.ShouldClose()
return nil return nil
}) })
if shouldClose { if shouldClose {
return CloseEvent{}, nil return &RegularTermination{}
} }
var screenSizeEvent *ScreenSizeEvent actualScale := 0.0
_ = u.runOnMainThread(func() error { _ = u.runOnMainThread(func() error {
if !u.sizeChanged { if !u.sizeChanged {
return nil return nil
} }
u.sizeChanged = false u.sizeChanged = false
screenSizeEvent = &ScreenSizeEvent{ actualScale = u.actualScreenScale()
Width: u.width,
Height: u.height,
ActualScale: u.actualScreenScale(),
Done: make(chan struct{}, 1),
}
return nil return nil
}) })
if screenSizeEvent != nil { if 0 < actualScale {
return *screenSizeEvent, nil if err := g.SetSize(u.width, u.height, actualScale); err != nil {
return err
}
} }
if err := u.runOnMainThread(func() error { if err := u.runOnMainThread(func() error {
@ -236,11 +233,12 @@ func (u *userInterface) Update() (interface{}, error) {
} }
return nil return nil
}); err != nil { }); err != nil {
return nil, err return err
} }
// Dummy channel if err := g.Update(); err != nil {
ch := make(chan struct{}, 1) return err
return RenderEvent{ch}, nil }
return nil
} }
func (u *userInterface) Terminate() error { func (u *userInterface) Terminate() error {
@ -251,9 +249,9 @@ func (u *userInterface) Terminate() error {
return nil return nil
} }
func (u *userInterface) AnimationFrameLoop(f func() error) error { func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error {
for { for {
if err := f(); err != nil { if err := u.update(g); err != nil {
return err return err
} }
// The bound framebuffer must be the default one (0) before swapping buffers. // The bound framebuffer must be the default one (0) before swapping buffers.

View File

@ -65,28 +65,26 @@ func (u *userInterface) ActualScreenScale() float64 {
return u.scale * u.deviceScale return u.scale * u.deviceScale
} }
func (u *userInterface) Update() (interface{}, error) { func (u *userInterface) update(g GraphicsContext) error {
if !u.windowFocus { if !u.windowFocus {
return NopEvent{}, nil return nil
} }
if !u.contextRestored { if !u.contextRestored {
return NopEvent{}, nil return nil
} }
currentInput.updateGamepads() currentInput.updateGamepads()
if u.sizeChanged { if u.sizeChanged {
u.sizeChanged = false u.sizeChanged = false
w, h := u.size() w, h := u.size()
e := ScreenSizeEvent{ if err := g.SetSize(w, h, u.ActualScreenScale()); err != nil {
Width: w, return err
Height: h,
ActualScale: u.ActualScreenScale(),
Done: make(chan struct{}, 1),
} }
return e, nil return nil
} }
// Dummy channel if err := g.Update(); err != nil {
ch := make(chan struct{}, 1) return err
return RenderEvent{ch}, nil }
return nil
} }
func (u *userInterface) Terminate() error { func (u *userInterface) Terminate() error {
@ -94,18 +92,18 @@ func (u *userInterface) Terminate() error {
return nil return nil
} }
func (u *userInterface) AnimationFrameLoop(f func() error) error { func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error {
ch := make(chan error) ch := make(chan error)
var ff func() var f func()
ff = func() { f = func() {
if err := f(); err != nil { if err := u.update(g); err != nil {
ch <- err ch <- err
close(ch) close(ch)
return return
} }
js.Global.Get("window").Call("requestAnimationFrame", ff) js.Global.Get("window").Call("requestAnimationFrame", f)
} }
ff() f()
return <-ch return <-ch
} }

View File

@ -81,28 +81,23 @@ func (u *userInterface) Terminate() error {
return nil return nil
} }
func (u *userInterface) Update() (interface{}, error) { func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error {
for {
if u.sizeChanged { if u.sizeChanged {
// Sizing also calls GL functions // Sizing also calls GL functions
<-chRender <-chRender
u.sizeChanged = false u.sizeChanged = false
e := ScreenSizeEvent{ if err := g.SetSize(u.width, u.height, u.actualScreenScale()); err != nil {
Width: u.width,
Height: u.height,
ActualScale: u.actualScreenScale(),
Done: chRenderEnd,
}
return e, nil
}
<-chRender
return RenderEvent{chRenderEnd}, nil
}
func (u *userInterface) AnimationFrameLoop(f func() error) error {
for {
if err := f(); err != nil {
return err return err
} }
chRenderEnd <- struct{}{}
continue
}
<-chRender
if err := g.Update(); err != nil {
return err
}
chRenderEnd <- struct{}{}
} }
} }