ebiten: Introduce type TouchID

Fixes #604
This commit is contained in:
Hajime Hoshi 2020-10-10 03:36:14 +09:00
parent 809b7a3afa
commit b1c67c7661
12 changed files with 49 additions and 40 deletions

View File

@ -84,7 +84,7 @@ type Input struct {
mouseDir Dir
touchState touchState
touchID int
touchID ebiten.TouchID
touchInitPosX int
touchInitPosY int
touchLastPosX int

View File

@ -106,7 +106,7 @@ func (m *MouseStrokeSource) IsJustReleased() bool {
// TouchStrokeSource is a StrokeSource implementation of touch.
type TouchStrokeSource struct {
ID int
ID ebiten.TouchID
}
func (t *TouchStrokeSource) Position() (int, int) {

View File

@ -182,6 +182,9 @@ func IsGamepadButtonPressed(id GamepadID, button GamepadButton) bool {
return uiDriver().Input().IsGamepadButtonPressed(id, driver.GamepadButton(button))
}
// TouchID represents a touch's identifier.
type TouchID = driver.TouchID
// TouchIDs returns the current touch states.
//
// If you want to know whether a touch started being pressed in the current frame,
@ -191,7 +194,7 @@ func IsGamepadButtonPressed(id GamepadID, button GamepadButton) bool {
// TouchIDs always returns nil on desktops.
//
// TouchIDs is concurrent-safe.
func TouchIDs() []int {
func TouchIDs() []TouchID {
return uiDriver().Input().TouchIDs()
}
@ -200,7 +203,7 @@ func TouchIDs() []int {
// If the touch of the specified ID is not present, TouchPosition returns (0, 0).
//
// TouchPosition is cuncurrent-safe.
func TouchPosition(id int) (int, int) {
func TouchPosition(id TouchID) (int, int) {
found := false
for _, i := range uiDriver().Input().TouchIDs() {
if id == i {

View File

@ -36,8 +36,8 @@ type inputState struct {
gamepadButtonDurations map[ebiten.GamepadID][]int
prevGamepadButtonDurations map[ebiten.GamepadID][]int
touchDurations map[int]int
prevTouchDurations map[int]int
touchDurations map[ebiten.TouchID]int
prevTouchDurations map[ebiten.TouchID]int
m sync.RWMutex
}
@ -55,8 +55,8 @@ var theInputState = &inputState{
gamepadButtonDurations: map[ebiten.GamepadID][]int{},
prevGamepadButtonDurations: map[ebiten.GamepadID][]int{},
touchDurations: map[int]int{},
prevTouchDurations: map[int]int{},
touchDurations: map[ebiten.TouchID]int{},
prevTouchDurations: map[ebiten.TouchID]int{},
}
func init() {
@ -134,10 +134,10 @@ func (i *inputState) update() {
}
// Touches
ids := map[int]struct{}{}
ids := map[ebiten.TouchID]struct{}{}
// Copy the touch durations.
i.prevTouchDurations = map[int]int{}
i.prevTouchDurations = map[ebiten.TouchID]int{}
for id := range i.touchDurations {
i.prevTouchDurations[id] = i.touchDurations[id]
}
@ -146,7 +146,7 @@ func (i *inputState) update() {
ids[id] = struct{}{}
i.touchDurations[id]++
}
touchIDsToDelete := []int{}
touchIDsToDelete := []ebiten.TouchID{}
for id := range i.touchDurations {
if _, ok := ids[id]; !ok {
touchIDsToDelete = append(touchIDsToDelete, id)
@ -292,8 +292,8 @@ func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton
// JustPressedTouchIDs might return nil when there is not touch.
//
// JustPressedTouchIDs is concurrent safe.
func JustPressedTouchIDs() []int {
var ids []int
func JustPressedTouchIDs() []ebiten.TouchID {
var ids []ebiten.TouchID
theInputState.m.RLock()
for id, s := range theInputState.touchDurations {
if s == 1 {
@ -301,7 +301,9 @@ func JustPressedTouchIDs() []int {
}
}
theInputState.m.RUnlock()
sort.Ints(ids)
sort.Slice(ids, func(a, b int) bool {
return ids[a] < ids[b]
})
return ids
}
@ -309,7 +311,7 @@ func JustPressedTouchIDs() []int {
// whether the given touch is released just in the current frame.
//
// IsTouchJustReleased is concurrent safe.
func IsTouchJustReleased(id int) bool {
func IsTouchJustReleased(id ebiten.TouchID) bool {
theInputState.m.RLock()
r := theInputState.touchDurations[id] == 0 && theInputState.prevTouchDurations[id] > 0
theInputState.m.RUnlock()
@ -319,7 +321,7 @@ func IsTouchJustReleased(id int) bool {
// TouchPressDuration returns how long the touch remains in frames.
//
// TouchPressDuration is concurrent safe.
func TouchPressDuration(id int) int {
func TouchPressDuration(id ebiten.TouchID) int {
theInputState.m.RLock()
s := theInputState.touchDurations[id]
theInputState.m.RUnlock()

View File

@ -16,6 +16,8 @@ package driver
type GamepadID int
type TouchID int
type Input interface {
CursorPosition() (x, y int)
GamepadSDLID(id GamepadID) string
@ -28,7 +30,7 @@ type Input interface {
IsKeyPressed(key Key) bool
IsMouseButtonPressed(button MouseButton) bool
RuneBuffer() []rune
TouchIDs() []int
TouchPosition(id int) (x, y int)
TouchIDs() []TouchID
TouchPosition(id TouchID) (x, y int)
Wheel() (xoff, yoff float64)
}

View File

@ -45,7 +45,7 @@ type Input struct {
cursorX int
cursorY int
gamepads [16]gamePad
touches map[int]pos // TODO: Implement this (#417)
touches map[driver.TouchID]pos // TODO: Implement this (#417)
runeBuffer []rune
ui *UserInterface
}
@ -173,11 +173,11 @@ func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.Gamepa
return r
}
func (i *Input) TouchIDs() []int {
func (i *Input) TouchIDs() []driver.TouchID {
if !i.ui.isRunning() {
return nil
}
var ids []int
var ids []driver.TouchID
_ = i.ui.t.Call(func() error {
if len(i.touches) == 0 {
return nil
@ -190,7 +190,7 @@ func (i *Input) TouchIDs() []int {
return ids
}
func (i *Input) TouchPosition(id int) (x, y int) {
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
if !i.ui.isRunning() {
return 0, 0
}

View File

@ -46,7 +46,7 @@ type Input struct {
wheelX float64
wheelY float64
gamepads [16]gamePad
touches map[int]pos
touches map[driver.TouchID]pos
runeBuffer []rune
ui *UserInterface
}
@ -118,19 +118,19 @@ func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.Gamepa
return i.gamepads[id].buttonPressed[button]
}
func (i *Input) TouchIDs() []int {
func (i *Input) TouchIDs() []driver.TouchID {
if len(i.touches) == 0 {
return nil
}
var ids []int
var ids []driver.TouchID
for id := range i.touches {
ids = append(ids, id)
}
return ids
}
func (i *Input) TouchPosition(id int) (x, y int) {
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
for tid, pos := range i.touches {
if id == tid {
x, y := i.ui.context.AdjustPosition(float64(pos.X), float64(pos.Y))
@ -346,10 +346,10 @@ func (i *Input) setMouseCursorFromEvent(e js.Value) {
func (i *Input) updateTouches(e js.Value) {
j := e.Get("targetTouches")
ts := map[int]pos{}
ts := map[driver.TouchID]pos{}
for i := 0; i < j.Length(); i++ {
jj := j.Call("item", i)
id := jj.Get("identifier").Int()
id := driver.TouchID(jj.Get("identifier").Int())
ts[id] = pos{
X: jj.Get("clientX").Int(),
Y: jj.Get("clientY").Int(),

View File

@ -30,7 +30,7 @@ type Input struct {
cursorY int
keys map[driver.Key]struct{}
runes []rune
touches map[int]pos
touches map[driver.TouchID]pos
gamepads []Gamepad
ui *UserInterface
}
@ -136,7 +136,7 @@ func (i *Input) IsGamepadButtonPressed(id driver.GamepadID, button driver.Gamepa
return false
}
func (i *Input) TouchIDs() []int {
func (i *Input) TouchIDs() []driver.TouchID {
i.ui.m.RLock()
defer i.ui.m.RUnlock()
@ -144,14 +144,14 @@ func (i *Input) TouchIDs() []int {
return nil
}
var ids []int
var ids []driver.TouchID
for id := range i.touches {
ids = append(ids, id)
}
return ids
}
func (i *Input) TouchPosition(id int) (x, y int) {
func (i *Input) TouchPosition(id driver.TouchID) (x, y int) {
i.ui.m.RLock()
defer i.ui.m.RUnlock()
@ -198,7 +198,7 @@ func (i *Input) update(keys map[driver.Key]struct{}, runes []rune, touches []*To
i.runes = make([]rune, len(runes))
copy(i.runes, runes)
i.touches = map[int]pos{}
i.touches = map[driver.TouchID]pos{}
for _, t := range touches {
i.touches[t.ID] = pos{
X: t.X,

View File

@ -215,7 +215,7 @@ func (u *UserInterface) appMain(a app.App) {
x, y := float64(e.X)/s, float64(e.Y)/s
// TODO: Is it ok to cast from int64 to int here?
touches[e.Sequence] = &Touch{
ID: int(e.Sequence),
ID: driver.TouchID(e.Sequence),
X: int(x),
Y: int(y),
}
@ -474,7 +474,7 @@ func (u *UserInterface) Window() driver.Window {
}
type Touch struct {
ID int
ID driver.TouchID
X int
Y int
}

View File

@ -29,7 +29,7 @@ type position struct {
var (
keys = map[driver.Key]struct{}{}
runes []rune
touches = map[int]position{}
touches = map[driver.TouchID]position{}
gamepads = map[driver.GamepadID]*mobile.Gamepad{}
)

View File

@ -201,10 +201,10 @@ func gamepadIDFromDeviceID(deviceID int) driver.GamepadID {
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
switch action {
case 0x00, 0x05, 0x02: // ACTION_DOWN, ACTION_POINTER_DOWN, ACTION_MOVE
touches[id] = position{x, y}
touches[driver.TouchID(id)] = position{x, y}
updateInput()
case 0x01, 0x06: // ACTION_UP, ACTION_POINTER_UP
delete(touches, id)
delete(touches, driver.TouchID(id))
updateInput()
}
}

View File

@ -18,6 +18,8 @@ package ebitenmobileview
import (
"fmt"
"github.com/hajimehoshi/ebiten/v2/internal/driver"
)
// #cgo CFLAGS: -x objective-c
@ -47,12 +49,12 @@ func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
switch phase {
case C.UITouchPhaseBegan, C.UITouchPhaseMoved, C.UITouchPhaseStationary:
id := getIDFromPtr(ptr)
touches[id] = position{x, y}
touches[driver.TouchID(id)] = position{x, y}
updateInput()
case C.UITouchPhaseEnded, C.UITouchPhaseCancelled:
id := getIDFromPtr(ptr)
delete(ptrToID, ptr)
delete(touches, id)
delete(touches, driver.TouchID(id))
updateInput()
default:
panic(fmt.Sprintf("ebitenmobileview: invalid phase: %d", phase))