ui: Use gopherwasm

This commit is contained in:
Hajime Hoshi 2018-05-27 01:59:35 +09:00
parent faaf391619
commit 8e9c3bd304
2 changed files with 64 additions and 75 deletions

View File

@ -19,7 +19,7 @@ package input
import (
"unicode"
"github.com/gopherjs/gopherjs/js"
"github.com/hajimehoshi/gopherwasm/js"
)
type mockRWLock struct{}
@ -147,7 +147,7 @@ func (i *Input) UpdateGamepads() {
for id := 0; id < l; id++ {
i.gamepads[id].valid = false
gamepad := gamepads.Index(id)
if gamepad == js.Undefined || gamepad == nil {
if gamepad == js.Undefined || gamepad == js.Null {
continue
}
i.gamepads[id].valid = true
@ -176,7 +176,7 @@ func (i *Input) UpdateGamepads() {
}
}
func OnKeyDown(e *js.Object) {
func OnKeyDown(e js.Value) {
c := e.Get("code")
if c == js.Undefined {
code := e.Get("keyCode").Int()
@ -203,15 +203,13 @@ func OnKeyDown(e *js.Object) {
theInput.keyDown(cs)
}
func OnKeyPress(e *js.Object) {
e.Call("preventDefault")
func OnKeyPress(e js.Value) {
if r := rune(e.Get("charCode").Int()); unicode.IsPrint(r) {
theInput.runeBuffer = append(theInput.runeBuffer, r)
}
}
func OnKeyUp(e *js.Object) {
e.Call("preventDefault")
func OnKeyUp(e js.Value) {
if e.Get("code") == js.Undefined {
// Assume that UA is Edge.
code := e.Get("keyCode").Int()
@ -222,46 +220,40 @@ func OnKeyUp(e *js.Object) {
theInput.keyUp(code)
}
func OnMouseDown(e *js.Object) {
e.Call("preventDefault")
func OnMouseDown(e js.Value) {
button := e.Get("button").Int()
theInput.mouseDown(button)
setMouseCursorFromEvent(e)
}
func OnMouseUp(e *js.Object) {
e.Call("preventDefault")
func OnMouseUp(e js.Value) {
button := e.Get("button").Int()
theInput.mouseUp(button)
setMouseCursorFromEvent(e)
}
func OnMouseMove(e *js.Object) {
e.Call("preventDefault")
func OnMouseMove(e js.Value) {
setMouseCursorFromEvent(e)
}
func OnTouchStart(e *js.Object) {
e.Call("preventDefault")
func OnTouchStart(e js.Value) {
theInput.updateTouches(e)
}
func OnTouchEnd(e *js.Object) {
e.Call("preventDefault")
func OnTouchEnd(e js.Value) {
theInput.updateTouches(e)
}
func OnTouchMove(e *js.Object) {
e.Call("preventDefault")
func OnTouchMove(e js.Value) {
theInput.updateTouches(e)
}
func setMouseCursorFromEvent(e *js.Object) {
func setMouseCursorFromEvent(e js.Value) {
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
theInput.setMouseCursor(x, y)
}
func (i *Input) updateTouches(e *js.Object) {
func (i *Input) updateTouches(e js.Value) {
j := e.Get("targetTouches")
ts := make([]*Touch, j.Get("length").Int())
for i := 0; i < len(ts); i++ {

View File

@ -18,9 +18,10 @@ package ui
import (
"image"
"runtime"
"strconv"
"github.com/gopherjs/gopherjs/js"
"github.com/hajimehoshi/gopherwasm/js"
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/hooks"
@ -29,7 +30,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/web"
)
var canvas *js.Object
var canvas js.Value
type userInterface struct {
width int
@ -204,69 +205,66 @@ func (u *userInterface) update(g GraphicsContext) error {
func (u *userInterface) loop(g GraphicsContext) error {
ch := make(chan error)
var f func()
f = func() {
go func() {
if err := u.update(g); err != nil {
ch <- err
close(ch)
return
}
js.Global.Get("window").Call("requestAnimationFrame", f)
}()
var f func([]js.Value)
var cf js.Callback
f = func([]js.Value) {
if err := u.update(g); err != nil {
ch <- err
close(ch)
return
}
js.Global.Get("window").Call("requestAnimationFrame", cf)
}
f()
cf = js.NewCallback(f)
f(nil)
return <-ch
}
func init() {
if err := initialize(); err != nil {
panic(err)
}
}
func initialize() error {
// Do nothing in node.js.
if web.IsNodeJS() {
return nil
return
}
doc := js.Global.Get("document")
window := js.Global.Get("window")
if doc.Get("body") == nil {
if doc.Get("body") == js.Null {
ch := make(chan struct{})
window.Call("addEventListener", "load", func() {
window.Call("addEventListener", "load", js.NewCallback(func([]js.Value) {
close(ch)
})
}))
if runtime.GOARCH == "js" {
js.Global.Get("console").Call("warn", "'deadlock' error is raised from GopherJS, but this is a known issue: https://github.com/gopherjs/gopherjs/issues/826")
}
<-ch
}
window.Call("addEventListener", "focus", func() {
window.Call("addEventListener", "focus", js.NewCallback(func([]js.Value) {
currentUI.windowFocus = true
if currentUI.suspended() {
hooks.SuspendAudio()
} else {
hooks.ResumeAudio()
}
})
window.Call("addEventListener", "blur", func() {
}))
window.Call("addEventListener", "blur", js.NewCallback(func([]js.Value) {
currentUI.windowFocus = false
if currentUI.suspended() {
hooks.SuspendAudio()
} else {
hooks.ResumeAudio()
}
})
doc.Call("addEventListener", "visibilitychange", func() {
}))
doc.Call("addEventListener", "visibilitychange", js.NewCallback(func([]js.Value) {
currentUI.pageVisible = !doc.Get("hidden").Bool()
if currentUI.suspended() {
hooks.SuspendAudio()
} else {
hooks.ResumeAudio()
}
})
window.Call("addEventListener", "resize", func() {
}))
window.Call("addEventListener", "resize", js.NewCallback(func([]js.Value) {
currentUI.updateScreenSize()
})
}))
// Adjust the initial scale to 1.
// https://developer.mozilla.org/en/docs/Mozilla/Mobile/Viewport_meta_tag
@ -293,9 +291,9 @@ func initialize() error {
bodyStyle.Set("padding", "0")
// TODO: This is OK as long as the game is in an independent iframe.
// What if the canvas is embedded in a HTML directly?
doc.Get("body").Call("addEventListener", "click", func() {
doc.Get("body").Call("addEventListener", "click", js.NewCallback(func([]js.Value) {
canvas.Call("focus")
})
}))
canvasStyle := canvas.Get("style")
canvasStyle.Set("position", "absolute")
@ -305,36 +303,35 @@ func initialize() error {
canvas.Get("style").Set("outline", "none")
// Keyboard
canvas.Call("addEventListener", "keydown", input.OnKeyDown)
canvas.Call("addEventListener", "keypress", input.OnKeyPress)
canvas.Call("addEventListener", "keyup", input.OnKeyUp)
canvas.Call("addEventListener", "keydown", js.NewEventCallback(true, false, false, input.OnKeyDown))
canvas.Call("addEventListener", "keypress", js.NewEventCallback(true, false, false, input.OnKeyPress))
canvas.Call("addEventListener", "keyup", js.NewEventCallback(true, false, false, input.OnKeyUp))
// Mouse
canvas.Call("addEventListener", "mousedown", input.OnMouseDown)
canvas.Call("addEventListener", "mouseup", input.OnMouseUp)
canvas.Call("addEventListener", "mousemove", input.OnMouseMove)
canvas.Call("addEventListener", "contextmenu", func(e *js.Object) {
e.Call("preventDefault")
})
canvas.Call("addEventListener", "mousedown", js.NewEventCallback(true, false, false, input.OnMouseDown))
canvas.Call("addEventListener", "mouseup", js.NewEventCallback(true, false, false, input.OnMouseUp))
canvas.Call("addEventListener", "mousemove", js.NewEventCallback(true, false, false, input.OnMouseMove))
// Touch
canvas.Call("addEventListener", "touchstart", input.OnTouchStart)
canvas.Call("addEventListener", "touchend", input.OnTouchEnd)
canvas.Call("addEventListener", "touchmove", input.OnTouchMove)
canvas.Call("addEventListener", "touchstart", js.NewEventCallback(true, false, false, input.OnTouchStart))
canvas.Call("addEventListener", "touchend", js.NewEventCallback(true, false, false, input.OnTouchEnd))
canvas.Call("addEventListener", "touchmove", js.NewEventCallback(true, false, false, input.OnTouchMove))
// Gamepad
window.Call("addEventListener", "gamepadconnected", func(e *js.Object) {
window.Call("addEventListener", "gamepadconnected", js.NewCallback(func(e []js.Value) {
// Do nothing.
})
}))
canvas.Call("addEventListener", "webglcontextlost", func(e *js.Object) {
e.Call("preventDefault")
})
canvas.Call("addEventListener", "webglcontextrestored", func(e *js.Object) {
canvas.Call("addEventListener", "contextmenu", js.NewEventCallback(true, false, false, func(js.Value) {
// Do nothing.
})
}))
return nil
canvas.Call("addEventListener", "webglcontextlost", js.NewEventCallback(true, false, false, func(js.Value) {
// Do nothing.
}))
canvas.Call("addEventListener", "webglcontextrestored", js.NewCallback(func(e []js.Value) {
// Do nothing.
}))
}
func RunMainThreadLoop(ch <-chan error) error {