mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
Move ui_*.go back to internal/ui again
This commit is contained in:
parent
a1aed91cf9
commit
3964944deb
@ -15,12 +15,24 @@
|
|||||||
package ebiten
|
package ebiten
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/audio"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
||||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||||
"image"
|
"image"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var glContext *opengl.Context
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ui.Init()
|
||||||
|
ui.ExecOnUIThread(func() {
|
||||||
|
glContext = opengl.NewContext()
|
||||||
|
})
|
||||||
|
audio.Init()
|
||||||
|
audio.Start()
|
||||||
|
}
|
||||||
|
|
||||||
// IsKeyPressed returns a boolean indicating whether key is pressed.
|
// IsKeyPressed returns a boolean indicating whether key is pressed.
|
||||||
func IsKeyPressed(key Key) bool {
|
func IsKeyPressed(key Key) bool {
|
||||||
return ui.IsKeyPressed(ui.Key(key))
|
return ui.IsKeyPressed(ui.Key(key))
|
||||||
|
@ -17,8 +17,15 @@ package ebiten
|
|||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func useGLContext(f func(*opengl.Context)) {
|
||||||
|
ui.ExecOnUIThread(func() {
|
||||||
|
f(glContext)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func newGraphicsContext(c *opengl.Context, screenWidth, screenHeight, screenScale int) (*graphicsContext, error) {
|
func newGraphicsContext(c *opengl.Context, screenWidth, screenHeight, screenScale int) (*graphicsContext, error) {
|
||||||
f, err := graphics.NewZeroFramebuffer(c, screenWidth*screenScale, screenHeight*screenScale)
|
f, err := graphics.NewZeroFramebuffer(c, screenWidth*screenScale, screenHeight*screenScale)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -50,6 +50,11 @@ func audioProcess(channel int) func(e js.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initialize() {
|
func initialize() {
|
||||||
|
// Do nothing in node.js.
|
||||||
|
if js.Global.Get("require") != js.Undefined {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
context = js.Global.Get("AudioContext").New()
|
context = js.Global.Get("AudioContext").New()
|
||||||
// TODO: ScriptProcessorNode will be replaced with Audio WebWorker.
|
// TODO: ScriptProcessorNode will be replaced with Audio WebWorker.
|
||||||
// https://developer.mozilla.org/ja/docs/Web/API/ScriptProcessorNode
|
// https://developer.mozilla.org/ja/docs/Web/API/ScriptProcessorNode
|
||||||
|
@ -40,6 +40,7 @@ func toBytes(l, r []int16) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initialize() {
|
func initialize() {
|
||||||
|
// Creating OpenAL device must be done after initializing UI. I'm not sure the reason.
|
||||||
ch := make(chan struct{})
|
ch := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
@ -66,7 +66,27 @@ type context struct {
|
|||||||
|
|
||||||
var lastFramebuffer Framebuffer
|
var lastFramebuffer Framebuffer
|
||||||
|
|
||||||
func NewContext(gl *webgl.Context) *Context {
|
func NewContext() *Context {
|
||||||
|
var gl *webgl.Context
|
||||||
|
|
||||||
|
if js.Global.Get("require") == js.Undefined {
|
||||||
|
// TODO: Define id?
|
||||||
|
canvas := js.Global.Get("document").Call("querySelector", "canvas")
|
||||||
|
var err error
|
||||||
|
gl, err = webgl.NewContext(canvas, &webgl.ContextAttributes{
|
||||||
|
Alpha: true,
|
||||||
|
PremultipliedAlpha: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use headless-gl for testing.
|
||||||
|
nodeGl := js.Global.Call("require", "gl")
|
||||||
|
webglContext := nodeGl.Call("createContext", 16, 16)
|
||||||
|
gl = &webgl.Context{Object: webglContext}
|
||||||
|
}
|
||||||
|
|
||||||
c := &Context{
|
c := &Context{
|
||||||
Nearest: Filter(gl.NEAREST),
|
Nearest: Filter(gl.NEAREST),
|
||||||
Linear: Filter(gl.LINEAR),
|
Linear: Filter(gl.LINEAR),
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UpdateInput(window *glfw.Window, scale int) error {
|
func updateInput(window *glfw.Window, scale int) error {
|
||||||
return currentInput.update(window, scale)
|
return currentInput.update(window, scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,30 +14,18 @@
|
|||||||
|
|
||||||
// +build !js
|
// +build !js
|
||||||
|
|
||||||
package ebiten
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
glfw "github.com/go-gl/glfw3"
|
glfw "github.com/go-gl/glfw3"
|
||||||
"github.com/hajimehoshi/ebiten/internal/audio"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var currentUI *userInterface
|
var currentUI *userInterface
|
||||||
|
|
||||||
func useGLContext(f func(*opengl.Context)) {
|
func Init() {
|
||||||
ch := make(chan struct{})
|
|
||||||
currentUI.funcs <- func() {
|
|
||||||
defer close(ch)
|
|
||||||
f(currentUI.glContext)
|
|
||||||
}
|
|
||||||
<-ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
|
||||||
glfw.SetErrorCallback(func(err glfw.ErrorCode, desc string) {
|
glfw.SetErrorCallback(func(err glfw.ErrorCode, desc string) {
|
||||||
@ -61,23 +49,48 @@ func init() {
|
|||||||
go func() {
|
go func() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
u.window.MakeContextCurrent()
|
u.window.MakeContextCurrent()
|
||||||
u.glContext = opengl.NewContext()
|
|
||||||
glfw.SwapInterval(1)
|
glfw.SwapInterval(1)
|
||||||
for f := range u.funcs {
|
for f := range u.funcs {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
audio.Init()
|
|
||||||
|
|
||||||
currentUI = u
|
currentUI = u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExecOnUIThread(f func()) {
|
||||||
|
ch := make(chan struct{})
|
||||||
|
currentUI.funcs <- func() {
|
||||||
|
defer close(ch)
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
<-ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start(width, height, scale int, title string) (actualScale int, err error) {
|
||||||
|
return currentUI.start(width, height, scale, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Terminate() {
|
||||||
|
currentUI.terminate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DoEvents() error {
|
||||||
|
return currentUI.doEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsClosed() bool {
|
||||||
|
return currentUI.isClosed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapBuffers() {
|
||||||
|
currentUI.swapBuffers()
|
||||||
|
}
|
||||||
|
|
||||||
type userInterface struct {
|
type userInterface struct {
|
||||||
window *glfw.Window
|
window *glfw.Window
|
||||||
scale int
|
scale int
|
||||||
glContext *opengl.Context
|
funcs chan func()
|
||||||
funcs chan func()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterface) start(width, height, scale int, title string) (actualScale int, err error) {
|
func (u *userInterface) start(width, height, scale int, title string) (actualScale int, err error) {
|
||||||
@ -122,14 +135,12 @@ func (u *userInterface) start(width, height, scale int, title string) (actualSca
|
|||||||
windowWidth, _ := window.GetFramebufferSize()
|
windowWidth, _ := window.GetFramebufferSize()
|
||||||
actualScale = windowWidth / width
|
actualScale = windowWidth / width
|
||||||
|
|
||||||
audio.Start()
|
|
||||||
|
|
||||||
return actualScale, nil
|
return actualScale, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterface) pollEvents() error {
|
func (u *userInterface) pollEvents() error {
|
||||||
glfw.PollEvents()
|
glfw.PollEvents()
|
||||||
return ui.UpdateInput(u.window, u.scale)
|
return updateInput(u.window, u.scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterface) doEvents() error {
|
func (u *userInterface) doEvents() error {
|
@ -14,19 +14,38 @@
|
|||||||
|
|
||||||
// +build js
|
// +build js
|
||||||
|
|
||||||
package ebiten
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gopherjs/gopherjs/js"
|
"github.com/gopherjs/gopherjs/js"
|
||||||
"github.com/gopherjs/webgl"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/audio"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/ui"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ExecOnUIThread(f func()) {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start(width, height, scale int, title string) (actualScale int, err error) {
|
||||||
|
return currentUI.start(width, height, scale, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Terminate() {
|
||||||
|
currentUI.terminate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DoEvents() error {
|
||||||
|
return currentUI.doEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsClosed() bool {
|
||||||
|
return currentUI.isClosed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SwapBuffers() {
|
||||||
|
currentUI.swapBuffers()
|
||||||
|
}
|
||||||
|
|
||||||
var canvas js.Object
|
var canvas js.Object
|
||||||
var context *opengl.Context
|
|
||||||
|
|
||||||
type userInterface struct{}
|
type userInterface struct{}
|
||||||
|
|
||||||
@ -38,10 +57,6 @@ func shown() bool {
|
|||||||
return !js.Global.Get("document").Get("hidden").Bool()
|
return !js.Global.Get("document").Get("hidden").Bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
func useGLContext(f func(*opengl.Context)) {
|
|
||||||
f(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
func vsync() {
|
func vsync() {
|
||||||
ch := make(chan struct{})
|
ch := make(chan struct{})
|
||||||
// TODO: In iOS8, this is called at every 1/30[sec] frame.
|
// TODO: In iOS8, this is called at every 1/30[sec] frame.
|
||||||
@ -57,7 +72,7 @@ func (*userInterface) doEvents() error {
|
|||||||
for !shown() {
|
for !shown() {
|
||||||
vsync()
|
vsync()
|
||||||
}
|
}
|
||||||
ui.CurrentInput().UpdateGamepads()
|
currentInput.UpdateGamepads()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,12 +88,9 @@ func (*userInterface) swapBuffers() {
|
|||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func Init() {
|
||||||
|
// Do nothing in node.js.
|
||||||
if js.Global.Get("require") != js.Undefined {
|
if js.Global.Get("require") != js.Undefined {
|
||||||
// Use headless-gl for testing.
|
|
||||||
nodeGl := js.Global.Call("require", "gl")
|
|
||||||
webglContext := nodeGl.Call("createContext", 16, 16)
|
|
||||||
context = opengl.NewContext(&webgl.Context{Object: webglContext})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,15 +127,6 @@ func init() {
|
|||||||
canvasStyle := canvas.Get("style")
|
canvasStyle := canvas.Get("style")
|
||||||
canvasStyle.Set("position", "absolute")
|
canvasStyle.Set("position", "absolute")
|
||||||
|
|
||||||
webglContext, err := webgl.NewContext(canvas, &webgl.ContextAttributes{
|
|
||||||
Alpha: true,
|
|
||||||
PremultipliedAlpha: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
context = opengl.NewContext(webglContext)
|
|
||||||
|
|
||||||
// Make the canvas focusable.
|
// Make the canvas focusable.
|
||||||
canvas.Call("setAttribute", "tabindex", 1)
|
canvas.Call("setAttribute", "tabindex", 1)
|
||||||
canvas.Get("style").Set("outline", "none")
|
canvas.Get("style").Set("outline", "none")
|
||||||
@ -132,25 +135,25 @@ func init() {
|
|||||||
canvas.Call("addEventListener", "keydown", func(e js.Object) {
|
canvas.Call("addEventListener", "keydown", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
code := e.Get("keyCode").Int()
|
code := e.Get("keyCode").Int()
|
||||||
ui.CurrentInput().KeyDown(code)
|
currentInput.KeyDown(code)
|
||||||
})
|
})
|
||||||
canvas.Call("addEventListener", "keyup", func(e js.Object) {
|
canvas.Call("addEventListener", "keyup", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
code := e.Get("keyCode").Int()
|
code := e.Get("keyCode").Int()
|
||||||
ui.CurrentInput().KeyUp(code)
|
currentInput.KeyUp(code)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Mouse
|
// Mouse
|
||||||
canvas.Call("addEventListener", "mousedown", func(e js.Object) {
|
canvas.Call("addEventListener", "mousedown", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
button := e.Get("button").Int()
|
button := e.Get("button").Int()
|
||||||
ui.CurrentInput().MouseDown(button)
|
currentInput.MouseDown(button)
|
||||||
setMouseCursorFromEvent(e)
|
setMouseCursorFromEvent(e)
|
||||||
})
|
})
|
||||||
canvas.Call("addEventListener", "mouseup", func(e js.Object) {
|
canvas.Call("addEventListener", "mouseup", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
button := e.Get("button").Int()
|
button := e.Get("button").Int()
|
||||||
ui.CurrentInput().MouseUp(button)
|
currentInput.MouseUp(button)
|
||||||
setMouseCursorFromEvent(e)
|
setMouseCursorFromEvent(e)
|
||||||
})
|
})
|
||||||
canvas.Call("addEventListener", "mousemove", func(e js.Object) {
|
canvas.Call("addEventListener", "mousemove", func(e js.Object) {
|
||||||
@ -165,14 +168,14 @@ func init() {
|
|||||||
// TODO: Need to create indimendent touch functions?
|
// TODO: Need to create indimendent touch functions?
|
||||||
canvas.Call("addEventListener", "touchstart", func(e js.Object) {
|
canvas.Call("addEventListener", "touchstart", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
ui.CurrentInput().MouseDown(0)
|
currentInput.MouseDown(0)
|
||||||
touches := e.Get("changedTouches")
|
touches := e.Get("changedTouches")
|
||||||
touch := touches.Index(0)
|
touch := touches.Index(0)
|
||||||
setMouseCursorFromEvent(touch)
|
setMouseCursorFromEvent(touch)
|
||||||
})
|
})
|
||||||
canvas.Call("addEventListener", "touchend", func(e js.Object) {
|
canvas.Call("addEventListener", "touchend", func(e js.Object) {
|
||||||
e.Call("preventDefault")
|
e.Call("preventDefault")
|
||||||
ui.CurrentInput().MouseUp(0)
|
currentInput.MouseUp(0)
|
||||||
touches := e.Get("changedTouches")
|
touches := e.Get("changedTouches")
|
||||||
touch := touches.Index(0)
|
touch := touches.Index(0)
|
||||||
setMouseCursorFromEvent(touch)
|
setMouseCursorFromEvent(touch)
|
||||||
@ -188,8 +191,6 @@ func init() {
|
|||||||
window.Call("addEventListener", "gamepadconnected", func(e js.Object) {
|
window.Call("addEventListener", "gamepadconnected", func(e js.Object) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
})
|
})
|
||||||
|
|
||||||
audio.Init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setMouseCursorFromEvent(e js.Object) {
|
func setMouseCursorFromEvent(e js.Object) {
|
||||||
@ -198,7 +199,7 @@ func setMouseCursorFromEvent(e js.Object) {
|
|||||||
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
|
x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
|
||||||
x -= rect.Get("left").Int()
|
x -= rect.Get("left").Int()
|
||||||
y -= rect.Get("top").Int()
|
y -= rect.Get("top").Int()
|
||||||
ui.CurrentInput().SetMouseCursor(x/scale, y/scale)
|
currentInput.SetMouseCursor(x/scale, y/scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
func devicePixelRatio() int {
|
func devicePixelRatio() int {
|
||||||
@ -229,7 +230,5 @@ func (*userInterface) start(width, height, scale int, title string) (actualScale
|
|||||||
|
|
||||||
canvas.Call("focus")
|
canvas.Call("focus")
|
||||||
|
|
||||||
audio.Start()
|
|
||||||
|
|
||||||
return actualScale, nil
|
return actualScale, nil
|
||||||
}
|
}
|
12
run.go
12
run.go
@ -17,6 +17,7 @@ package ebiten
|
|||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/audio"
|
"github.com/hajimehoshi/ebiten/internal/audio"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphics/internal/opengl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,12 +38,11 @@ func CurrentFPS() float64 {
|
|||||||
// but this is not strictly guaranteed.
|
// but this is not strictly guaranteed.
|
||||||
// If you need to care about time, you need to check current time every time f is called.
|
// If you need to care about time, you need to check current time every time f is called.
|
||||||
func Run(f func(*Image) error, width, height, scale int, title string) error {
|
func Run(f func(*Image) error, width, height, scale int, title string) error {
|
||||||
ui := currentUI
|
actualScale, err := ui.Start(width, height, scale, title)
|
||||||
actualScale, err := ui.start(width, height, scale, title)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer ui.terminate()
|
defer ui.Terminate()
|
||||||
|
|
||||||
var graphicsContext *graphicsContext
|
var graphicsContext *graphicsContext
|
||||||
useGLContext(func(c *opengl.Context) {
|
useGLContext(func(c *opengl.Context) {
|
||||||
@ -55,10 +55,10 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
|
|||||||
frames := 0
|
frames := 0
|
||||||
t := time.Now().UnixNano()
|
t := time.Now().UnixNano()
|
||||||
for {
|
for {
|
||||||
if err := ui.doEvents(); err != nil {
|
if err := ui.DoEvents(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if ui.isClosed() {
|
if ui.IsClosed() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := graphicsContext.preUpdate(); err != nil {
|
if err := graphicsContext.preUpdate(); err != nil {
|
||||||
@ -72,7 +72,7 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
|
|||||||
}
|
}
|
||||||
// TODO: I'm not sure this is 'Update'. Is 'Tick' better?
|
// TODO: I'm not sure this is 'Update'. Is 'Tick' better?
|
||||||
audio.Update()
|
audio.Update()
|
||||||
ui.swapBuffers()
|
ui.SwapBuffers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user