internal/ui: refactoring: allow slices in InputState

This commit is contained in:
Hajime Hoshi 2023-01-22 00:04:30 +09:00
parent d53803615a
commit b79f0394cc
11 changed files with 61 additions and 67 deletions

View File

@ -147,8 +147,8 @@ func (g *gameForUI) Layout(outsideWidth, outsideHeight float64) (float64, float6
return float64(sw), float64(sh)
}
func (g *gameForUI) UpdateInputState(inputState ui.InputState) {
theInputState.set(inputState)
func (g *gameForUI) UpdateInputState(fn func(*ui.InputState)) {
fn(&theInputState.state)
}
func (g *gameForUI) Update() error {

View File

@ -405,7 +405,7 @@ func (i *inputState) set(inputState ui.InputState) {
func (i *inputState) appendInputChars(runes []rune) []rune {
i.m.Lock()
defer i.m.Unlock()
return append(runes, i.state.Runes[:i.state.RunesCount]...)
return append(runes, i.state.Runes...)
}
func (i *inputState) isKeyPressed(key Key) bool {
@ -453,9 +453,6 @@ func (i *inputState) appendTouchIDs(touches []TouchID) []TouchID {
defer i.m.Unlock()
for _, t := range i.state.Touches {
if !t.Valid {
continue
}
touches = append(touches, t.ID)
}
return touches
@ -466,9 +463,6 @@ func (i *inputState) touchPosition(id TouchID) (int, int) {
defer i.m.Unlock()
for _, t := range i.state.Touches {
if !t.Valid {
continue
}
if id != t.ID {
continue
}

View File

@ -36,7 +36,7 @@ type Game interface {
NewOffscreenImage(width, height int) *Image
NewScreenImage(width, height int) *Image
Layout(outsideWidth, outsideHeight float64) (screenWidth, screenHeight float64)
UpdateInputState(InputState)
UpdateInputState(fn func(*InputState))
Update() error
DrawOffscreen() error
DrawFinalScreen(scale, offsetX, offsetY float64)
@ -128,9 +128,9 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
// Update the game.
for i := 0; i < updateCount; i++ {
// Read the input state and use it for one tick to give a consistent result for one tick (#2496, #2501).
var inputState InputState
ui.readInputState(&inputState)
c.game.UpdateInputState(inputState)
c.game.UpdateInputState(func(inputState *InputState) {
ui.readInputState(inputState)
})
if err := hooks.RunBeforeUpdateHooks(); err != nil {
return err

View File

@ -32,10 +32,9 @@ const (
type TouchID int
type Touch struct {
Valid bool
ID TouchID
X int
Y int
ID TouchID
X int
Y int
}
type InputState struct {
@ -45,16 +44,28 @@ type InputState struct {
CursorY int
WheelX float64
WheelY float64
Touches [16]Touch
Runes [16]rune
RunesCount int
Touches []Touch
Runes []rune
WindowBeingClosed bool
}
func (i *InputState) reset() {
func (i *InputState) copyAndReset(dst *InputState) {
dst.KeyPressed = i.KeyPressed
dst.MouseButtonPressed = i.MouseButtonPressed
dst.CursorX = i.CursorX
dst.CursorY = i.CursorY
dst.WheelX = i.WheelX
dst.WheelY = i.WheelY
dst.Touches = append(dst.Touches[:0], i.Touches...)
dst.Runes = append(dst.Runes[:0], i.Runes...)
dst.WindowBeingClosed = i.WindowBeingClosed
// Reset the members that are updated by deltas, rather than absolute values.
i.WheelX = 0
i.WheelY = 0
i.RunesCount = 0
i.Runes = i.Runes[:0]
// Reset the member that is never reset until it is explicitly done.
i.WindowBeingClosed = false
}
@ -62,10 +73,5 @@ func (i *InputState) appendRune(r rune) {
if !unicode.IsPrint(r) {
return
}
if i.RunesCount >= len(i.Runes) {
return
}
i.Runes[i.RunesCount] = r
i.RunesCount++
i.Runes = append(i.Runes, r)
}

View File

@ -123,20 +123,17 @@ func (u *userInterfaceImpl) recoverCursorPosition() {
}
func (u *userInterfaceImpl) updateTouchesFromEvent(e js.Value) {
for i := range u.inputState.Touches {
u.inputState.Touches[i].Valid = false
}
u.inputState.Touches = u.inputState.Touches[:0]
touches := e.Get("targetTouches")
for i := 0; i < touches.Length(); i++ {
t := touches.Call("item", i)
x, y := u.context.clientPositionToLogicalPosition(t.Get("clientX").Float(), t.Get("clientY").Float(), u.DeviceScaleFactor())
u.inputState.Touches[i] = Touch{
Valid: true,
ID: TouchID(t.Get("identifier").Int()),
X: int(x),
Y: int(y),
}
u.inputState.Touches = append(u.inputState.Touches, Touch{
ID: TouchID(t.Get("identifier").Int()),
X: int(x),
Y: int(y),
})
}
}

View File

@ -35,20 +35,16 @@ func (u *userInterfaceImpl) updateInputState(keys map[Key]struct{}, runes []rune
u.inputState.KeyPressed[k] = ok
}
copy(u.inputState.Runes[:], runes)
u.inputState.RunesCount = len(runes)
u.inputState.Runes = append(u.inputState.Runes, runes...)
for i := range u.inputState.Touches {
u.inputState.Touches[i].Valid = false
}
for i, t := range touches {
u.inputState.Touches = u.inputState.Touches[:0]
for _, t := range touches {
x, y := u.context.clientPositionToLogicalPosition(t.X, t.Y, u.DeviceScaleFactor())
u.inputState.Touches[i] = Touch{
Valid: true,
ID: t.ID,
X: int(x),
Y: int(y),
}
u.inputState.Touches = append(u.inputState.Touches, Touch{
ID: t.ID,
X: int(x),
Y: int(y),
})
}
}

View File

@ -38,17 +38,17 @@ func (u *userInterfaceImpl) updateInputState() {
C.ebitengine_GetTouches(&u.nativeTouches[0])
}
for i := range u.inputState.Touches {
u.inputState.Touches[i].Valid = false
}
for i, t := range u.nativeTouches {
u.m.Lock()
defer u.m.Unlock()
u.inputState.Touches = u.inputState.Touches[:0]
for _, t := range u.nativeTouches {
x, y := u.context.clientPositionToLogicalPosition(float64(t.x), float64(t.y), deviceScaleFactor)
u.inputState.Touches[i] = Touch{
Valid: true,
ID: TouchID(t.id),
X: int(x),
Y: int(y),
}
u.inputState.Touches = append(u.inputState.Touches, Touch{
ID: TouchID(t.id),
X: int(x),
Y: int(y),
})
}
}

View File

@ -1341,8 +1341,7 @@ func monitorFromWindow(window *glfw.Window) *glfw.Monitor {
func (u *userInterfaceImpl) readInputState(inputState *InputState) {
u.m.Lock()
defer u.m.Unlock()
*inputState = u.inputState
u.inputState.reset()
u.inputState.copyAndReset(inputState)
}
func (u *userInterfaceImpl) Window() Window {

View File

@ -676,8 +676,7 @@ func (u *userInterfaceImpl) updateScreenSize() {
}
func (u *userInterfaceImpl) readInputState(inputState *InputState) {
*inputState = u.inputState
u.inputState.reset()
u.inputState.copyAndReset(inputState)
u.keyboardLayoutMap = js.Value{}
}

View File

@ -421,8 +421,7 @@ func (u *userInterfaceImpl) DeviceScaleFactor() float64 {
func (u *userInterfaceImpl) readInputState(inputState *InputState) {
u.m.Lock()
defer u.m.Unlock()
*inputState = u.inputState
u.inputState.reset()
u.inputState.copyAndReset(inputState)
}
func (u *userInterfaceImpl) Window() Window {

View File

@ -23,6 +23,7 @@ import "C"
import (
stdcontext "context"
"runtime"
"sync"
"golang.org/x/sync/errgroup"
@ -69,6 +70,8 @@ type userInterfaceImpl struct {
mainThread *thread.OSThread
renderThread *thread.OSThread
m sync.Mutex
}
func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
@ -149,8 +152,9 @@ func (*userInterfaceImpl) ScreenSizeInFullscreen() (int, int) {
}
func (u *userInterfaceImpl) readInputState(inputState *InputState) {
*inputState = u.inputState
u.inputState.reset()
u.m.Lock()
defer u.m.Unlock()
u.inputState.copyAndReset(inputState)
}
func (*userInterfaceImpl) CursorMode() CursorMode {