fix jitter and mouse cursor accuracy

This commit is contained in:
visionmercer 2026-05-27 11:03:51 +02:00
commit e3054bdb79
3 changed files with 257 additions and 300 deletions

View file

@ -4,7 +4,7 @@ type statetype
bcolor as long
offsetx as long
offsety as long
zoom as single
zoom as long
brushsize as integer
startx as long
starty as long
@ -55,7 +55,7 @@ for y=0 to _height-16 step 16
next
_dest 0
state.tool=1
state.zoom=1.0
state.zoom=1
state.offsetx=70+20
state.offsety=20
state. brushsize=1
@ -66,8 +66,8 @@ addcommand"bcolor ("+hex$(state.bcolor)+")"
dim lastmx,lastmy
dim keyin as string
dim mouseworldy as integer
dim mouseworldx as integer
dim mouseworldy as long
dim mouseworldx as long
dim diffx as integer
dim diffy as integer
@ -76,6 +76,7 @@ dim oldheight as integer
oldwidth=_width
oldheight=_height
do
' 1. Check for window resizing first
if checkresize(_source)=-1 then
diffx=_width-oldwidth
diffy=_height-oldheight
@ -85,12 +86,10 @@ do
oldheight=_height
end if
canvas
if showtoolbox then toolbox
if showcolorpicker then colorpicker
if showcommands then commandlist
' 2. Clear the screen BEFORE drawing anything for this frame
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
'Mouse Handling
' 3. Process all inputs and update offsets FIRST
while _mouseinput:mw=mw+_mousewheel:wend
mouseclicked=0
rmouseclicked=0
@ -101,63 +100,43 @@ do
' Panning (Middle Mouse)
if _mousebutton(3) then
state.offsetx=int(state.offsetx+(_mousex-lastmx))
state.offsety=int(state.offsety+(_mousey-lastmy))
state.offsetx=state.offsetx+(_mousex-lastmx)
state.offsety=state.offsety+(_mousey-lastmy)
end if
lastmx=_mousex:lastmy=_mousey
' Zooming
if mw<>0 then
' 1. Capture current world position
mouseworldx=(_mousex-state.offsetx)/state.zoom
mouseworldy=(_mousey-state.offsety)/state.zoom
' 2. Calculate the new zoom level (Snap to whole numbers)
if mw>0 then
state.zoom=state.zoom+1
else
state.zoom=state.zoom-1
end if
' 3. Constrain zoom (Min 1, Max 20)
if mw>0 then state.zoom=state.zoom+1 else state.zoom=state.zoom-1
if state.zoom<1 then state.zoom=1
if state.zoom>20 then state.zoom=20
' 4. Adjust offsets
state.offsetx=_mousex-(mouseworldx*state.zoom)
state.offsety=_mousey-(mouseworldy*state.zoom)
mw=0
end if
' Keyboarding
keyin=inkey$
select case keyin
case "+"
state.brushsize=state.brushsize+1
addcommand"brushsize ("+tst(state.brushsize)+")"
case "-"
if state.brushsize>1 then state.brushsize=state.brushsize-1
addcommand"brushsize ("+tst(state.brushsize)+")"
case chr$(19) ' ctrl+s
'TODO: save logic
case chr$(27) ' esc
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
case "l"
showcommands=not showcommands
case "+": state.brushsize=state.brushsize+1: addcommand"brushsize ("+tst(state.brushsize)+")"
case "-": if state.brushsize>1 then state.brushsize=state.brushsize-1: addcommand"brushsize ("+tst(state.brushsize)+")"
case "h": state.zoom=1: 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
case "l": showcommands=not showcommands
end select
' 4. Draw everything using the freshly updated math
canvas
if showtoolbox then toolbox
if showcolorpicker then colorpicker
if showcommands then commandlist
' 5. Flip the buffer to the monitor cleanly
_limit 30
_display
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
loop
sub commandlist
@ -366,50 +345,30 @@ sub canvas
if showcolorpicker then viewy2=_height-20 else viewy2=_height-1
_dest 0
' 2. Render Layers with Clipping
dim srcx1 as long
dim srcy1 as long
dim srcx2 as long
dim srcy2 as long
dim drawx1 as long
dim drawy1 as long
dim drawx2 as long
dim drawy2 as long
dim i as integer
for i=0 to ubound(layers)
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)
drawx1=state.offsetx
drawy1=state.offsety
drawx2=state.offsetx+fullscaledw
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
srcx1=int((drawx1-state.offsetx)/state.zoom)
srcy1=int((drawy1-state.offsety)/state.zoom)
srcx2=int((drawx2-state.offsetx)/state.zoom)
srcy2=int((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
' 2. Render Layers (Let QB64 handle the viewport clipping natively)
dim i as integer
for i = 0 to ubound(layers)
dim img as long: img = layers(i).ihandle
dim imgw as integer: imgw = _width(img)
dim imgh as integer: imgh = _height(img)
' Calculate the absolute unclipped destination positions
drawx1 = state.offsetx
drawy1 = state.offsety
drawx2 = state.offsetx + (imgw * state.zoom)
drawy2 = state.offsety + (imgh * state.zoom)
' Direct 1:1 mapping of the entire source asset
srcx1 = 0
srcy1 = 0
srcx2 = imgw
srcy2 = imgh
' Only draw if the asset is within the general view window range
if drawx2 > viewx1 and drawx1 < viewx2 and drawy2 > viewy1 and drawy1 < viewy2 then
_putimage (drawx1, drawy1)-(drawx2, drawy2), img, 0, (srcx1, srcy1)-(srcx2, srcy2)
end if
next
_dest layers(2).ihandle:cls,0:_dest 0
' 2.5 if the mouse is in ui thats all we need
if showtoolbox then
@ -428,12 +387,14 @@ sub canvas
end if
end if
' 3. Calculate Canvas Coordinates
' 3. Calculate Canvas Coordinates (Center-aligned to the zoom block)
dim canx as long
dim cany as long
canx=int((_mousex-state.offsetx)/state.zoom)
cany=int((_mousey-state.offsety)/state.zoom)
' Add half a zoomed pixel block to align the mouse tip to the block center
canx = int((_mousex - state.offsetx + (state.zoom \ 2)) / state.zoom)
cany = int((_mousey - state.offsety + (state.zoom \ 2)) / state.zoom)
static drawcol
if _mousebutton(1) then drawcol=state.fcolor
if _mousebutton(2) then drawcol=state.bcolor