mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-26 10:42:42 +01:00
Add uidriver package and move UI implementation to this packaage
This commit is contained in:
parent
a4a129e3af
commit
7e5085f15b
@ -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
|
||||
|
5
input.go
5
input.go
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
// +build !windows js
|
||||
|
||||
package ui
|
||||
package glfw
|
||||
|
||||
// hideConsoleWindowOnWindows does nothing on non-Windows systems.
|
||||
func hideConsoleWindowOnWindows() {}
|
@ -14,7 +14,7 @@
|
||||
|
||||
// +build !js
|
||||
|
||||
package ui
|
||||
package glfw
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -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
|
@ -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()
|
||||
}
|
@ -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
|
||||
}
|
@ -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()
|
||||
}
|
@ -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")
|
@ -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()
|
||||
}
|
@ -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
43
run.go
@ -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
29
ui_glfw.go
Normal 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
26
ui_js.go
Normal 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
26
ui_mobile.go
Normal 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()
|
||||
}
|
Loading…
Reference in New Issue
Block a user