InputChars (#403)

This implements #400
This commit is contained in:
Jake 2017-08-14 12:11:51 -07:00 committed by Hajime Hoshi
parent 93173506f5
commit 0d703ca3d4
7 changed files with 101 additions and 2 deletions

51
examples/runes/main.go Normal file
View File

@ -0,0 +1,51 @@
// Copyright 2017 The Ebiten Authors
//
// 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 example
package main
import (
"log"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
)
var runes = append(make([]rune, 0, 1024), []rune("Type on the keyboard:\n")...)
var buf = make([]rune, 1024)
var counter int
func update(screen *ebiten.Image) error {
runes = append(runes, ebiten.InputChars()...)
if ebiten.IsKeyPressed(ebiten.KeyEnter) {
if len(runes) > 0 && runes[len(runes)-1] != '\n' {
runes = append(runes, '\n')
}
}
counter++
if ebiten.IsRunningSlowly() {
return nil
}
if counter%60 < 30 {
return ebitenutil.DebugPrint(screen, string(append(runes, '_')))
}
return ebitenutil.DebugPrint(screen, string(runes))
}
func main() {
log.Fatal(ebiten.Run(update, 320, 240, 2.0, "Runes (Ebiten Demo)")) // ebiterm?
}

View File

@ -18,6 +18,20 @@ import (
"github.com/hajimehoshi/ebiten/internal/ui" "github.com/hajimehoshi/ebiten/internal/ui"
) )
// InputChars return "printable" runes read from the keyboard at the time update is called.
//
// InputChars represents the environment's locale-dependent translation of keyboard
// input to Unicode characters.
//
// IsKeyPressed is based on a mapping of device codes to input device keys.
// "Control" and modifier keys should be handled with IsKeyPressed.
//
// This function is concurrent-safe.
func InputChars() []rune {
rb := ui.CurrentInput().RuneBuffer()
return append(make([]rune, 0, len(rb)), rb...)
}
// IsKeyPressed returns a boolean indicating whether key is pressed. // IsKeyPressed returns a boolean indicating whether key is pressed.
// //
// This function is concurrent-safe. // This function is concurrent-safe.

View File

@ -21,6 +21,7 @@ package ui
import ( import (
"sync" "sync"
"unicode"
glfw "github.com/go-gl/glfw/v3.2/glfw" glfw "github.com/go-gl/glfw/v3.2/glfw"
) )
@ -32,9 +33,16 @@ type Input struct {
cursorY int cursorY int
gamepads [16]gamePad gamepads [16]gamePad
touches []touch touches []touch
runeBuffer []rune
m sync.RWMutex m sync.RWMutex
} }
func (i *Input) RuneBuffer() []rune {
i.m.RLock()
defer i.m.RUnlock()
return i.runeBuffer
}
func (i *Input) IsKeyPressed(key Key) bool { func (i *Input) IsKeyPressed(key Key) bool {
i.m.RLock() i.m.RLock()
defer i.m.RUnlock() defer i.m.RUnlock()
@ -78,7 +86,16 @@ var glfwMouseButtonToMouseButton = map[glfw.MouseButton]MouseButton{
func (i *Input) update(window *glfw.Window, scale float64) { func (i *Input) update(window *glfw.Window, scale float64) {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
if i.runeBuffer == nil {
i.runeBuffer = make([]rune, 0, 1024)
window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
if unicode.IsPrint(char) {
i.m.Lock()
i.runeBuffer = append(i.runeBuffer, char)
i.m.Unlock()
}
})
}
if i.keyPressed == nil { if i.keyPressed == nil {
i.keyPressed = map[glfw.Key]bool{} i.keyPressed = map[glfw.Key]bool{}
} }

View File

@ -35,9 +35,14 @@ type Input struct {
cursorY int cursorY int
gamepads [16]gamePad gamepads [16]gamePad
touches []touch touches []touch
runeBuffer []rune
m mockRWLock m mockRWLock
} }
func (i *Input) RuneBuffer() []rune {
return i.runeBuffer
}
func (i *Input) IsKeyPressed(key Key) bool { func (i *Input) IsKeyPressed(key Key) bool {
if i.keyPressed != nil { if i.keyPressed != nil {
for _, c := range keyToCodes[key] { for _, c := range keyToCodes[key] {

View File

@ -28,6 +28,10 @@ type Input struct {
m sync.RWMutex m sync.RWMutex
} }
func (i *Input) RuneBuffer() []rune {
return nil
}
func (i *Input) IsKeyPressed(key Key) bool { func (i *Input) IsKeyPressed(key Key) bool {
return false return false
} }

View File

@ -445,6 +445,7 @@ func (u *userInterface) update(g GraphicsContext) error {
if err := g.Update(); err != nil { if err := g.Update(); err != nil {
return err return err
} }
currentInput.runeBuffer = currentInput.runeBuffer[:0]
return nil return nil
} }

View File

@ -19,6 +19,7 @@ package ui
import ( import (
"strconv" "strconv"
"strings" "strings"
"unicode"
"github.com/gopherjs/gopherjs/js" "github.com/gopherjs/gopherjs/js"
"github.com/hajimehoshi/ebiten/internal/opengl" "github.com/hajimehoshi/ebiten/internal/opengl"
@ -134,6 +135,7 @@ func (u *userInterface) update(g GraphicsContext) error {
if err := g.Update(); err != nil { if err := g.Update(); err != nil {
return err return err
} }
currentInput.runeBuffer = nil
return nil return nil
} }
@ -238,7 +240,6 @@ func initialize() error {
// Keyboard // Keyboard
canvas.Call("addEventListener", "keydown", func(e *js.Object) { canvas.Call("addEventListener", "keydown", func(e *js.Object) {
e.Call("preventDefault")
if e.Get("code") == js.Undefined { if e.Get("code") == js.Undefined {
// Assume that UA is Safari. // Assume that UA is Safari.
code := e.Get("keyCode").Int() code := e.Get("keyCode").Int()
@ -248,6 +249,12 @@ func initialize() error {
code := e.Get("code").String() code := e.Get("code").String()
currentInput.keyDown(code) currentInput.keyDown(code)
}) })
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) { canvas.Call("addEventListener", "keyup", func(e *js.Object) {
e.Call("preventDefault") e.Call("preventDefault")
if e.Get("code") == js.Undefined { if e.Get("code") == js.Undefined {