doodle/pkg/uix/canvas_zoom.go
Noah Petherbridge ed492a4451 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.
2021-07-11 21:54:28 -07:00

122 lines
2.4 KiB
Go

package uix
import (
"git.kirsle.net/apps/doodle/pkg/drawtool"
"git.kirsle.net/go/render"
)
// Functions related to the Zoom Tool to magnify the size of the canvas.
/*
GetZoomMultiplier parses the .Zoom integer and returns a multiplier.
Examples:
Zoom = 0: neutral (100% scale, 1x)
Zoom = 1: 2x zoom
Zoom = 2: 4x zoom
Zoom = 3: 8x zoom
Zoom = -1: 0.5x zoom
Zoom = -2: 0.25x zoom
*/
func (w *Canvas) GetZoomMultiplier() float64 {
// Get and bounds cap the zoom setting.
if w.Zoom < -2 {
w.Zoom = -2
} else if w.Zoom > 3 {
w.Zoom = 3
}
// Return the multipliers.
switch w.Zoom {
case -2:
return 0.25
case -1:
return 0.5
case 0:
return 1
case 1:
return 1.5
case 2:
return 2
case 3:
return 2.5
default:
return 1
}
}
/*
ZoomMultiply multiplies a width or height value by the Zoom Multiplier and
returns the modified integer.
Usage is like:
// when building a render.Rect destination box.
dest.W *= ZoomMultiply(dest.W)
dest.H *= ZoomMultiply(dest.H)
*/
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{
ID: stroke.ID,
Shape: stroke.Shape,
Color: stroke.Color,
Thickness: stroke.Thickness,
ExtraData: stroke.ExtraData,
PointA: stroke.PointA,
PointB: stroke.PointB,
Points: stroke.Points,
OriginalPoints: stroke.OriginalPoints,
}
return copy
// 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.ZoomDivide(p.X)
p.Y = w.ZoomDivide(p.Y)
return p
}
copy.PointA = adjust(copy.PointA)
copy.PointB = adjust(copy.PointB)
for i := range copy.Points {
copy.Points[i] = adjust(copy.Points[i])
}
return copy
}