tools
This commit is contained in:
parent
6af399f587
commit
b4678feada
2 changed files with 235 additions and 32 deletions
145
include/tools.bm
Normal file
145
include/tools.bm
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
|
||||||
|
|
||||||
|
sub filledPolygon (Points() as single, col as long)
|
||||||
|
dim i as integer, j as integer
|
||||||
|
dim x1 as single, y1 as single, x2 as single, y2 as single
|
||||||
|
dim intersectX as single
|
||||||
|
' get the number of points from the upper bound of the array
|
||||||
|
' divide by 2 since we have x,y pairs
|
||||||
|
dim numPoints as integer
|
||||||
|
numPoints = (ubound(Points) + 1) \ 2
|
||||||
|
' loop through each scanline (rows of pixels)
|
||||||
|
dim intersections(100) as single
|
||||||
|
dim numIntersections as integer
|
||||||
|
for y = 0 to _height ' adjust for screen height
|
||||||
|
numIntersections = 0
|
||||||
|
' check for intersections between the polygon edges and this scanline
|
||||||
|
for i = 0 to numPoints - 1
|
||||||
|
x1 = Points(i * 2)
|
||||||
|
y1 = Points(i * 2 + 1)
|
||||||
|
x2 = Points(((i + 1) mod numPoints) * 2)
|
||||||
|
y2 = Points(((i + 1) mod numPoints) * 2 + 1)
|
||||||
|
' check if the scanline intersects with the edge of the polygon
|
||||||
|
if ((y1 > y and y2 <= y) or (y2 > y and y1 <= y)) then
|
||||||
|
' calculate intersection point with the scanline
|
||||||
|
intersectX = x1 + (y - y1) * (x2 - x1) / (y2 - y1)
|
||||||
|
intersections(numIntersections) = intersectX
|
||||||
|
numIntersections = numIntersections + 1
|
||||||
|
end if
|
||||||
|
next i
|
||||||
|
' sort the intersections (sort by x-coordinates)
|
||||||
|
for i = 0 to numIntersections - 1
|
||||||
|
for j = i + 1 to numIntersections - 1
|
||||||
|
if intersections(i) > intersections(j) then
|
||||||
|
swap intersections(i), intersections(j)
|
||||||
|
end if
|
||||||
|
next j
|
||||||
|
next i
|
||||||
|
' fill the area between pairs of intersections
|
||||||
|
for i = 0 to numIntersections - 1 step 2
|
||||||
|
line(intersections(i),y)-(intersections(i+1),y),col
|
||||||
|
next i
|
||||||
|
next y
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub thickline(x1,y1,x2,y2, col as long)
|
||||||
|
if state.brushsize=1 then
|
||||||
|
line(x1,y1)-(x2,y2),col
|
||||||
|
else
|
||||||
|
dim tempimg as long
|
||||||
|
dim od as long
|
||||||
|
tempimg=_newimage(10,10,32)
|
||||||
|
od =_dest
|
||||||
|
_dest tempimg
|
||||||
|
pset(0,0),col
|
||||||
|
_dest od
|
||||||
|
a = _Atan2(y2 - y1, x2 - x1)
|
||||||
|
a = a + _Pi / 2
|
||||||
|
x0 = 0.5 * state.brushsize * Cos(a)
|
||||||
|
y0 = 0.5 * state.brushsize * Sin(a)
|
||||||
|
_maptriangle _seamless(0,0)-(0,0)-(0,0),tempimg to(x1-x0, y1-y0)-(x1+x0,y1+y0)-(x2+x0,y2+y0),,_smooth
|
||||||
|
_maptriangle _seamless(0,0)-(0,0)-(0,0),tempimg to(x1-x0, y1-y0)-(x2+x0,y2+y0)-(x2-x0,y2-y0),,_smooth
|
||||||
|
_freeimage tempimg
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
|
Sub polygon (pa() As Long,col as long)
|
||||||
|
For i = 2 To UBound(pa) Step 2
|
||||||
|
thickLine pa(i - 2), pa(i - 1),pa(i), pa(i + 1),col
|
||||||
|
Next i
|
||||||
|
thickLine pa(i - 1), pa(i - 2),pa(0), pa(1),col
|
||||||
|
End Sub
|
||||||
|
sub thickcircle(x, y, r, col as long)
|
||||||
|
if state.brushsize <= 1 then
|
||||||
|
circle (x, y), r, col
|
||||||
|
else
|
||||||
|
dim rp as single, rm as single, rp2 as single, rm2 as single
|
||||||
|
dim rpi2 as single, rmi2 as single, sp as single, sm as single
|
||||||
|
dim i as single
|
||||||
|
|
||||||
|
rp = r + state.brushsize / 2
|
||||||
|
rm = r - state.brushsize / 2
|
||||||
|
|
||||||
|
' If the brush is thicker than the circle, it's just a filled circle
|
||||||
|
if rm < 0 then
|
||||||
|
filledcircle x, y, rp, col
|
||||||
|
exit sub
|
||||||
|
end if
|
||||||
|
|
||||||
|
rp2 = rp ^ 2
|
||||||
|
rm2 = rm ^ 2
|
||||||
|
|
||||||
|
' Outer edges (Top/Bottom caps)
|
||||||
|
for i = -rp to -rm step .2
|
||||||
|
rpi2 = rp2 - i ^ 2
|
||||||
|
if rpi2 < 0 then rpi2 = 0 ' Safety Gate
|
||||||
|
sp = sqr(rpi2)
|
||||||
|
line (x + i, y - sp)-(x + i, y + sp), col, bf
|
||||||
|
next
|
||||||
|
|
||||||
|
' Side rings (where the hole in the middle exists)
|
||||||
|
for i = -rm to rm step .2
|
||||||
|
rpi2 = rp2 - i ^ 2
|
||||||
|
rmi2 = rm2 - i ^ 2
|
||||||
|
if rpi2 < 0 then rpi2 = 0 ' Safety Gate
|
||||||
|
if rmi2 < 0 then rmi2 = 0 ' Safety Gate
|
||||||
|
sp = sqr(rpi2)
|
||||||
|
sm = sqr(rmi2)
|
||||||
|
' Draw the top and bottom segments only
|
||||||
|
line (x + i, y + sm)-(x + i, y + sp), col, bf
|
||||||
|
line (x + i, y - sm)-(x + i, y - sp), col, bf
|
||||||
|
next
|
||||||
|
|
||||||
|
' Outer edges (Right cap)
|
||||||
|
for i = rm to rp step .2
|
||||||
|
rpi2 = rp2 - i ^ 2
|
||||||
|
if rpi2 < 0 then rpi2 = 0 ' Safety Gate
|
||||||
|
sp = sqr(rpi2)
|
||||||
|
line (x + i, y - sp)-(x + i, y + sp), col, bf
|
||||||
|
next
|
||||||
|
end if
|
||||||
|
end sub
|
||||||
|
|
||||||
|
sub filledcircle(x,y,r,col as long)
|
||||||
|
dim __radius as integer, radiuserror as integer
|
||||||
|
dim tx as integer, ty as integer
|
||||||
|
__radius=abs(r)-1
|
||||||
|
radiuserror=-__radius
|
||||||
|
tx=__radius
|
||||||
|
ty=0
|
||||||
|
line (x-tx,y)-(x+tx,y),col
|
||||||
|
while tx>ty
|
||||||
|
radiuserror=radiuserror+ty*2+1
|
||||||
|
if radiuserror >= 0 then
|
||||||
|
if tx<>ty+1 then
|
||||||
|
line (x-ty,y-tx)-(x+ty,y-tx),col
|
||||||
|
line (x-ty,y+tx)-(x+ty,y+tx),col
|
||||||
|
end if
|
||||||
|
tx=tx-1
|
||||||
|
radiuserror=radiuserror-tx*2
|
||||||
|
end if
|
||||||
|
ty=ty+1
|
||||||
|
line (x-tx,y-ty)-(x+tx,y-ty),col
|
||||||
|
line (x-tx,y+ty)-(x+tx,y+ty),col
|
||||||
|
wend
|
||||||
|
end sub
|
||||||
114
pixler.bas
114
pixler.bas
|
|
@ -5,6 +5,10 @@ type statetype
|
||||||
offsetX as single
|
offsetX as single
|
||||||
offsetY as single
|
offsetY as single
|
||||||
zoom as single
|
zoom as single
|
||||||
|
brushsize as integer
|
||||||
|
startX as integer
|
||||||
|
startY as integer
|
||||||
|
isDrawing as integer
|
||||||
end type
|
end type
|
||||||
|
|
||||||
type layertype
|
type layertype
|
||||||
|
|
@ -14,11 +18,10 @@ type layertype
|
||||||
kind as long
|
kind as long
|
||||||
end type
|
end type
|
||||||
|
|
||||||
redim shared layers(1) as layertype
|
redim shared layers(2) as layertype
|
||||||
dim shared state as statetype
|
dim shared state as statetype
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dim shared mouseclicked as integer
|
dim shared mouseclicked as integer
|
||||||
dim shared mousedown as integer
|
dim shared mousedown as integer
|
||||||
dim shared rmouseclicked as integer
|
dim shared rmouseclicked as integer
|
||||||
|
|
@ -33,6 +36,7 @@ dim as integer ch1,ch2,ch3,bt
|
||||||
loadpalette "endesga16",pal()
|
loadpalette "endesga16",pal()
|
||||||
layers(0).ihandle=_newimage(640,350,32)
|
layers(0).ihandle=_newimage(640,350,32)
|
||||||
layers(1).ihandle=_newimage(640,350,32)
|
layers(1).ihandle=_newimage(640,350,32)
|
||||||
|
layers(2).ihandle=_newimage(640,350,32)
|
||||||
_dest layers(0).ihandle
|
_dest layers(0).ihandle
|
||||||
line (0,0)-(_width-1,_height-1),_rgb32(255),bf
|
line (0,0)-(_width-1,_height-1),_rgb32(255),bf
|
||||||
_dest 0
|
_dest 0
|
||||||
|
|
@ -42,11 +46,13 @@ state.bcolor = 2
|
||||||
state.zoom = 1.0
|
state.zoom = 1.0
|
||||||
state.offsetX = 70 + 20 ' To the right of the toolbox
|
state.offsetX = 70 + 20 ' To the right of the toolbox
|
||||||
state.offsetY = 20
|
state.offsetY = 20
|
||||||
|
state. brushsize = 1
|
||||||
dim lastMX, lastMY
|
dim lastMX, lastMY
|
||||||
dim diffX as integer
|
dim diffX as integer
|
||||||
dim diffY as integer
|
dim diffY as integer
|
||||||
dim oldWidth as integer
|
dim oldWidth as integer
|
||||||
dim oldHeight as integer
|
dim oldHeight as integer
|
||||||
|
dim keyin as string
|
||||||
|
|
||||||
oldWidth=_width
|
oldWidth=_width
|
||||||
oldHeight=_height
|
oldHeight=_height
|
||||||
|
|
@ -62,9 +68,9 @@ do
|
||||||
|
|
||||||
cls
|
cls
|
||||||
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
|
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
|
||||||
while _mouseinput:mw=mw+_mousewheel:wend
|
|
||||||
|
|
||||||
' --- Global Mouse Handling (Left & Right) ---
|
'Mouse Handling
|
||||||
|
while _mouseinput:mw=mw+_mousewheel:wend
|
||||||
mouseclicked = 0
|
mouseclicked = 0
|
||||||
rmouseclicked = 0
|
rmouseclicked = 0
|
||||||
if mousedown = -1 and _mousebutton(1) = 0 then mouseclicked = -1
|
if mousedown = -1 and _mousebutton(1) = 0 then mouseclicked = -1
|
||||||
|
|
@ -85,10 +91,19 @@ do
|
||||||
if state.zoom < 0.1 then state.zoom = 0.1
|
if state.zoom < 0.1 then state.zoom = 0.1
|
||||||
mw=0
|
mw=0
|
||||||
end if
|
end if
|
||||||
'state.zoom=mw/100
|
|
||||||
canvas ' Uses mousedown and rmousedown for drawing/erasing
|
' Keyboarding
|
||||||
|
keyin=inkey$
|
||||||
|
select case keyin
|
||||||
|
case "+"
|
||||||
|
state.brushsize=state.brushsize+1
|
||||||
|
case "-"
|
||||||
|
if state.brushsize>1 then state.brushsize=state.brushsize-1
|
||||||
|
end select
|
||||||
|
_dest 0
|
||||||
|
canvas 'draw canvas first so it doesn't over
|
||||||
toolbox
|
toolbox
|
||||||
colorpicker ' Uses rmouseclicked for bcolor
|
colorpicker
|
||||||
|
|
||||||
_limit 30
|
_limit 30
|
||||||
_display
|
_display
|
||||||
|
|
@ -140,7 +155,7 @@ sub canvas
|
||||||
' Workspace background
|
' Workspace background
|
||||||
line (boxX1, 0)-(_width - 1, boxHeight), _rgb32(32), bf
|
line (boxX1, 0)-(_width - 1, boxHeight), _rgb32(32), bf
|
||||||
|
|
||||||
' Render Layers with Zoom/Offset[cite: 4]
|
' Render Layers (0 = background,1 = drawlayer, 2=reference 3 = Preview)
|
||||||
dim i as integer
|
dim i as integer
|
||||||
for i = 0 to ubound(layers)
|
for i = 0 to ubound(layers)
|
||||||
dim w as integer: w = _width(layers(i).ihandle) * state.zoom
|
dim w as integer: w = _width(layers(i).ihandle) * state.zoom
|
||||||
|
|
@ -148,31 +163,73 @@ sub canvas
|
||||||
_putimage (state.offsetX, state.offsetY)-(state.offsetX + w, state.offsetY + h), layers(i).ihandle
|
_putimage (state.offsetX, state.offsetY)-(state.offsetX + w, state.offsetY + h), layers(i).ihandle
|
||||||
next
|
next
|
||||||
|
|
||||||
' --- Drawing Logic (Multi-Button) ---
|
' Translate Mouse to Canvas Space
|
||||||
if (mousedown or rmousedown) and _mousex > boxX1 then
|
dim canX as integer: canX = (_mousex - state.offsetX) / state.zoom
|
||||||
' Translate to Canvas Space
|
dim canY as integer: canY = (_mousey - state.offsetY) / state.zoom
|
||||||
dim canX as integer: canX = (_mousex - state.offsetX) / state.zoom
|
|
||||||
dim canY as integer: canY = (_mousey - state.offsetY) / state.zoom
|
|
||||||
|
|
||||||
' Boundary Check
|
' Color Selection: Left Click = Foreground, Right Click = Background
|
||||||
if canX >= 0 and canX < _width(layers(0).ihandle) then
|
dim drawCol as _unsigned long
|
||||||
if canY >= 0 and canY < _height(layers(0).ihandle) then
|
if mousedown or mouseclicked then drawCol = state.fcolor else drawCol = state.bcolor
|
||||||
_dest layers(0).ihandle
|
|
||||||
|
|
||||||
' Select color based on button pressed
|
' Interaction Boundary Check
|
||||||
dim drawCol as _unsigned long
|
if _mousex > boxX1 then
|
||||||
if mousedown then drawCol = state.fcolor else drawCol = state.bcolor
|
' On Initial Click: Set the anchor point for shapes
|
||||||
|
if (mousedown or rmousedown) and state.isDrawing = 0 then
|
||||||
|
state.startX = canX
|
||||||
|
state.startY = canY
|
||||||
|
state.isDrawing = -1
|
||||||
|
end if
|
||||||
|
|
||||||
' Apply Tool
|
if state.isDrawing then
|
||||||
if state.tool = 1 then
|
' preview layer handles the "rubber-banding" of shapes
|
||||||
pset (canX, canY), drawCol
|
_dest layers(2).ihandle
|
||||||
elseif state.tool = 2 then
|
cls , 0
|
||||||
' Example: Square brush
|
|
||||||
line (canX - 1, canY - 1)-(canX + 1, canY + 1), drawCol, bf
|
|
||||||
end if
|
|
||||||
|
|
||||||
_dest 0
|
select case state.tool
|
||||||
|
case 1 ' Pencil (Direct to Canvas)
|
||||||
|
_dest layers(1).ihandle
|
||||||
|
thickline state.startX, state.startY, canX, canY, drawCol
|
||||||
|
state.startX = canX: state.startY = canY
|
||||||
|
|
||||||
|
case 2 ' Straight Line
|
||||||
|
thickline state.startX, state.startY, canX, canY, drawCol
|
||||||
|
|
||||||
|
case 3 ' Thick Circle (Outline)
|
||||||
|
dim r as single: r = sqr((canX - state.startX)^2 + (canY - state.startY)^2)
|
||||||
|
r=abs(r)+1
|
||||||
|
thickcircle state.startX, state.startY, r, drawCol
|
||||||
|
|
||||||
|
case 4 ' Filled Circle
|
||||||
|
dim r_fill as single: r_fill = sqr((canX - state.startX)^2 + (canY - state.startY)^2)
|
||||||
|
filledcircle state.startX, state.startY, r_fill, drawCol
|
||||||
|
|
||||||
|
case 5 ' Rectangle Outline (using thickline)
|
||||||
|
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
|
||||||
|
|
||||||
|
case 6 ' Filled Rectangle
|
||||||
|
line (state.startX, state.startY)-(canX, canY), drawCol, bf
|
||||||
|
|
||||||
|
case 7
|
||||||
|
|
||||||
|
case 8 ' Polygon Outline (using thickline)
|
||||||
|
' Simple preview of a line; complex polygons usually require
|
||||||
|
' a point-collection state machine.
|
||||||
|
thickline state.startX, state.startY, canX, canY, drawCol
|
||||||
|
|
||||||
|
end select
|
||||||
|
|
||||||
|
' Release Logic: Commit preview to permanent layer
|
||||||
|
if _mousebutton(1) = 0 and _mousebutton(2) = 0 then
|
||||||
|
_dest layers(1).ihandle
|
||||||
|
_putimage , layers(2).ihandle
|
||||||
|
_dest layers(2).ihandle
|
||||||
|
cls , 0
|
||||||
|
state.isDrawing = 0
|
||||||
end if
|
end if
|
||||||
|
_dest 0
|
||||||
end if
|
end if
|
||||||
end if
|
end if
|
||||||
end sub
|
end sub
|
||||||
|
|
@ -208,6 +265,7 @@ end function
|
||||||
'$include: 'include/ui.bm'
|
'$include: 'include/ui.bm'
|
||||||
'$include: 'include/imgout.bm'
|
'$include: 'include/imgout.bm'
|
||||||
'$include: 'include/palette.bm'
|
'$include: 'include/palette.bm'
|
||||||
|
'$include: 'include/tools.bm'
|
||||||
|
|
||||||
function adduiicon(imagehandle as long)
|
function adduiicon(imagehandle as long)
|
||||||
dim unknown as long
|
dim unknown as long
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue