Add input package

This commit is contained in:
Hajime Hoshi 2018-04-01 23:20:45 +09:00
parent 861c737495
commit 4de2dc0240
19 changed files with 346 additions and 299 deletions

View File

@ -15,7 +15,7 @@
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/ui"
"github.com/hajimehoshi/ebiten/internal/input"
)
// A GamepadButton represents a gamepad button.
@ -23,37 +23,37 @@ type GamepadButton int
// GamepadButtons
const (
GamepadButton0 GamepadButton = GamepadButton(ui.GamepadButton0)
GamepadButton1 GamepadButton = GamepadButton(ui.GamepadButton1)
GamepadButton2 GamepadButton = GamepadButton(ui.GamepadButton2)
GamepadButton3 GamepadButton = GamepadButton(ui.GamepadButton3)
GamepadButton4 GamepadButton = GamepadButton(ui.GamepadButton4)
GamepadButton5 GamepadButton = GamepadButton(ui.GamepadButton5)
GamepadButton6 GamepadButton = GamepadButton(ui.GamepadButton6)
GamepadButton7 GamepadButton = GamepadButton(ui.GamepadButton7)
GamepadButton8 GamepadButton = GamepadButton(ui.GamepadButton8)
GamepadButton9 GamepadButton = GamepadButton(ui.GamepadButton9)
GamepadButton10 GamepadButton = GamepadButton(ui.GamepadButton10)
GamepadButton11 GamepadButton = GamepadButton(ui.GamepadButton11)
GamepadButton12 GamepadButton = GamepadButton(ui.GamepadButton12)
GamepadButton13 GamepadButton = GamepadButton(ui.GamepadButton13)
GamepadButton14 GamepadButton = GamepadButton(ui.GamepadButton14)
GamepadButton15 GamepadButton = GamepadButton(ui.GamepadButton15)
GamepadButton16 GamepadButton = GamepadButton(ui.GamepadButton16)
GamepadButton17 GamepadButton = GamepadButton(ui.GamepadButton17)
GamepadButton18 GamepadButton = GamepadButton(ui.GamepadButton18)
GamepadButton19 GamepadButton = GamepadButton(ui.GamepadButton19)
GamepadButton20 GamepadButton = GamepadButton(ui.GamepadButton20)
GamepadButton21 GamepadButton = GamepadButton(ui.GamepadButton21)
GamepadButton22 GamepadButton = GamepadButton(ui.GamepadButton22)
GamepadButton23 GamepadButton = GamepadButton(ui.GamepadButton23)
GamepadButton24 GamepadButton = GamepadButton(ui.GamepadButton24)
GamepadButton25 GamepadButton = GamepadButton(ui.GamepadButton25)
GamepadButton26 GamepadButton = GamepadButton(ui.GamepadButton26)
GamepadButton27 GamepadButton = GamepadButton(ui.GamepadButton27)
GamepadButton28 GamepadButton = GamepadButton(ui.GamepadButton28)
GamepadButton29 GamepadButton = GamepadButton(ui.GamepadButton29)
GamepadButton30 GamepadButton = GamepadButton(ui.GamepadButton30)
GamepadButton31 GamepadButton = GamepadButton(ui.GamepadButton31)
GamepadButton0 GamepadButton = GamepadButton(input.GamepadButton0)
GamepadButton1 GamepadButton = GamepadButton(input.GamepadButton1)
GamepadButton2 GamepadButton = GamepadButton(input.GamepadButton2)
GamepadButton3 GamepadButton = GamepadButton(input.GamepadButton3)
GamepadButton4 GamepadButton = GamepadButton(input.GamepadButton4)
GamepadButton5 GamepadButton = GamepadButton(input.GamepadButton5)
GamepadButton6 GamepadButton = GamepadButton(input.GamepadButton6)
GamepadButton7 GamepadButton = GamepadButton(input.GamepadButton7)
GamepadButton8 GamepadButton = GamepadButton(input.GamepadButton8)
GamepadButton9 GamepadButton = GamepadButton(input.GamepadButton9)
GamepadButton10 GamepadButton = GamepadButton(input.GamepadButton10)
GamepadButton11 GamepadButton = GamepadButton(input.GamepadButton11)
GamepadButton12 GamepadButton = GamepadButton(input.GamepadButton12)
GamepadButton13 GamepadButton = GamepadButton(input.GamepadButton13)
GamepadButton14 GamepadButton = GamepadButton(input.GamepadButton14)
GamepadButton15 GamepadButton = GamepadButton(input.GamepadButton15)
GamepadButton16 GamepadButton = GamepadButton(input.GamepadButton16)
GamepadButton17 GamepadButton = GamepadButton(input.GamepadButton17)
GamepadButton18 GamepadButton = GamepadButton(input.GamepadButton18)
GamepadButton19 GamepadButton = GamepadButton(input.GamepadButton19)
GamepadButton20 GamepadButton = GamepadButton(input.GamepadButton20)
GamepadButton21 GamepadButton = GamepadButton(input.GamepadButton21)
GamepadButton22 GamepadButton = GamepadButton(input.GamepadButton22)
GamepadButton23 GamepadButton = GamepadButton(input.GamepadButton23)
GamepadButton24 GamepadButton = GamepadButton(input.GamepadButton24)
GamepadButton25 GamepadButton = GamepadButton(input.GamepadButton25)
GamepadButton26 GamepadButton = GamepadButton(input.GamepadButton26)
GamepadButton27 GamepadButton = GamepadButton(input.GamepadButton27)
GamepadButton28 GamepadButton = GamepadButton(input.GamepadButton28)
GamepadButton29 GamepadButton = GamepadButton(input.GamepadButton29)
GamepadButton30 GamepadButton = GamepadButton(input.GamepadButton30)
GamepadButton31 GamepadButton = GamepadButton(input.GamepadButton31)
GamepadButtonMax GamepadButton = GamepadButton31
)

