From 0d6b42fedd21a7e36487e0fe44fea0f48f7a8ead Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 9 Nov 2022 01:07:03 +0900 Subject: [PATCH] internal/ui: refactoring: keep screen/offscreen sizes as float64 Updates #2285 --- gameforui.go | 36 ++++++++++++---------------- internal/ui/context.go | 54 ++++++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/gameforui.go b/gameforui.go index 710342dc0..c06705a43 100644 --- a/gameforui.go +++ b/gameforui.go @@ -125,8 +125,20 @@ func (g *gameForUI) NewScreenImage(width, height int) *ui.Image { return g.screen.image } -func (g *gameForUI) Layout(outsideWidth, outsideHeight int) (int, int) { - return g.game.Layout(outsideWidth, outsideHeight) +func (g *gameForUI) Layout(outsideWidth, outsideHeight float64) (float64, float64) { + // Even if the original value is less than 1, the value must be a positive integer (#2340). + // This is for a simple implementation of Layout, which returns the argument values without modifications. + // TODO: Remove this hack when Game.Layout takes floats instead of integers. + if outsideWidth < 1 { + outsideWidth = 1 + } + if outsideHeight < 1 { + outsideHeight = 1 + } + + // TODO: Add a new Layout function taking float values (#2285). + sw, sh := g.game.Layout(int(outsideWidth), int(outsideHeight)) + return float64(sw), float64(sh) } func (g *gameForUI) Update() error { @@ -147,8 +159,7 @@ func (g *gameForUI) DrawOffscreen() error { return nil } -func (g *gameForUI) DrawFinalScreen() { - scale, offsetX, offsetY := g.ScreenScaleAndOffsets() +func (g *gameForUI) DrawFinalScreen(scale, offsetX, offsetY float64) { var geoM GeoM geoM.Scale(scale, scale) geoM.Translate(offsetX, offsetY) @@ -176,20 +187,3 @@ func (g *gameForUI) DrawFinalScreen() { g.screen.DrawRectShader(w, h, g.screenShader, op) } } - -func (g *gameForUI) ScreenScaleAndOffsets() (scale, offsetX, offsetY float64) { - if g.screen == nil { - return - } - - sw, sh := g.screen.Size() - ow, oh := g.offscreen.Size() - scaleX := float64(sw) / float64(ow) - scaleY := float64(sh) / float64(oh) - scale = math.Min(scaleX, scaleY) - width := float64(ow) * scale - height := float64(oh) * scale - offsetX = (float64(sw) - width) / 2 - offsetY = (float64(sh) - height) / 2 - return -} diff --git a/internal/ui/context.go b/internal/ui/context.go index 54285a8ff..cfa3bf630 100644 --- a/internal/ui/context.go +++ b/internal/ui/context.go @@ -35,11 +35,10 @@ var ( type Game interface { NewOffscreenImage(width, height int) *Image NewScreenImage(width, height int) *Image - Layout(outsideWidth, outsideHeight int) (int, int) + Layout(outsideWidth, outsideHeight float64) (screenWidth, screenHeight float64) Update() error DrawOffscreen() error - DrawFinalScreen() - ScreenScaleAndOffsets() (scale, offsetX, offsetY float64) + DrawFinalScreen(scale, offsetX, offsetY float64) } type context struct { @@ -50,9 +49,10 @@ type context struct { offscreen *Image screen *Image - // The following members must be protected by the mutex m. - outsideWidth float64 - outsideHeight float64 + screenWidth float64 + screenHeight float64 + offscreenWidth float64 + offscreenHeight float64 isOffscreenDirty bool @@ -190,7 +190,7 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics, forceDraw boo c.screen.clear() } - c.game.DrawFinalScreen() + c.game.DrawFinalScreen(c.screenScaleAndOffsets()) // The final screen is never used as the rendering source. // Flush its buffer here just in case. @@ -201,24 +201,21 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics, forceDraw boo } func (c *context) layoutGame(outsideWidth, outsideHeight float64, deviceScaleFactor float64) (int, int) { - c.outsideWidth = outsideWidth - c.outsideHeight = outsideHeight - - // Adjust the outside size to integer values. - // Even if the original value is less than 1, the value must be a positive integer (#2340). - iow, ioh := int(outsideWidth), int(outsideHeight) - if iow == 0 { - iow = 1 - } - if ioh == 0 { - ioh = 1 - } - ow, oh := c.game.Layout(iow, ioh) - if ow <= 0 || oh <= 0 { + owf, ohf := c.game.Layout(outsideWidth, outsideHeight) + if owf <= 0 || ohf <= 0 { panic("ui: Layout must return positive numbers") } - sw, sh := int(outsideWidth*deviceScaleFactor), int(outsideHeight*deviceScaleFactor) + c.screenWidth = outsideWidth * deviceScaleFactor + c.screenHeight = outsideHeight * deviceScaleFactor + c.offscreenWidth = owf + c.offscreenHeight = ohf + + sw := int(math.Ceil(c.screenWidth)) + sh := int(math.Ceil(c.screenHeight)) + ow := int(math.Ceil(c.offscreenWidth)) + oh := int(math.Ceil(c.offscreenHeight)) + if c.screen != nil { if c.screen.width != sw || c.screen.height != sh { c.screen.MarkDisposed() @@ -246,7 +243,7 @@ func (c *context) layoutGame(outsideWidth, outsideHeight float64, deviceScaleFac } func (c *context) adjustPosition(x, y float64, deviceScaleFactor float64) (float64, float64) { - s, ox, oy := c.game.ScreenScaleAndOffsets() + s, ox, oy := c.screenScaleAndOffsets() // The scale 0 indicates that the screen is not initialized yet. // As any cursor values don't make sense, just return NaN. if s == 0 { @@ -254,3 +251,14 @@ func (c *context) adjustPosition(x, y float64, deviceScaleFactor float64) (float } return (x*deviceScaleFactor - ox) / s, (y*deviceScaleFactor - oy) / s } + +func (c *context) screenScaleAndOffsets() (scale, offsetX, offsetY float64) { + scaleX := c.screenWidth / c.offscreenWidth + scaleY := c.screenHeight / c.offscreenHeight + scale = math.Min(scaleX, scaleY) + width := c.offscreenWidth * scale + height := c.offscreenHeight * scale + offsetX = (c.screenWidth - width) / 2 + offsetY = (c.screenHeight - height) / 2 + return +}