Add uidriver package and move UI implementation to this packaage

This commit is contained in:
Hajime Hoshi 2019-04-07 10:42:55 +09:00
parent a4a129e3af
commit 7e5085f15b
16 changed files with 325 additions and 264 deletions

View File

@ -24,7 +24,6 @@ import (
"github.com/hajimehoshi/ebiten/internal/hooks"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/shareable"
"github.com/hajimehoshi/ebiten/internal/ui"
)
func init() {
@ -64,7 +63,7 @@ func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale flo
// Round up the screensize not to cause glitches e.g. on Xperia (#622)
w := int(math.Ceil(float64(screenWidth) * screenScale))
h := int(math.Ceil(float64(screenHeight) * screenScale))
px0, py0, px1, py1 := ui.ScreenPadding()
px0, py0, px1, py1 := uiDriver().ScreenPadding()
c.screen = newImageWithScreenFramebuffer(w+int(math.Ceil(px0+px1)), h+int(math.Ceil(py0+py1)))
c.screenWidth = w
c.screenHeight = h

View File

@ -17,7 +17,6 @@ package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/input"
"github.com/hajimehoshi/ebiten/internal/ui"
)
// InputChars return "printable" runes read from the keyboard at the time update is called.
@ -50,7 +49,7 @@ func IsKeyPressed(key Key) bool {
//
// CursorPosition is concurrent-safe.
func CursorPosition() (x, y int) {
return ui.AdjustPosition(input.Get().CursorPosition())
return uiDriver().AdjustPosition(input.Get().CursorPosition())
}
// Wheel returns the x and y offset of the mouse wheel or touchpad scroll.
@ -146,7 +145,7 @@ func TouchPosition(id int) (int, int) {
return 0, 0
}
return ui.AdjustPosition(input.Get().TouchPosition(id))
return uiDriver().AdjustPosition(input.Get().TouchPosition(id))
}
// Touch is deprecated as of 1.7.0. Use TouchPosition instead.

View File

