From ed492a445188adb82346bada626b2ababefe9022 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Sun, 11 Jul 2021 21:54:28 -0700 Subject: [PATCH] Progress on the Zoom In/Out Feature * Got the level chunks AND the wallpaper to both scale UP and DOWN consistently together. * Trying to draw new pixels while zoomed in/out ends up offsetting the pixels by 2X still. Still seems an issue between screen coordinates and world coordinates. Zoom in 2X and try and draw a line 64px from the corners of the screen? The committed line appropriately lands at the 64px coord on the level data but, zoomed in, it appears 2X to the right on the screen from where I dropped the cursor! * When zooming OUT, the limit on number of chunks the viewport will try and render is not increased, leaving dead space in the screen; more chunks should render when there's room. --- pkg/balance/theme.go | 13 +++++++++ pkg/branding/branding.go | 1 + pkg/main_scene.go | 37 +++++++++++++++--------- pkg/uix/canvas_editable.go | 3 +- pkg/uix/canvas_present.go | 40 +++++++++++++++++--------- pkg/uix/canvas_wallpaper.go | 56 ++++++++++++++++++------------------- pkg/uix/canvas_zoom.go | 32 ++++++++++++++++++--- 7 files changed, 121 insertions(+), 61 deletions(-) diff --git a/pkg/balance/theme.go b/pkg/balance/theme.go index a167a25..be0ae22 100644 --- a/pkg/balance/theme.go +++ b/pkg/balance/theme.go @@ -15,6 +15,19 @@ var ( Stroke: render.SkyBlue, Shadow: render.Black, } + TitleScreenSubtitleFont = render.Text{ + FontFilename: "DejaVuSans.ttf", + Size: 18, + Color: render.SkyBlue, + Shadow: render.SkyBlue.Darken(128), + // Color: render.RGBA(255, 153, 0, 255), + // Shadow: render.RGBA(200, 80, 0, 255), + } + TitleScreenVersionFont = render.Text{ + Size: 14, + Color: render.Grey, + Shadow: render.Black, + } // Window and panel styles. TitleConfig = ui.Config{ diff --git a/pkg/branding/branding.go b/pkg/branding/branding.go index 8fe8f73..62d8495 100644 --- a/pkg/branding/branding.go +++ b/pkg/branding/branding.go @@ -7,6 +7,7 @@ const ( Version = "0.7.1" Website = "https://www.sketchymaze.com" Copyright = "2021 Noah Petherbridge" + Byline = "a game by Noah Petherbridge." // Update check URL UpdateCheckJSON = "https://download.sketchymaze.com/version.json" diff --git a/pkg/main_scene.go b/pkg/main_scene.go index 04ea028..fca4bc3 100644 --- a/pkg/main_scene.go +++ b/pkg/main_scene.go @@ -28,13 +28,14 @@ type MainScene struct { canvas *uix.Canvas // UI components. - labelTitle *ui.Label - labelVersion *ui.Label - labelHint *ui.Label - frame *ui.Frame // Main button frame - btnRegister *ui.Button - winRegister *ui.Window - winSettings *ui.Window + labelTitle *ui.Label + labelSubtitle *ui.Label + labelVersion *ui.Label + labelHint *ui.Label + frame *ui.Frame // Main button frame + btnRegister *ui.Button + winRegister *ui.Window + winSettings *ui.Window // Update check variables. updateButton *ui.Button @@ -66,6 +67,13 @@ func (s *MainScene) Setup(d *Doodle) error { }) s.labelTitle.Compute(d.Engine) + // Subtitle/byline. + s.labelSubtitle = ui.NewLabel(ui.Label{ + Text: branding.Byline, + Font: balance.TitleScreenSubtitleFont, + }) + s.labelSubtitle.Compute(d.Engine) + // Version label. var shareware string if !license.IsRegistered() { @@ -73,11 +81,7 @@ func (s *MainScene) Setup(d *Doodle) error { } ver := ui.NewLabel(ui.Label{ Text: fmt.Sprintf("v%s%s", branding.Version, shareware), - Font: render.Text{ - Size: 18, - Color: render.Grey, - Shadow: render.Black, - }, + Font: balance.TitleScreenVersionFont, }) ver.Compute(d.Engine) s.labelVersion = ver @@ -372,10 +376,17 @@ func (s *MainScene) Draw(d *Doodle) error { }) s.labelTitle.Present(d.Engine, s.labelTitle.Point()) + // App subtitle label (byline). + s.labelSubtitle.MoveTo(render.Point{ + X: (d.width / 2) - (s.labelSubtitle.Size().W / 2), + Y: s.labelTitle.Point().Y + s.labelTitle.Size().H + 8, + }) + s.labelSubtitle.Present(d.Engine, s.labelSubtitle.Point()) + // Version label s.labelVersion.MoveTo(render.Point{ X: (d.width / 2) - (s.labelVersion.Size().W / 2), - Y: s.labelTitle.Point().Y + s.labelTitle.Size().H + 8, + Y: s.labelSubtitle.Point().Y + s.labelSubtitle.Size().H + 8, }) s.labelVersion.Present(d.Engine, s.labelVersion.Point()) diff --git a/pkg/uix/canvas_editable.go b/pkg/uix/canvas_editable.go index f09e290..cc486e8 100644 --- a/pkg/uix/canvas_editable.go +++ b/pkg/uix/canvas_editable.go @@ -29,8 +29,7 @@ func (w *Canvas) commitStroke(tool drawtool.Tool, addHistory bool) { } // Zoom the stroke coordinates (this modifies the pointer) - zStroke := w.ZoomStroke(w.currentStroke) - _ = zStroke + w.currentStroke = w.ZoomStroke(w.currentStroke) // Mark the canvas as modified. w.modified = true diff --git a/pkg/uix/canvas_present.go b/pkg/uix/canvas_present.go index 741e7af..fb120b1 100644 --- a/pkg/uix/canvas_present.go +++ b/pkg/uix/canvas_present.go @@ -15,6 +15,11 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { var ( S = w.Size() Viewport = w.Viewport() + // Bezel = render.NewRect( + // p.X+w.Scroll.X+w.BoxThickness(1), + // p.Y+w.Scroll.Y+w.BoxThickness(1), + // ) + // zoomMultiplier = int(w.GetZoomMultiplier()) ) // w.MoveTo(p) // TODO: when uncommented the canvas will creep down the Workspace frame in EditorMode w.DrawBox(e, p) @@ -44,7 +49,11 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { } // Zoom in the texture. - texSize := tex.Size() + var ( + texSize = tex.Size() + texSizeOrig = tex.Size() + ) + if w.Zoom != 0 { texSize.W = w.ZoomMultiply(texSize.W) texSize.H = w.ZoomMultiply(texSize.H) @@ -66,8 +75,8 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { } dst := render.Rect{ - X: p.X + w.Scroll.X + w.BoxThickness(1) + (coord.X * chunk.Size), - Y: p.Y + w.Scroll.Y + w.BoxThickness(1) + (coord.Y * chunk.Size), + X: p.X + w.Scroll.X + w.BoxThickness(1) + w.ZoomMultiply(coord.X*chunk.Size), + Y: p.Y + w.Scroll.Y + w.BoxThickness(1) + w.ZoomMultiply(coord.Y*chunk.Size), // src.W and src.H will be AT MOST the full width and height of // a Canvas widget. Subtract the scroll offset to keep it bounded @@ -76,16 +85,6 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { H: src.H, } - // Zoom the destination rect. - if w.Zoom != 0 { - // dst.X += int(w.GetZoomMultiplier()) - // dst.Y += int(w.GetZoomMultiplier()) - // dst.X = w.ZoomMultiply(dst.X) - // dst.Y = w.ZoomMultiply(dst.Y) - // dst.W = w.ZoomMultiply(dst.W) - // dst.H = w.ZoomMultiply(dst.H) - } - // TODO: all this shit is in TrimBox(), make it DRY // If the destination width will cause it to overflow the widget @@ -144,6 +143,21 @@ func (w *Canvas) Present(e render.Engine, p render.Point) { dst.W = S.W - w.BoxThickness(1) } + if w.Zoom < 0 { + log.Warn("dst: %+v", dst) + } + + // When zooming OUT, make sure the source rect is at least the + // full size of the chunk texture; otherwise the ZoomMultiplies + // above do correctly scale e.g. 128x128 to 64x64, but it only + // samples the top-left 64x64 then and not the full texture so + // it more crops it than scales it, but does fit it neatly with + // its neighbors. + if w.Zoom < 0 { + src.W = texSizeOrig.W + src.H = texSizeOrig.H + } + e.Copy(tex, src, dst) } } diff --git a/pkg/uix/canvas_wallpaper.go b/pkg/uix/canvas_wallpaper.go index 561797d..0115dde 100644 --- a/pkg/uix/canvas_wallpaper.go +++ b/pkg/uix/canvas_wallpaper.go @@ -74,9 +74,10 @@ func (w *Canvas) loopContainActorsInsideLevel(a *Actor) { // top-left corner of the Canvas widget relative to the application window. func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error { var ( - wp = w.wallpaper - S = w.Size() - size = wp.corner.Size() + wp = w.wallpaper + S = w.Size() + size = wp.corner.Size() + sizeOrig = wp.corner.Size() // Get the relative viewport of world coordinates looked at by the canvas. // The X,Y values are the negative Scroll value @@ -187,17 +188,20 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error { H: src.H, } - // Zoom the output texture. - if w.Zoom != 0 { - // dst.X = w.ZoomMultiply(dst.X - p.X) - // dst.Y = w.ZoomMultiply(dst.Y - p.Y) - // dst.W = w.ZoomMultiply(dst.W) - // dst.H = w.ZoomMultiply(dst.H) - } - // Trim the edges of the destination box, like in canvas.go#Present render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) + // When zooming OUT, make sure the source rect is at least the + // full size of the chunk texture; otherwise the ZoomMultiplies + // above do correctly scale e.g. 128x128 to 64x64, but it only + // samples the top-left 64x64 then and not the full texture so + // it more crops it than scales it, but does fit it neatly with + // its neighbors. + if w.Zoom < 0 { + src.W = sizeOrig.W + src.H = sizeOrig.H + } + e.Copy(wp.repeat, src, dst) } } @@ -216,12 +220,10 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error { H: src.H, } - // Zoom the output texture. - if w.Zoom != 0 { - // dst.X = w.ZoomMultiply(dst.X - origin.X) - // dst.Y = w.ZoomMultiply(dst.Y - origin.Y) - // dst.W = w.ZoomMultiply(dst.W) - // dst.H = w.ZoomMultiply(dst.H) + // Zoom-out min size constraint. + if w.Zoom < 0 { + src.W = sizeOrig.W + src.H = sizeOrig.H } render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) @@ -241,12 +243,10 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error { H: src.H, } - // Zoom the output texture. - if w.Zoom != 0 { - // dst.X = w.ZoomMultiply(dst.X - origin.X) - // dst.Y = w.ZoomMultiply(dst.Y - origin.Y) - // dst.W = w.ZoomMultiply(dst.W) - // dst.H = w.ZoomMultiply(dst.H) + // Zoom-out min size constraint. + if w.Zoom < 0 { + src.W = sizeOrig.W + src.H = sizeOrig.H } render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) @@ -266,12 +266,10 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error { H: src.H, } - // Zoom the output texture. - if w.Zoom != 0 { - // dst.X = w.ZoomMultiply(dst.X - origin.X) - // dst.Y = w.ZoomMultiply(dst.Y - origin.Y) - // dst.W = w.ZoomMultiply(dst.W) - // dst.H = w.ZoomMultiply(dst.H) + // Zoom out min size constraint. + if w.Zoom < 0 { + src.W = sizeOrig.W + src.H = sizeOrig.H } render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) diff --git a/pkg/uix/canvas_zoom.go b/pkg/uix/canvas_zoom.go index ab2d731..574057b 100644 --- a/pkg/uix/canvas_zoom.go +++ b/pkg/uix/canvas_zoom.go @@ -60,13 +60,37 @@ func (w *Canvas) ZoomMultiply(value int) int { return int(float64(value) * w.GetZoomMultiplier()) } +/* +ZoomDivide divides an integer by the zoom inversely. +*/ +func (w *Canvas) ZoomDivide(value int) int { + var divider float64 + switch w.Zoom { + case -2: + divider = 2 + case -1: + divider = 2 + case 0: + divider = 1 + case 1: + divider = 0.5 + case 2: + divider = 0.25 + case 3: + divider = 0.125 + default: + divider = 1 + } + return int(float64(value) * divider) +} + /* ZoomStroke adjusts a drawn stroke on the canvas to account for the zoom level. Returns a copy Stroke value without changing the original. */ -func (w *Canvas) ZoomStroke(stroke *drawtool.Stroke) drawtool.Stroke { - copy := drawtool.Stroke{ +func (w *Canvas) ZoomStroke(stroke *drawtool.Stroke) *drawtool.Stroke { + copy := &drawtool.Stroke{ ID: stroke.ID, Shape: stroke.Shape, Color: stroke.Color, @@ -82,8 +106,8 @@ func (w *Canvas) ZoomStroke(stroke *drawtool.Stroke) drawtool.Stroke { // Multiply all coordinates in this stroke, which should be World // Coordinates in the level data, by the zoom multiplier. adjust := func(p render.Point) render.Point { - p.X = w.ZoomMultiply(p.X) - p.Y = w.ZoomMultiply(p.Y) + p.X = w.ZoomDivide(p.X) + p.Y = w.ZoomDivide(p.Y) return p }