pixler/pixler.bas

661 lines
22 KiB
QBasic
Raw Normal View History

2026-04-29 09:28:35 +02:00
type statetype
tool as long
fcolor as long
bcolor as long
2026-05-04 11:51:47 +02:00
offsetX as long
offsetY as long
2026-04-30 10:09:05 +02:00
zoom as single
2026-04-30 13:16:00 +02:00
brushsize as integer
2026-05-11 10:29:29 +02:00
startX as long
startY as long
2026-04-30 13:16:00 +02:00
isDrawing as integer
2026-04-29 09:28:35 +02:00
end type
type layertype
ihandle as long
blendmode as long
filter as long
2026-04-29 12:36:31 +02:00
kind as long
2026-04-29 09:28:35 +02:00
end type
2026-05-01 00:30:34 +02:00
redim shared layers(3) as layertype
2026-04-29 09:28:35 +02:00
dim shared state as statetype
2026-05-06 13:28:56 +02:00
redim shared commands(0) as string
2026-05-04 11:24:14 +02:00
dim shared showtoolbox as _byte: showtoolbox=-1
dim shared showcolorpicker as _byte: showcolorpicker=-1
2026-05-06 13:28:56 +02:00
dim shared showcommands as _byte: showcommands=0
2026-04-29 09:28:35 +02:00
dim shared mouseclicked as integer
dim shared mousedown as integer
2026-04-29 12:36:31 +02:00
dim shared rmouseclicked as integer
dim shared rmousedown as integer
2026-04-30 10:09:05 +02:00
2026-04-29 12:36:31 +02:00
$resize:on
2026-04-30 08:23:26 +02:00
screen _newimage(750,480,32)
2026-04-29 12:36:31 +02:00
_delay 0.1
temp&=_resize
redim shared pal(0) as _unsigned long
2026-04-29 09:28:35 +02:00
dim as integer ch1,ch2,ch3,bt
2026-05-01 00:30:34 +02:00
loadpalette "slso8",pal()
2026-05-04 12:14:29 +02:00
layers(0).ihandle=_newimage(320,320,32)
layers(1).ihandle=_newimage(320,320,32)
layers(2).ihandle=_newimage(320,320,32)
layers(3).ihandle=_newimage(320,320,32)
2026-05-01 00:30:34 +02:00
2026-04-29 21:17:20 +02:00
_dest layers(0).ihandle
addcommand "canvas ("+tst(_width)+","+tst(_height)+")"
2026-05-11 11:39:10 +02:00
for y = 0 to _height - 16 step 16
for x = 0 to _width - 16 step 16
2026-05-11 11:41:58 +02:00
if ((x + y) / 16 AND 1) = 0 then
2026-05-11 11:39:10 +02:00
line (x, y)-(x + 16, y + 16), _rgb32(127), bf
else
line (x, y)-(x + 16, y + 16), _rgb32(192), bf
end if
next
next
2026-04-29 21:17:20 +02:00
_dest 0
2026-04-30 10:09:05 +02:00
state.tool = 1
state.zoom = 1.0
2026-05-11 10:03:44 +02:00
state.offsetX = 70 + 20
2026-04-30 10:09:05 +02:00
state.offsetY = 20
2026-04-30 13:16:00 +02:00
state. brushsize = 1
2026-05-11 10:03:44 +02:00
state.fcolor=closestcolor(_rgb32(0,0,0),pal())
state.bcolor=closestcolor(_rgb32(255,255,255),pal())
addcommand "fcolor ("+hex$(state.fcolor)+")"
addcommand "bcolor ("+hex$(state.bcolor)+")"
2026-04-30 10:09:05 +02:00
dim lastMX, lastMY
dim diffX as integer
dim diffY as integer
dim oldWidth as integer
dim oldHeight as integer
2026-04-30 13:16:00 +02:00
dim keyin as string
2026-05-11 10:03:44 +02:00
dim mouseWorldY as integer
dim mouseWorldX as integer
2026-04-29 09:28:35 +02:00
2026-04-30 10:09:05 +02:00
oldWidth=_width
oldHeight=_height
2026-04-29 09:28:35 +02:00
do
2026-04-30 10:09:05 +02:00
if CheckResize(_source) = -1 THEN
diffX = _width - oldWidth
diffY = _height - oldHeight
state.offsetX = state.offsetX + (diffX / 2)
state.offsetY = state.offsetY + (diffY / 2)
oldWidth = _width
oldHeight = _height
end if
2026-05-04 13:49:56 +02:00
2026-05-11 10:03:44 +02:00
canvas
if showtoolbox then toolbox
if showcolorpicker then colorpicker
if showcommands then commandlist
2026-05-04 13:49:56 +02:00
2026-04-30 13:16:00 +02:00
'Mouse Handling
while _mouseinput:mw=mw+_mousewheel:wend
2026-04-30 10:09:05 +02:00
mouseclicked = 0
rmouseclicked = 0
if mousedown = -1 and _mousebutton(1) = 0 then mouseclicked = -1
if rmousedown = -1 and _mousebutton(2) = 0 then rmouseclicked = -1
mousedown = _mousebutton(1)
rmousedown = _mousebutton(2)
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
' Panning (Middle Mouse)
if _mousebutton(3) then
2026-05-04 11:51:47 +02:00
state.offsetX = int(state.offsetX + (_mousex - lastMX))
state.offsetY = int(state.offsetY + (_mousey - lastMY))
2026-04-30 10:09:05 +02:00
end if
lastMX = _mousex: lastMY = _mousey
2026-05-04 11:24:14 +02:00
2026-04-30 10:09:05 +02:00
' Zooming
2026-05-04 11:24:14 +02:00
if mw <> 0 then
2026-05-04 12:14:29 +02:00
' 1. Capture current world position
2026-05-11 10:03:44 +02:00
mouseWorldX = (_mousex - state.offsetX) / state.zoom
mouseWorldY = (_mousey - state.offsetY) / state.zoom
2026-05-04 13:49:56 +02:00
2026-05-04 12:14:29 +02:00
' 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
2026-05-04 13:49:56 +02:00
2026-05-04 12:14:29 +02:00
' 3. Constrain zoom (Min 1, Max 20)
if state.zoom < 1 then state.zoom = 1
2026-05-04 11:24:14 +02:00
if state.zoom > 20 then state.zoom = 20
2026-05-04 13:49:56 +02:00
2026-05-11 10:03:44 +02:00
' 4. Adjust offsets
2026-05-04 11:24:14 +02:00
state.offsetX = _mousex - (mouseWorldX * state.zoom)
state.offsetY = _mousey - (mouseWorldY * state.zoom)
2026-05-04 13:49:56 +02:00
2026-05-04 11:24:14 +02:00
mw = 0
end if
2026-04-30 13:16:00 +02:00
' Keyboarding
keyin=inkey$
select case keyin
case "+"
state.brushsize=state.brushsize+1
addcommand "brushsize ("+tst(state.brushsize)+")"
2026-04-30 13:16:00 +02:00
case "-"
if state.brushsize>1 then state.brushsize=state.brushsize-1
addcommand "brushsize ("+tst(state.brushsize)+")"
2026-05-01 00:30:34 +02:00
case chr$(19) ' ctrl+s
'TODO: save logic
case chr$(27)' esc
2026-05-04 13:49:56 +02:00
menu
2026-05-04 11:24:14 +02:00
case "h"
2026-05-11 10:03:44 +02:00
state.zoom=1.0
state.offsetX=(_width/2)- (_width(layers(0).ihandle)/2)
state.offsetY=(_height/2)- (_height(layers(0).ihandle)/2)
2026-05-04 11:24:14 +02:00
case "t"
showtoolbox=not showtoolbox
case "c"
showcolorpicker=not showcolorpicker
2026-05-06 13:28:56 +02:00
case "l"
showcommands=not showcommands
2026-05-04 13:49:56 +02:00
end select
2026-05-01 00:30:34 +02:00
2026-04-29 09:28:35 +02:00
_limit 30
_display
2026-05-11 10:03:44 +02:00
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
2026-04-29 09:28:35 +02:00
loop
2026-05-06 13:28:56 +02:00
sub commandlist
dim i as long
2026-05-11 10:03:44 +02:00
dim listWidth as integer:listWidth = 150
dim x as integer:x=_width-listWidth
2026-05-06 13:28:56 +02:00
' Draw background for the list
2026-05-11 10:03:44 +02:00
line (x,0)-(_width-1,_height - 1),backgroundcolor1, bf
line (x,0)-(x,_height-1),backgroundcolor2
2026-05-06 13:28:56 +02:00
_printmode _keepbackground
2026-05-11 10:03:44 +02:00
dim y as integer
for i = ubound(commands) - 1 to 0 step -1
y = (ubound(commands)-i) * 16
2026-05-06 13:28:56 +02:00
if y < _height - 20 then
_printstring (x + 5, y + 5), left$(commands(i), 18)
end if
next i
end sub
2026-04-29 09:28:35 +02:00
sub toolbox
2026-04-30 10:09:05 +02:00
dim i, x, y
dim btnSize : btnSize = 32
dim spacing : spacing = 1
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
for i = 0 to 19
' Force integer math to keep columns locked at 2
' x will only ever be 0 or 33
x = (i mod 2) * (btnSize + spacing)
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
' y will only increase every 2 buttons
' Use Int() if your language doesn't support the \ operator
y = Int(i / 2) * (btnSize + spacing)
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
if imagebutton(x, y, btnSize, btnSize, icon(i)) then
state.tool = i + 1
end if
next
2026-05-11 10:03:44 +02:00
'colorindicator
y=y+btnSize+16
line (16,y+16)-(64,y+64),state.bcolor,bf
line (16,y+16)-(64,y+64),highlightcolor,b
line (0,y)-(48,y+48),state.fcolor,bf
line (0,y)-(48,y+48),highlightcolor,b
2026-05-11 12:41:20 +02:00
if clickregion(0, y, 48, 48) then
palettemanager state.fcolor
elseif clickregion(16, y + 16, 48, 48) then
palettemanager state.bcolor
end if
end sub
2026-04-29 09:28:35 +02:00
sub colorpicker
2026-04-29 12:36:31 +02:00
dim img as long
img=_newimage(16,16,32)
for i=0 to ubound(pal)
_dest img
cls ,pal(i)
line (0,0)-(_width-1,height-1),pal(i),bf
_dest 0
select case imagebutton(i*16,_height-17,16,16,img)
case -1
state.fcolor=pal(i)
2026-05-06 13:28:56 +02:00
addcommand "fcolor ("+hex$(pal(i))+")"
2026-04-29 12:36:31 +02:00
case -2
state.bcolor=pal(i)
2026-05-06 13:28:56 +02:00
addcommand "bcolor ("+hex$(pal(i))+")"
2026-05-04 13:49:56 +02:00
end select
2026-04-29 12:36:31 +02:00
next i
_freeimage img
2026-04-29 09:28:35 +02:00
end sub
2026-05-06 13:28:56 +02:00
sub addcommand(cmd as string)
'this check is probably more clever than good is.
if commands(ubound(commands)+(ubound(commands)>0))<>cmd then
commands(ubound(commands))=cmd
redim _preserve commands(ubound(commands)+1) as string
end if
end sub
sub canvas
2026-05-04 11:24:14 +02:00
' 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
2026-05-06 13:28:56 +02:00
dim viewX2 as integer
if showcommands then viewX2 = _width - 151 else viewX2 = _width - 1
2026-05-04 11:24:14 +02:00
dim viewY2 as integer
if showcolorpicker then viewY2 = _height - 20 else viewY2 = _height - 1
2026-05-01 00:30:34 +02:00
_dest 0
2026-05-04 13:49:56 +02:00
2026-05-04 11:24:14 +02:00
' 2. Render Layers with Clipping
2026-05-04 11:51:47 +02:00
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
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
dim i as integer
2026-04-29 21:17:20 +02:00
for i = 0 to ubound(layers)
2026-05-04 11:24:14 +02:00
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)
2026-05-04 11:51:47 +02:00
drawX1 = state.offsetX
drawY1 = state.offsetY
drawX2 = state.offsetX + fullScaledW
drawY2 = state.offsetY + fullScaledH
2026-05-04 11:24:14 +02:00
' 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
2026-05-04 11:51:47 +02:00
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)
2026-05-04 11:24:14 +02:00
' 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
2026-04-29 21:17:20 +02:00
next
2026-05-04 12:30:34 +02:00
' 2.5 if the mouse is in ui thats all we need
if showtoolbox then
if _mousex >= 0 and _mousex <= 70 then
exit sub
end if
end if
if showcolorpicker then
if _mousey >= _height - 20 then
exit sub
end if
end if
2026-05-06 13:28:56 +02:00
if showcommands then
if _mousex >= drawX2 then
exit sub
end if
end if
dim r as integer
2026-05-04 12:30:34 +02:00
2026-05-01 00:30:34 +02:00
' 3. Calculate Canvas Coordinates
2026-05-11 10:29:29 +02:00
dim canX as long
dim canY as long
2026-05-06 13:28:56 +02:00
canX = int((_mousex - state.offsetX) / state.zoom)
canY = int((_mousey - state.offsetY) / state.zoom)
2026-05-04 12:14:29 +02:00
2026-05-04 13:49:56 +02:00
static polypoints(200) as single
2026-05-04 12:14:29 +02:00
static pointCount as integer
2026-05-04 11:24:14 +02:00
static drawCol
if _mousebutton(1) then drawCol = state.fcolor
if _mousebutton(2) then drawCol = state.bcolor
2026-05-04 13:49:56 +02:00
2026-05-01 00:30:34 +02:00
' 4. Interaction Logic
2026-05-04 13:49:56 +02:00
'if _mousex > boxX1 then
2026-05-01 00:30:34 +02:00
' Start Drawing Logic
2026-05-01 13:58:36 +02:00
if state.tool = 9 and (mouseclicked or rmouseclicked) then
2026-05-04 09:01:12 +02:00
_dest layers(1).ihandle
_source layers(1).ihandle
2026-05-01 13:58:36 +02:00
if mouseclicked then
floodfill canX,canY,state.fcolor
addcommand "floodfill ("+tst(canX)+","+tst(canY)+","+hex$(state.fcolor)+")"
2026-05-01 13:58:36 +02:00
else
floodfill canX,canY,state.bcolor
addcommand "floodfill ("+tst(canX)+","+tst(canY)+","+hex$(state.bcolor)+")"
2026-05-01 13:58:36 +02:00
end if
_dest 0
_source 0
2026-05-04 11:24:14 +02:00
exit sub
2026-05-01 13:58:36 +02:00
end if
2026-05-04 12:37:19 +02:00
if state.tool = 10 and (mouseclicked or rmouseclicked) then
_dest layers(1).ihandle
_source layers(1).ihandle
if mouseclicked then
state.fcolor=point(canX,canY)
2026-05-06 13:28:56 +02:00
addcommand "fcolor ("+hex$(point(canX,canY))+")"
2026-05-04 12:37:19 +02:00
else
state.bcolor=point(canX,canY)
2026-05-06 13:28:56 +02:00
addcommand "bcolor ("+hex$(point(canX,cany))+")"
2026-05-04 12:37:19 +02:00
end if
_dest 0
_source 0
exit sub
end if
2026-05-01 00:30:34 +02:00
if state.tool = 7 or state.tool = 8 then
if mouseclicked then
2026-04-30 13:28:15 +02:00
polypoints(pointCount * 2) = canX
polypoints(pointCount * 2 + 1) = canY
pointCount = pointCount + 1
state.isDrawing = -1
2026-05-01 00:30:34 +02:00
end if
else
if (mousedown or rmousedown) and state.isDrawing = 0 then
2026-04-30 13:28:15 +02:00
state.startX = canX
state.startY = canY
state.isDrawing = -1
end if
2026-04-30 13:16:00 +02:00
end if
2026-05-04 13:49:56 +02:00
2026-04-30 13:16:00 +02:00
if state.isDrawing then
2026-05-01 00:30:34 +02:00
' We use Layer 2 as the temporary preview "rubber-band" layer
2026-05-04 13:49:56 +02:00
_dest layers(2).ihandle
cls , 0
2026-04-30 13:16:00 +02:00
select case state.tool
2026-05-04 11:24:14 +02:00
case 1 ' Pencil
2026-04-30 13:16:00 +02:00
_dest layers(1).ihandle
2026-05-11 10:29:29 +02:00
if canX=state.startX and canY=state.startY then
thickpixel canX,canY,drawCol
addcommand "pixel ("+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-11 10:29:29 +02:00
else
thickline state.startX, state.startY, canX, canY, drawCol
addcommand "line ("+tst(state.startX)+","+tst(state.startY)+","+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-11 10:29:29 +02:00
end if
2026-04-30 13:16:00 +02:00
state.startX = canX: state.startY = canY
2026-05-01 00:30:34 +02:00
case 2 ' Straight Line
2026-04-30 13:16:00 +02:00
thickline state.startX, state.startY, canX, canY, drawCol
2026-04-30 13:28:15 +02:00
case 3 ' Circle
2026-05-06 13:28:56 +02:00
r = sqr((canX - state.startX)^2 + (canY - state.startY)^2)
2026-04-30 13:28:15 +02:00
thickcircle state.startX, state.startY, r + 1, drawCol
2026-04-30 13:16:00 +02:00
case 4 ' Filled Circle
2026-05-06 13:28:56 +02:00
r = sqr((canX - state.startX)^2 + (canY - state.startY)^2)
filledcircle state.startX, state.startY, r, drawCol
2026-04-30 13:28:15 +02:00
case 5 ' Rect
2026-04-30 13:16:00 +02:00
thickline state.startX, state.startY, canX, state.startY, drawCol
thickline canX, state.startY, canX, canY, drawCol
thickline canX, canY, state.startX, canY, drawCol
thickline state.startX, canY, state.startX, state.startY, drawCol
2026-04-30 13:28:15 +02:00
case 6 ' Filled Rect
2026-04-30 13:16:00 +02:00
line (state.startX, state.startY)-(canX, canY), drawCol, bf
2026-05-04 09:01:12 +02:00
case 7, 8 ' Polygons
2026-04-30 13:28:15 +02:00
if pointCount > 0 then
for p = 1 to pointCount - 1
2026-05-04 11:24:14 +02:00
thickline polypoints((p - 1) * 2), polypoints((p - 1) * 2 + 1), polypoints(p * 2), polypoints(p * 2 + 1), state.fcolor
2026-04-30 13:28:15 +02:00
next p
2026-05-04 11:24:14 +02:00
thickline polypoints((pointCount - 1) * 2), polypoints((pointCount - 1) * 2 + 1), canX, canY, state.fcolor
2026-04-30 13:28:15 +02:00
end if
2026-04-30 13:16:00 +02:00
end select
2026-05-04 13:49:56 +02:00
2026-05-01 00:30:34 +02:00
' 5. Commit Logic
dim commit as integer: commit = 0
2026-04-30 13:28:15 +02:00
if state.tool = 7 or state.tool = 8 then
2026-05-01 00:30:34 +02:00
if rmouseclicked then commit = -1
2026-04-30 13:28:15 +02:00
else
2026-05-04 11:24:14 +02:00
if (mousedown=0) and (rmousedown=0) then commit = -1
2026-04-30 13:28:15 +02:00
end if
2026-05-01 00:30:34 +02:00
if commit then
_dest layers(1).ihandle ' Final destination is always the drawing layer
2026-05-01 13:58:36 +02:00
if (state.tool = 8 or state.tool=7) and pointCount > 2 then
redim finalP(pointCount * 2 - 1) as long
2026-05-01 00:30:34 +02:00
for p = 0 to (pointCount * 2) - 1: finalP(p) = polypoints(p): next
2026-05-06 13:28:56 +02:00
dim tmpstr as string
if state.tool =8 then
filledPolygon finalP(), state.fcolor
2026-05-06 13:28:56 +02:00
tmpstr="fpolygon ("
for i=0 to ubound(finalP)-1
tmpstr=tmpstr+tst(finalP(i))+","
2026-05-06 13:28:56 +02:00
next i
tmpstr=tmpstr+tst(finalP(i))+","+hex$(state.fcolor)+")"
2026-05-06 13:28:56 +02:00
addcommand tmpstr
else
2026-05-06 13:28:56 +02:00
Polygon finalP(), state.fcolor
tmpstr="polygon ("
for i=0 to ubound(finalP)-1
tmpstr=tmpstr+tst(finalP(i))+","
2026-05-06 13:28:56 +02:00
next i
tmpstr=tmpstr+tst(finalP(i))+","+hex$(state.fcolor)+")"
2026-05-06 13:28:56 +02:00
addcommand tmpstr
end if
2026-04-30 13:28:15 +02:00
else
2026-05-01 13:58:36 +02:00
' Merge the preview into the drawing layer
2026-05-11 10:03:44 +02:00
'_putimage , layers(2).ihandle, layers(1).ihandle
2026-05-06 13:28:56 +02:00
select case state.tool
case 2 ' Line
2026-05-11 10:29:29 +02:00
if canX=state.startX and canY=state.startY then
thickpixel canX,canY,drawCol
addcommand "pixel ("+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-11 10:29:29 +02:00
else
thickline state.startX, state.startY, canX, canY, drawCol
addcommand "line ("+tst(state.startX)+","+tst(state.startY)+","+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-11 10:29:29 +02:00
end if
2026-05-06 13:28:56 +02:00
case 3 ' Circle
r = int(sqr((canX - state.startX)^2 + (canY - state.startY)^2))
thickcircle state.startX, state.startY, r + 1, drawCol
addcommand "circle ("+tst(state.startX)+","+tst(state.startY)+","+tst(int(r))+","+hex$(drawCol)+")"
case 4
2026-05-06 13:28:56 +02:00
r = int(sqr((canX - state.startX)^2 + (canY - state.startY)^2))
filledcircle state.startX, state.startY, r + 1, drawCol
addcommand "fcircle ("+tst(state.startX)+","+tst(state.startY)+","+tst(int(r))+","+hex$(drawCol)+")"
2026-05-06 13:28:56 +02:00
case 5 ' Box
line (state.startX, state.startY)-(canX, canY), drawCol, b
addcommand "box ("+tst(state.startX)+","+tst(state.startY)+","+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-06 13:28:56 +02:00
case 6 ' Filled Box
line (state.startX, state.startY)-(canX, canY), drawCol, bf
addcommand "fbox ("+tst(state.startX)+","+tst(state.startY)+","+tst(canX)+","+tst(canY)+","+hex$(drawCol)+")"
2026-05-06 13:28:56 +02:00
end select
2026-04-30 13:28:15 +02:00
end if
2026-05-04 13:49:56 +02:00
_dest layers(2).ihandle: cls , 0
2026-04-30 13:16:00 +02:00
state.isDrawing = 0
2026-05-04 13:49:56 +02:00
pointCount = 0
2026-04-30 10:09:05 +02:00
end if
end if
2026-05-04 13:49:56 +02:00
'end if
2026-05-04 11:24:14 +02:00
_dest 0 ' Ensure we return to main screen
2026-04-29 09:28:35 +02:00
end sub
2026-04-30 10:09:05 +02:00
function icon (index as long)
2026-04-29 09:28:35 +02:00
static init as integer
static icons() as long
if not init then
2026-04-30 10:09:05 +02:00
redim icons(19) as long ' Room for 20 icons
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
' Define your specific tool icons here
2026-05-04 11:24:14 +02:00
icons(0) = _newimage(32,32,32): _dest icons(0): line (5, 27)-(27, 5): _dest 0
icons(1) = _newimage(32,32,32): _dest icons(1): circle (15, 15), 13: _dest 0
icons(2) = _newimage(32,32,32): _dest icons(2): line (5, 5)-(27, 27), , b: _dest 0
icons(6) = _newimage(32,32,32): _dest icons(6)
line (5,15)-(15,5):line -(25,15):line -(20,25): line -(10,25):line -(5,15)
2026-05-01 00:30:34 +02:00
_dest 0
2026-05-04 13:49:56 +02:00
2026-05-01 00:30:34 +02:00
icons(7) = _newimage(32, 32, 32): _dest icons(7)
' Draw a small filled shape for the filled polygon icon
for fy = 10 to 20: line (10, fy)-(22, fy): next
_dest 0
2026-05-01 13:58:36 +02:00
icons(8) = _newimage(32, 32, 32): _dest icons(8)
' Simple "Bucket" icon
line (8, 10)-(24, 10): line -(26, 22): line -(6, 22): line -(8, 10)
line (10, 8)-(22, 8) ' Handle
_dest 0
2026-04-30 10:09:05 +02:00
' Fill the remaining slots with blank 32x32 images
dim j as integer
2026-05-01 00:30:34 +02:00
for j = 0 to 19
2026-04-30 10:09:05 +02:00
if icons(j) = 0 then icons(j) = _newimage(32, 32, 32)
next
2026-05-04 13:49:56 +02:00
2026-04-30 10:09:05 +02:00
init = -1
2026-04-29 09:28:35 +02:00
end if
2026-04-30 10:09:05 +02:00
' Bounds checking to prevent returning 0 or crashing
if index >= 0 and index <= 19 then
icon = icons(index)
else
icon = icons(0)
2026-04-29 09:28:35 +02:00
end if
end function
'$include: 'include/ui.bm'
'$include: 'include/imgout.bm'
'$include: 'include/palette.bm'
2026-04-30 13:16:00 +02:00
'$include: 'include/tools.bm'
2026-05-04 11:24:14 +02:00
''$include: 'include/effects.bm'
2026-04-29 09:28:35 +02:00
function adduiicon(imagehandle as long)
dim unknown as long
adduiicon=__internaluiicon(unknown,imagehandle,1)
end function
function adduiiconfromfile(filename as string)
dim unknown as long
adduiiconfromfile=__internaluiicon(unknown,_loadimage(filename),1)
end function
function uiicon(index)
dim unknown as long
uiicon=internaluiicon(index,unknown,2)
end function
function __internaluiicon&(index as long,imagehandle as long,mode as integer)
static init as integer
static icons() as long
if not init or mode=3 then
2026-05-04 13:49:56 +02:00
if mode<3 then
2026-04-29 09:28:35 +02:00
redim icons(3) as long
else
_freeimage icons(0)
_freeimage icons(1)
_freeimage icons(2)
_freeimage icons(3)
end if
icons(0)=_newimage(23,23,32) 'Up arrow'
_dest icons(0)
color textcolor
2026-05-04 13:49:56 +02:00
2026-04-29 09:28:35 +02:00
icons(1)=_newimage(23,23,32) 'Down arrow'
_dest icons(1)
color textcolor
2026-05-04 13:49:56 +02:00
2026-04-29 09:28:35 +02:00
icons(2)=_newimage(23,23,32) 'Left arrow'
_dest icons(2)
color textcolor
2026-05-04 13:49:56 +02:00
2026-04-29 09:28:35 +02:00
icons(3)=_newimage(23,23,32) 'Right arrow'
2026-05-04 13:49:56 +02:00
_dest icons(3)
2026-04-29 09:28:35 +02:00
color textcolor
2026-05-04 13:49:56 +02:00
2026-04-29 09:28:35 +02:00
_dest 0
init=-1
end if
2026-05-04 13:49:56 +02:00
2026-04-29 09:28:35 +02:00
select case mode
case 1
redim _preserve icons(ubound(icons)+1)
icons(ubound(icons))=imagehandle
__internaluiicon=ubound(icons)
case 2
__internaluiicon=icons(index)
end select
end function
2026-04-29 12:36:31 +02:00
2026-04-29 13:37:02 +02:00
FUNCTION CheckResize (CurrentScreen AS _UNSIGNED LONG) 'pulled straight out of the wiki'
2026-04-29 12:36:31 +02:00
DIM TempScreen AS _UNSIGNED LONG
CheckResize = 0
IF _RESIZE THEN
TempScreen = _COPYIMAGE(CurrentScreen, 32)
SCREEN TempScreen
_FREEIMAGE CurrentScreen
CurrentScreen = _NEWIMAGE(_RESIZEWIDTH, _RESIZEHEIGHT, 32)
SCREEN CurrentScreen
_PUTIMAGE (0, 0), TempScreen, CurrentScreen
_DISPLAY
_FREEIMAGE TempScreen
CheckResize = -1
END IF
END FUNCTION
2026-05-04 13:49:56 +02:00
sub menu()
2026-05-11 10:03:44 +02:00
dim logo as long
logo=_loadimage("logo.png")
Line (0,0)-(_width-1,_height-1),_rgb32(0,192),bf
2026-05-04 13:49:56 +02:00
do until done
k$=inkey$
while _mouseinput:wend
mouseclicked=mbd and not _mousebutton(1)
mbd=_mousebutton(1)
2026-05-11 10:03:44 +02:00
if link(10,10,"open") then system
if link(10,34,"save") then system
if link(10,56,"exit") then system
2026-05-04 13:49:56 +02:00
if k$=chr$(27) then done=-1
_limit 30
_display
loop
end sub
2026-05-11 10:03:44 +02:00
sub palettemanager(col as _unsigned long)
line (0,0)-(_width-1,_height-1),col,bf
'TODO: build palette mamager ui
end sub
2026-05-11 10:03:44 +02:00
FUNCTION closestcolor~& (colour AS _UNSIGNED LONG, carr() AS _UNSIGNED LONG)
DIM r AS INTEGER
DIM g AS INTEGER
DIM b AS INTEGER
DIM ar AS INTEGER
DIM ag AS INTEGER
DIM ab AS INTEGER
DIM i AS INTEGER
DIM nearest AS INTEGER
DIM shortestdistance AS INTEGER
DIM distance AS INTEGER
r = _RED (colour)
g = _GREEN(colour)
b = _BLUE (colour)
shortestdistance = 443
FOR i = 0 TO UBOUND(carr)
ar = _RED (carr(i))
ag = _GREEN(carr(i))
ab = _BLUE (carr(i))
distance = SQR((r - ar) ^ 2 + (g - ag) ^ 2 + (b - ab) ^ 2)
IF distance <= shortestdistance THEN shortestdistance = distance: nearest = i
NEXT i
closestcolor = carr(nearest)
END FUNCTION
' trimmed str$
function tst$(numb)
tst=_trim$(str$(numb))
end function