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.
This commit is contained in:
Noah 2021-07-11 21:54:28 -07:00
parent 456863839e
commit ed492a4451
7 changed files with 121 additions and 61 deletions

View File

@ -15,6 +15,19 @@ var (
Stroke: render.SkyBlue, Stroke: render.SkyBlue,
Shadow: render.Black, 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. // Window and panel styles.
TitleConfig = ui.Config{ TitleConfig = ui.Config{

View File

@ -7,6 +7,7 @@ const (
Version = "0.7.1" Version = "0.7.1"
Website = "https://www.sketchymaze.com" Website = "https://www.sketchymaze.com"
Copyright = "2021 Noah Petherbridge" Copyright = "2021 Noah Petherbridge"
Byline = "a game by Noah Petherbridge."
// Update check URL // Update check URL
UpdateCheckJSON = "https://download.sketchymaze.com/version.json" UpdateCheckJSON = "https://download.sketchymaze.com/version.json"

View File

@ -29,6 +29,7 @@ type MainScene struct {
// UI components. // UI components.
labelTitle *ui.Label labelTitle *ui.Label
labelSubtitle *ui.Label
labelVersion *ui.Label labelVersion *ui.Label
labelHint *ui.Label labelHint *ui.Label
frame *ui.Frame // Main button frame frame *ui.Frame // Main button frame
@ -66,6 +67,13 @@ func (s *MainScene) Setup(d *Doodle) error {
}) })
s.labelTitle.Compute(d.Engine) 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. // Version label.
var shareware string var shareware string
if !license.IsRegistered() { if !license.IsRegistered() {
@ -73,11 +81,7 @@ func (s *MainScene) Setup(d *Doodle) error {
} }
ver := ui.NewLabel(ui.Label{ ver := ui.NewLabel(ui.Label{
Text: fmt.Sprintf("v%s%s", branding.Version, shareware), Text: fmt.Sprintf("v%s%s", branding.Version, shareware),
Font: render.Text{ Font: balance.TitleScreenVersionFont,
Size: 18,
Color: render.Grey,
Shadow: render.Black,
},
}) })
ver.Compute(d.Engine) ver.Compute(d.Engine)
s.labelVersion = ver s.labelVersion = ver
@ -372,10 +376,17 @@ func (s *MainScene) Draw(d *Doodle) error {
}) })
s.labelTitle.Present(d.Engine, s.labelTitle.Point()) 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 // Version label
s.labelVersion.MoveTo(render.Point{ s.labelVersion.MoveTo(render.Point{
X: (d.width / 2) - (s.labelVersion.Size().W / 2), 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()) s.labelVersion.Present(d.Engine, s.labelVersion.Point())

View File

@ -29,8 +29,7 @@ func (w *Canvas) commitStroke(tool drawtool.Tool, addHistory bool) {
} }
// Zoom the stroke coordinates (this modifies the pointer) // Zoom the stroke coordinates (this modifies the pointer)
zStroke := w.ZoomStroke(w.currentStroke) w.currentStroke = w.ZoomStroke(w.currentStroke)
_ = zStroke
// Mark the canvas as modified. // Mark the canvas as modified.
w.modified = true w.modified = true

View File

@ -15,6 +15,11 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
var ( var (
S = w.Size() S = w.Size()
Viewport = w.Viewport() 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.MoveTo(p) // TODO: when uncommented the canvas will creep down the Workspace frame in EditorMode
w.DrawBox(e, p) w.DrawBox(e, p)
@ -44,7 +49,11 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
} }
// Zoom in the texture. // Zoom in the texture.
texSize := tex.Size() var (
texSize = tex.Size()
texSizeOrig = tex.Size()
)
if w.Zoom != 0 { if w.Zoom != 0 {
texSize.W = w.ZoomMultiply(texSize.W) texSize.W = w.ZoomMultiply(texSize.W)
texSize.H = w.ZoomMultiply(texSize.H) texSize.H = w.ZoomMultiply(texSize.H)
@ -66,8 +75,8 @@ func (w *Canvas) Present(e render.Engine, p render.Point) {
} }
dst := render.Rect{ dst := render.Rect{
X: p.X + w.Scroll.X + w.BoxThickness(1) + (coord.X * 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) + (coord.Y * 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 // 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 // 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, 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 // TODO: all this shit is in TrimBox(), make it DRY
// If the destination width will cause it to overflow the widget // 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) 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) e.Copy(tex, src, dst)
} }
} }

View File

@ -77,6 +77,7 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error {
wp = w.wallpaper wp = w.wallpaper
S = w.Size() S = w.Size()
size = wp.corner.Size() size = wp.corner.Size()
sizeOrig = wp.corner.Size()
// Get the relative viewport of world coordinates looked at by the canvas. // Get the relative viewport of world coordinates looked at by the canvas.
// The X,Y values are the negative Scroll value // 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, 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 // Trim the edges of the destination box, like in canvas.go#Present
render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) 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) e.Copy(wp.repeat, src, dst)
} }
} }
@ -216,12 +220,10 @@ func (w *Canvas) PresentWallpaper(e render.Engine, p render.Point) error {
H: src.H, H: src.H,
} }
// Zoom the output texture. // Zoom-out min size constraint.
if w.Zoom != 0 { if w.Zoom < 0 {
// dst.X = w.ZoomMultiply(dst.X - origin.X) src.W = sizeOrig.W
// dst.Y = w.ZoomMultiply(dst.Y - origin.Y) src.H = sizeOrig.H
// dst.W = w.ZoomMultiply(dst.W)
// dst.H = w.ZoomMultiply(dst.H)
} }
render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) 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, H: src.H,
} }
// Zoom the output texture. // Zoom-out min size constraint.
if w.Zoom != 0 { if w.Zoom < 0 {
// dst.X = w.ZoomMultiply(dst.X - origin.X) src.W = sizeOrig.W
// dst.Y = w.ZoomMultiply(dst.Y - origin.Y) src.H = sizeOrig.H
// dst.W = w.ZoomMultiply(dst.W)
// dst.H = w.ZoomMultiply(dst.H)
} }
render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) 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, H: src.H,
} }
// Zoom the output texture. // Zoom out min size constraint.
if w.Zoom != 0 { if w.Zoom < 0 {
// dst.X = w.ZoomMultiply(dst.X - origin.X) src.W = sizeOrig.W
// dst.Y = w.ZoomMultiply(dst.Y - origin.Y) src.H = sizeOrig.H
// dst.W = w.ZoomMultiply(dst.W)
// dst.H = w.ZoomMultiply(dst.H)
} }
render.TrimBox(&src, &dst, p, S, w.BoxThickness(1)) render.TrimBox(&src, &dst, p, S, w.BoxThickness(1))

View File

@ -60,13 +60,37 @@ func (w *Canvas) ZoomMultiply(value int) int {
return int(float64(value) * w.GetZoomMultiplier()) 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. ZoomStroke adjusts a drawn stroke on the canvas to account for the zoom level.
Returns a copy Stroke value without changing the original. Returns a copy Stroke value without changing the original.
*/ */
func (w *Canvas) ZoomStroke(stroke *drawtool.Stroke) drawtool.Stroke { func (w *Canvas) ZoomStroke(stroke *drawtool.Stroke) *drawtool.Stroke {
copy := drawtool.Stroke{ copy := &drawtool.Stroke{
ID: stroke.ID, ID: stroke.ID,
Shape: stroke.Shape, Shape: stroke.Shape,
Color: stroke.Color, 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 // Multiply all coordinates in this stroke, which should be World
// Coordinates in the level data, by the zoom multiplier. // Coordinates in the level data, by the zoom multiplier.
adjust := func(p render.Point) render.Point { adjust := func(p render.Point) render.Point {
p.X = w.ZoomMultiply(p.X) p.X = w.ZoomDivide(p.X)
p.Y = w.ZoomMultiply(p.Y) p.Y = w.ZoomDivide(p.Y)
return p return p
} }