@ -16,6 +16,7 @@ package driver
import (
"errors"
"image"
)
type GraphicsContext interface {
@ -27,3 +28,29 @@ type GraphicsContext interface {
// Run can return this error, and if this error is received,
// the game loop should be terminated as soon as possible.
var RegularTermination = errors.New("regular termination")
type UI interface {
AdjustPosition(x, y int) (int, int)
DeviceScaleFactor() float64
IsCursorVisible() bool
IsFullscreen() bool
IsRunnableInBackground() bool
IsVsyncEnabled() bool
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
ScreenPadding() (x0, y0, x1, y1 float64)
ScreenScale() float64
ScreenSizeInFullscreen() (int, int)
SetCursorVisible(visible bool)
SetFullscreen(fullscreen bool)
SetRunnableInBackground(runnableInBackground bool)
SetScreenScale(scale float64)
SetScreenSize(width, height int)
SetVsyncEnabled(enabled bool)
SetWindowDecorated(decorated bool)
SetWindowIcon(iconImages []image.Image)
SetWindowResizable(resizable bool)
SetWindowTitle(title string)
}

View File

@ -14,7 +14,7 @@
// +build !windows js
package ui
package glfw
// hideConsoleWindowOnWindows does nothing on non-Windows systems.
func hideConsoleWindowOnWindows() {}

View File

@ -14,7 +14,7 @@
// +build !js
package ui
package glfw
import (
"fmt"

View File

@ -17,7 +17,7 @@
// +build !android
// +build !ios
package ui
package glfw
import (
"image"
@ -33,7 +33,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/mainthread"
)
type userInterface struct {
type UserInterface struct {
title string
window *glfw.Window
width int
@ -77,7 +77,7 @@ const (
)
var (
theUI = &userInterface{
theUI = &UserInterface{
origPosX: invalidPos,
origPosY: invalidPos,
initCursorVisible: true,
@ -86,6 +86,10 @@ var (
}
)
func Get() *UserInterface {
return theUI
}
func init() {
hideConsoleWindowOnWindows()
if err := initialize(); err != nil {
@ -112,7 +116,7 @@ func initialize() error {
theUI.window = w
theUI.initMonitor = theUI.currentMonitorFromPosition()
v := theUI.initMonitor.GetVideoMode()
s := glfwScale()
s := theUI.glfwScale()
theUI.initFullscreenWidth = int(float64(v.Width) / s)
theUI.initFullscreenHeight = int(float64(v.Height) / s)
theUI.window.Destroy()
@ -163,108 +167,107 @@ func getCachedMonitor(wx, wy int) (*cachedMonitor, bool) {
return nil, false
}
func Loop(ch <-chan error) error {
theUI.setRunning(true)
func (u *UserInterface) Loop(ch <-chan error) error {
u.setRunning(true)
if err := mainthread.Loop(ch); err != nil {
return err
}
theUI.setRunning(false)
u.setRunning(false)
return nil
}
func (u *userInterface) isRunning() bool {
func (u *UserInterface) isRunning() bool {
u.m.Lock()
v := u.running
u.m.Unlock()
return v
}
func (u *userInterface) setRunning(running bool) {
func (u *UserInterface) setRunning(running bool) {
u.m.Lock()
u.running = running
u.m.Unlock()
}
func (u *userInterface) isInitFullscreen() bool {
func (u *UserInterface) isInitFullscreen() bool {
u.m.Lock()
v := u.initFullscreen
u.m.Unlock()
return v
}
func (u *userInterface) setInitFullscreen(initFullscreen bool) {
func (u *UserInterface) setInitFullscreen(initFullscreen bool) {
u.m.Lock()
u.initFullscreen = initFullscreen
u.m.Unlock()
}
func (u *userInterface) isInitCursorVisible() bool {
func (u *UserInterface) isInitCursorVisible() bool {
u.m.Lock()
v := u.initCursorVisible
u.m.Unlock()
return v
}
func (u *userInterface) setInitCursorVisible(visible bool) {
func (u *UserInterface) setInitCursorVisible(visible bool) {
u.m.Lock()
u.initCursorVisible = visible
u.m.Unlock()
}
func (u *userInterface) isInitWindowDecorated() bool {
func (u *UserInterface) isInitWindowDecorated() bool {
u.m.Lock()
v := u.initWindowDecorated
u.m.Unlock()
return v
}
func (u *userInterface) setInitWindowDecorated(decorated bool) {
func (u *UserInterface) setInitWindowDecorated(decorated bool) {
u.m.Lock()
u.initWindowDecorated = decorated
u.m.Unlock()
}
func (u *userInterface) isRunnableInBackground() bool {
func (u *UserInterface) isRunnableInBackground() bool {
u.m.Lock()
v := u.runnableInBackground
u.m.Unlock()
return v
}
func (u *userInterface) setRunnableInBackground(runnableInBackground bool) {
func (u *UserInterface) setRunnableInBackground(runnableInBackground bool) {
u.m.Lock()
u.runnableInBackground = runnableInBackground
u.m.Unlock()
}
func (u *userInterface) isInitWindowResizable() bool {
func (u *UserInterface) isInitWindowResizable() bool {
u.m.Lock()
v := u.initWindowResizable
u.m.Unlock()
return v
}
func (u *userInterface) setInitWindowResizable(resizable bool) {
func (u *UserInterface) setInitWindowResizable(resizable bool) {
u.m.Lock()
u.initWindowResizable = resizable
u.m.Unlock()
}
func (u *userInterface) getInitIconImages() []image.Image {
func (u *UserInterface) getInitIconImages() []image.Image {
u.m.Lock()
i := u.initIconImages
u.m.Unlock()
return i
}
func (u *userInterface) setInitIconImages(iconImages []image.Image) {
func (u *UserInterface) setInitIconImages(iconImages []image.Image) {
u.m.Lock()
u.initIconImages = iconImages
u.m.Unlock()
}
func ScreenSizeInFullscreen() (int, int) {
u := theUI
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
if !u.isRunning() {
return u.initFullscreenWidth, u.initFullscreenHeight
}
@ -273,14 +276,13 @@ func ScreenSizeInFullscreen() (int, int) {
s := 0.0
_ = mainthread.Run(func() error {
v = u.currentMonitor().GetVideoMode()
s = glfwScale()
s = u.glfwScale()
return nil
})
return int(float64(v.Width) / s), int(float64(v.Height) / s)
}
func SetScreenSize(width, height int) {
u := theUI
func (u *UserInterface) SetScreenSize(width, height int) {
if !u.isRunning() {
panic("ui: Run is not called yet")
}
@ -291,22 +293,18 @@ func SetScreenSize(width, height int) {
})
}
func SetScreenScale(scale float64) bool {
u := theUI
func (u *UserInterface) SetScreenScale(scale float64) {
if !u.isRunning() {
panic("ui: Run is not called yet")
}
r := false
_ = mainthread.Run(func() error {
// TODO: What if the window is maximized? (#320)
r = u.setScreenSize(u.width, u.height, scale, u.isFullscreen(), u.vsync)
u.setScreenSize(u.width, u.height, scale, u.isFullscreen(), u.vsync)
return nil
})
return r
}
func ScreenScale() float64 {
u := theUI
func (u *UserInterface) ScreenScale() float64 {
if !u.isRunning() {
return 0
}
@ -319,15 +317,14 @@ func ScreenScale() float64 {
}
// isFullscreen must be called from the main thread.
func (u *userInterface) isFullscreen() bool {
func (u *UserInterface) isFullscreen() bool {
if !u.isRunning() {
panic("ui: the game must be running at isFullscreen")
}
return u.window.GetMonitor() != nil
}
func IsFullscreen() bool {
u := theUI
func (u *UserInterface) IsFullscreen() bool {
if !u.isRunning() {
return u.isInitFullscreen()
}
@ -339,29 +336,26 @@ func IsFullscreen() bool {
return b
}
func SetFullscreen(fullscreen bool) {
u := theUI
func (u *UserInterface) SetFullscreen(fullscreen bool) {
if !u.isRunning() {
u.setInitFullscreen(fullscreen)
return
}
_ = mainthread.Run(func() error {
u := theUI
u.setScreenSize(u.width, u.height, u.scale, fullscreen, u.vsync)
return nil
})
}
func SetRunnableInBackground(runnableInBackground bool) {
theUI.setRunnableInBackground(runnableInBackground)
func (u *UserInterface) SetRunnableInBackground(runnableInBackground bool) {
u.setRunnableInBackground(runnableInBackground)
}
func IsRunnableInBackground() bool {
return theUI.isRunnableInBackground()
func (u *UserInterface) IsRunnableInBackground() bool {
return u.isRunnableInBackground()
}
func SetVsyncEnabled(enabled bool) {
u := theUI
func (u *UserInterface) SetVsyncEnabled(enabled bool) {
if !u.isRunning() {
// In general, m is used for locking init* values.
// m is not used for updating vsync in setScreenSize so far, but
@ -373,47 +367,44 @@ func SetVsyncEnabled(enabled bool) {
return
}
_ = mainthread.Run(func() error {
u := theUI
u.setScreenSize(u.width, u.height, u.scale, u.isFullscreen(), enabled)
return nil
})
}
func IsVsyncEnabled() bool {
u := theUI
func (u *UserInterface) IsVsyncEnabled() bool {
u.m.Lock()
r := u.vsync
u.m.Unlock()
return r
}
func SetWindowTitle(title string) {
if !theUI.isRunning() {
func (u *UserInterface) SetWindowTitle(title string) {
if !u.isRunning() {
return
}
_ = mainthread.Run(func() error {
theUI.window.SetTitle(title)
u.window.SetTitle(title)
return nil
})
}
func SetWindowIcon(iconImages []image.Image) {
if !theUI.isRunning() {
theUI.setInitIconImages(iconImages)
func (u *UserInterface) SetWindowIcon(iconImages []image.Image) {
if !u.isRunning() {
u.setInitIconImages(iconImages)
return
}
_ = mainthread.Run(func() error {
theUI.window.SetIcon(iconImages)
u.window.SetIcon(iconImages)
return nil
})
}
func ScreenPadding() (x0, y0, x1, y1 float64) {
u := theUI
func (u *UserInterface) ScreenPadding() (x0, y0, x1, y1 float64) {
if !u.isRunning() {
return 0, 0, 0, 0
}
if !IsFullscreen() {
if !u.IsFullscreen() {
if u.width == u.windowWidth {
return 0, 0, 0, 0
}
@ -437,7 +428,7 @@ func ScreenPadding() (x0, y0, x1, y1 float64) {
d = devicescale.GetAt(m.GetPos())
sx = float64(u.width) * u.actualScreenScale()
sy = float64(u.height) * u.actualScreenScale()
gs = glfwScale()
gs = u.glfwScale()
v := m.GetVideoMode()
vw, vh = float64(v.Width), float64(v.Height)
@ -451,35 +442,32 @@ func ScreenPadding() (x0, y0, x1, y1 float64) {
return ox, oy, (mx - sx) - ox, (my - sy) - oy
}
func AdjustPosition(x, y int) (int, int) {
u := theUI
func (u *UserInterface) AdjustPosition(x, y int) (int, int) {
if !u.isRunning() {
return x, y
}
ox, oy, _, _ := ScreenPadding()
ox, oy, _, _ := u.ScreenPadding()
s := 0.0
_ = mainthread.Run(func() error {
s = theUI.actualScreenScale()
s = u.actualScreenScale()
return nil
})
return x - int(ox/s), y - int(oy/s)
}
func IsCursorVisible() bool {
u := theUI
func (u *UserInterface) IsCursorVisible() bool {
if !u.isRunning() {
return u.isInitCursorVisible()
}
v := false
_ = mainthread.Run(func() error {
v = theUI.window.GetInputMode(glfw.CursorMode) == glfw.CursorNormal
v = u.window.GetInputMode(glfw.CursorMode) == glfw.CursorNormal
return nil
})
return v
}
func SetCursorVisible(visible bool) {
u := theUI
func (u *UserInterface) SetCursorVisible(visible bool) {
if !u.isRunning() {
u.setInitCursorVisible(visible)
return
@ -489,26 +477,24 @@ func SetCursorVisible(visible bool) {
if !visible {
c = glfw.CursorHidden
}
theUI.window.SetInputMode(glfw.CursorMode, c)
u.window.SetInputMode(glfw.CursorMode, c)
return nil
})
}
func IsWindowDecorated() bool {
u := theUI
func (u *UserInterface) IsWindowDecorated() bool {
if !u.isRunning() {
return u.isInitWindowDecorated()
}
v := false
_ = mainthread.Run(func() error {
v = theUI.window.GetAttrib(glfw.Decorated) == glfw.True
v = u.window.GetAttrib(glfw.Decorated) == glfw.True
return nil
})
return v
}
func SetWindowDecorated(decorated bool) {
u := theUI
func (u *UserInterface) SetWindowDecorated(decorated bool) {
if !u.isRunning() {
u.setInitWindowDecorated(decorated)
return
@ -525,26 +511,25 @@ func SetWindowDecorated(decorated bool) {
// v = glfw.True
// }
// })
// theUI.window.SetAttrib(glfw.Decorated, v)
// u.window.SetAttrib(glfw.Decorated, v)
// return nil
}
func IsWindowResizable() bool {
u := theUI
func (u *UserInterface) IsWindowResizable() bool {
if !u.isRunning() {
return u.isInitWindowResizable()
}
v := false
_ = mainthread.Run(func() error {
v = theUI.window.GetAttrib(glfw.Resizable) == glfw.True
v = u.window.GetAttrib(glfw.Resizable) == glfw.True
return nil
})
return v
}
func SetWindowResizable(resizable bool) {
if !theUI.isRunning() {
theUI.setInitWindowResizable(resizable)
func (u *UserInterface) SetWindowResizable(resizable bool) {
if !u.isRunning() {
u.setInitWindowResizable(resizable)
return
}
@ -553,9 +538,8 @@ func SetWindowResizable(resizable bool) {
// TODO: Now SetAttrib doesn't exist on GLFW 3.2. Revisit later (#556).
}
func DeviceScaleFactor() float64 {
func (u *UserInterface) DeviceScaleFactor() float64 {
f := 0.0
u := theUI
if !u.isRunning() {
return devicescale.GetAt(u.initMonitor.GetPos())
}
@ -568,8 +552,7 @@ func DeviceScaleFactor() float64 {
return f
}
func Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
u := theUI
func (u *UserInterface) Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
_ = mainthread.Run(func() error {
u.graphics = graphics
u.input = input
@ -662,7 +645,7 @@ func Run(width, height int, scale float64, title string, g driver.GraphicsContex
return
}
s := glfwScale()
s := u.glfwScale()
w := int(float64(width) / u.scale / s)
h := int(float64(height) / u.scale / s)
u.reqWidth = w
@ -681,21 +664,21 @@ func Run(width, height int, scale float64, title string, g driver.GraphicsContex
}
// getSize must be called from the main thread.
func (u *userInterface) glfwSize() (int, int) {
w := int(float64(u.windowWidth) * u.getScale() * glfwScale())
h := int(float64(u.height) * u.getScale() * glfwScale())
func (u *UserInterface) glfwSize() (int, int) {
w := int(float64(u.windowWidth) * u.getScale() * u.glfwScale())
h := int(float64(u.height) * u.getScale() * u.glfwScale())
return w, h
}
// getScale must be called from the main thread.
func (u *userInterface) getScale() float64 {
func (u *UserInterface) getScale() float64 {
if !u.isFullscreen() {
return u.scale
}
if u.fullscreenScale == 0 {
v := u.window.GetMonitor().GetVideoMode()
sw := float64(v.Width) / glfwScale() / float64(u.width)
sh := float64(v.Height) / glfwScale() / float64(u.height)
sw := float64(v.Width) / u.glfwScale() / float64(u.width)
sh := float64(v.Height) / u.glfwScale() / float64(u.height)
s := sw
if s > sh {
s = sh
@ -706,7 +689,7 @@ func (u *userInterface) getScale() float64 {
}
// actualScreenScale must be called from the main thread.
func (u *userInterface) actualScreenScale() float64 {
func (u *UserInterface) actualScreenScale() float64 {
// Avoid calling monitor.GetPos if we have the monitor position cached already.
if cm, ok := getCachedMonitor(u.window.GetPos()); ok {
return u.getScale() * devicescale.GetAt(cm.x, cm.y)
@ -714,7 +697,7 @@ func (u *userInterface) actualScreenScale() float64 {
return u.getScale() * devicescale.GetAt(u.currentMonitor().GetPos())
}
func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
func (u *UserInterface) updateGraphicsContext(g driver.GraphicsContext) {
actualScale := 0.0
sizeChanged := false
// TODO: Is it possible to reduce 'runOnMainThread' calls?
@ -738,7 +721,7 @@ func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
}
}
func (u *userInterface) update(g driver.GraphicsContext) error {
func (u *UserInterface) update(g driver.GraphicsContext) error {
shouldClose := false
_ = mainthread.Run(func() error {
shouldClose = u.window.ShouldClose()
@ -750,7 +733,6 @@ func (u *userInterface) update(g driver.GraphicsContext) error {
_ = mainthread.Run(func() error {
if u.isInitFullscreen() {
u := theUI
u.setScreenSize(u.width, u.height, u.scale, true, u.vsync)
u.setInitFullscreen(false)
}
@ -767,7 +749,7 @@ func (u *userInterface) update(g driver.GraphicsContext) error {
Update(window *glfw.Window, scale float64)
}
u.input.(updater).Update(u.window, u.getScale()*glfwScale())
u.input.(updater).Update(u.window, u.getScale()*u.glfwScale())
defer hooks.ResumeAudio()
@ -802,7 +784,7 @@ func (u *userInterface) update(g driver.GraphicsContext) error {
return nil
}
func (u *userInterface) loop(g driver.GraphicsContext) error {
func (u *UserInterface) loop(g driver.GraphicsContext) error {
defer func() {
_ = mainthread.Run(func() error {
glfw.Terminate()
@ -830,14 +812,14 @@ func (u *userInterface) loop(g driver.GraphicsContext) error {
}
// swapBuffers must be called from the main thread.
func (u *userInterface) swapBuffers() {
func (u *UserInterface) swapBuffers() {
if u.graphics.IsGL() {
u.window.SwapBuffers()
}
}
// setScreenSize must be called from the main thread.
func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) bool {
func (u *UserInterface) setScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) bool {
if u.width == width && u.height == height && u.scale == scale && u.isFullscreen() == fullscreen && u.vsync == vsync {
return false
}
@ -846,12 +828,12 @@ func (u *userInterface) setScreenSize(width, height int, scale float64, fullscre
}
// forceSetScreenSize must be called from the main thread.
func (u *userInterface) forceSetScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) {
func (u *UserInterface) forceSetScreenSize(width, height int, scale float64, fullscreen bool, vsync bool) {
// On Windows, giving a too small width doesn't call a callback (#165).
// To prevent hanging up, return asap if the width is too small.
// 252 is an arbitrary number and I guess this is small enough.
minWindowWidth := 252
if theUI.window.GetAttrib(glfw.Decorated) == glfw.False {
if u.window.GetAttrib(glfw.Decorated) == glfw.False {
minWindowWidth = 1
}
@ -951,7 +933,7 @@ func (u *userInterface) forceSetScreenSize(width, height int, scale float64, ful
// currentMonitor returns the monitor most suitable with the current window.
//
// currentMonitor must be called on the main thread.
func (u *userInterface) currentMonitor() *glfw.Monitor {
func (u *UserInterface) currentMonitor() *glfw.Monitor {
w := u.window
if m := w.GetMonitor(); m != nil {
return m

View File

@ -12,11 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// +build darwin
// +build !js
// +build !ios
package ui
package glfw
// #cgo CFLAGS: -x objective-c
// #cgo LDFLAGS: -framework AppKit
@ -48,7 +47,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/glfw"
)
func glfwScale() float64 {
func (u *UserInterface) glfwScale() float64 {
return 1
}
@ -56,7 +55,7 @@ func adjustWindowPosition(x, y int) (int, int) {
return x, y
}
func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
x := C.int(0)
y := C.int(0)
// Note: [NSApp mainWindow] is nil when it doesn't have its border. Use u.window here.
@ -71,6 +70,6 @@ func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor()
}
func (u *userInterface) nativeWindow() uintptr {
func (u *UserInterface) nativeWindow() uintptr {
return u.window.GetCocoaWindow()
}

View File

@ -16,18 +16,18 @@
// +build !js
// +build !android
package ui
package glfw
import (
"github.com/hajimehoshi/ebiten/internal/devicescale"
"github.com/hajimehoshi/ebiten/internal/glfw"
)
func glfwScale() float64 {
func (u *UserInterface) glfwScale() float64 {
// This function must be called on the main thread.
cm, ok := getCachedMonitor(theUI.window.GetPos())
cm, ok := getCachedMonitor(u.window.GetPos())
if !ok {
return devicescale.GetAt(theUI.currentMonitor().GetPos())
return devicescale.GetAt(u.currentMonitor().GetPos())
}
return devicescale.GetAt(cm.x, cm.y)
}
@ -36,7 +36,7 @@ func adjustWindowPosition(x, y int) (int, int) {
return x, y
}
func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
// TODO: Return more appropriate display.
if cm, ok := getCachedMonitor(u.window.GetPos()); ok {
return cm.m
@ -44,7 +44,7 @@ func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor()
}
func (u *userInterface) nativeWindow() uintptr {
func (u *UserInterface) nativeWindow() uintptr {
// TODO: Implement this.
return 0
}

View File

@ -14,7 +14,7 @@
// +build !js
package ui
package glfw
import (
"fmt"
@ -100,9 +100,9 @@ func getMonitorInfoW(hMonitor uintptr, lpmi *monitorInfo) error {
return nil
}
func glfwScale() float64 {
func (u *UserInterface) glfwScale() float64 {
// This function must be called on the main thread.
return devicescale.GetAt(theUI.currentMonitor().GetPos())
return devicescale.GetAt(u.currentMonitor().GetPos())
}
func adjustWindowPosition(x, y int) (int, int) {
@ -121,7 +121,7 @@ func adjustWindowPosition(x, y int) (int, int) {
return x, y
}
func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
func (u *UserInterface) currentMonitorFromPosition() *glfw.Monitor {
// TODO: Should we use u.window.GetWin32Window() here?
w, err := getActiveWindow()
if err != nil {
@ -165,6 +165,6 @@ func (u *userInterface) currentMonitorFromPosition() *glfw.Monitor {
return glfw.GetPrimaryMonitor()
}
func (u *userInterface) nativeWindow() uintptr {
func (u *UserInterface) nativeWindow() uintptr {
return u.window.GetWin32Window()
}

View File

@ -14,7 +14,7 @@
// +build js
package ui
package js
import (
"image"
@ -38,7 +38,7 @@ type inputDriver interface {
UpdateGamepads()
}
type userInterface struct {
type UserInterface struct {
width int
height int
scale float64
@ -56,13 +56,17 @@ type userInterface struct {
input inputDriver
}
var theUI = &userInterface{
var theUI = &UserInterface{
sizeChanged: true,
windowFocus: true,
pageVisible: true,
vsync: true,
}
func Get() *UserInterface {
return theUI
}
var (
window = js.Global().Get("window")
document = js.Global().Get("document")
@ -70,64 +74,64 @@ var (
setTimeout = window.Get("setTimeout")
)
func ScreenSizeInFullscreen() (int, int) {
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
return window.Get("innerWidth").Int(), window.Get("innerHeight").Int()
}
func SetScreenSize(width, height int) bool {
return theUI.setScreenSize(width, height, theUI.scale, theUI.fullscreen)
func (u *UserInterface) SetScreenSize(width, height int) {
u.setScreenSize(width, height, u.scale, u.fullscreen)
}
func SetScreenScale(scale float64) bool {
return theUI.setScreenSize(theUI.width, theUI.height, scale, theUI.fullscreen)
func (u *UserInterface) SetScreenScale(scale float64) {
u.setScreenSize(u.width, u.height, scale, u.fullscreen)
}
func ScreenScale() float64 {
return theUI.scale
func (u *UserInterface) ScreenScale() float64 {
return u.scale
}
func SetFullscreen(fullscreen bool) {
theUI.setScreenSize(theUI.width, theUI.height, theUI.scale, fullscreen)
func (u *UserInterface) SetFullscreen(fullscreen bool) {
u.setScreenSize(u.width, u.height, u.scale, fullscreen)
}
func IsFullscreen() bool {
return theUI.fullscreen
func (u *UserInterface) IsFullscreen() bool {
return u.fullscreen
}
func SetRunnableInBackground(runnableInBackground bool) {
theUI.runnableInBackground = runnableInBackground
func (u *UserInterface) SetRunnableInBackground(runnableInBackground bool) {
u.runnableInBackground = runnableInBackground
}
func IsRunnableInBackground() bool {
return theUI.runnableInBackground
func (u *UserInterface) IsRunnableInBackground() bool {
return u.runnableInBackground
}
func SetVsyncEnabled(enabled bool) {
theUI.vsync = enabled
func (u *UserInterface) SetVsyncEnabled(enabled bool) {
u.vsync = enabled
}
func IsVsyncEnabled() bool {
return theUI.vsync
func (u *UserInterface) IsVsyncEnabled() bool {
return u.vsync
}
func ScreenPadding() (x0, y0, x1, y1 float64) {
func (u *UserInterface) ScreenPadding() (x0, y0, x1, y1 float64) {
return 0, 0, 0, 0
}
func AdjustPosition(x, y int) (int, int) {
func (u *UserInterface) AdjustPosition(x, y int) (int, int) {
rect := canvas.Call("getBoundingClientRect")
x -= rect.Get("left").Int()
y -= rect.Get("top").Int()
scale := theUI.getScale()
scale := u.getScale()
return int(float64(x) / scale), int(float64(y) / scale)
}
func IsCursorVisible() bool {
func (u *UserInterface) IsCursorVisible() bool {
// The initial value is an empty string, so don't compare with "auto" here.
return canvas.Get("style").Get("cursor").String() != "none"
}
func SetCursorVisible(visible bool) {
func (u *UserInterface) SetCursorVisible(visible bool) {
if visible {
canvas.Get("style").Set("cursor", "auto")
} else {
@ -135,35 +139,35 @@ func SetCursorVisible(visible bool) {
}
}
func SetWindowTitle(title string) {
func (u *UserInterface) SetWindowTitle(title string) {
document.Set("title", title)
}
func SetWindowIcon(iconImages []image.Image) {
func (u *UserInterface) SetWindowIcon(iconImages []image.Image) {
// Do nothing
}
func IsWindowDecorated() bool {
func (u *UserInterface) IsWindowDecorated() bool {
return false
}
func SetWindowDecorated(decorated bool) {
func (u *UserInterface) SetWindowDecorated(decorated bool) {
// Do nothing
}
func IsWindowResizable() bool {
func (u *UserInterface) IsWindowResizable() bool {
return false
}
func SetWindowResizable(decorated bool) {
func (u *UserInterface) SetWindowResizable(decorated bool) {
// Do nothing
}
func DeviceScaleFactor() float64 {
func (u *UserInterface) DeviceScaleFactor() float64 {
return devicescale.GetAt(0, 0)
}
func (u *userInterface) getScale() float64 {
func (u *UserInterface) getScale() float64 {
if !u.fullscreen {
return u.scale
}
@ -178,7 +182,7 @@ func (u *userInterface) getScale() float64 {
return sw
}
func (u *userInterface) actualScreenScale() float64 {
func (u *UserInterface) actualScreenScale() float64 {
// CSS imageRendering property seems useful to enlarge the screen,
// but doesn't work in some cases (#306):
// * Chrome just after restoring the lost context
@ -187,7 +191,7 @@ func (u *userInterface) actualScreenScale() float64 {
return u.getScale() * devicescale.GetAt(0, 0)
}
func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
func (u *UserInterface) updateGraphicsContext(g driver.GraphicsContext) {
a := u.actualScreenScale()
if u.lastActualScale != a {
u.updateScreenSize()
@ -200,11 +204,11 @@ func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
}
}
func (u *userInterface) suspended() bool {
func (u *UserInterface) suspended() bool {
return !u.runnableInBackground && (!u.windowFocus || !u.pageVisible)
}
func (u *userInterface) update(g driver.GraphicsContext) error {
func (u *UserInterface) update(g driver.GraphicsContext) error {
if u.suspended() {
hooks.SuspendAudio()
return nil
@ -221,7 +225,7 @@ func (u *userInterface) update(g driver.GraphicsContext) error {
return nil
}
func (u *userInterface) loop(g driver.GraphicsContext) <-chan error {
func (u *UserInterface) loop(g driver.GraphicsContext) <-chan error {
ch := make(chan error)
var cf js.Callback
f := func([]js.Value) {
@ -381,12 +385,11 @@ func init() {
}))
}
func Loop(ch <-chan error) error {
func (u *UserInterface) Loop(ch <-chan error) error {
return <-ch
}
func Run(width, height int, scale float64, title string, g driver.GraphicsContext, mainloop bool, graphics driver.Graphics, input driver.Input) error {
u := theUI
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)
document.Set("title", title)
@ -407,7 +410,7 @@ func Run(width, height int, scale float64, title string, g driver.GraphicsContex
return nil
}
func (u *userInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
func (u *UserInterface) setScreenSize(width, height int, scale float64, fullscreen bool) bool {
if u.width == width && u.height == height &&
u.scale == scale && fullscreen == u.fullscreen {
return false
@ -420,7 +423,7 @@ func (u *userInterface) setScreenSize(width, height int, scale float64, fullscre
return true
}
func (u *userInterface) updateScreenSize() {
func (u *UserInterface) updateScreenSize() {
canvas.Set("width", int(float64(u.width)*u.actualScreenScale()))
canvas.Set("height", int(float64(u.height)*u.actualScreenScale()))
canvasStyle := canvas.Get("style")

View File

@ -14,7 +14,7 @@
// +build android ios
package ui
package mobile
import (
"errors"
@ -41,10 +41,14 @@ var (
glContextCh = make(chan gl.Context)
renderCh = make(chan struct{})
renderChEnd = make(chan struct{})
theUI = &userInterface{}
theUI = &UserInterface{}
)
func Render(chError <-chan error) error {
func Get() *UserInterface {
return theUI
}
func (u *UserInterface) Render(chError <-chan error) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@ -63,7 +67,7 @@ func Render(chError <-chan error) error {
}
}
type userInterface struct {
type UserInterface struct {
width int
height int
scale float64
@ -113,7 +117,7 @@ func appMain(a app.App) {
glctx = nil
}
case size.Event:
setFullscreen(e.WidthPx, e.HeightPx)
theUI.setFullscreenImpl(e.WidthPx, e.HeightPx)
case paint.Event:
if glctx == nil || e.External {
continue
@ -148,13 +152,11 @@ func appMain(a app.App) {
}
}
func 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, input driver.Input) error {
if graphics != opengl.Get() {
panic("ui: graphics driver must be OpenGL")
}
u := theUI
u.m.Lock()
u.width = width
u.height = height
@ -180,7 +182,7 @@ func Run(width, height int, scale float64, title string, g driver.GraphicsContex
}
// Loop runs the main routine for gomobile-build.
func Loop(ch <-chan error) error {
func (u *UserInterface) Loop(ch <-chan error) error {
go func() {
// As mobile apps never ends, Loop can't return. Just panic here.
err := <-ch
@ -190,7 +192,7 @@ func Loop(ch <-chan error) error {
return nil
}
func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
func (u *UserInterface) updateGraphicsContext(g driver.GraphicsContext) {
width, height := 0, 0
actualScale := 0.0
@ -210,18 +212,14 @@ func (u *userInterface) updateGraphicsContext(g driver.GraphicsContext) {
}
}
func actualScale() float64 {
return theUI.actualScale()
}
func (u *userInterface) actualScale() float64 {
func (u *UserInterface) ActualScale() float64 {
u.m.Lock()
s := u.scaleImpl() * getDeviceScale()
u.m.Unlock()
return s
}
func (u *userInterface) scaleImpl() float64 {
func (u *UserInterface) scaleImpl() float64 {
scale := u.scale
if u.fullscreenScale != 0 {
scale = u.fullscreenScale
@ -229,7 +227,7 @@ func (u *userInterface) scaleImpl() float64 {
return scale
}
func (u *userInterface) update(g driver.GraphicsContext) error {
func (u *UserInterface) update(g driver.GraphicsContext) error {
render:
for {
select {
@ -254,29 +252,20 @@ render:
return nil
}
func screenSize() (int, int) {
return theUI.screenSize()
}
func (u *userInterface) screenSize() (int, int) {
func (u *UserInterface) ScreenSize() (int, int) {
u.m.Lock()
w, h := u.width, u.height
u.m.Unlock()
return w, h
}
func ScreenSizeInFullscreen() (int, int) {
func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
// TODO: This function should return fullscreenWidthPx, fullscreenHeightPx,
// but these values are not initialized until the main loop starts.
return 0, 0
}
func SetScreenSize(width, height int) bool {
theUI.setScreenSize(width, height)
return true
}
func (u *userInterface) setScreenSize(width, height int) {
func (u *UserInterface) SetScreenSize(width, height int) {
u.m.Lock()
if u.width != width || u.height != height {
u.width = width
@ -287,12 +276,7 @@ func (u *userInterface) setScreenSize(width, height int) {
u.m.Unlock()
}
func SetScreenScale(scale float64) bool {
theUI.setScreenScale(scale)
return false
}
func (u *userInterface) setScreenScale(scale float64) {
func (u *UserInterface) SetScreenScale(scale float64) {
u.m.Lock()
if u.scale != scale {
u.scale = scale
@ -301,19 +285,15 @@ func (u *userInterface) setScreenScale(scale float64) {
u.m.Unlock()
}
func ScreenScale() float64 {
u := theUI
func (u *UserInterface) ScreenScale() float64 {
u.m.RLock()
s := u.scale
u.m.RUnlock()
return s
}
func setFullscreen(widthPx, heightPx int) {
theUI.setFullscreen(widthPx, heightPx)
}
func (u *userInterface) setFullscreen(widthPx, heightPx int) {
func (u *UserInterface) setFullscreenImpl(widthPx, heightPx int) {
// This implementation is only for gomobile-build so far.
u.m.Lock()
u.fullscreenWidthPx = widthPx
u.fullscreenHeightPx = heightPx
@ -322,7 +302,7 @@ func (u *userInterface) setFullscreen(widthPx, heightPx int) {
u.m.Unlock()
}
func (u *userInterface) updateFullscreenScaleIfNeeded() {
func (u *UserInterface) updateFullscreenScaleIfNeeded() {
if u.fullscreenWidthPx == 0 || u.fullscreenHeightPx == 0 {
return
}
@ -337,18 +317,14 @@ func (u *userInterface) updateFullscreenScaleIfNeeded() {
u.sizeChanged = true
}
func ScreenPadding() (x0, y0, x1, y1 float64) {
return theUI.screenPadding()
}
func (u *userInterface) screenPadding() (x0, y0, x1, y1 float64) {
func (u *UserInterface) ScreenPadding() (x0, y0, x1, y1 float64) {
u.m.Lock()
x0, y0, x1, y1 = u.screenPaddingImpl()
u.m.Unlock()
return
}
func (u *userInterface) screenPaddingImpl() (x0, y0, x1, y1 float64) {
func (u *UserInterface) screenPaddingImpl() (x0, y0, x1, y1 float64) {
if u.fullscreenScale == 0 {
return 0, 0, 0, 0
}
@ -358,11 +334,7 @@ func (u *userInterface) screenPaddingImpl() (x0, y0, x1, y1 float64) {
return ox, oy, ox, oy
}
func AdjustPosition(x, y int) (int, int) {
return theUI.adjustPosition(x, y)
}
func (u *userInterface) adjustPosition(x, y int) (int, int) {
func (u *UserInterface) AdjustPosition(x, y int) (int, int) {
u.m.Lock()
ox, oy, _, _ := u.screenPaddingImpl()
s := u.scaleImpl()
@ -371,62 +343,62 @@ func (u *userInterface) adjustPosition(x, y int) (int, int) {
return int(float64(x)/s - ox/as), int(float64(y)/s - oy/as)
}
func IsCursorVisible() bool {
func (u *UserInterface) IsCursorVisible() bool {
return false
}
func SetCursorVisible(visible bool) {
func (u *UserInterface) SetCursorVisible(visible bool) {
// Do nothing
}
func IsFullscreen() bool {
func (u *UserInterface) IsFullscreen() bool {
return false
}
func SetFullscreen(fullscreen bool) {
func (u *UserInterface) SetFullscreen(fullscreen bool) {
// Do nothing
}
func IsRunnableInBackground() bool {
func (u *UserInterface) IsRunnableInBackground() bool {
return false
}
func SetRunnableInBackground(runnableInBackground bool) {
func (u *UserInterface) SetRunnableInBackground(runnableInBackground bool) {
// Do nothing
}
func SetWindowTitle(title string) {
func (u *UserInterface) SetWindowTitle(title string) {
// Do nothing
}
func SetWindowIcon(iconImages []image.Image) {
func (u *UserInterface) SetWindowIcon(iconImages []image.Image) {
// Do nothing
}
func IsWindowDecorated() bool {
func (u *UserInterface) IsWindowDecorated() bool {
return false
}
func SetWindowDecorated(decorated bool) {
func (u *UserInterface) SetWindowDecorated(decorated bool) {
// Do nothing
}
func IsWindowResizable() bool {
func (u *UserInterface) IsWindowResizable() bool {
return false
}
func SetWindowResizable(decorated bool) {
func (u *UserInterface) SetWindowResizable(decorated bool) {
// Do nothing
}
func IsVsyncEnabled() bool {
func (u *UserInterface) IsVsyncEnabled() bool {
return true
}
func SetVsyncEnabled(enabled bool) {
func (u *UserInterface) SetVsyncEnabled(enabled bool) {
// Do nothing
}
func DeviceScaleFactor() float64 {
func (u *UserInterface) DeviceScaleFactor() float64 {
return getDeviceScale()
}

View File

@ -20,7 +20,7 @@ import (
"errors"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/internal/ui"
"github.com/hajimehoshi/ebiten/internal/uidriver/mobile"
)
var (
@ -35,7 +35,7 @@ func update() error {
if !running {
return errors.New("mobile: start must be called ahead of update")
}
return ui.Render(chError)
return mobile.Get().Render(chError)
}
func start(f func(*ebiten.Image) error, width, height int, scale float64, title string) {

43
run.go
View File

@ -21,7 +21,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/ui"
"github.com/hajimehoshi/ebiten/internal/web"
)
@ -98,7 +97,7 @@ func run(width, height int, scale float64, title string, g *graphicsContext, mai
if !web.IsGopherJS() {
defer atomic.StoreInt32(&isRunning, 0)
}
if err := ui.Run(width, height, scale, title, g, mainloop, graphicsDriver(), input.Get()); err != nil {
if err := uiDriver().Run(width, height, scale, title, g, mainloop, graphicsDriver(), input.Get()); err != nil {
if err == driver.RegularTermination {
return nil
}
@ -157,7 +156,7 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
}
}()
// TODO: Use context in Go 1.7?
if err := ui.Loop(ch); err != nil {
if err := uiDriver().Loop(ch); err != nil {
return err
}
return nil
@ -214,7 +213,7 @@ func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64,
//
// ScreenSizeInFullscreen must be called on the main thread before ebiten.Run, and is concurrent-safe after ebiten.Run.
func ScreenSizeInFullscreen() (int, int) {
return ui.ScreenSizeInFullscreen()
return uiDriver().ScreenSizeInFullscreen()
}
// MonitorSize is deprecated as of 1.8.0-alpha. Use ScreenSizeInFullscreen instead.
@ -232,7 +231,7 @@ func SetScreenSize(width, height int) {
if width <= 0 || height <= 0 {
panic("ebiten: width and height must be positive")
}
ui.SetScreenSize(width, height)
uiDriver().SetScreenSize(width, height)
}
// SetScreenScale changes the scale of the screen.
@ -248,7 +247,7 @@ func SetScreenScale(scale float64) {
if scale <= 0 {
panic("ebiten: scale must be positive")
}
ui.SetScreenScale(scale)
uiDriver().SetScreenScale(scale)
}
// ScreenScale returns the current screen scale.
@ -257,7 +256,7 @@ func SetScreenScale(scale float64) {
//
// ScreenScale is concurrent-safe.
func ScreenScale() float64 {
return ui.ScreenScale()
return uiDriver().ScreenScale()
}
// IsCursorVisible returns a boolean value indicating whether
@ -267,7 +266,7 @@ func ScreenScale() float64 {
//
// IsCursorVisible is concurrent-safe.
func IsCursorVisible() bool {
return ui.IsCursorVisible()
return uiDriver().IsCursorVisible()
}
// SetCursorVisible changes the state of cursor visiblity.
@ -276,7 +275,7 @@ func IsCursorVisible() bool {
//
// SetCursorVisible is concurrent-safe.
func SetCursorVisible(visible bool) {
ui.SetCursorVisible(visible)
uiDriver().SetCursorVisible(visible)
}
// SetCursorVisibility is deprecated as of 1.6.0-alpha. Use SetCursorVisible instead.
@ -291,7 +290,7 @@ func SetCursorVisibility(visible bool) {
//
// IsFullscreen is concurrent-safe.
func IsFullscreen() bool {
return ui.IsFullscreen()
return uiDriver().IsFullscreen()
}
// SetFullscreen changes the current mode to fullscreen or not.
@ -312,7 +311,7 @@ func IsFullscreen() bool {
//
// SetFullscreen is concurrent-safe.
func SetFullscreen(fullscreen bool) {
ui.SetFullscreen(fullscreen)
uiDriver().SetFullscreen(fullscreen)
}
// IsRunnableInBackground returns a boolean value indicating whether
@ -320,7 +319,7 @@ func SetFullscreen(fullscreen bool) {
//
// IsRunnableInBackground is concurrent-safe.
func IsRunnableInBackground() bool {
return ui.IsRunnableInBackground()
return uiDriver().IsRunnableInBackground()
}
// SetWindowDecorated sets the state if the window is decorated.
@ -334,14 +333,14 @@ func IsRunnableInBackground() bool {
//
// SetWindowDecorated is concurrent-safe.
func SetWindowDecorated(decorated bool) {
ui.SetWindowDecorated(decorated)
uiDriver().SetWindowDecorated(decorated)
}
// IsWindowDecorated reports whether the window is decorated.
//
// IsWindowDecorated is concurrent-safe.
func IsWindowDecorated() bool {
return ui.IsWindowDecorated()
return uiDriver().IsWindowDecorated()
}
// setWindowResizable is unexported until specification is determined (#320)
@ -359,14 +358,14 @@ func IsWindowDecorated() bool {
//
// setWindowResizable is concurrent-safe.
func setWindowResizable(resizable bool) {
ui.SetWindowResizable(resizable)
uiDriver().SetWindowResizable(resizable)
}
// IsWindowResizable reports whether the window is resizable.
//
// IsWindowResizable is concurrent-safe.
func IsWindowResizable() bool {
return ui.IsWindowResizable()
return uiDriver().IsWindowResizable()
}
// SetRunnableInBackground sets the state if the game runs even in background.
@ -381,7 +380,7 @@ func IsWindowResizable() bool {
//
// SetRunnableInBackground is concurrent-safe.
func SetRunnableInBackground(runnableInBackground bool) {
ui.SetRunnableInBackground(runnableInBackground)
uiDriver().SetRunnableInBackground(runnableInBackground)
}
// SetWindowTitle sets the title of the window.
@ -390,7 +389,7 @@ func SetRunnableInBackground(runnableInBackground bool) {
//
// SetWindowTitle is concurrent-safe.
func SetWindowTitle(title string) {
ui.SetWindowTitle(title)
uiDriver().SetWindowTitle(title)
}
// SetWindowIcon sets the icon of the game window.
@ -414,7 +413,7 @@ func SetWindowTitle(title string) {
//
// SetWindowIcon is concurrent-safe.
func SetWindowIcon(iconImages []image.Image) {
ui.SetWindowIcon(iconImages)
uiDriver().SetWindowIcon(iconImages)
}
// DeviceScaleFactor returns a device scale factor value of the current monitor which the window belongs to.
@ -427,7 +426,7 @@ func SetWindowIcon(iconImages []image.Image) {
//
// DeviceScaleFactor must be called on the main thread before ebiten.Run, and is concurrent-safe after ebiten.Run.
func DeviceScaleFactor() float64 {
return ui.DeviceScaleFactor()
return uiDriver().DeviceScaleFactor()
}
// IsVsyncEnabled returns a boolean value indicating whether
@ -435,7 +434,7 @@ func DeviceScaleFactor() float64 {
//
// IsVsyncEnabled is concurrent-safe.
func IsVsyncEnabled() bool {
return ui.IsVsyncEnabled()
return uiDriver().IsVsyncEnabled()
}
// SetVsyncEnabled sets a boolean value indicating whether
@ -453,7 +452,7 @@ func IsVsyncEnabled() bool {
//
// SetVsyncEnabled is concurrent-safe.
func SetVsyncEnabled(enabled bool) {
ui.SetVsyncEnabled(enabled)
uiDriver().SetVsyncEnabled(enabled)
}
// MaxTPS returns the current maximum TPS.

29
ui_glfw.go Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2019 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 darwin freebsd linux windows
// +build !js
// +build !android
// +build !ios
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/uidriver/glfw"
)
func uiDriver() driver.UI {
return glfw.Get()
}

26
ui_js.go Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2019 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 js
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/uidriver/js"
)
func uiDriver() driver.UI {
return js.Get()
}

26
ui_mobile.go Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2019 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 android ios
package ebiten
import (
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/uidriver/mobile"
)
func uiDriver() driver.UI {
return mobile.Get()
}