From 6da16aa1a02fd7b454213d4ae1ea1eca47fa83e2 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 2 Sep 2016 00:53:05 +0900 Subject: [PATCH] ui: Refactoring: Remove events --- internal/loop/run.go | 44 +++++++++++----------------------------- internal/ui/event.go | 32 ----------------------------- internal/ui/ui.go | 15 ++++++++++++-- internal/ui/ui_glfw.go | 32 ++++++++++++++--------------- internal/ui/ui_js.go | 34 +++++++++++++++---------------- internal/ui/ui_mobile.go | 33 +++++++++++++----------------- 6 files changed, 70 insertions(+), 120 deletions(-) delete mode 100644 internal/ui/event.go diff --git a/internal/loop/run.go b/internal/loop/run.go index 37dae05ad..da43d3d24 100644 --- a/internal/loop/run.go +++ b/internal/loop/run.go @@ -86,10 +86,17 @@ type GraphicsContext interface { UpdateAndDraw(context *opengl.Context, updateCount int) error } -type regularTermination struct{} +type loopGraphicsContext struct { + runContext *runContext + graphicsContext GraphicsContext +} -func (e regularTermination) Error() string { - return "regular termination" +func (g *loopGraphicsContext) SetSize(width, height int, scale float64) error { + 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) { @@ -114,10 +121,8 @@ func Run(g GraphicsContext, width, height int, scale float64, title string, fps currentRunContext.lastUpdated = n currentRunContext.lastFPSUpdated = n - if err := ui.CurrentUI().AnimationFrameLoop(func() error { - return currentRunContext.update(g) - }); err != nil { - if err == (regularTermination{}) { + if err := ui.CurrentUI().AnimationFrameLoop(&loopGraphicsContext{currentRunContext, g}); err != nil { + if _, ok := err.(*ui.RegularTermination); ok { return nil } return err @@ -125,31 +130,6 @@ func Run(g GraphicsContext, width, height int, scale float64, title string, fps 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 { fps := c.fps n := now() diff --git a/internal/ui/event.go b/internal/ui/event.go deleted file mode 100644 index fecaf97d8..000000000 --- a/internal/ui/event.go +++ /dev/null @@ -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{} -} diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 6de6a5150..56683ee24 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -14,12 +14,23 @@ package ui +type GraphicsContext interface { + SetSize(width, height int, scale float64) error + Update() error +} + type UserInterface interface { Start(width, height int, scale float64, title string) error - Update() (interface{}, error) Terminate() error - AnimationFrameLoop(f func() error) error + AnimationFrameLoop(g GraphicsContext) error ScreenScale() float64 SetScreenSize(width, height int) (bool, error) SetScreenScale(scale float64) (bool, error) } + +type RegularTermination struct { +} + +func (*RegularTermination) Error() string { + return "regular termination" +} diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 82d31fb89..a815ddb44 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -192,32 +192,29 @@ func (u *userInterface) pollEvents() error { return currentInput.update(u.window, u.scale*glfwScale()) } -func (u *userInterface) Update() (interface{}, error) { +func (u *userInterface) update(g GraphicsContext) error { shouldClose := false _ = u.runOnMainThread(func() error { shouldClose = u.window.ShouldClose() return nil }) if shouldClose { - return CloseEvent{}, nil + return &RegularTermination{} } - var screenSizeEvent *ScreenSizeEvent + actualScale := 0.0 _ = u.runOnMainThread(func() error { if !u.sizeChanged { return nil } u.sizeChanged = false - screenSizeEvent = &ScreenSizeEvent{ - Width: u.width, - Height: u.height, - ActualScale: u.actualScreenScale(), - Done: make(chan struct{}, 1), - } + actualScale = u.actualScreenScale() return nil }) - if screenSizeEvent != nil { - return *screenSizeEvent, nil + if 0 < actualScale { + if err := g.SetSize(u.width, u.height, actualScale); err != nil { + return err + } } if err := u.runOnMainThread(func() error { @@ -236,11 +233,12 @@ func (u *userInterface) Update() (interface{}, error) { } return nil }); err != nil { - return nil, err + return err } - // Dummy channel - ch := make(chan struct{}, 1) - return RenderEvent{ch}, nil + if err := g.Update(); err != nil { + return err + } + return nil } func (u *userInterface) Terminate() error { @@ -251,9 +249,9 @@ func (u *userInterface) Terminate() error { return nil } -func (u *userInterface) AnimationFrameLoop(f func() error) error { +func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error { for { - if err := f(); err != nil { + if err := u.update(g); err != nil { return err } // The bound framebuffer must be the default one (0) before swapping buffers. diff --git a/internal/ui/ui_js.go b/internal/ui/ui_js.go index 3d4f1eb22..9b23ec7fb 100644 --- a/internal/ui/ui_js.go +++ b/internal/ui/ui_js.go @@ -65,28 +65,26 @@ func (u *userInterface) ActualScreenScale() float64 { return u.scale * u.deviceScale } -func (u *userInterface) Update() (interface{}, error) { +func (u *userInterface) update(g GraphicsContext) error { if !u.windowFocus { - return NopEvent{}, nil + return nil } if !u.contextRestored { - return NopEvent{}, nil + return nil } currentInput.updateGamepads() if u.sizeChanged { u.sizeChanged = false w, h := u.size() - e := ScreenSizeEvent{ - Width: w, - Height: h, - ActualScale: u.ActualScreenScale(), - Done: make(chan struct{}, 1), + if err := g.SetSize(w, h, u.ActualScreenScale()); err != nil { + return err } - return e, nil + return nil } - // Dummy channel - ch := make(chan struct{}, 1) - return RenderEvent{ch}, nil + if err := g.Update(); err != nil { + return err + } + return nil } func (u *userInterface) Terminate() error { @@ -94,18 +92,18 @@ func (u *userInterface) Terminate() error { return nil } -func (u *userInterface) AnimationFrameLoop(f func() error) error { +func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error { ch := make(chan error) - var ff func() - ff = func() { - if err := f(); err != nil { + var f func() + f = func() { + if err := u.update(g); err != nil { ch <- err close(ch) return } - js.Global.Get("window").Call("requestAnimationFrame", ff) + js.Global.Get("window").Call("requestAnimationFrame", f) } - ff() + f() return <-ch } diff --git a/internal/ui/ui_mobile.go b/internal/ui/ui_mobile.go index 8f869f052..c169f76d0 100644 --- a/internal/ui/ui_mobile.go +++ b/internal/ui/ui_mobile.go @@ -81,28 +81,23 @@ func (u *userInterface) Terminate() error { return nil } -func (u *userInterface) Update() (interface{}, error) { - if u.sizeChanged { - // Sizing also calls GL functions - <-chRender - u.sizeChanged = false - e := ScreenSizeEvent{ - 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 { +func (u *userInterface) AnimationFrameLoop(g GraphicsContext) error { for { - if err := f(); err != nil { + if u.sizeChanged { + // Sizing also calls GL functions + <-chRender + u.sizeChanged = false + if err := g.SetSize(u.width, u.height, u.actualScreenScale()); err != nil { + return err + } + chRenderEnd <- struct{}{} + continue + } + <-chRender + if err := g.Update(); err != nil { return err } + chRenderEnd <- struct{}{} } }