uidriver: Move input implementation to uidrivers

This commit is contained in:
Hajime Hoshi 2019-04-07 18:55:56 +09:00
parent a1697feeb1
commit 26c32d36b5
13 changed files with 256 additions and 169 deletions

View File

@ -287,13 +287,13 @@ const (
)
`
const inputKeysGlfwTmpl = `{{.License}}
const uidriverGlfwKeysTmpl = `{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package input
package glfw
import (
"github.com/hajimehoshi/ebiten/internal/driver"
@ -312,13 +312,13 @@ var glfwKeyCodeToKey = map[glfw.Key]driver.Key{
}
`
const inputKeysJSTmpl = `{{.License}}
const uidriverJsKeysTmpl = `{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package input
package js
import (
"github.com/hajimehoshi/ebiten/internal/driver"
@ -472,11 +472,11 @@ func main() {
sort.Strings(codes)
for path, tmpl := range map[string]string{
"keys.go": ebitenKeysTmpl,
"internal/driver/keys.go": driverKeysTmpl,
"internal/input/keys_glfw.go": inputKeysGlfwTmpl,
"internal/input/keys_js.go": inputKeysJSTmpl,
"internal/glfw/keys.go": glfwKeysTmpl,
"keys.go": ebitenKeysTmpl,
"internal/driver/keys.go": driverKeysTmpl,
"internal/glfw/keys.go": glfwKeysTmpl,
"internal/uidriver/glfw/keys.go": uidriverGlfwKeysTmpl,
"internal/uidriver/js/keys.go": uidriverJsKeysTmpl,
} {
f, err := os.Create(path)
if err != nil {
@ -496,12 +496,12 @@ func main() {
// Pass the build tag and extract this in the template to make `go vet` happy.
buildTag := ""
switch path {
case "internal/input/keys_glfw.go":
case "internal/uidriver/glfw/keys.go":
buildTag = "// +build darwin freebsd linux windows" +
"\n// +build !js" +
"\n// +build !android" +
"\n// +build !ios"
case "internal/input/keys_js.go":
case "internal/uidriver/js/keys.go":
buildTag = "// +build js"
}
// NOTE: According to godoc, maps are automatically sorted by key.

View File

@ -39,7 +39,7 @@ type UI interface {
IsWindowDecorated() bool
IsWindowResizable() bool
Loop(ch <-chan error) error
Run(width, height int, scale float64, title string, g GraphicsContext, mainloop bool, graphics Graphics, input Input) error
Run(width, height int, scale float64, title string, g GraphicsContext, mainloop bool, graphics Graphics) error
ScreenPadding() (x0, y0, x1, y1 float64)
ScreenScale() float64
ScreenSizeInFullscreen() (int, int)

View File

@ -1,63 +0,0 @@
// Copyright 2016 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build android ios
package input
import (
"sync"
"github.com/hajimehoshi/ebiten/internal/driver"
)
type Input struct {
cursorX int
cursorY int
gamepads [16]gamePad
touches map[int]pos
m sync.RWMutex
}
func (i *Input) RuneBuffer() []rune {
return nil
}
func (i *Input) IsKeyPressed(key driver.Key) bool {
return false
}
func (i *Input) Wheel() (xoff, yoff float64) {
return 0, 0
}
func (i *Input) IsMouseButtonPressed(key driver.MouseButton) bool {
return false
}
func (i *Input) Update(touches []*driver.Touch) {
i.m.Lock()
i.touches = map[int]pos{}
for _, t := range touches {
i.touches[t.ID] = pos{
X: t.X,
Y: t.Y,
}
}
i.m.Unlock()
}
func (i *Input) ResetForFrame() {
// Do nothing
}

View File

@ -17,7 +17,7 @@
// +build !android
// +build !ios
package input
package glfw
import (
"sync"
@ -27,6 +27,14 @@ import (
"github.com/hajimehoshi/ebiten/internal/glfw"
)
type gamePad struct {
valid bool
axisNum int
axes [16]float64
buttonNum int
buttonPressed [256]bool
}
type Input struct {
keyPressed map[glfw.Key]bool
mouseButtonPressed map[glfw.MouseButton]bool
@ -41,6 +49,95 @@ type Input struct {
m sync.RWMutex
}
type pos struct {
X int
Y int
}
func (i *Input) CursorPosition() (x, y int) {
i.m.RLock()
defer i.m.RUnlock()
return i.cursorX, i.cursorY
}
func (i *Input) GamepadIDs() []int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) == 0 {
return nil
}
r := []int{}
for id, g := range i.gamepads {
if g.valid {
r = append(r, id)
}
}
return r
}
func (i *Input) GamepadAxisNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axisNum
}
func (i *Input) GamepadAxis(id int, axis int) float64 {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axes[axis]
}
func (i *Input) GamepadButtonNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].buttonNum
}
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return false
}
return i.gamepads[id].buttonPressed[button]
}
func (i *Input) TouchIDs() []int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.touches) == 0 {
return nil
}
var ids []int
for id := range i.touches {
ids = append(ids, id)
}
return ids
}
func (i *Input) TouchPosition(id int) (x, y int) {
i.m.RLock()
defer i.m.RUnlock()
for tid, pos := range i.touches {
if id == tid {
return pos.X, pos.Y
}
}
return 0, 0
}
func (i *Input) RuneBuffer() []rune {
i.m.RLock()
defer i.m.RUnlock()
@ -116,7 +213,7 @@ func (i *Input) setWheel(xoff, yoff float64) {
i.m.Unlock()
}
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()

View File

@ -19,7 +19,7 @@
// +build !android
// +build !ios
package input
package glfw
import (
"github.com/hajimehoshi/ebiten/internal/driver"

View File

@ -65,7 +65,7 @@ type UserInterface struct {
reqHeight int
graphics driver.Graphics
input driver.Input
input Input
m sync.Mutex
}
@ -552,10 +552,9 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
return f
}
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics) error {
_ = mainthread.Run(func() error {
u.graphics = graphics
u.input = input
if graphics.IsGL() {
glfw.WindowHint(glfw.ContextVersionMajor, 2)
@ -745,11 +744,7 @@ func (u *UserInterface) update(g driver.GraphicsContext) error {
_ = mainthread.Run(func() error {
glfw.PollEvents()
type updater interface {
Update(window *glfw.Window, scale float64)
}
u.input.(updater).Update(u.window, u.getScale()*u.glfwScale())
u.input.update(u.window, u.getScale()*u.glfwScale())
defer hooks.ResumeAudio()
@ -943,5 +938,5 @@ func (u *UserInterface) currentMonitor() *glfw.Monitor {
}
func (u *UserInterface) Input() driver.Input {
return u.input
return &u.input
}

View File

@ -14,7 +14,7 @@
// +build js
package input
package js
import (
"unicode"
@ -24,12 +24,18 @@ import (
"github.com/hajimehoshi/ebiten/internal/driver"
)
type mockRWLock struct{}
type pos struct {
X int
Y int
}
func (m mockRWLock) Lock() {}
func (m mockRWLock) Unlock() {}
func (m mockRWLock) RLock() {}
func (m mockRWLock) RUnlock() {}
type gamePad struct {
valid bool
axisNum int
axes [16]float64
buttonNum int
buttonPressed [256]bool
}
type Input struct {
keyPressed map[string]bool
@ -42,7 +48,72 @@ type Input struct {
gamepads [16]gamePad
touches map[int]pos
runeBuffer []rune
m mockRWLock
}
func (i *Input) CursorPosition() (x, y int) {
return i.cursorX, i.cursorY
}
func (i *Input) GamepadIDs() []int {
if len(i.gamepads) == 0 {
return nil
}
r := []int{}
for id, g := range i.gamepads {
if g.valid {
r = append(r, id)
}
}
return r
}
func (i *Input) GamepadAxisNum(id int) int {
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axisNum
}
func (i *Input) GamepadAxis(id int, axis int) float64 {
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axes[axis]
}
func (i *Input) GamepadButtonNum(id int) int {
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].buttonNum
}
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
if len(i.gamepads) <= id {
return false
}
return i.gamepads[id].buttonPressed[button]
}
func (i *Input) TouchIDs() []int {
if len(i.touches) == 0 {
return nil
}
var ids []int
for id := range i.touches {
ids = append(ids, id)
}
return ids
}
func (i *Input) TouchPosition(id int) (x, y int) {
for tid, pos := range i.touches {
if id == tid {
return pos.X, pos.Y
}
}
return 0, 0
}
func (i *Input) RuneBuffer() []rune {

View File

@ -16,7 +16,7 @@
// +build js
package input
package js
import (
"github.com/hajimehoshi/ebiten/internal/driver"

View File

@ -31,13 +31,6 @@ import (
var canvas js.Value
type inputDriver interface {
driver.Input
Update(e js.Value)
UpdateGamepads()
}
type UserInterface struct {
width int
height int
@ -53,7 +46,7 @@ type UserInterface struct {
lastActualScale float64
input inputDriver
input Input
}
var theUI = &UserInterface{
@ -389,9 +382,7 @@ func (u *UserInterface) Loop(ch <-chan error) error {
return <-ch
}
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
u.input = input.(inputDriver)
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics) error {
document.Set("title", title)
u.setScreenSize(width, height, scale, u.fullscreen)
canvas.Call("focus")
@ -438,5 +429,5 @@ func (u *UserInterface) updateScreenSize() {
}
func (u *UserInterface) Input() driver.Input {
return u.input
return &u.input
}

View File

@ -1,4 +1,4 @@
// Copyright 2015 Hajime Hoshi
// Copyright 2016 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -12,21 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package input
// +build android ios
package mobile
import (
"sync"
"github.com/hajimehoshi/ebiten/internal/driver"
)
var theInput = &Input{}
type pos struct {
X int
Y int
}
func Get() driver.Input {
return theInput
type Input struct {
cursorX int
cursorY int
touches map[int]pos
m sync.RWMutex
}
func (i *Input) CursorPosition() (x, y int) {
@ -36,54 +41,23 @@ func (i *Input) CursorPosition() (x, y int) {
}
func (i *Input) GamepadIDs() []int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) == 0 {
return nil
}
r := []int{}
for id, g := range i.gamepads {
if g.valid {
r = append(r, id)
}
}
return r
return nil
}
func (i *Input) GamepadAxisNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axisNum
return 0
}
func (i *Input) GamepadAxis(id int, axis int) float64 {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].axes[axis]
return 0
}
func (i *Input) GamepadButtonNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
return i.gamepads[id].buttonNum
return 0
}
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
i.m.RLock()
defer i.m.RUnlock()
if len(i.gamepads) <= id {
return false
}
return i.gamepads[id].buttonPressed[button]
return false
}
func (i *Input) TouchIDs() []int {
@ -113,10 +87,34 @@ func (i *Input) TouchPosition(id int) (x, y int) {
return 0, 0
}
type gamePad struct {
valid bool
axisNum int
axes [16]float64
buttonNum int
buttonPressed [256]bool
func (i *Input) RuneBuffer() []rune {
return nil
}
func (i *Input) IsKeyPressed(key driver.Key) bool {
return false
}
func (i *Input) Wheel() (xoff, yoff float64) {
return 0, 0
}
func (i *Input) IsMouseButtonPressed(key driver.MouseButton) bool {
return false
}
func (i *Input) update(touches []*driver.Touch) {
i.m.Lock()
i.touches = map[int]pos{}
for _, t := range touches {
i.touches[t.ID] = pos{
X: t.X,
Y: t.Y,
}
}
i.m.Unlock()
}
func (i *Input) ResetForFrame() {
// Do nothing
}

View File

@ -34,7 +34,6 @@ import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl"
"github.com/hajimehoshi/ebiten/internal/hooks"
"github.com/hajimehoshi/ebiten/internal/input"
)
var (
@ -78,6 +77,8 @@ type UserInterface struct {
fullscreenWidthPx int
fullscreenHeightPx int
input Input
m sync.RWMutex
}
@ -144,15 +145,12 @@ func appMain(a app.App) {
for _, t := range touches {
ts = append(ts, t)
}
type updater interface {
Update(touches []*driver.Touch)
}
input.Get().(updater).Update(ts)
theUI.input.update(ts)
}
}
}
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics) error {
if graphics != opengl.Get() {
panic("ui: graphics driver must be OpenGL")
}
@ -404,5 +402,9 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
}
func (u *UserInterface) Input() driver.Input {
return input.Get()
return &u.input
}
func (u *UserInterface) UpdateInput(touches []*driver.Touch) {
u.input.update(touches)
}

View File

@ -18,7 +18,7 @@ package mobile
import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/uidriver/mobile"
)
type position struct {
@ -39,8 +39,5 @@ func updateTouches() {
Y: position.y,
})
}
type updater interface {
Update(touches []*driver.Touch)
}
input.Get().(updater).Update(ts)
mobile.Get().UpdateInput(ts)
}

3
run.go
View File

@ -20,7 +20,6 @@ import (
"github.com/hajimehoshi/ebiten/internal/clock"
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/web"
)
@ -97,7 +96,7 @@ func run(width, height int, scale float64, title string, g *graphicsContext, mai
if !web.IsGopherJS() {
defer atomic.StoreInt32(&isRunning, 0)
}
if err := uiDriver().Run(width, height, scale, title, g, mainloop, graphicsDriver(), input.Get()); err != nil {
if err := uiDriver().Run(width, height, scale, title, g, mainloop, graphicsDriver()); err != nil {
if err == driver.RegularTermination {
return nil
}