View File

@ -137,7 +137,7 @@ const ebitenKeysTmpl = `{{.License}}
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/ui"
"github.com/hajimehoshi/ebiten/internal/input"
)
// A Key represents a keyboard key.
@ -147,16 +147,16 @@ type Key int
// Keys
const (
{{range $index, $name := .KeyNames}}Key{{$name}} Key = Key(ui.Key{{$name}})
{{range $index, $name := .KeyNames}}Key{{$name}} Key = Key(input.Key{{$name}})
{{end}} KeyMax Key = Key{{.LastKeyName}}
)
`
const uiKeysTmpl = `{{.License}}
const inputKeysTmpl = `{{.License}}
{{.DoNotEdit}}
package ui
package input
type Key int
@ -166,13 +166,13 @@ const (
)
`
const uiKeysGlfwTmpl = `{{.License}}
const inputKeysGlfwTmpl = `{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package ui
package input
import (
glfw "github.com/go-gl/glfw/v3.2/glfw"
@ -190,13 +190,13 @@ var glfwKeyCodeToKey = map[glfw.Key]Key{
}
`
const uiKeysJSTmpl = `{{.License}}
const inputKeysJSTmpl = `{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package ui
package input
var keyToCodes = map[Key][]string{
{{range $name, $codes := .NameToCodes}}Key{{$name}}: []string{
@ -323,9 +323,9 @@ func main() {
for path, tmpl := range map[string]string{
"keys.go": ebitenKeysTmpl,
"internal/ui/keys.go": uiKeysTmpl,
"internal/ui/keys_glfw.go": uiKeysGlfwTmpl,
"internal/ui/keys_js.go": uiKeysJSTmpl,
"internal/input/keys.go": inputKeysTmpl,
"internal/input/keys_glfw.go": inputKeysGlfwTmpl,
"internal/input/keys_js.go": inputKeysJSTmpl,
} {
f, err := os.Create(path)
if err != nil {
@ -340,12 +340,12 @@ func main() {
// Pass the build tag and extract this in the template to make `go vet` happy.
buildTag := ""
switch path {
case "internal/ui/keys_glfw.go":
case "internal/input/keys_glfw.go":
buildTag = "// +build darwin freebsd linux windows" +
"\n// +build !js" +
"\n// +build !android" +
"\n// +build !ios"
case "internal/ui/keys_js.go":
case "internal/input/keys_js.go":
buildTag = "// +build js"
}
// NOTE: According to godoc, maps are automatically sorted by key.

View File

@ -15,6 +15,7 @@
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/ui"
)
@ -28,7 +29,7 @@ import (
//
// This function is concurrent-safe.
func InputChars() []rune {
rb := ui.CurrentInput().RuneBuffer()
rb := input.Get().RuneBuffer()
return append(make([]rune, 0, len(rb)), rb...)
}
@ -36,14 +37,14 @@ func InputChars() []rune {
//
// This function is concurrent-safe.
func IsKeyPressed(key Key) bool {
return ui.CurrentInput().IsKeyPressed(ui.Key(key))
return input.Get().IsKeyPressed(input.Key(key))
}
// CursorPosition returns a position of a mouse cursor.
//
// This function is concurrent-safe.
func CursorPosition() (x, y int) {
return ui.CurrentInput().CursorPosition()
return ui.AdjustedCursorPosition()
}
// IsMouseButtonPressed returns a boolean indicating whether mouseButton is pressed.
@ -53,7 +54,7 @@ func CursorPosition() (x, y int) {
// Note that touch events not longer affect this function's result as of 1.4.0-alpha.
// Use Touches instead.
func IsMouseButtonPressed(mouseButton MouseButton) bool {
return ui.CurrentInput().IsMouseButtonPressed(ui.MouseButton(mouseButton))
return input.Get().IsMouseButtonPressed(input.MouseButton(mouseButton))
}
// GamepadIDs returns a slice indicating available gamepad IDs.
@ -62,7 +63,7 @@ func IsMouseButtonPressed(mouseButton MouseButton) bool {
//
// This function always returns an empty slice on mobiles.
func GamepadIDs() []int {
return ui.CurrentInput().GamepadIDs()
return input.Get().GamepadIDs()
}
// GamepadAxisNum returns the number of axes of the gamepad (id).
@ -71,7 +72,7 @@ func GamepadIDs() []int {
//
// This function always returns 0 on mobiles.
func GamepadAxisNum(id int) int {
return ui.CurrentInput().GamepadAxisNum(id)
return input.Get().GamepadAxisNum(id)
}
// GamepadAxis returns the float value [-1.0 - 1.0] of the given gamepad (id)'s axis (axis).
@ -80,7 +81,7 @@ func GamepadAxisNum(id int) int {
//
// This function always returns 0 on mobiles.
func GamepadAxis(id int, axis int) float64 {
return ui.CurrentInput().GamepadAxis(id, axis)
return input.Get().GamepadAxis(id, axis)
}
// GamepadButtonNum returns the number of the buttons of the given gamepad (id).
@ -89,7 +90,7 @@ func GamepadAxis(id int, axis int) float64 {
//
// This function always returns 0 on mobiles.
func GamepadButtonNum(id int) int {
return ui.CurrentInput().GamepadButtonNum(id)
return input.Get().GamepadButtonNum(id)
}
// IsGamepadButtonPressed returns the boolean indicating the given button of the gamepad (id) is pressed or not.
@ -102,7 +103,7 @@ func GamepadButtonNum(id int) int {
//
// This function always returns false on mobiles.
func IsGamepadButtonPressed(id int, button GamepadButton) bool {
return ui.CurrentInput().IsGamepadButtonPressed(id, ui.GamepadButton(button))
return input.Get().IsGamepadButtonPressed(id, input.GamepadButton(button))
}
// Touch represents a touch state.
@ -118,7 +119,7 @@ type Touch interface {
//
// Touches always returns nil on desktops.
func Touches() []Touch {
t := ui.CurrentInput().Touches()
t := input.Get().Touches()
tt := make([]Touch, len(t))
for i := 0; i < len(tt); i++ {
tt[i] = t[i]

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package ui
package input
type GamepadButton int

View File

@ -12,23 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package ui
package input
var currentInput = &Input{}
var theInput = &Input{}
type Touch interface {
ID() int
Position() (x, y int)
}
func CurrentInput() *Input {
return currentInput
func Get() *Input {
return theInput
}
func (i *Input) CursorPosition() (x, y int) {
i.m.RLock()
defer i.m.RUnlock()
return adjustCursorPosition(i.cursorX, i.cursorY)
return i.cursorX, i.cursorY
}
var emptyIDs = []int{}
@ -86,9 +81,9 @@ func (i *Input) IsGamepadButtonPressed(id int, button GamepadButton) bool {
return i.gamepads[id].buttonPressed[button]
}
var emptyTouches = []Touch{}
var emptyTouches = []*Touch{}
func (in *Input) Touches() []Touch {
func (in *Input) Touches() []*Touch {
in.m.RLock()
defer in.m.RUnlock()
@ -98,9 +93,9 @@ func (in *Input) Touches() []Touch {
return emptyTouches
}
t := make([]Touch, len(in.touches))
t := make([]*Touch, len(in.touches))
for i := 0; i < len(t); i++ {
t[i] = &in.touches[i]
t[i] = in.touches[i]
}
return t
}
@ -113,16 +108,24 @@ type gamePad struct {
buttonPressed [256]bool
}
type touch struct {
type Touch struct {
id int
x int
y int
}
func (t *touch) ID() int {
func NewTouch(id int, x, y int) *Touch {
return &Touch{
id: id,
x: x,
y: y,
}
}
func (t *Touch) ID() int {
return t.id
}
func (t *touch) Position() (x, y int) {
func (t *Touch) Position() (x, y int) {
return t.x, t.y
}

View File

@ -17,7 +17,7 @@
// +build !android
// +build !ios
package ui
package input
import (
"sync"
@ -32,7 +32,7 @@ type Input struct {
cursorX int
cursorY int
gamepads [16]gamePad
touches []touch // This is not updated until GLFW 3.3 is available (#417)
touches []*Touch // This is not updated until GLFW 3.3 is available (#417)
runeBuffer []rune
m sync.RWMutex
}
@ -43,6 +43,12 @@ func (i *Input) RuneBuffer() []rune {
return i.runeBuffer
}
func (i *Input) ClearRuneBuffer() {
i.m.RLock()
defer i.m.RUnlock()
i.runeBuffer = i.runeBuffer[:0]
}
func (i *Input) IsKeyPressed(key Key) bool {
i.m.RLock()
defer i.m.RUnlock()
@ -83,7 +89,7 @@ var glfwMouseButtonToMouseButton = map[glfw.MouseButton]MouseButton{
glfw.MouseButtonMiddle: MouseButtonMiddle,
}
func (i *Input) update(window *glfw.Window, scale float64) {
func (i *Input) Update(window *glfw.Window, scale float64) {
i.m.Lock()
defer i.m.Unlock()
if i.runeBuffer == nil {

View File

@ -14,9 +14,11 @@
// +build js
package ui
package input
import (
"unicode"
"github.com/gopherjs/gopherjs/js"
)
@ -34,7 +36,7 @@ type Input struct {
cursorX int
cursorY int
gamepads [16]gamePad
touches []touch
touches []*Touch
runeBuffer []rune
m mockRWLock
}
@ -43,6 +45,10 @@ func (i *Input) RuneBuffer() []rune {
return i.runeBuffer
}
func (i *Input) ClearRuneBuffer() {
i.runeBuffer = nil
}
func (i *Input) IsKeyPressed(key Key) bool {
if i.keyPressed != nil {
for _, c := range keyToCodes[key] {
@ -131,7 +137,7 @@ func (i *Input) setMouseCursor(x, y int) {
i.cursorX, i.cursorY = x, y
}
func (i *Input) updateGamepads() {
func (i *Input) UpdateGamepads() {
nav := js.Global.Get("navigator")
if nav.Get("getGamepads") == js.Undefined {
return
@ -170,7 +176,111 @@ func (i *Input) updateGamepads() {
}
}
func (i *Input) updateTouches(t []touch) {
i.touches = make([]touch, len(t))
func (i *Input) updateTouches(t []*Touch) {
i.touches = make([]*Touch, len(t))
copy(i.touches, t)
}
func OnKeyDown(e *js.Object) {
c := e.Get("code")
if c == js.Undefined {
code := e.Get("keyCode").Int()
if keyCodeToKeyEdge[code] == KeyUp ||
keyCodeToKeyEdge[code] == KeyDown ||
keyCodeToKeyEdge[code] == KeyLeft ||
keyCodeToKeyEdge[code] == KeyRight ||
keyCodeToKeyEdge[code] == KeyBackspace ||
keyCodeToKeyEdge[code] == KeyTab {
e.Call("preventDefault")
}
theInput.keyDownEdge(code)
return
}
cs := c.String()
if cs == keyToCodes[KeyUp][0] ||
cs == keyToCodes[KeyDown][0] ||
cs == keyToCodes[KeyLeft][0] ||
cs == keyToCodes[KeyRight][0] ||
cs == keyToCodes[KeyBackspace][0] ||
cs == keyToCodes[KeyTab][0] {
e.Call("preventDefault")
}
theInput.keyDown(cs)
}
func OnKeyPress(e *js.Object) {
e.Call("preventDefault")
if r := rune(e.Get("charCode").Int()); unicode.IsPrint(r) {
theInput.runeBuffer = append(theInput.runeBuffer, r)
}
}
func OnKeyUp(e *js.Object) {
e.Call("preventDefault")
if e.Get("code") == js.Undefined {
// Assume that UA is Edge.
code := e.Get("keyCode").Int()
theInput.keyUpEdge(code)
return
}
code := e.Get("code").String()
theInput.keyUp(code)
}
func OnMouseDown(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
button := e.Get("button").Int()
theInput.mouseDown(button)
setMouseCursorFromEvent(e, scale, left, top)
}
func OnMouseUp(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
button := e.Get("button").Int()
theInput.mouseUp(button)
setMouseCursorFromEvent(e, scale, left, top)
}
func OnMouseMove(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
setMouseCursorFromEvent(e, scale, left, top)
}
func OnTouchStart(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
theInput.updateTouches(touchEventToTouches(e, scale, left, top))
}
func OnTouchEnd(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
theInput.updateTouches(touchEventToTouches(e, scale, left, top))
}
func OnTouchMove(e *js.Object, scale float64, left, top int) {
e.Call("preventDefault")
theInput.updateTouches(touchEventToTouches(e, scale, left, top))
}
func setMouseCursorFromEvent(e *js.Object, scale float64, left, top int) {
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
x -= left
y -= top
theInput.setMouseCursor(int(float64(x)/scale), int(float64(y)/scale))
}
func touchEventToTouches(e *js.Object, scale float64, left, top int) []*Touch {
j := e.Get("targetTouches")
t := make([]*Touch, j.Get("length").Int())
for i := 0; i < len(t); i++ {
jj := j.Call("item", i)
id := jj.Get("identifier").Int()
x := int(float64(jj.Get("clientX").Int()-left) / scale)
y := int(float64(jj.Get("clientY").Int()-top) / scale)
t[i] = &Touch{
id: id,
x: x,
y: y,
}
}
return t
}

View File

@ -14,7 +14,7 @@
// +build android ios
package ui
package input
import (
"sync"
@ -24,7 +24,7 @@ type Input struct {
cursorX int
cursorY int
gamepads [16]gamePad
touches []touch
touches []*Touch
m sync.RWMutex
}
@ -40,13 +40,16 @@ func (i *Input) IsMouseButtonPressed(key MouseButton) bool {
return false
}
func (i *Input) updateTouches(touches []Touch, dx, dy int) {
func (i *Input) UpdateTouches(touches []*Touch, dx, dy int) {
i.m.Lock()
ts := make([]touch, len(touches))
ts := make([]*Touch, len(touches))
for i := 0; i < len(ts); i++ {
ts[i].id = touches[i].ID()
x, y := touches[i].Position()
ts[i].x, ts[i].y = x+dx, y+dy
ts[i] = &Touch{
id: touches[i].id,
x: x + dx,
y: y + dy,
}
}
i.touches = ts
i.m.Unlock()

View File

@ -14,7 +14,7 @@
// Code generated by genkeys.go using 'go generate'. DO NOT EDIT.
package ui
package input
type Key int

View File

@ -19,7 +19,7 @@
// +build !android
// +build !ios
package ui
package input
import (
glfw "github.com/go-gl/glfw/v3.2/glfw"

View File

@ -16,7 +16,7 @@
// +build js
package ui
package input
var keyToCodes = map[Key][]string{
Key0: {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package ui
package input
type MouseButton int

View File

@ -22,9 +22,10 @@ import (
"golang.org/x/mobile/event/lifecycle"
"golang.org/x/mobile/event/paint"
"golang.org/x/mobile/event/size"
mtouch "golang.org/x/mobile/event/touch"
"golang.org/x/mobile/event/touch"
"golang.org/x/mobile/gl"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/opengl"
)
@ -34,7 +35,7 @@ var (
func appMain(a app.App) {
var glctx gl.Context
touches := map[mtouch.Sequence]*touch{}
touches := map[touch.Sequence]*input.Touch{}
for e := range a.Events() {
switch e := a.Filter(e).(type) {
case lifecycle.Event:
@ -61,20 +62,17 @@ func appMain(a app.App) {
<-chRenderEnd
a.Publish()
a.Send(paint.Event{})
case mtouch.Event:
case touch.Event:
switch e.Type {
case mtouch.TypeBegin, mtouch.TypeMove:
case touch.TypeBegin, touch.TypeMove:
s := float32(actualScale())
t := &touch{
id: int(e.Sequence), // TODO: Is it ok to cast from int64 to int here?
x: int(e.X / s),
y: int(e.Y / s),
}
// TODO: Is it ok to cast from int64 to int here?
t := input.NewTouch(int(e.Sequence), int(e.X/s), int(e.Y/s))
touches[e.Sequence] = t
case mtouch.TypeEnd:
case touch.TypeEnd:
delete(touches, e.Sequence)
}
ts := []Touch{}
ts := []*input.Touch{}
for _, t := range touches {
ts = append(ts, t)
}

View File

@ -29,6 +29,7 @@ import (
"github.com/go-gl/glfw/v3.2/glfw"
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/opengl"
)
@ -347,6 +348,10 @@ func ScreenPadding() (x0, y0, x1, y1 float64) {
return ox, oy, ox, oy
}
func AdjustedCursorPosition() (x, y int) {
return adjustCursorPosition(input.Get().CursorPosition())
}
func adjustCursorPosition(x, y int) (int, int) {
u := currentUI
if !u.isRunning() {
@ -486,7 +491,7 @@ func (u *userInterface) actualScreenScale() float64 {
// pollEvents must be called from the main thread.
func (u *userInterface) pollEvents() {
glfw.PollEvents()
currentInput.update(u.window, u.getScale()*glfwScale())
input.Get().Update(u.window, u.getScale()*glfwScale())
}
func (u *userInterface) updateGraphicsContext(g GraphicsContext) {
@ -542,7 +547,7 @@ func (u *userInterface) update(g GraphicsContext) error {
return nil
})
if err := g.Update(func() {
currentInput.runeBuffer = currentInput.runeBuffer[:0]
input.Get().ClearRuneBuffer()
// The offscreens must be updated every frame (#490).
u.updateGraphicsContext(g)
}); err != nil {

View File

@ -19,11 +19,11 @@ package ui
import (
"image"
"strconv"
"unicode"
"github.com/gopherjs/gopherjs/js"
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/opengl"
)
@ -77,8 +77,8 @@ func ScreenPadding() (x0, y0, x1, y1 float64) {
return 0, 0, 0, 0
}
func adjustCursorPosition(x, y int) (int, int) {
return x, y
func AdjustedCursorPosition() (x, y int) {
return input.Get().CursorPosition()
}
func IsCursorVisible() bool {
@ -151,10 +151,10 @@ func (u *userInterface) update(g GraphicsContext) error {
return nil
}
currentInput.updateGamepads()
input.Get().UpdateGamepads()
u.updateGraphicsContext(g)
if err := g.Update(func() {
currentInput.runeBuffer = nil
input.Get().ClearRuneBuffer()
// The offscreens must be updated every frame (#490).
u.updateGraphicsContext(g)
}); err != nil {
@ -180,21 +180,6 @@ func (u *userInterface) loop(g GraphicsContext) error {
return <-ch
}
func touchEventToTouches(e *js.Object) []touch {
scale := currentUI.getScale()
j := e.Get("targetTouches")
rect := canvas.Call("getBoundingClientRect")
left, top := rect.Get("left").Int(), rect.Get("top").Int()
t := make([]touch, j.Get("length").Int())
for i := 0; i < len(t); i++ {
jj := j.Call("item", i)
t[i].id = jj.Get("identifier").Int()
t[i].x = int(float64(jj.Get("clientX").Int()-left) / scale)
t[i].y = int(float64(jj.Get("clientY").Int()-top) / scale)
}
return t
}
func init() {
if err := initialize(); err != nil {
panic(err)
@ -263,66 +248,22 @@ func initialize() error {
canvas.Get("style").Set("outline", "none")
// Keyboard
canvas.Call("addEventListener", "keydown", func(e *js.Object) {
c := e.Get("code")
if c == js.Undefined {
code := e.Get("keyCode").Int()
if keyCodeToKeyEdge[code] == KeyUp ||
keyCodeToKeyEdge[code] == KeyDown ||
keyCodeToKeyEdge[code] == KeyLeft ||
keyCodeToKeyEdge[code] == KeyRight ||
keyCodeToKeyEdge[code] == KeyBackspace ||
keyCodeToKeyEdge[code] == KeyTab {
e.Call("preventDefault")
}
currentInput.keyDownEdge(code)
return
}
cs := c.String()
if cs == keyToCodes[KeyUp][0] ||
cs == keyToCodes[KeyDown][0] ||
cs == keyToCodes[KeyLeft][0] ||
cs == keyToCodes[KeyRight][0] ||
cs == keyToCodes[KeyBackspace][0] ||
cs == keyToCodes[KeyTab][0] {
e.Call("preventDefault")
}
currentInput.keyDown(cs)
})
canvas.Call("addEventListener", "keypress", func(e *js.Object) {
e.Call("preventDefault")
if r := rune(e.Get("charCode").Int()); unicode.IsPrint(r) {
currentInput.runeBuffer = append(currentInput.runeBuffer, r)
}
})
canvas.Call("addEventListener", "keyup", func(e *js.Object) {
e.Call("preventDefault")
if e.Get("code") == js.Undefined {
// Assume that UA is Edge.
code := e.Get("keyCode").Int()
currentInput.keyUpEdge(code)
return
}
code := e.Get("code").String()
currentInput.keyUp(code)
})
canvas.Call("addEventListener", "keydown", input.OnKeyDown)
canvas.Call("addEventListener", "keypress", input.OnKeyPress)
canvas.Call("addEventListener", "keyup", input.OnKeyUp)
// Mouse
canvas.Call("addEventListener", "mousedown", func(e *js.Object) {
e.Call("preventDefault")
button := e.Get("button").Int()
currentInput.mouseDown(button)
setMouseCursorFromEvent(e)
rect := canvas.Call("getBoundingClientRect")
input.OnMouseDown(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
canvas.Call("addEventListener", "mouseup", func(e *js.Object) {
e.Call("preventDefault")
button := e.Get("button").Int()
currentInput.mouseUp(button)
setMouseCursorFromEvent(e)
rect := canvas.Call("getBoundingClientRect")
input.OnMouseUp(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
canvas.Call("addEventListener", "mousemove", func(e *js.Object) {
e.Call("preventDefault")
setMouseCursorFromEvent(e)
rect := canvas.Call("getBoundingClientRect")
input.OnMouseMove(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
canvas.Call("addEventListener", "contextmenu", func(e *js.Object) {
e.Call("preventDefault")
@ -330,16 +271,16 @@ func initialize() error {
// Touch
canvas.Call("addEventListener", "touchstart", func(e *js.Object) {
e.Call("preventDefault")
currentInput.updateTouches(touchEventToTouches(e))
rect := canvas.Call("getBoundingClientRect")
input.OnTouchStart(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
canvas.Call("addEventListener", "touchend", func(e *js.Object) {
e.Call("preventDefault")
currentInput.updateTouches(touchEventToTouches(e))
rect := canvas.Call("getBoundingClientRect")
input.OnTouchEnd(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
canvas.Call("addEventListener", "touchmove", func(e *js.Object) {
e.Call("preventDefault")
currentInput.updateTouches(touchEventToTouches(e))
rect := canvas.Call("getBoundingClientRect")
input.OnTouchMove(e, currentUI.getScale(), rect.Get("left").Int(), rect.Get("top").Int())
})
// Gamepad
@ -357,15 +298,6 @@ func initialize() error {
return nil
}
func setMouseCursorFromEvent(e *js.Object) {
scale := currentUI.getScale()
rect := canvas.Call("getBoundingClientRect")
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
x -= rect.Get("left").Int()
y -= rect.Get("top").Int()
currentInput.setMouseCursor(int(float64(x)/scale), int(float64(y)/scale))
}
func RunMainThreadLoop(ch <-chan error) error {
return <-ch
}

View File

@ -24,6 +24,7 @@ import (
"time"
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/opengl"
)
@ -237,8 +238,8 @@ func (u *userInterface) screenPaddingImpl() (x0, y0, x1, y1 float64) {
return ox, oy, ox, oy
}
func adjustCursorPosition(x, y int) (int, int) {
return currentUI.adjustCursorPosition(x, y)
func AdjustedCursorPosition() (x, y int) {
return currentUI.adjustCursorPosition(input.Get().CursorPosition())
}
func (u *userInterface) adjustCursorPosition(x, y int) (int, int) {
@ -285,10 +286,10 @@ func SetWindowDecorated(decorated bool) {
// Do nothing
}
func UpdateTouches(touches []Touch) {
func UpdateTouches(touches []*input.Touch) {
currentUI.m.Lock()
ox, oy, _, _ := currentUI.screenPaddingImpl()
s := currentUI.actualScaleImpl()
currentUI.m.Unlock()
currentInput.updateTouches(touches, -int(ox/s), -int(oy/s))
input.Get().UpdateTouches(touches, -int(ox/s), -int(oy/s))
}

158
keys.go
View File

@ -17,7 +17,7 @@
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/ui"
"github.com/hajimehoshi/ebiten/internal/input"
)
// A Key represents a keyboard key.
@ -27,83 +27,83 @@ type Key int
// Keys
const (
Key0 Key = Key(ui.Key0)
Key1 Key = Key(ui.Key1)
Key2 Key = Key(ui.Key2)
Key3 Key = Key(ui.Key3)
Key4 Key = Key(ui.Key4)
Key5 Key = Key(ui.Key5)
Key6 Key = Key(ui.Key6)
Key7 Key = Key(ui.Key7)
Key8 Key = Key(ui.Key8)
Key9 Key = Key(ui.Key9)
KeyA Key = Key(ui.KeyA)
KeyB Key = Key(ui.KeyB)
KeyC Key = Key(ui.KeyC)
KeyD Key = Key(ui.KeyD)
KeyE Key = Key(ui.KeyE)
KeyF Key = Key(ui.KeyF)
KeyG Key = Key(ui.KeyG)
KeyH Key = Key(ui.KeyH)
KeyI Key = Key(ui.KeyI)
KeyJ Key = Key(ui.KeyJ)
KeyK Key = Key(ui.KeyK)
KeyL Key = Key(ui.KeyL)
KeyM Key = Key(ui.KeyM)
KeyN Key = Key(ui.KeyN)
KeyO Key = Key(ui.KeyO)
KeyP Key = Key(ui.KeyP)
KeyQ Key = Key(ui.KeyQ)
KeyR Key = Key(ui.KeyR)
KeyS Key = Key(ui.KeyS)
KeyT Key = Key(ui.KeyT)
KeyU Key = Key(ui.KeyU)
KeyV Key = Key(ui.KeyV)
KeyW Key = Key(ui.KeyW)
KeyX Key = Key(ui.KeyX)
KeyY Key = Key(ui.KeyY)
KeyZ Key = Key(ui.KeyZ)
KeyAlt Key = Key(ui.KeyAlt)
KeyApostrophe Key = Key(ui.KeyApostrophe)
KeyBackslash Key = Key(ui.KeyBackslash)
KeyBackspace Key = Key(ui.KeyBackspace)
KeyCapsLock Key = Key(ui.KeyCapsLock)
KeyComma Key = Key(ui.KeyComma)
KeyControl Key = Key(ui.KeyControl)
KeyDelete Key = Key(ui.KeyDelete)
KeyDown Key = Key(ui.KeyDown)
KeyEnd Key = Key(ui.KeyEnd)
KeyEnter Key = Key(ui.KeyEnter)
KeyEqual Key = Key(ui.KeyEqual)
KeyEscape Key = Key(ui.KeyEscape)
KeyF1 Key = Key(ui.KeyF1)
KeyF2 Key = Key(ui.KeyF2)
KeyF3 Key = Key(ui.KeyF3)
KeyF4 Key = Key(ui.KeyF4)
KeyF5 Key = Key(ui.KeyF5)
KeyF6 Key = Key(ui.KeyF6)
KeyF7 Key = Key(ui.KeyF7)
KeyF8 Key = Key(ui.KeyF8)
KeyF9 Key = Key(ui.KeyF9)
KeyF10 Key = Key(ui.KeyF10)
KeyF11 Key = Key(ui.KeyF11)
KeyF12 Key = Key(ui.KeyF12)
KeyGraveAccent Key = Key(ui.KeyGraveAccent)
KeyHome Key = Key(ui.KeyHome)
KeyInsert Key = Key(ui.KeyInsert)
KeyLeft Key = Key(ui.KeyLeft)
KeyLeftBracket Key = Key(ui.KeyLeftBracket)
KeyMinus Key = Key(ui.KeyMinus)
KeyPageDown Key = Key(ui.KeyPageDown)
KeyPageUp Key = Key(ui.KeyPageUp)
KeyPeriod Key = Key(ui.KeyPeriod)
KeyRight Key = Key(ui.KeyRight)
KeyRightBracket Key = Key(ui.KeyRightBracket)
KeySemicolon Key = Key(ui.KeySemicolon)
KeyShift Key = Key(ui.KeyShift)
KeySlash Key = Key(ui.KeySlash)
KeySpace Key = Key(ui.KeySpace)
KeyTab Key = Key(ui.KeyTab)
KeyUp Key = Key(ui.KeyUp)
Key0 Key = Key(input.Key0)
Key1 Key = Key(input.Key1)
Key2 Key = Key(input.Key2)
Key3 Key = Key(input.Key3)
Key4 Key = Key(input.Key4)
Key5 Key = Key(input.Key5)
Key6 Key = Key(input.Key6)
Key7 Key = Key(input.Key7)
Key8 Key = Key(input.Key8)
Key9 Key = Key(input.Key9)
KeyA Key = Key(input.KeyA)
KeyB Key = Key(input.KeyB)
KeyC Key = Key(input.KeyC)
KeyD Key = Key(input.KeyD)
KeyE Key = Key(input.KeyE)
KeyF Key = Key(input.KeyF)
KeyG Key = Key(input.KeyG)
KeyH Key = Key(input.KeyH)
KeyI Key = Key(input.KeyI)
KeyJ Key = Key(input.KeyJ)
KeyK Key = Key(input.KeyK)
KeyL Key = Key(input.KeyL)
KeyM Key = Key(input.KeyM)
KeyN Key = Key(input.KeyN)
KeyO Key = Key(input.KeyO)
KeyP Key = Key(input.KeyP)
KeyQ Key = Key(input.KeyQ)
KeyR Key = Key(input.KeyR)
KeyS Key = Key(input.KeyS)
KeyT Key = Key(input.KeyT)
KeyU Key = Key(input.KeyU)
KeyV Key = Key(input.KeyV)
KeyW Key = Key(input.KeyW)
KeyX Key = Key(input.KeyX)
KeyY Key = Key(input.KeyY)
KeyZ Key = Key(input.KeyZ)
KeyAlt Key = Key(input.KeyAlt)
KeyApostrophe Key = Key(input.KeyApostrophe)
KeyBackslash Key = Key(input.KeyBackslash)
KeyBackspace Key = Key(input.KeyBackspace)
KeyCapsLock Key = Key(input.KeyCapsLock)
KeyComma Key = Key(input.KeyComma)
KeyControl Key = Key(input.KeyControl)
KeyDelete Key = Key(input.KeyDelete)
KeyDown Key = Key(input.KeyDown)
KeyEnd Key = Key(input.KeyEnd)
KeyEnter Key = Key(input.KeyEnter)
KeyEqual Key = Key(input.KeyEqual)
KeyEscape Key = Key(input.KeyEscape)
KeyF1 Key = Key(input.KeyF1)
KeyF2 Key = Key(input.KeyF2)
KeyF3 Key = Key(input.KeyF3)
KeyF4 Key = Key(input.KeyF4)
KeyF5 Key = Key(input.KeyF5)
KeyF6 Key = Key(input.KeyF6)
KeyF7 Key = Key(input.KeyF7)
KeyF8 Key = Key(input.KeyF8)
KeyF9 Key = Key(input.KeyF9)
KeyF10 Key = Key(input.KeyF10)
KeyF11 Key = Key(input.KeyF11)
KeyF12 Key = Key(input.KeyF12)
KeyGraveAccent Key = Key(input.KeyGraveAccent)
KeyHome Key = Key(input.KeyHome)
KeyInsert Key = Key(input.KeyInsert)
KeyLeft Key = Key(input.KeyLeft)
KeyLeftBracket Key = Key(input.KeyLeftBracket)
KeyMinus Key = Key(input.KeyMinus)
KeyPageDown Key = Key(input.KeyPageDown)
KeyPageUp Key = Key(input.KeyPageUp)
KeyPeriod Key = Key(input.KeyPeriod)
KeyRight Key = Key(input.KeyRight)
KeyRightBracket Key = Key(input.KeyRightBracket)
KeySemicolon Key = Key(input.KeySemicolon)
KeyShift Key = Key(input.KeyShift)
KeySlash Key = Key(input.KeySlash)
KeySpace Key = Key(input.KeySpace)
KeyTab Key = Key(input.KeyTab)
KeyUp Key = Key(input.KeyUp)
KeyMax Key = KeyUp
)

View File

@ -17,6 +17,7 @@
package mobile
import (
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/ui"
)
@ -29,26 +30,13 @@ var (
touches = map[int]position{}
)
// touch implements ui.Touch.
type touch struct {
id int
position position
}
func (t touch) ID() int {
return t.id
}
func (t touch) Position() (int, int) {
// TODO: Is this OK to adjust the position here?
return int(float64(t.position.x) / ui.ScreenScale()),
int(float64(t.position.y) / ui.ScreenScale())
}
func updateTouches() {
ts := []ui.Touch{}
ts := []*input.Touch{}
for id, position := range touches {
ts = append(ts, touch{id, position})
// TODO: Is this OK to adjust the position here?
x := int(float64(position.x) / ui.ScreenScale())
y := int(float64(position.y) / ui.ScreenScale())
ts = append(ts, input.NewTouch(id, x, y))
}
ui.UpdateTouches(ts)
}

View File

@ -15,7 +15,7 @@
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/ui"
"github.com/hajimehoshi/ebiten/internal/input"
)
// A MouseButton represents a mouse button.
@ -23,7 +23,7 @@ type MouseButton int
// MouseButtons
const (
MouseButtonLeft MouseButton = MouseButton(ui.MouseButtonLeft)
MouseButtonRight MouseButton = MouseButton(ui.MouseButtonRight)
MouseButtonMiddle MouseButton = MouseButton(ui.MouseButtonMiddle)
MouseButtonLeft MouseButton = MouseButton(input.MouseButtonLeft)
MouseButtonRight MouseButton = MouseButton(input.MouseButtonRight)
MouseButtonMiddle MouseButton = MouseButton(input.MouseButtonMiddle)
)