driver: Simplify UIContext.Update

This commit is contained in:
Hajime Hoshi 2020-04-03 00:06:42 +09:00
parent 218281ce6f
commit 8777140e91
9 changed files with 50 additions and 39 deletions

View File

@ -25,7 +25,6 @@ type Input interface {
IsGamepadButtonPressed(id int, button GamepadButton) bool IsGamepadButtonPressed(id int, button GamepadButton) bool
IsKeyPressed(key Key) bool IsKeyPressed(key Key) bool
IsMouseButtonPressed(button MouseButton) bool IsMouseButtonPressed(button MouseButton) bool
ResetForFrame()
RuneBuffer() []rune RuneBuffer() []rune
TouchIDs() []int TouchIDs() []int
TouchPosition(id int) (x, y int) TouchPosition(id int) (x, y int)

View File

@ -20,7 +20,7 @@ import (
) )
type UIContext interface { type UIContext interface {
Update(afterFrameUpdate func()) error Update() error
Draw() error Draw() error
Layout(outsideWidth, outsideHeight float64) Layout(outsideWidth, outsideHeight float64)
AdjustPosition(x, y float64) (float64, float64) AdjustPosition(x, y float64) (float64, float64)
@ -38,6 +38,7 @@ type UI interface {
DeviceScaleFactor() float64 DeviceScaleFactor() float64
IsFocused() bool IsFocused() bool
ScreenSizeInFullscreen() (int, int) ScreenSizeInFullscreen() (int, int)
ResetForFrame()
CursorMode() CursorMode CursorMode() CursorMode
SetCursorMode(mode CursorMode) SetCursorMode(mode CursorMode)

View File

@ -228,7 +228,7 @@ func (i *Input) RuneBuffer() []rune {
return r return r
} }
func (i *Input) ResetForFrame() { func (i *Input) resetForFrame() {
if !i.ui.isRunning() { if !i.ui.isRunning() {
return return
} }

View File

@ -37,8 +37,9 @@ import (
) )
type UserInterface struct { type UserInterface struct {
title string context driver.UIContext
window *glfw.Window title string
window *glfw.Window
// windowWidth and windowHeight represents a window size. // windowWidth and windowHeight represents a window size.
// The unit is device-dependent pixels. // The unit is device-dependent pixels.
@ -552,6 +553,8 @@ func init() {
} }
func (u *UserInterface) Run(uicontext driver.UIContext) error { 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). // Initialize the main thread first so the thread is available at u.run (#809).
u.t = thread.New() u.t = thread.New()
u.Graphics().SetThread(u.t) u.Graphics().SetThread(u.t)
@ -562,7 +565,7 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
go func() { go func() {
defer cancel() defer cancel()
defer close(ch) defer close(ch)
if err := u.run(uicontext); err != nil { if err := u.run(); err != nil {
ch <- err ch <- err
} }
}() }()
@ -626,7 +629,7 @@ func (u *UserInterface) createWindow() error {
return nil return nil
} }
func (u *UserInterface) run(context driver.UIContext) error { func (u *UserInterface) run() error {
if err := u.t.Call(func() error { if err := u.t.Call(func() error {
// The window is created at initialize(). // The window is created at initialize().
u.window.Destroy() 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 { if g, ok := u.Graphics().(interface{ SetWindow(unsafe.Pointer) }); ok {
g.SetWindow(w) 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 var w, h int
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
w, h = u.windowWidth, u.windowHeight w, h = u.windowWidth, u.windowHeight
@ -761,11 +764,11 @@ func (u *UserInterface) updateSize(context driver.UIContext) {
h = u.toDeviceIndependentPixel(float64(wh)) h = u.toDeviceIndependentPixel(float64(wh))
return nil 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 shouldClose := false
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
shouldClose = u.window.ShouldClose() shouldClose = u.window.ShouldClose()
@ -786,13 +789,13 @@ func (u *UserInterface) update(context driver.UIContext) error {
} }
// This call is needed for initialization. // This call is needed for initialization.
u.updateSize(context) u.updateSize()
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
glfw.PollEvents() glfw.PollEvents()
return nil return nil
}) })
u.input.update(u.window, context) u.input.update(u.window, u.context)
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
defer hooks.ResumeAudio() defer hooks.ResumeAudio()
@ -807,13 +810,10 @@ func (u *UserInterface) update(context driver.UIContext) error {
} }
return nil return nil
}) })
if err := context.Update(func() { if err := u.context.Update(); err != nil {
// The offscreens must be updated every frame (#490).
u.updateSize(context)
}); err != nil {
return err return err
} }
if err := context.Draw(); err != nil { if err := u.context.Draw(); err != nil {
return err return err
} }
@ -834,7 +834,7 @@ func (u *UserInterface) update(context driver.UIContext) error {
return nil return nil
} }
func (u *UserInterface) loop(context driver.UIContext) error { func (u *UserInterface) loop() error {
defer func() { defer func() {
_ = u.t.Call(func() error { _ = u.t.Call(func() error {
glfw.Terminate() glfw.Terminate()
@ -856,7 +856,7 @@ func (u *UserInterface) loop(context driver.UIContext) error {
if unfocused { if unfocused {
t1 = time.Now() t1 = time.Now()
} }
if err := u.update(context); err != nil { if err := u.update(); err != nil {
return err return err
} }
@ -1065,6 +1065,12 @@ func (u *UserInterface) IsScreenTransparent() bool {
return val 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 { func (u *UserInterface) Input() driver.Input {
return &u.input return &u.input
} }

View File

@ -146,7 +146,7 @@ func (i *Input) RuneBuffer() []rune {
return i.runeBuffer return i.runeBuffer
} }
func (i *Input) ResetForFrame() { func (i *Input) resetForFrame() {
i.runeBuffer = nil i.runeBuffer = nil
i.wheelX = 0 i.wheelX = 0
i.wheelY = 0 i.wheelY = 0

View File

@ -167,9 +167,7 @@ func (u *UserInterface) update() error {
u.input.UpdateGamepads() u.input.UpdateGamepads()
u.updateSize() u.updateSize()
if err := u.context.Update(func() { if err := u.context.Update(); err != nil {
u.updateSize()
}); err != nil {
return err return err
} }
if err := u.context.Draw(); err != nil { if err := u.context.Draw(); err != nil {
@ -459,6 +457,11 @@ func (u *UserInterface) IsScreenTransparent() bool {
return bodyStyle.Get("backgroundColor").String() == "transparent" return bodyStyle.Get("backgroundColor").String() == "transparent"
} }
func (u *UserInterface) ResetForFrame() {
u.updateSize()
u.input.resetForFrame()
}
func (u *UserInterface) Input() driver.Input { func (u *UserInterface) Input() driver.Input {
return &u.input return &u.input
} }

View File

@ -210,6 +210,6 @@ func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*To
copy(i.gamepads, gamepads) copy(i.gamepads, gamepads)
} }
func (i *Input) ResetForFrame() { func (i *Input) resetForFrame() {
i.runes = nil i.runes = nil
} }

View File

@ -302,15 +302,15 @@ func (u *UserInterface) run(context driver.UIContext, mainloop bool) (err error)
} }
// Force to set the screen size // Force to set the screen size
u.updateSize(context) u.updateSize()
for { for {
if err := u.update(context); err != nil { if err := u.update(); err != nil {
return err return err
} }
} }
} }
func (u *UserInterface) updateSize(context driver.UIContext) { func (u *UserInterface) updateSize() {
var outsideWidth, outsideHeight float64 var outsideWidth, outsideHeight float64
u.m.Lock() u.m.Lock()
@ -330,22 +330,20 @@ func (u *UserInterface) updateSize(context driver.UIContext) {
u.m.Unlock() u.m.Unlock()
if sizeChanged { 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 <-renderCh
defer func() { defer func() {
renderEndCh <- struct{}{} renderEndCh <- struct{}{}
}() }()
if err := context.Update(func() { if err := u.context.Update(); err != nil {
u.updateSize(context)
}); err != nil {
return err return err
} }
if err := context.Draw(); err != nil { if err := u.context.Draw(); err != nil {
return err return err
} }
return nil return nil
@ -436,6 +434,11 @@ func (u *UserInterface) IsScreenTransparent() bool {
return false return false
} }
func (u *UserInterface) ResetForFrame() {
u.updateSize()
u.input.resetForFrame()
}
func (u *UserInterface) Input() driver.Input { func (u *UserInterface) Input() driver.Input {
return &u.input return &u.input
} }

View File

@ -227,7 +227,7 @@ func (c *uiContext) offsets() (float64, float64) {
return (c.outsideWidth*d - width) / 2, (c.outsideHeight*d - height) / 2 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. // TODO: If updateCount is 0 and vsync is disabled, swapping buffers can be skipped.
if err, ok := c.err.Load().(error); ok && err != nil { 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 { if err := buffered.BeginFrame(); err != nil {
return err return err
} }
if err := c.update(afterFrameUpdate); err != nil { if err := c.update(); err != nil {
return err return err
} }
if err := buffered.EndFrame(); err != nil { if err := buffered.EndFrame(); err != nil {
@ -259,7 +259,7 @@ func (c *uiContext) Draw() error {
return nil return nil
} }
func (c *uiContext) update(afterFrameUpdate func()) error { func (c *uiContext) update() error {
_, hasDraw := c.game.(interface{ Draw(*Image) }) _, hasDraw := c.game.(interface{ Draw(*Image) })
updateCount := clock.Update(MaxTPS()) updateCount := clock.Update(MaxTPS())
@ -285,8 +285,7 @@ func (c *uiContext) update(afterFrameUpdate func()) error {
if err := c.game.Update(c.offscreen); err != nil { if err := c.game.Update(c.offscreen); err != nil {
return err return err
} }
uiDriver().Input().ResetForFrame() uiDriver().ResetForFrame()
afterFrameUpdate()
} }
return nil return nil
} }