mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
parent
0e74b34705
commit
626c91e360
@ -224,10 +224,11 @@ func (q *commandQueue) Enqueue(command command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Flush flushes the command queue.
|
// Flush flushes the command queue.
|
||||||
func (q *commandQueue) Flush() error {
|
func (q *commandQueue) Flush() (err error) {
|
||||||
return runOnMainThread(func() error {
|
RunOnMainThread(func() {
|
||||||
return q.flush()
|
err = q.flush()
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush must be called the main thread.
|
// flush must be called the main thread.
|
||||||
@ -699,18 +700,19 @@ func (c *newShaderCommand) Exec(indexOffset int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InitializeGraphicsDriverState initialize the current graphics driver state.
|
// InitializeGraphicsDriverState initialize the current graphics driver state.
|
||||||
func InitializeGraphicsDriverState() error {
|
func InitializeGraphicsDriverState() (err error) {
|
||||||
return runOnMainThread(func() error {
|
RunOnMainThread(func() {
|
||||||
return theGraphicsDriver.Initialize()
|
err = theGraphicsDriver.Initialize()
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetGraphicsDriverState resets the current graphics driver state.
|
// ResetGraphicsDriverState resets the current graphics driver state.
|
||||||
// If the graphics driver doesn't have an API to reset, ResetGraphicsDriverState does nothing.
|
// If the graphics driver doesn't have an API to reset, ResetGraphicsDriverState does nothing.
|
||||||
func ResetGraphicsDriverState() error {
|
func ResetGraphicsDriverState() (err error) {
|
||||||
if r, ok := theGraphicsDriver.(interface{ Reset() error }); ok {
|
if r, ok := theGraphicsDriver.(interface{ Reset() error }); ok {
|
||||||
return runOnMainThread(func() error {
|
RunOnMainThread(func() {
|
||||||
return r.Reset()
|
err = r.Reset()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -719,9 +721,8 @@ func ResetGraphicsDriverState() error {
|
|||||||
// MaxImageSize returns the maximum size of an image.
|
// MaxImageSize returns the maximum size of an image.
|
||||||
func MaxImageSize() int {
|
func MaxImageSize() int {
|
||||||
var size int
|
var size int
|
||||||
_ = runOnMainThread(func() error {
|
RunOnMainThread(func() {
|
||||||
size = theGraphicsDriver.MaxImageSize()
|
size = theGraphicsDriver.MaxImageSize()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ package graphicscommand
|
|||||||
var theThread Thread
|
var theThread Thread
|
||||||
|
|
||||||
type Thread interface {
|
type Thread interface {
|
||||||
Call(f func() error) error
|
Call(f func())
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMainThread must be called from the main thread (i.e, the goroutine where the thread is created).
|
// SetMainThread must be called from the main thread (i.e, the goroutine where the thread is created).
|
||||||
@ -25,12 +25,14 @@ func SetMainThread(thread Thread) {
|
|||||||
theThread = thread
|
theThread = thread
|
||||||
}
|
}
|
||||||
|
|
||||||
func runOnMainThread(f func() error) error {
|
// RunOnMainThread calls f on the main thread, and returns an error if any.
|
||||||
|
func RunOnMainThread(f func()) {
|
||||||
// The thread is nil when 1) GOOS=js or 2) using golang.org/x/mobile/gl.
|
// The thread is nil when 1) GOOS=js or 2) using golang.org/x/mobile/gl.
|
||||||
// When golang.org/x/mobile/gl is used, all the GL functions are called via Context, which already runs on an
|
// When golang.org/x/mobile/gl is used, all the GL functions are called via Context, which already runs on an
|
||||||
// appropriate thread.
|
// appropriate thread.
|
||||||
if theThread == nil {
|
if theThread == nil {
|
||||||
return f()
|
f()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return theThread.Call(f)
|
theThread.Call(f)
|
||||||
}
|
}
|
||||||
|
@ -14,20 +14,18 @@
|
|||||||
|
|
||||||
package thread
|
package thread
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Thread defines threading behavior in Ebiten.
|
// Thread defines threading behavior in Ebiten.
|
||||||
type Thread interface {
|
type Thread interface {
|
||||||
Call(func() error) error
|
Call(func())
|
||||||
Loop()
|
Loop()
|
||||||
|
Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSThread represents an OS thread.
|
// OSThread represents an OS thread.
|
||||||
type OSThread struct {
|
type OSThread struct {
|
||||||
funcs chan func() error
|
funcs chan func()
|
||||||
results chan error
|
done chan struct{}
|
||||||
|
terminate chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOSThread creates a new thread.
|
// NewOSThread creates a new thread.
|
||||||
@ -35,38 +33,45 @@ type OSThread struct {
|
|||||||
// It is assumed that the OS thread is fixed by runtime.LockOSThread when NewOSThread is called.
|
// It is assumed that the OS thread is fixed by runtime.LockOSThread when NewOSThread is called.
|
||||||
func NewOSThread() *OSThread {
|
func NewOSThread() *OSThread {
|
||||||
return &OSThread{
|
return &OSThread{
|
||||||
funcs: make(chan func() error),
|
funcs: make(chan func()),
|
||||||
results: make(chan error),
|
done: make(chan struct{}),
|
||||||
|
terminate: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BreakLoop represents an termination of the loop.
|
// Loop starts the thread loop until Stop is called.
|
||||||
var BreakLoop = errors.New("break loop")
|
|
||||||
|
|
||||||
// Loop starts the thread loop until a posted function returns BreakLoop.
|
|
||||||
//
|
//
|
||||||
// Loop must be called on the thread.
|
// Loop must be called on the thread.
|
||||||
func (t *OSThread) Loop() {
|
func (t *OSThread) Loop() {
|
||||||
for f := range t.funcs {
|
for {
|
||||||
err := f()
|
select {
|
||||||
if err == BreakLoop {
|
case fn := <-t.funcs:
|
||||||
t.results <- nil
|
func() {
|
||||||
|
defer func() {
|
||||||
|
t.done <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
fn()
|
||||||
|
}()
|
||||||
|
case <-t.terminate:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.results <- err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop stops the thread loop.
|
||||||
|
func (t *OSThread) Stop() {
|
||||||
|
close(t.terminate)
|
||||||
|
}
|
||||||
|
|
||||||
// Call calls f on the thread.
|
// Call calls f on the thread.
|
||||||
//
|
//
|
||||||
// Do not call this from the same thread. This would block forever.
|
// Do not call this from the same thread. This would block forever.
|
||||||
//
|
//
|
||||||
// If f returns BreakLoop, Loop returns.
|
|
||||||
//
|
|
||||||
// Call blocks if Loop is not called.
|
// Call blocks if Loop is not called.
|
||||||
func (t *OSThread) Call(f func() error) error {
|
func (t *OSThread) Call(f func()) {
|
||||||
t.funcs <- f
|
t.funcs <- f
|
||||||
return <-t.results
|
<-t.done
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoopThread is used to disable threading.
|
// NoopThread is used to disable threading.
|
||||||
@ -81,6 +86,7 @@ func NewNoopThread() *NoopThread {
|
|||||||
func (t *NoopThread) Loop() {}
|
func (t *NoopThread) Loop() {}
|
||||||
|
|
||||||
// Call executes the func immediately
|
// Call executes the func immediately
|
||||||
func (t *NoopThread) Call(f func() error) error {
|
func (t *NoopThread) Call(f func()) { f() }
|
||||||
return f()
|
|
||||||
}
|
// Stop does nothing
|
||||||
|
func (t *NoopThread) Stop() {}
|
||||||
|
@ -32,16 +32,13 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
|
|||||||
|
|
||||||
ch := make(chan error, 1)
|
ch := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer u.t.Stop()
|
||||||
_ = u.t.Call(func() error {
|
|
||||||
return thread.BreakLoop
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
|
|
||||||
if err := u.t.Call(func() error {
|
var err error
|
||||||
return u.init()
|
if u.t.Call(func() {
|
||||||
|
err = u.init()
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
return
|
return
|
||||||
@ -77,11 +74,7 @@ func (u *UserInterface) runOnAnotherThreadFromMainThread(f func() error) error {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer u.t.Stop()
|
||||||
_ = u.t.Call(func() error {
|
|
||||||
return thread.BreakLoop
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
err = f()
|
err = f()
|
||||||
}()
|
}()
|
||||||
u.t.Loop()
|
u.t.Loop()
|
||||||
|
@ -484,12 +484,11 @@ func (u *UserInterface) ScreenSizeInFullscreen() (int, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var w, h int
|
var w, h int
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
m := u.currentMonitor()
|
m := u.currentMonitor()
|
||||||
v := m.GetVideoMode()
|
v := m.GetVideoMode()
|
||||||
w = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m))
|
w = int(u.dipFromGLFWMonitorPixel(float64(v.Width), m))
|
||||||
h = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m))
|
h = int(u.dipFromGLFWMonitorPixel(float64(v.Height), m))
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return w, h
|
return w, h
|
||||||
}
|
}
|
||||||
@ -507,9 +506,8 @@ func (u *UserInterface) IsFullscreen() bool {
|
|||||||
return u.isInitFullscreen()
|
return u.isInitFullscreen()
|
||||||
}
|
}
|
||||||
b := false
|
b := false
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
b = u.isFullscreen()
|
b = u.isFullscreen()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
@ -521,18 +519,16 @@ func (u *UserInterface) SetFullscreen(fullscreen bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var update bool
|
var update bool
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
update = u.isFullscreen() != fullscreen
|
update = u.isFullscreen() != fullscreen
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
if !update {
|
if !update {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
w, h := u.windowWidthInDIP, u.windowHeightInDIP
|
w, h := u.windowWidthInDIP, u.windowHeightInDIP
|
||||||
u.setWindowSizeInDIP(w, h, fullscreen)
|
u.setWindowSizeInDIP(w, h, fullscreen)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,9 +538,8 @@ func (u *UserInterface) IsFocused() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var focused bool
|
var focused bool
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
focused = u.window.GetAttrib(glfw.Focused) == glfw.True
|
focused = u.window.GetAttrib(glfw.Focused) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return focused
|
return focused
|
||||||
}
|
}
|
||||||
@ -564,14 +559,13 @@ func (u *UserInterface) SetFPSMode(mode driver.FPSMode) {
|
|||||||
u.m.Unlock()
|
u.m.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
if !u.fpsModeInited {
|
if !u.fpsModeInited {
|
||||||
u.fpsMode = mode
|
u.fpsMode = mode
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
u.setFPSMode(mode)
|
u.setFPSMode(mode)
|
||||||
u.updateVsync()
|
u.updateVsync()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,9 +577,8 @@ func (u *UserInterface) FPSMode() driver.FPSMode {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
var v driver.FPSMode
|
var v driver.FPSMode
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
v = u.fpsMode
|
v = u.fpsMode
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -603,21 +596,23 @@ func (u *UserInterface) CursorMode() driver.CursorMode {
|
|||||||
if !u.isRunning() {
|
if !u.isRunning() {
|
||||||
return u.getInitCursorMode()
|
return u.getInitCursorMode()
|
||||||
}
|
}
|
||||||
var v driver.CursorMode
|
|
||||||
_ = u.t.Call(func() error {
|
var mode int
|
||||||
mode := u.window.GetInputMode(glfw.CursorMode)
|
u.t.Call(func() {
|
||||||
switch mode {
|
mode = u.window.GetInputMode(glfw.CursorMode)
|
||||||
case glfw.CursorNormal:
|
|
||||||
v = driver.CursorModeVisible
|
|
||||||
case glfw.CursorHidden:
|
|
||||||
v = driver.CursorModeHidden
|
|
||||||
case glfw.CursorDisabled:
|
|
||||||
v = driver.CursorModeCaptured
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("glfw: invalid GLFW cursor mode: %d", mode))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var v driver.CursorMode
|
||||||
|
switch mode {
|
||||||
|
case glfw.CursorNormal:
|
||||||
|
v = driver.CursorModeVisible
|
||||||
|
case glfw.CursorHidden:
|
||||||
|
v = driver.CursorModeHidden
|
||||||
|
case glfw.CursorDisabled:
|
||||||
|
v = driver.CursorModeCaptured
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("glfw: invalid GLFW cursor mode: %d", mode))
|
||||||
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,9 +621,8 @@ func (u *UserInterface) SetCursorMode(mode driver.CursorMode) {
|
|||||||
u.setInitCursorMode(mode)
|
u.setInitCursorMode(mode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
u.window.SetInputMode(glfw.CursorMode, driverCursorModeToGLFWCursorMode(mode))
|
u.window.SetInputMode(glfw.CursorMode, driverCursorModeToGLFWCursorMode(mode))
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,9 +638,8 @@ func (u *UserInterface) SetCursorShape(shape driver.CursorShape) {
|
|||||||
if !u.isRunning() {
|
if !u.isRunning() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
u.setNativeCursor(shape)
|
u.setNativeCursor(shape)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,9 +650,8 @@ func (u *UserInterface) DeviceScaleFactor() float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f := 0.0
|
f := 0.0
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
f = u.deviceScaleFactor(u.currentMonitor())
|
f = u.deviceScaleFactor(u.currentMonitor())
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
@ -745,7 +737,7 @@ func (u *UserInterface) registerWindowSetSizeCallback() {
|
|||||||
|
|
||||||
var outsideWidth, outsideHeight float64
|
var outsideWidth, outsideHeight float64
|
||||||
|
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
if width != 0 || height != 0 {
|
if width != 0 || height != 0 {
|
||||||
w := int(u.dipFromGLFWPixel(float64(width), u.currentMonitor()))
|
w := int(u.dipFromGLFWPixel(float64(width), u.currentMonitor()))
|
||||||
h := int(u.dipFromGLFWPixel(float64(height), u.currentMonitor()))
|
h := int(u.dipFromGLFWPixel(float64(height), u.currentMonitor()))
|
||||||
@ -753,16 +745,14 @@ func (u *UserInterface) registerWindowSetSizeCallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outsideWidth, outsideHeight = u.updateSize()
|
outsideWidth, outsideHeight = u.updateSize()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
u.context.Layout(outsideWidth, outsideHeight)
|
u.context.Layout(outsideWidth, outsideHeight)
|
||||||
if err := u.context.ForceUpdateFrame(); err != nil {
|
if err := u.context.ForceUpdateFrame(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if u.Graphics().IsGL() {
|
if u.Graphics().IsGL() {
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
u.swapBuffers()
|
u.swapBuffers()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -1023,12 +1013,7 @@ func (u *UserInterface) update() (float64, float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) loop() error {
|
func (u *UserInterface) loop() error {
|
||||||
defer func() {
|
defer u.t.Call(glfw.Terminate)
|
||||||
_ = u.t.Call(func() error {
|
|
||||||
glfw.Terminate()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var unfocused bool
|
var unfocused bool
|
||||||
@ -1047,10 +1032,9 @@ func (u *UserInterface) loop() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var outsideWidth, outsideHeight float64
|
var outsideWidth, outsideHeight float64
|
||||||
if err := u.t.Call(func() error {
|
var err error
|
||||||
var err error
|
if u.t.Call(func() {
|
||||||
outsideWidth, outsideHeight, err = u.update()
|
outsideWidth, outsideHeight, err = u.update()
|
||||||
return err
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1084,14 +1068,13 @@ func (u *UserInterface) loop() error {
|
|||||||
newImgs[i] = rgba
|
newImgs[i] = rgba
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
// In the fullscreen mode, reset the icon images and try again later.
|
// In the fullscreen mode, reset the icon images and try again later.
|
||||||
if u.isFullscreen() {
|
if u.isFullscreen() {
|
||||||
u.setIconImages(imgs)
|
u.setIconImages(imgs)
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
u.window.SetIcon(newImgs)
|
u.window.SetIcon(newImgs)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -1100,10 +1083,7 @@ func (u *UserInterface) loop() error {
|
|||||||
// However, (*thread).Call is not good for performance due to channels.
|
// However, (*thread).Call is not good for performance due to channels.
|
||||||
// Let's avoid this whenever possible (#1367).
|
// Let's avoid this whenever possible (#1367).
|
||||||
if u.Graphics().IsGL() {
|
if u.Graphics().IsGL() {
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(u.swapBuffers)
|
||||||
u.swapBuffers()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if unfocused {
|
if unfocused {
|
||||||
@ -1399,9 +1379,8 @@ func (u *UserInterface) IsScreenTransparent() bool {
|
|||||||
return u.isInitScreenTransparent()
|
return u.isInitScreenTransparent()
|
||||||
}
|
}
|
||||||
val := false
|
val := false
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
val = u.window.GetAttrib(glfw.TransparentFramebuffer) == glfw.True
|
val = u.window.GetAttrib(glfw.TransparentFramebuffer) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
@ -1409,9 +1388,8 @@ func (u *UserInterface) IsScreenTransparent() bool {
|
|||||||
func (u *UserInterface) ResetForFrame() {
|
func (u *UserInterface) ResetForFrame() {
|
||||||
// The offscreens must be updated every frame (#490).
|
// The offscreens must be updated every frame (#490).
|
||||||
var w, h float64
|
var w, h float64
|
||||||
_ = u.t.Call(func() error {
|
u.t.Call(func() {
|
||||||
w, h = u.updateSize()
|
w, h = u.updateSize()
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
u.context.Layout(w, h)
|
u.context.Layout(w, h)
|
||||||
u.input.resetForFrame()
|
u.input.resetForFrame()
|
||||||
|
@ -32,9 +32,8 @@ func (w *window) IsDecorated() bool {
|
|||||||
return w.ui.isInitWindowDecorated()
|
return w.ui.isInitWindowDecorated()
|
||||||
}
|
}
|
||||||
v := false
|
v := false
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
v = w.ui.window.GetAttrib(glfw.Decorated) == glfw.True
|
v = w.ui.window.GetAttrib(glfw.Decorated) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -45,13 +44,12 @@ func (w *window) SetDecorated(decorated bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
if w.ui.isNativeFullscreen() {
|
if w.ui.isNativeFullscreen() {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.ui.setWindowDecorated(decorated)
|
w.ui.setWindowDecorated(decorated)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,9 +58,8 @@ func (w *window) IsResizable() bool {
|
|||||||
return w.ui.isInitWindowResizable()
|
return w.ui.isInitWindowResizable()
|
||||||
}
|
}
|
||||||
v := false
|
v := false
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
v = w.ui.window.GetAttrib(glfw.Resizable) == glfw.True
|
v = w.ui.window.GetAttrib(glfw.Resizable) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -72,12 +69,11 @@ func (w *window) SetResizable(resizable bool) {
|
|||||||
w.ui.setInitWindowResizable(resizable)
|
w.ui.setInitWindowResizable(resizable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
if w.ui.isNativeFullscreen() {
|
if w.ui.isNativeFullscreen() {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
w.ui.setWindowResizable(resizable)
|
w.ui.setWindowResizable(resizable)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,9 +82,8 @@ func (w *window) IsFloating() bool {
|
|||||||
return w.ui.isInitWindowFloating()
|
return w.ui.isInitWindowFloating()
|
||||||
}
|
}
|
||||||
var v bool
|
var v bool
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
v = w.ui.window.GetAttrib(glfw.Floating) == glfw.True
|
v = w.ui.window.GetAttrib(glfw.Floating) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -98,12 +93,11 @@ func (w *window) SetFloating(floating bool) {
|
|||||||
w.ui.setInitWindowFloating(floating)
|
w.ui.setInitWindowFloating(floating)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
if w.ui.isNativeFullscreen() {
|
if w.ui.isNativeFullscreen() {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
w.ui.setWindowFloating(floating)
|
w.ui.setWindowFloating(floating)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +106,8 @@ func (w *window) IsMaximized() bool {
|
|||||||
return w.ui.isInitWindowMaximized()
|
return w.ui.isInitWindowMaximized()
|
||||||
}
|
}
|
||||||
var v bool
|
var v bool
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
v = w.ui.window.GetAttrib(glfw.Maximized) == glfw.True
|
v = w.ui.window.GetAttrib(glfw.Maximized) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -127,10 +120,7 @@ func (w *window) Maximize() {
|
|||||||
w.ui.setInitWindowMaximized(true)
|
w.ui.setInitWindowMaximized(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(w.ui.maximizeWindow)
|
||||||
w.ui.maximizeWindow()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) IsMinimized() bool {
|
func (w *window) IsMinimized() bool {
|
||||||
@ -138,9 +128,8 @@ func (w *window) IsMinimized() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
var v bool
|
var v bool
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
v = w.ui.window.GetAttrib(glfw.Iconified) == glfw.True
|
v = w.ui.window.GetAttrib(glfw.Iconified) == glfw.True
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@ -150,10 +139,7 @@ func (w *window) Minimize() {
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(w.ui.iconifyWindow)
|
||||||
w.ui.iconifyWindow()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) Restore() {
|
func (w *window) Restore() {
|
||||||
@ -161,10 +147,7 @@ func (w *window) Restore() {
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(w.ui.restoreWindow)
|
||||||
w.ui.restoreWindow()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) Position() (int, int) {
|
func (w *window) Position() (int, int) {
|
||||||
@ -172,7 +155,7 @@ func (w *window) Position() (int, int) {
|
|||||||
panic("glfw: WindowPosition can't be called before the main loop starts")
|
panic("glfw: WindowPosition can't be called before the main loop starts")
|
||||||
}
|
}
|
||||||
x, y := 0, 0
|
x, y := 0, 0
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
var wx, wy int
|
var wx, wy int
|
||||||
if w.ui.isFullscreen() && !w.ui.isNativeFullscreenAvailable() {
|
if w.ui.isFullscreen() && !w.ui.isNativeFullscreenAvailable() {
|
||||||
wx, wy = w.ui.origPos()
|
wx, wy = w.ui.origPos()
|
||||||
@ -186,7 +169,6 @@ func (w *window) Position() (int, int) {
|
|||||||
xf := w.ui.dipFromGLFWPixel(float64(wx), m)
|
xf := w.ui.dipFromGLFWPixel(float64(wx), m)
|
||||||
yf := w.ui.dipFromGLFWPixel(float64(wy), m)
|
yf := w.ui.dipFromGLFWPixel(float64(wy), m)
|
||||||
x, y = int(xf), int(yf)
|
x, y = int(xf), int(yf)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
@ -196,9 +178,8 @@ func (w *window) SetPosition(x, y int) {
|
|||||||
w.ui.setInitWindowPositionInDIP(x, y)
|
w.ui.setInitWindowPositionInDIP(x, y)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
w.ui.setWindowPositionInDIP(x, y, w.ui.currentMonitor())
|
w.ui.setWindowPositionInDIP(x, y, w.ui.currentMonitor())
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,10 +189,9 @@ func (w *window) Size() (int, int) {
|
|||||||
return w.ui.adjustWindowSizeBasedOnSizeLimitsInDIP(ww, wh)
|
return w.ui.adjustWindowSizeBasedOnSizeLimitsInDIP(ww, wh)
|
||||||
}
|
}
|
||||||
ww, wh := 0, 0
|
ww, wh := 0, 0
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
ww = w.ui.windowWidthInDIP
|
ww = w.ui.windowWidthInDIP
|
||||||
wh = w.ui.windowHeightInDIP
|
wh = w.ui.windowHeightInDIP
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
return ww, wh
|
return ww, wh
|
||||||
}
|
}
|
||||||
@ -221,15 +201,14 @@ func (w *window) SetSize(width, height int) {
|
|||||||
w.ui.setInitWindowSizeInDIP(width, height)
|
w.ui.setInitWindowSizeInDIP(width, height)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
// When a window is a native fullscreen, forcing to resize the window might leave unexpected image lags.
|
// When a window is a native fullscreen, forcing to resize the window might leave unexpected image lags.
|
||||||
// Forbid this.
|
// Forbid this.
|
||||||
if w.ui.isNativeFullscreen() {
|
if w.ui.isNativeFullscreen() {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.ui.setWindowSizeInDIP(width, height, w.ui.isFullscreen())
|
w.ui.setWindowSizeInDIP(width, height, w.ui.isFullscreen())
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,10 +224,7 @@ func (w *window) SetSizeLimits(minw, minh, maxw, maxh int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(w.ui.updateWindowSizeLimits)
|
||||||
w.ui.updateWindowSizeLimits()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) SetIcon(iconImages []image.Image) {
|
func (w *window) SetIcon(iconImages []image.Image) {
|
||||||
@ -264,9 +240,8 @@ func (w *window) SetTitle(title string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.ui.title = title
|
w.ui.title = title
|
||||||
_ = w.ui.t.Call(func() error {
|
w.ui.t.Call(func() {
|
||||||
w.ui.setWindowTitle(title)
|
w.ui.setWindowTitle(title)
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +88,7 @@ func (u *UserInterface) Update() error {
|
|||||||
renderCh <- struct{}{}
|
renderCh <- struct{}{}
|
||||||
go func() {
|
go func() {
|
||||||
<-renderEndCh
|
<-renderEndCh
|
||||||
u.t.Call(func() error {
|
u.t.Stop()
|
||||||
return thread.BreakLoop
|
|
||||||
})
|
|
||||||
}()
|
}()
|
||||||
u.t.Loop()
|
u.t.Loop()
|
||||||
return nil
|
return nil
|
||||||
|
6
run.go
6
run.go
@ -19,6 +19,7 @@ import (
|
|||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/clock"
|
"github.com/hajimehoshi/ebiten/v2/internal/clock"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Game defines necessary functions for a game.
|
// Game defines necessary functions for a game.
|
||||||
@ -168,6 +169,11 @@ func RunGame(game Game) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunOnMainThread calls the given f on the main thread, and blocks until f returns.
|
||||||
|
func RunOnMainThread(f func()) {
|
||||||
|
graphicscommand.RunOnMainThread(f)
|
||||||
|
}
|
||||||
|
|
||||||
func isRunGameEnded() bool {
|
func isRunGameEnded() bool {
|
||||||
return atomic.LoadInt32(&isRunGameEnded_) != 0
|
return atomic.LoadInt32(&isRunGameEnded_) != 0
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user