better zoom and view

This commit is contained in:
visionmercer 2026-05-04 11:24:14 +02:00
commit 35deeaba29

View file

@ -21,6 +21,8 @@ end type
redim shared layers(3) as layertype
dim shared state as statetype
dim shared showtoolbox as _byte: showtoolbox=-1
dim shared showcolorpicker as _byte: showcolorpicker=-1
dim shared mouseclicked as integer
dim shared mousedown as integer
@ -89,8 +91,16 @@ do
' Zooming
if mw <> 0 then
state.zoom = state.zoom + (mw * 0.1)
if state.zoom < 0.1 then state.zoom = 0.1
' 1. Capture the current world position under the mouse
dim mouseWorldX as single: mouseWorldX = (_mousex - state.offsetX) / state.zoom
dim mouseWorldY as single: mouseWorldY = (_mousey - state.offsetY) / state.zoom
' 2. Calculate the new zoom level
state.zoom = state.zoom + (mw * 0.1 * state.zoom) ' Multiplier makes it feel smoother
if state.zoom < 0.05 then state.zoom = 0.05
if state.zoom > 20 then state.zoom = 20
' 3. Adjust offsets so the world position stays under the mouse
state.offsetX = _mousex - (mouseWorldX * state.zoom)
state.offsetY = _mousey - (mouseWorldY * state.zoom)
mw = 0
end if
@ -105,12 +115,19 @@ do
'TODO: save logic
case chr$(27)' esc
'TODO: main menu
case "h"
state.zoom = 1.0
state.offsetX = (_width / 2) - (_width(layers(0).ihandle) / 2)
state.offsetY = (_height / 2) - (_height(layers(0).ihandle) / 2)
case "t"
showtoolbox=not showtoolbox
case "c"
showcolorpicker=not showcolorpicker
end select
canvas
toolbox
colorpicker
if showtoolbox then toolbox
if showcolorpicker then colorpicker
_limit 30
_display
@ -155,26 +172,59 @@ sub colorpicker
end sub
sub canvas
dim boxX1 as integer: boxX1 = 70
dim boxWidth as integer: boxWidth = _width - 1 - boxX1
dim boxHeight as integer: boxHeight = _height - 20
static polypoints(200) as single
static pointCount as integer
' 1. Define the Viewport (The "Window" on your screen)
dim viewX1 as integer
if showtoolbox then viewX1 = 70 else viewX1 = 0
dim viewY1 as integer: viewY1 = 0
dim viewX2 as integer: viewX2 = _width - 1
dim viewY2 as integer
if showcolorpicker then viewY2 = _height - 20 else viewY2 = _height - 1
_dest 0
line (boxX1, 0)-(_width - 1, boxHeight), _rgb32(32), bf
' 2. Render Layers with Clipping
dim i as integer
for i = 0 to ubound(layers)
dim w as integer: w = _width(layers(i).ihandle) * state.zoom
dim h as integer: h = _height(layers(i).ihandle) * state.zoom
_putimage (state.offsetX, state.offsetY)-(state.offsetX + w, state.offsetY + h), layers(i).ihandle
dim img as long: img = layers(i).ihandle
dim imgW as integer: imgW = _width(img)
dim imgH as integer: imgH = _height(img)
' Current scaled dimensions
dim fullScaledW as single: fullScaledW = imgW * state.zoom
dim fullScaledH as single: fullScaledH = imgH * state.zoom
' Calculate visible area in screen coordinates (Overlap of image and viewport)
dim drawX1 as single: drawX1 = state.offsetX
dim drawY1 as single: drawY1 = state.offsetY
dim drawX2 as single: drawX2 = state.offsetX + fullScaledW
dim drawY2 as single: drawY2 = state.offsetY + fullScaledH
' Clip the destination to the Viewport
if drawX1 < viewX1 then drawX1 = viewX1
if drawY1 < viewY1 then drawY1 = viewY1
if drawX2 > viewX2 then drawX2 = viewX2
if drawY2 > viewY2 then drawY2 = viewY2
' Only draw if the image is actually inside the viewport
if drawX2 > drawX1 and drawY2 > drawY1 then
' Map screen-clipped coordinates back to the source image coordinates
dim srcX1 as single: srcX1 = (drawX1 - state.offsetX) / state.zoom
dim srcY1 as single: srcY1 = (drawY1 - state.offsetY) / state.zoom
dim srcX2 as single: srcX2 = (drawX2 - state.offsetX) / state.zoom
dim srcY2 as single: srcY2 = (drawY2 - state.offsetY) / state.zoom
' Syntax: _PUTIMAGE (destX1, destY1)-(destX2, destY2), sourceHandle, 0, (srcX1, srcY1)-(srcX2, srcY2)
_putimage (drawX1, drawY1)-(drawX2, drawY2), img, 0, (srcX1, srcY1)-(srcX2, srcY2)
end if
next
' 3. Calculate Canvas Coordinates
dim canX as integer: canX = (_mousex - state.offsetX) / state.zoom
dim canY as integer: canY = (_mousey - state.offsetY) / state.zoom
dim drawCol as _unsigned long
drawCol = state.fcolor
static drawCol
if _mousebutton(1) then drawCol = state.fcolor
if _mousebutton(2) then drawCol = state.bcolor
' 4. Interaction Logic
if _mousex > boxX1 then
@ -189,7 +239,9 @@ sub canvas
end if
_dest 0
_source 0
exit sub
end if
if state.tool = 7 or state.tool = 8 then
if mouseclicked then
polypoints(pointCount * 2) = canX
@ -211,7 +263,7 @@ sub canvas
cls , 0
select case state.tool
case 1 ' Pencil: This is the only tool that writes to Layer 1 IMMEDIATELY
case 1 ' Pencil
_dest layers(1).ihandle
thickline state.startX, state.startY, canX, canY, drawCol
state.startX = canX: state.startY = canY
@ -233,9 +285,9 @@ sub canvas
case 7, 8 ' Polygons
if pointCount > 0 then
for p = 1 to pointCount - 1
thickline polypoints((p - 1) * 2), polypoints((p - 1) * 2 + 1), polypoints(p * 2), polypoints(p * 2 + 1), drawCol
thickline polypoints((p - 1) * 2), polypoints((p - 1) * 2 + 1), polypoints(p * 2), polypoints(p * 2 + 1), state.fcolor
next p
thickline polypoints((pointCount - 1) * 2), polypoints((pointCount - 1) * 2 + 1), canX, canY, drawCol
thickline polypoints((pointCount - 1) * 2), polypoints((pointCount - 1) * 2 + 1), canX, canY, state.fcolor
end if
end select
@ -244,7 +296,7 @@ sub canvas
if state.tool = 7 or state.tool = 8 then
if rmouseclicked then commit = -1
else
if mousedown = 0 then commit = -1
if (mousedown=0) and (rmousedown=0) then commit = -1
end if
if commit then
@ -252,7 +304,7 @@ sub canvas
if (state.tool = 8 or state.tool=7) and pointCount > 2 then
redim finalP(pointCount * 2 - 1) as long
for p = 0 to (pointCount * 2) - 1: finalP(p) = polypoints(p): next
if state.tool =8 then filledPolygon finalP(), drawCol else Polygon finalP(), drawCol
if state.tool =8 then filledPolygon finalP(), state.fcolor else Polygon finalP(), state.fcolor
else
' Merge the preview into the drawing layer
_putimage , layers(2).ihandle, layers(1).ihandle
@ -264,7 +316,7 @@ sub canvas
end if
end if
end if
_dest 0 ' Ensure we return to main screen[cite: 1]
_dest 0 ' Ensure we return to main screen
end sub
function icon (index as long)
@ -311,6 +363,7 @@ end function
'$include: 'include/imgout.bm'
'$include: 'include/palette.bm'
'$include: 'include/tools.bm'
''$include: 'include/effects.bm'
function adduiicon(imagehandle as long)
dim unknown as long