From bb511b2c135ea13e6eed5d105204248a2fd60207 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 19 Jun 2016 02:59:17 +0900 Subject: [PATCH] ui: Scale is now float64 (#236) --- examples/paint/main.go | 2 +- graphicscontext.go | 8 +++++--- internal/loop/run.go | 4 ++-- internal/ui/event.go | 2 +- internal/ui/input_glfw.go | 8 +++----- internal/ui/ui.go | 6 +++--- internal/ui/ui_glfw.go | 31 +++++++++++++++---------------- internal/ui/ui_js.go | 28 ++++++++++++++-------------- internal/ui/ui_mobile.go | 12 ++++++------ mobile/run.go | 10 +++++----- run.go | 8 ++++---- 11 files changed, 59 insertions(+), 60 deletions(-) diff --git a/examples/paint/main.go b/examples/paint/main.go index a2eecce81..8d26db6e5 100644 --- a/examples/paint/main.go +++ b/examples/paint/main.go @@ -107,7 +107,7 @@ func main() { } canvasImage.Fill(color.White) - if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Paint (Ebiten Demo)"); err != nil { + if err := ebiten.Run(update, screenWidth, screenHeight, 1.5, "Paint (Ebiten Demo)"); err != nil { log.Fatal(err) } } diff --git a/graphicscontext.go b/graphicscontext.go index d3f55b979..555b368c4 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -30,11 +30,11 @@ type graphicsContext struct { f func(*Image) error offscreen *Image screen *Image - screenScale int + screenScale float64 initialized bool } -func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) error { +func (c *graphicsContext) SetSize(screenWidth, screenHeight int, screenScale float64) error { if c.screen != nil { c.screen.Dispose() } @@ -45,7 +45,9 @@ func (c *graphicsContext) SetSize(screenWidth, screenHeight, screenScale int) er if err != nil { return err } - c.screen, err = newImageWithScreenFramebuffer(screenWidth*screenScale, screenHeight*screenScale) + w := int(float64(screenWidth) * screenScale) + h := int(float64(screenHeight) * screenScale) + c.screen, err = newImageWithScreenFramebuffer(w, h) if err != nil { return err } diff --git a/internal/loop/run.go b/internal/loop/run.go index f9d5bff99..dfb7513d8 100644 --- a/internal/loop/run.go +++ b/internal/loop/run.go @@ -98,12 +98,12 @@ func (c *runContext) setRunningSlowly(isRunningSlowly bool) { } type GraphicsContext interface { - SetSize(width, height, scale int) error + SetSize(width, height int, scale float64) error UpdateAndDraw() error Draw() error } -func Run(g GraphicsContext, width, height, scale int, title string, fps int) error { +func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) error { if currentRunContext != nil { return errors.New("loop: The game is already running") } diff --git a/internal/ui/event.go b/internal/ui/event.go index 631c444a1..fad7bcdf5 100644 --- a/internal/ui/event.go +++ b/internal/ui/event.go @@ -20,7 +20,7 @@ type CloseEvent struct { type ScreenSizeEvent struct { Width int Height int - ActualScale int + ActualScale float64 } type RenderEvent struct { diff --git a/internal/ui/input_glfw.go b/internal/ui/input_glfw.go index f441940c9..8ca638349 100644 --- a/internal/ui/input_glfw.go +++ b/internal/ui/input_glfw.go @@ -20,8 +20,6 @@ package ui import ( - "math" - glfw "github.com/go-gl/glfw/v3.1/glfw" ) @@ -31,7 +29,7 @@ var glfwMouseButtonToMouseButton = map[glfw.MouseButton]MouseButton{ glfw.MouseButtonMiddle: MouseButtonMiddle, } -func (i *input) update(window *glfw.Window, scale int) error { +func (i *input) update(window *glfw.Window, scale float64) error { i.m.Lock() defer i.m.Unlock() @@ -42,8 +40,8 @@ func (i *input) update(window *glfw.Window, scale int) error { i.mouseButtonPressed[e] = window.GetMouseButton(g) == glfw.Press } x, y := window.GetCursorPos() - i.cursorX = int(math.Floor(x)) / scale - i.cursorY = int(math.Floor(y)) / scale + i.cursorX = int(x / scale) + i.cursorY = int(y / scale) for id := glfw.Joystick(0); id < glfw.Joystick(len(i.gamepads)); id++ { if !glfw.JoystickPresent(id) { continue diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 81e6b0b33..5f5af75b7 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -15,11 +15,11 @@ package ui type UserInterface interface { - Start(width, height, scale int, title string) error + Start(width, height int, scale float64, title string) error Update() (interface{}, error) SwapBuffers() error Terminate() error - ScreenScale() int + ScreenScale() float64 SetScreenSize(width, height int) bool - SetScreenScale(scale int) bool + SetScreenScale(scale float64) bool } diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index 29a37ea0e..f6d38eea1 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -32,9 +32,9 @@ type userInterface struct { window *glfw.Window width int height int - scale int + scale float64 deviceScale float64 - framebufferScale int + framebufferScale float64 context *opengl.Context funcs chan func() sizeChanged bool @@ -125,7 +125,7 @@ func (u *userInterface) SetScreenSize(width, height int) bool { return r } -func (u *userInterface) SetScreenScale(scale int) bool { +func (u *userInterface) SetScreenScale(scale float64) bool { r := false u.runOnMainThread(func() { r = u.setScreenSize(u.width, u.height, scale) @@ -133,22 +133,21 @@ func (u *userInterface) SetScreenScale(scale int) bool { return r } -func (u *userInterface) ScreenScale() int { - s := 0 +func (u *userInterface) ScreenScale() float64 { + s := 0.0 u.runOnMainThread(func() { s = u.scale }) return s } -func (u *userInterface) Start(width, height, scale int, title string) error { +func (u *userInterface) Start(width, height int, scale float64, title string) error { var err error u.runOnMainThread(func() { m := glfw.GetPrimaryMonitor() v := m.GetVideoMode() u.deviceScale = deviceScale() u.framebufferScale = 1 - if !u.setScreenSize(width, height, scale) { err = errors.New("ui: Fail to set the screen size") return @@ -156,18 +155,18 @@ func (u *userInterface) Start(width, height, scale int, title string) error { u.window.SetTitle(title) u.window.Show() - x := (v.Width - width*u.windowScale()) / 2 - y := (v.Height - height*u.windowScale()) / 3 + x := (v.Width - int(float64(width)*u.windowScale())) / 2 + y := (v.Height - int(float64(height)*u.windowScale())) / 3 u.window.SetPos(x, y) }) return err } -func (u *userInterface) windowScale() int { - return u.scale * int(u.deviceScale) +func (u *userInterface) windowScale() float64 { + return u.scale * u.deviceScale } -func (u *userInterface) actualScreenScale() int { +func (u *userInterface) actualScreenScale() float64 { return u.windowScale() * u.framebufferScale } @@ -260,7 +259,7 @@ func (u *userInterface) FinishRendering() error { return nil } -func (u *userInterface) setScreenSize(width, height, scale int) bool { +func (u *userInterface) setScreenSize(width, height int, scale float64) bool { if u.width == width && u.height == height && u.scale == scale { return false } @@ -273,7 +272,7 @@ func (u *userInterface) setScreenSize(width, height, scale int) bool { // To prevent hanging up, return asap if the width is too small. // 252 is an arbitrary number and I guess this is small enough. const minWindowWidth = 252 - if width*u.actualScreenScale() < minWindowWidth { + if int(float64(width)*u.actualScreenScale()) < minWindowWidth { u.scale = origScale return false } @@ -290,7 +289,7 @@ func (u *userInterface) setScreenSize(width, height, scale int) bool { window.SetFramebufferSizeCallback(nil) close(ch) }) - window.SetSize(width*u.windowScale(), height*u.windowScale()) + window.SetSize(int(float64(width)*u.windowScale()), int(float64(height)*u.windowScale())) event: for { @@ -303,7 +302,7 @@ event: } // This is usually 1, but sometimes more than 1 (e.g. Retina Mac) fw, _ := window.GetFramebufferSize() - u.framebufferScale = fw / width / u.windowScale() + u.framebufferScale = float64(fw) / float64(width) / u.windowScale() u.sizeChanged = true return true } diff --git a/internal/ui/ui_js.go b/internal/ui/ui_js.go index 91ce6ef8c..55bebd138 100644 --- a/internal/ui/ui_js.go +++ b/internal/ui/ui_js.go @@ -26,7 +26,7 @@ import ( var canvas *js.Object type userInterface struct { - scale int + scale float64 deviceScale float64 sizeChanged bool } @@ -66,17 +66,17 @@ func (u *userInterface) SetScreenSize(width, height int) bool { return u.setScreenSize(width, height, u.scale) } -func (u *userInterface) SetScreenScale(scale int) bool { +func (u *userInterface) SetScreenScale(scale float64) bool { width, height := u.size() return u.setScreenSize(width, height, scale) } -func (u *userInterface) ScreenScale() int { +func (u *userInterface) ScreenScale() float64 { return u.scale } -func (u *userInterface) ActualScreenScale() int { - return u.scale * int(u.deviceScale) +func (u *userInterface) ActualScreenScale() float64 { + return u.scale * u.deviceScale } func (u *userInterface) Update() (interface{}, error) { @@ -122,8 +122,8 @@ func touchEventToTouches(e *js.Object) []touch { for i := 0; i < len(t); i++ { jj := j.Call("item", i) t[i].id = jj.Get("identifier").Int() - t[i].x = (jj.Get("clientX").Int() - left) / scale - t[i].y = (jj.Get("clientY").Int() - top) / scale + t[i].x = int(float64(jj.Get("clientX").Int()-left) / scale) + t[i].y = int(float64(jj.Get("clientY").Int()-top) / scale) } return t } @@ -242,7 +242,7 @@ func setMouseCursorFromEvent(e *js.Object) { x, y := e.Get("clientX").Int(), e.Get("clientY").Int() x -= rect.Get("left").Int() y -= rect.Get("top").Int() - currentInput.setMouseCursor(x/scale, y/scale) + currentInput.setMouseCursor(int(float64(x)/scale), int(float64(y)/scale)) } func devicePixelRatio() float64 { @@ -258,7 +258,7 @@ func Main() error { return nil } -func (u *userInterface) Start(width, height, scale int, title string) error { +func (u *userInterface) Start(width, height int, scale float64, title string) error { doc := js.Global.Get("document") doc.Set("title", title) u.setScreenSize(width, height, scale) @@ -277,7 +277,7 @@ func (u *userInterface) size() (width, height int) { return } -func (u *userInterface) setScreenSize(width, height, scale int) bool { +func (u *userInterface) setScreenSize(width, height int, scale float64) bool { w, h := u.size() s := u.scale if w == width && h == height && s == scale { @@ -285,12 +285,12 @@ func (u *userInterface) setScreenSize(width, height, scale int) bool { } u.scale = scale u.deviceScale = devicePixelRatio() - canvas.Set("width", width*u.ActualScreenScale()) - canvas.Set("height", height*u.ActualScreenScale()) + canvas.Set("width", int(float64(width)*u.ActualScreenScale())) + canvas.Set("height", int(float64(height)*u.ActualScreenScale())) canvasStyle := canvas.Get("style") - cssWidth := width * scale - cssHeight := height * scale + cssWidth := int(float64(width) * scale) + cssHeight := int(float64(height) * scale) canvasStyle.Set("width", strconv.Itoa(cssWidth)+"px") canvasStyle.Set("height", strconv.Itoa(cssHeight)+"px") // CSS calc requires space chars. diff --git a/internal/ui/ui_mobile.go b/internal/ui/ui_mobile.go index f842456d5..802eeb48d 100644 --- a/internal/ui/ui_mobile.go +++ b/internal/ui/ui_mobile.go @@ -76,7 +76,7 @@ loop: type userInterface struct { width int height int - scale int + scale float64 sizeChanged bool } @@ -94,7 +94,7 @@ func CurrentUI() UserInterface { return currentUI } -func (u *userInterface) Start(width, height, scale int, title string) error { +func (u *userInterface) Start(width, height int, scale float64, title string) error { u.width = width u.height = height u.scale = scale @@ -135,17 +135,17 @@ func (u *userInterface) SetScreenSize(width, height int) bool { return false } -func (u *userInterface) SetScreenScale(scale int) bool { +func (u *userInterface) SetScreenScale(scale float64) bool { // TODO: Implement return false } -func (u *userInterface) ScreenScale() int { +func (u *userInterface) ScreenScale() float64 { return u.scale } -func (u *userInterface) actualScreenScale() int { - return u.scale * int(deviceScale()) +func (u *userInterface) actualScreenScale() float64 { + return u.scale * deviceScale() } func UpdateTouches(touches []Touch) { diff --git a/mobile/run.go b/mobile/run.go index e4cfbd52d..231380478 100644 --- a/mobile/run.go +++ b/mobile/run.go @@ -29,7 +29,7 @@ var chError <-chan error type EventDispatcher interface { SetScreenSize(width, height int) - SetScreenScale(scale int) + SetScreenScale(scale float64) Render() error UpdateTouchesOnAndroid(action int, id int, x, y int) UpdateTouchesOnIOS(phase int, ptr int, x, y int) @@ -38,7 +38,7 @@ type EventDispatcher interface { // Start starts the game and returns immediately. // // Different from ebiten.Run, this invokes only the game loop and not the main (UI) loop. -func Start(f func(*ebiten.Image) error, width, height, scale int, title string) (EventDispatcher, error) { +func Start(f func(*ebiten.Image) error, width, height int, scale float64, title string) (EventDispatcher, error) { chError = ebiten.RunWithoutMainLoop(f, width, height, scale, title) return &eventDispatcher{ touches: map[int]position{}, @@ -58,7 +58,7 @@ func (e *eventDispatcher) SetScreenSize(width, height int) { ui.CurrentUI().SetScreenSize(width, height) } -func (e *eventDispatcher) SetScreenScale(scale int) { +func (e *eventDispatcher) SetScreenScale(scale float64) { ui.CurrentUI().SetScreenScale(scale) } @@ -81,8 +81,8 @@ func (t touch) ID() int { func (t touch) Position() (int, int) { // TODO: Is this OK to adjust the position here? - return t.position.x / ui.CurrentUI().ScreenScale(), - t.position.y / ui.CurrentUI().ScreenScale() + return int(float64(t.position.x) / ui.CurrentUI().ScreenScale()), + int(float64(t.position.y) / ui.CurrentUI().ScreenScale()) } // UpdateTouchesOnAndroid updates the touch state on Android. diff --git a/run.go b/run.go index aad693bbb..4303aeb1d 100644 --- a/run.go +++ b/run.go @@ -53,7 +53,7 @@ func IsRunningSlowly() bool { // The given function f is guaranteed to be called 60 times a second // even if a rendering frame is skipped. // f is not called when the screen is not shown. -func Run(f func(*Image) error, width, height, scale int, title string) error { +func Run(f func(*Image) error, width, height int, scale float64, title string) error { ch := make(chan error) go func() { g := newGraphicsContext(f) @@ -68,7 +68,7 @@ func Run(f func(*Image) error, width, height, scale int, title string) error { // // Typically, Ebiten users don't have to call this directly. // Instead, functions in github.com/hajimehoshi/ebiten/mobile module call this. -func RunWithoutMainLoop(f func(*Image) error, width, height, scale int, title string) <-chan error { +func RunWithoutMainLoop(f func(*Image) error, width, height int, scale float64, title string) <-chan error { ch := make(chan error) go func() { g := newGraphicsContext(f) @@ -94,7 +94,7 @@ func SetScreenSize(width, height int) { // SetScreenScale changes the scale of the screen. // // This function is concurrent-safe. -func SetScreenScale(scale int) { +func SetScreenScale(scale float64) { if scale <= 0 { panic("ebiten: scale must be positive") } @@ -104,6 +104,6 @@ func SetScreenScale(scale int) { // ScreenScale returns the current screen scale. // // This function is concurrent-safe. -func ScreenScale() int { +func ScreenScale() float64 { return ui.CurrentUI().ScreenScale() }