diff --git a/internal/driver/input.go b/internal/driver/input.go index 0068c0ca6..c1edccaa4 100644 --- a/internal/driver/input.go +++ b/internal/driver/input.go @@ -25,7 +25,6 @@ type Input interface { IsGamepadButtonPressed(id int, button GamepadButton) bool IsKeyPressed(key Key) bool IsMouseButtonPressed(button MouseButton) bool - ResetForFrame() RuneBuffer() []rune TouchIDs() []int TouchPosition(id int) (x, y int) diff --git a/internal/driver/ui.go b/internal/driver/ui.go index 3500f6022..feb45d87c 100644 --- a/internal/driver/ui.go +++ b/internal/driver/ui.go @@ -20,7 +20,7 @@ import ( ) type UIContext interface { - Update(afterFrameUpdate func()) error + Update() error Draw() error Layout(outsideWidth, outsideHeight float64) AdjustPosition(x, y float64) (float64, float64) @@ -38,6 +38,7 @@ type UI interface { DeviceScaleFactor() float64 IsFocused() bool ScreenSizeInFullscreen() (int, int) + ResetForFrame() CursorMode() CursorMode SetCursorMode(mode CursorMode) diff --git a/internal/uidriver/glfw/input.go b/internal/uidriver/glfw/input.go index 137da0357..099611782 100644 --- a/internal/uidriver/glfw/input.go +++ b/internal/uidriver/glfw/input.go @@ -228,7 +228,7 @@ func (i *Input) RuneBuffer() []rune { return r } -func (i *Input) ResetForFrame() { +func (i *Input) resetForFrame() { if !i.ui.isRunning() { return } diff --git a/internal/uidriver/glfw/ui.go b/internal/uidriver/glfw/ui.go index 23c0bf046..04300e119 100644 --- a/internal/uidriver/glfw/ui.go +++ b/internal/uidriver/glfw/ui.go @@ -37,8 +37,9 @@ import ( ) type UserInterface struct { - title string - window *glfw.Window + context driver.UIContext + title string + window *glfw.Window // windowWidth and windowHeight represents a window size. // The unit is device-dependent pixels. @@ -552,6 +553,8 @@ func init() { } func (u *UserInterface) Run(uicontext driver.UIContext) error { + u.context = uicontext + // Initialize the main thread first so the thread is available at u.run (#809). u.t = thread.New() u.Graphics().SetThread(u.t) @@ -562,7 +565,7 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error { go func() { defer cancel() defer close(ch) - if err := u.run(uicontext); err != nil { + if err := u.run(); err != nil { ch <- err } }() @@ -626,7 +629,7 @@ func (u *UserInterface) createWindow() error { return nil } -func (u *UserInterface) run(context driver.UIContext) error { +func (u *UserInterface) run() error { if err := u.t.Call(func() error { // The window is created at initialize(). u.window.Destroy() @@ -725,10 +728,10 @@ func (u *UserInterface) run(context driver.UIContext) error { if g, ok := u.Graphics().(interface{ SetWindow(unsafe.Pointer) }); ok { g.SetWindow(w) } - return u.loop(context) + return u.loop() } -func (u *UserInterface) updateSize(context driver.UIContext) { +func (u *UserInterface) updateSize() { var w, h int _ = u.t.Call(func() error { w, h = u.windowWidth, u.windowHeight @@ -761,11 +764,11 @@ func (u *UserInterface) updateSize(context driver.UIContext) { h = u.toDeviceIndependentPixel(float64(wh)) return nil }) - context.Layout(w, h) + u.context.Layout(w, h) } } -func (u *UserInterface) update(context driver.UIContext) error { +func (u *UserInterface) update() error { shouldClose := false _ = u.t.Call(func() error { shouldClose = u.window.ShouldClose() @@ -786,13 +789,13 @@ func (u *UserInterface) update(context driver.UIContext) error { } // This call is needed for initialization. - u.updateSize(context) + u.updateSize() _ = u.t.Call(func() error { glfw.PollEvents() return nil }) - u.input.update(u.window, context) + u.input.update(u.window, u.context) _ = u.t.Call(func() error { defer hooks.ResumeAudio() @@ -807,13 +810,10 @@ func (u *UserInterface) update(context driver.UIContext) error { } return nil }) - if err := context.Update(func() { - // The offscreens must be updated every frame (#490). - u.updateSize(context) - }); err != nil { + if err := u.context.Update(); err != nil { return err } - if err := context.Draw(); err != nil { + if err := u.context.Draw(); err != nil { return err } @@ -834,7 +834,7 @@ func (u *UserInterface) update(context driver.UIContext) error { return nil } -func (u *UserInterface) loop(context driver.UIContext) error { +func (u *UserInterface) loop() error { defer func() { _ = u.t.Call(func() error { glfw.Terminate() @@ -856,7 +856,7 @@ func (u *UserInterface) loop(context driver.UIContext) error { if unfocused { t1 = time.Now() } - if err := u.update(context); err != nil { + if err := u.update(); err != nil { return err } @@ -1065,6 +1065,12 @@ func (u *UserInterface) IsScreenTransparent() bool { return val } +func (u *UserInterface) ResetForFrame() { + // The offscreens must be updated every frame (#490). + u.updateSize() + u.input.resetForFrame() +} + func (u *UserInterface) Input() driver.Input { return &u.input } diff --git a/internal/uidriver/js/input.go b/internal/uidriver/js/input.go index 951d5db6d..af91a29b6 100644 --- a/internal/uidriver/js/input.go +++ b/internal/uidriver/js/input.go @@ -146,7 +146,7 @@ func (i *Input) RuneBuffer() []rune { return i.runeBuffer } -func (i *Input) ResetForFrame() { +func (i *Input) resetForFrame() { i.runeBuffer = nil i.wheelX = 0 i.wheelY = 0 diff --git a/internal/uidriver/js/ui.go b/internal/uidriver/js/ui.go index f8c6426c3..63c96ec67 100644 --- a/internal/uidriver/js/ui.go +++ b/internal/uidriver/js/ui.go @@ -167,9 +167,7 @@ func (u *UserInterface) update() error { u.input.UpdateGamepads() u.updateSize() - if err := u.context.Update(func() { - u.updateSize() - }); err != nil { + if err := u.context.Update(); err != nil { return err } if err := u.context.Draw(); err != nil { @@ -459,6 +457,11 @@ func (u *UserInterface) IsScreenTransparent() bool { return bodyStyle.Get("backgroundColor").String() == "transparent" } +func (u *UserInterface) ResetForFrame() { + u.updateSize() + u.input.resetForFrame() +} + func (u *UserInterface) Input() driver.Input { return &u.input } diff --git a/internal/uidriver/mobile/input.go b/internal/uidriver/mobile/input.go index 6af118799..796fbfe13 100644 --- a/internal/uidriver/mobile/input.go +++ b/internal/uidriver/mobile/input.go @@ -210,6 +210,6 @@ func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*To copy(i.gamepads, gamepads) } -func (i *Input) ResetForFrame() { +func (i *Input) resetForFrame() { i.runes = nil } diff --git a/internal/uidriver/mobile/ui.go b/internal/uidriver/mobile/ui.go index 62e9503e0..4ce901eca 100644 --- a/internal/uidriver/mobile/ui.go +++ b/internal/uidriver/mobile/ui.go @@ -302,15 +302,15 @@ func (u *UserInterface) run(context driver.UIContext, mainloop bool) (err error) } // Force to set the screen size - u.updateSize(context) + u.updateSize() for { - if err := u.update(context); err != nil { + if err := u.update(); err != nil { return err } } } -func (u *UserInterface) updateSize(context driver.UIContext) { +func (u *UserInterface) updateSize() { var outsideWidth, outsideHeight float64 u.m.Lock() @@ -330,22 +330,20 @@ func (u *UserInterface) updateSize(context driver.UIContext) { u.m.Unlock() if sizeChanged { - context.Layout(outsideWidth, outsideHeight) + u.context.Layout(outsideWidth, outsideHeight) } } -func (u *UserInterface) update(context driver.UIContext) error { +func (u *UserInterface) update() error { <-renderCh defer func() { renderEndCh <- struct{}{} }() - if err := context.Update(func() { - u.updateSize(context) - }); err != nil { + if err := u.context.Update(); err != nil { return err } - if err := context.Draw(); err != nil { + if err := u.context.Draw(); err != nil { return err } return nil @@ -436,6 +434,11 @@ func (u *UserInterface) IsScreenTransparent() bool { return false } +func (u *UserInterface) ResetForFrame() { + u.updateSize() + u.input.resetForFrame() +} + func (u *UserInterface) Input() driver.Input { return &u.input } diff --git a/uicontext.go b/uicontext.go index 6256ce0b2..19c76748f 100644 --- a/uicontext.go +++ b/uicontext.go @@ -227,7 +227,7 @@ func (c *uiContext) offsets() (float64, float64) { return (c.outsideWidth*d - width) / 2, (c.outsideHeight*d - height) / 2 } -func (c *uiContext) Update(afterFrameUpdate func()) error { +func (c *uiContext) Update() error { // TODO: If updateCount is 0 and vsync is disabled, swapping buffers can be skipped. if err, ok := c.err.Load().(error); ok && err != nil { @@ -236,7 +236,7 @@ func (c *uiContext) Update(afterFrameUpdate func()) error { if err := buffered.BeginFrame(); err != nil { return err } - if err := c.update(afterFrameUpdate); err != nil { + if err := c.update(); err != nil { return err } if err := buffered.EndFrame(); err != nil { @@ -259,7 +259,7 @@ func (c *uiContext) Draw() error { return nil } -func (c *uiContext) update(afterFrameUpdate func()) error { +func (c *uiContext) update() error { _, hasDraw := c.game.(interface{ Draw(*Image) }) updateCount := clock.Update(MaxTPS()) @@ -285,8 +285,7 @@ func (c *uiContext) update(afterFrameUpdate func()) error { if err := c.game.Update(c.offscreen); err != nil { return err } - uiDriver().Input().ResetForFrame() - afterFrameUpdate() + uiDriver().ResetForFrame() } return nil }