mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
ui: Introduce ScreenSizeEvent to simplify the run loop
This commit is contained in:
parent
faff188574
commit
335781759c
@ -15,7 +15,6 @@
|
|||||||
package loop
|
package loop
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -24,10 +23,6 @@ import (
|
|||||||
|
|
||||||
const FPS = 60
|
const FPS = 60
|
||||||
|
|
||||||
func Main() {
|
|
||||||
ui.Main()
|
|
||||||
}
|
|
||||||
|
|
||||||
func CurrentFPS() float64 {
|
func CurrentFPS() float64 {
|
||||||
return currentRunContext.currentFPS()
|
return currentRunContext.currentFPS()
|
||||||
}
|
}
|
||||||
@ -40,26 +35,11 @@ func IsRunningSlowly() bool {
|
|||||||
return currentRunContext.isRunningSlowly()
|
return currentRunContext.isRunningSlowly()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetScreenSize(width, height int) error {
|
|
||||||
return currentRunContext.setScreenSize(width, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetScreenScale(scale int) error {
|
|
||||||
return currentRunContext.setScreenScale(scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScreenScale() int {
|
|
||||||
return ui.CurrentUI().ScreenScale()
|
|
||||||
}
|
|
||||||
|
|
||||||
type runContext struct {
|
type runContext struct {
|
||||||
running bool
|
running bool
|
||||||
fps float64
|
fps float64
|
||||||
newScreenWidth int
|
runningSlowly bool
|
||||||
newScreenHeight int
|
m sync.RWMutex
|
||||||
newScreenScale int
|
|
||||||
runningSlowly bool
|
|
||||||
m sync.RWMutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentRunContext runContext
|
var currentRunContext runContext
|
||||||
@ -114,60 +94,6 @@ func (c *runContext) setRunningSlowly(isRunningSlowly bool) {
|
|||||||
c.runningSlowly = isRunningSlowly
|
c.runningSlowly = isRunningSlowly
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *runContext) updateScreenSize(g GraphicsContext) error {
|
|
||||||
c.m.Lock()
|
|
||||||
defer c.m.Unlock()
|
|
||||||
if c.newScreenWidth == 0 && c.newScreenHeight == 0 && c.newScreenScale == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
changed := false
|
|
||||||
if 0 < c.newScreenWidth || 0 < c.newScreenHeight {
|
|
||||||
c := ui.CurrentUI().SetScreenSize(c.newScreenWidth, c.newScreenHeight)
|
|
||||||
changed = changed || c
|
|
||||||
}
|
|
||||||
if 0 < c.newScreenScale {
|
|
||||||
c := ui.CurrentUI().SetScreenScale(c.newScreenScale)
|
|
||||||
changed = changed || c
|
|
||||||
}
|
|
||||||
if changed {
|
|
||||||
w, h := c.newScreenWidth, c.newScreenHeight
|
|
||||||
if err := g.SetSize(w, h, ui.CurrentUI().ActualScreenScale()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.newScreenWidth = 0
|
|
||||||
c.newScreenHeight = 0
|
|
||||||
c.newScreenScale = 0
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runContext) setScreenSize(width, height int) error {
|
|
||||||
c.m.Lock()
|
|
||||||
defer c.m.Unlock()
|
|
||||||
if !c.running {
|
|
||||||
return errors.New("ebiten: SetScreenSize must be called during Run")
|
|
||||||
}
|
|
||||||
if width <= 0 || height <= 0 {
|
|
||||||
return errors.New("ebiten: width and height must be positive")
|
|
||||||
}
|
|
||||||
c.newScreenWidth = width
|
|
||||||
c.newScreenHeight = height
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *runContext) setScreenScale(scale int) error {
|
|
||||||
c.m.Lock()
|
|
||||||
defer c.m.Unlock()
|
|
||||||
if !c.running {
|
|
||||||
return errors.New("ebiten: SetScreenScale must be called during Run")
|
|
||||||
}
|
|
||||||
if scale <= 0 {
|
|
||||||
return errors.New("ebiten: scale must be positive")
|
|
||||||
}
|
|
||||||
c.newScreenScale = scale
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GraphicsContext interface {
|
type GraphicsContext interface {
|
||||||
SetSize(width, height, scale int) error
|
SetSize(width, height, scale int) error
|
||||||
Update() error
|
Update() error
|
||||||
@ -182,23 +108,20 @@ func Run(g GraphicsContext, width, height, scale int, title string) error {
|
|||||||
}
|
}
|
||||||
defer ui.CurrentUI().Terminate()
|
defer ui.CurrentUI().Terminate()
|
||||||
|
|
||||||
if err := g.SetSize(width, height, ui.CurrentUI().ActualScreenScale()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
frames := 0
|
frames := 0
|
||||||
n := now()
|
n := now()
|
||||||
beforeForUpdate := n
|
beforeForUpdate := n
|
||||||
beforeForFPS := n
|
beforeForFPS := n
|
||||||
for {
|
for {
|
||||||
if err := currentRunContext.updateScreenSize(g); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
e, err := ui.CurrentUI().Update()
|
e, err := ui.CurrentUI().Update()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch e.(type) {
|
switch e := e.(type) {
|
||||||
|
case ui.ScreenSizeEvent:
|
||||||
|
if err := g.SetSize(e.Width, e.Height, e.ActualScale); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case ui.CloseEvent:
|
case ui.CloseEvent:
|
||||||
return nil
|
return nil
|
||||||
case ui.RenderEvent:
|
case ui.RenderEvent:
|
||||||
|
@ -19,3 +19,10 @@ type CloseEvent struct {
|
|||||||
|
|
||||||
type RenderEvent struct {
|
type RenderEvent struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ScreenSizeEvent struct {
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
|
Scale int
|
||||||
|
ActualScale int
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ type UserInterface struct {
|
|||||||
framebufferScale int
|
framebufferScale int
|
||||||
context *opengl.Context
|
context *opengl.Context
|
||||||
funcs chan func()
|
funcs chan func()
|
||||||
|
sizeChanged bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentUI *UserInterface
|
var currentUI *UserInterface
|
||||||
@ -61,8 +62,9 @@ func initialize() (*opengl.Context, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u := &UserInterface{
|
u := &UserInterface{
|
||||||
window: window,
|
window: window,
|
||||||
funcs: make(chan func()),
|
funcs: make(chan func()),
|
||||||
|
sizeChanged: true,
|
||||||
}
|
}
|
||||||
ch := make(chan error)
|
ch := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
@ -140,14 +142,6 @@ func (u *UserInterface) ScreenScale() int {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserInterface) ActualScreenScale() int {
|
|
||||||
s := 0
|
|
||||||
u.runOnMainThread(func() {
|
|
||||||
s = u.actualScreenScale()
|
|
||||||
})
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *UserInterface) Start(width, height, scale int, title string) error {
|
func (u *UserInterface) Start(width, height, scale int, title string) error {
|
||||||
var err error
|
var err error
|
||||||
u.runOnMainThread(func() {
|
u.runOnMainThread(func() {
|
||||||
@ -200,6 +194,24 @@ func (u *UserInterface) Update() (interface{}, error) {
|
|||||||
if shouldClose {
|
if shouldClose {
|
||||||
return CloseEvent{}, nil
|
return CloseEvent{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var screenSizeEvent *ScreenSizeEvent
|
||||||
|
u.runOnMainThread(func() {
|
||||||
|
if !u.sizeChanged {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u.sizeChanged = false
|
||||||
|
screenSizeEvent = &ScreenSizeEvent{
|
||||||
|
Width: u.width,
|
||||||
|
Height: u.height,
|
||||||
|
Scale: u.scale,
|
||||||
|
ActualScale: u.actualScreenScale(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if screenSizeEvent != nil {
|
||||||
|
return *screenSizeEvent, nil
|
||||||
|
}
|
||||||
|
|
||||||
var ferr error
|
var ferr error
|
||||||
u.runOnMainThread(func() {
|
u.runOnMainThread(func() {
|
||||||
if err := u.pollEvents(); err != nil {
|
if err := u.pollEvents(); err != nil {
|
||||||
@ -291,5 +303,6 @@ event:
|
|||||||
// This is usually 1, but sometimes more than 1 (e.g. Retina Mac)
|
// This is usually 1, but sometimes more than 1 (e.g. Retina Mac)
|
||||||
fw, _ := window.GetFramebufferSize()
|
fw, _ := window.GetFramebufferSize()
|
||||||
u.framebufferScale = fw / width / u.windowScale()
|
u.framebufferScale = fw / width / u.windowScale()
|
||||||
|
u.sizeChanged = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,12 @@ var canvas *js.Object
|
|||||||
type UserInterface struct {
|
type UserInterface struct {
|
||||||
scale int
|
scale int
|
||||||
deviceScale float64
|
deviceScale float64
|
||||||
|
sizeChanged bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentUI = &UserInterface{}
|
var currentUI = &UserInterface{
|
||||||
|
sizeChanged: true,
|
||||||
|
}
|
||||||
|
|
||||||
func CurrentUI() *UserInterface {
|
func CurrentUI() *UserInterface {
|
||||||
return currentUI
|
return currentUI
|
||||||
@ -79,6 +82,17 @@ func vsync() {
|
|||||||
|
|
||||||
func (u *UserInterface) Update() (interface{}, error) {
|
func (u *UserInterface) Update() (interface{}, error) {
|
||||||
currentInput.UpdateGamepads()
|
currentInput.UpdateGamepads()
|
||||||
|
if u.sizeChanged {
|
||||||
|
u.sizeChanged = false
|
||||||
|
w, h := u.size()
|
||||||
|
e := ScreenSizeEvent{
|
||||||
|
Width: w,
|
||||||
|
Height: h,
|
||||||
|
Scale: u.ScreenScale(),
|
||||||
|
ActualScale: u.ActualScreenScale(),
|
||||||
|
}
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
return RenderEvent{}, nil
|
return RenderEvent{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,5 +290,6 @@ func (u *UserInterface) setScreenSize(width, height, scale int) bool {
|
|||||||
// CSS calc requires space chars.
|
// CSS calc requires space chars.
|
||||||
canvasStyle.Set("left", "calc((100% - "+strconv.Itoa(cssWidth)+"px) / 2)")
|
canvasStyle.Set("left", "calc((100% - "+strconv.Itoa(cssWidth)+"px) / 2)")
|
||||||
canvasStyle.Set("top", "calc((100% - "+strconv.Itoa(cssHeight)+"px) / 2)")
|
canvasStyle.Set("top", "calc((100% - "+strconv.Itoa(cssHeight)+"px) / 2)")
|
||||||
|
u.sizeChanged = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
15
run.go
15
run.go
@ -16,6 +16,7 @@ package ebiten
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/loop"
|
"github.com/hajimehoshi/ebiten/internal/loop"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FPS represents how many times game updating happens in a second.
|
// FPS represents how many times game updating happens in a second.
|
||||||
@ -58,7 +59,7 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
|
|||||||
g := newGraphicsContext(f)
|
g := newGraphicsContext(f)
|
||||||
ch <- loop.Run(g, width, height, scale, title)
|
ch <- loop.Run(g, width, height, scale, title)
|
||||||
}()
|
}()
|
||||||
loop.Main()
|
ui.Main()
|
||||||
return <-ch
|
return <-ch
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,23 +68,25 @@ func Run(f func(*Image) error, width, height, scale int, title string) error {
|
|||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func SetScreenSize(width, height int) {
|
func SetScreenSize(width, height int) {
|
||||||
if err := loop.SetScreenSize(width, height); err != nil {
|
if width <= 0 || height <= 0 {
|
||||||
panic(err)
|
panic("ebiten: width and height must be positive")
|
||||||
}
|
}
|
||||||
|
ui.CurrentUI().SetScreenSize(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScreenScale changes the scale of the screen.
|
// SetScreenScale changes the scale of the screen.
|
||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func SetScreenScale(scale int) {
|
func SetScreenScale(scale int) {
|
||||||
if err := loop.SetScreenScale(scale); err != nil {
|
if scale <= 0 {
|
||||||
panic(err)
|
panic("ebiten: scale must be positive")
|
||||||
}
|
}
|
||||||
|
ui.CurrentUI().SetScreenScale(scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScreenScale returns the current screen scale.
|
// ScreenScale returns the current screen scale.
|
||||||
//
|
//
|
||||||
// This function is concurrent-safe.
|
// This function is concurrent-safe.
|
||||||
func ScreenScale() int {
|
func ScreenScale() int {
|
||||||
return loop.ScreenScale()
|
return ui.CurrentUI().ScreenScale()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user