Last active
June 11, 2022 21:18
-
-
Save akkartik/b141370fbb2bb5ae6f8b47de36a121d1 to your computer and use it in GitHub Desktop.
Little drawing program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- To run: | |
-- Download LÖVE from https://love2d.org | |
-- Download this file to a directory and rename it to `main.lua` | |
-- Run the program from that directory. | |
-- * on Linux (using the appimage binary): `chmod +x path/to/love-11.4-x86_64.AppImage; path/to/love-11.4-x86_64.AppImage .` | |
-- * on Mac: `path/to/love.app/Contents/MacOS/love .` | |
-- | |
-- Based on https://love2d.org/forums/viewtopic.php?t=87469 | |
function love.load() | |
img=love.graphics.newImage("pointers.png") | |
up=love.graphics.newQuad(0,0,19,10,img:getDimensions()) | |
down=love.graphics.newQuad(19,0,19,10,img:getDimensions()) | |
ex=love.graphics.newQuad(38,0,13,12,img:getDimensions()) | |
-- maximize window | |
love.window.setMode(0,0) | |
local width, height, flags = love.window.getMode() | |
-- shrink slightly to account for window decoration | |
width = width-100 | |
height = height-100 | |
love.window.setMode(width, height) | |
love.window.setTitle("Love Paint") | |
local status_height = 20 | |
UI={ | |
x=5,y=5,w=width-10,h=100, -- menu area | |
status_height=status_height, | |
x2=5,y2=110,w2=width-10,h2=height-status_height-115, -- shapes area | |
-- top-left coords for lots of widgets on screen | |
-- shapes | |
dotx=145,doty=30, | |
freehandx=125,freehandy=30, | |
linex=145,liney=50, | |
horvertx=125,horverty=50, | |
circlex=145,circley=70, | |
-- large square for the selected color | |
colorx=165,colory=30, | |
-- colors | |
px=235,py=30, -- black | |
bx=235,by=65, -- white | |
vx=265,vy=30, -- red | |
vex=265,vey=65, -- green | |
ax=295,ay=30, -- blue | |
amx=295,amy=65, -- yellow | |
lx=325,ly=30, -- orange | |
rx=325,ry=65, -- pink | |
acx=355,acy=30, -- cyan | |
rox=355,roy=65, -- purple | |
-- color arrows | |
uprx=400,upry=65, | |
downrx=400,downry=80, | |
upgx=440,upgy=65, | |
downgx=440,downgy=80, | |
upbx=485,upby=65, | |
downbx=485,downby=80, | |
} | |
mouse={x=0,y=0} | |
R=255; G=0; B=0; | |
shapes_committed={} | |
current_shape='dot' | |
pending={} | |
end | |
function love.mousepressed(x,y,button) | |
if button==1 then | |
if x>UI.px and x<UI.px+25 and y>UI.py and y<UI.py+25 then R=0; G=0; B=0 end | |
if x>UI.bx and x<UI.bx+25 and y>UI.by and y<UI.by+25 then R=255; G=255; B=255 end | |
if x>UI.vx and x<UI.vx+25 and y>UI.vy and y<UI.vy+25 then R=255; G=0; B=0; end | |
if x>UI.vex and x<UI.vex+25 and y>UI.vey and y<UI.vey+25 then R=0; G=255; B=0 end | |
if x>UI.ax and x<UI.ax+25 and y>UI.ay and y<UI.ay+25 then R=0; G=0; B=255 end | |
if x>UI.amx and x<UI.amx+25 and y>UI.amy and y<UI.amy+25 then R=255; G=255; B=0 end | |
if x>UI.lx and x<UI.lx+25 and y>UI.ly and y<UI.ly+25 then R=255; G=128; B=0 end | |
if x>UI.rx and x<UI.rx+25 and y>UI.ry and y<UI.ry+25 then R=255; G=128; B=255 end | |
if x>UI.acx and x<UI.acx+25 and y>UI.acy and y<UI.acy+25 then R=0; G=125; B=192 end | |
if x>UI.rox and x<UI.rox+25 and y>UI.roy and y<UI.roy+25 then R=163; G=73; B=164 end | |
if x>UI.dotx and x<UI.dotx+20 and y>UI.doty and y<UI.doty+20 then current_shape='dot' end | |
if x>UI.freehandx and x<UI.freehandx+20 and y>UI.freehandy and y<UI.freehandy+20 then current_shape='freehand' end | |
if x>UI.horvertx and x<UI.horvertx+20 and y>UI.horverty and y<UI.horverty+20 then current_shape='horvert' end | |
if x>UI.linex and x<UI.linex+20 and y>UI.liney and y<UI.liney+20 then current_shape='line' end | |
if x>UI.circlex and x<UI.circlex+20 and y>UI.circley and y<UI.circley+20 then current_shape='circle' end | |
if x>UI.x2 and x<UI.x2+UI.w2 and y>UI.y2 and y<UI.y2+UI.h2 then | |
if current_shape == 'line' then | |
pending = {shape='line', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B} | |
elseif current_shape == 'horvert' then | |
pending = {shape='horvert', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B} | |
elseif current_shape == 'freehand' then | |
pending = {shape='freehand', points={{x=x,y=y}}, Vermelho=R,Verde=G,Azul=B} | |
elseif current_shape == 'circle' then | |
pending = {shape='circle', cx=x,cy=y, Vermelho=R,Verde=G,Azul=B} | |
end | |
end | |
end | |
end | |
function love.mousereleased(x,y,button) | |
if x>UI.x2 and x<UI.x2+UI.w2 and y>UI.y2 and y<UI.y2+UI.h2 then | |
if pending.shape == 'line' then | |
pending.x2 = x | |
pending.y2 = y | |
table.insert(shapes_committed, pending) | |
elseif pending.shape == 'horvert' then | |
pending.shape = 'line' | |
if math.abs(x-pending.x1) > math.abs(y-pending.y1) then | |
pending.x2 = x | |
pending.y2 = pending.y1 | |
else | |
pending.x2 = pending.x1 | |
pending.y2 = y | |
end | |
love.mouse.setPosition(pending.x2, pending.y2) -- make mouse position intuitive | |
table.insert(shapes_committed, pending) | |
elseif pending.shape == 'freehand' then | |
table.insert(pending.points, {x=x,y=y}) | |
table.insert(shapes_committed, pending) | |
elseif pending.shape == 'circle' then | |
pending.r = math.dist(pending.cx, pending.cy, x, y) | |
table.insert(shapes_committed, pending) | |
end | |
pending = {} | |
end | |
end | |
function love.update() | |
if R>255 then R=255 end if R<0 then R=0 end | |
if G>255 then G=255 end if G<0 then G=0 end | |
if B>255 then B=255 end if B<0 then B=0 end | |
mouse.x=love.mouse.getX() | |
mouse.y=love.mouse.getY() | |
if love.mouse.isDown("1") then | |
-- updates that can depend on dragging | |
if mouse.x>UI.x2 and mouse.x<UI.x2+UI.w2 and mouse.y>UI.y2 and mouse.y<UI.y2+UI.h2 then | |
if current_shape == 'dot' then | |
table.insert(shapes_committed,{shape='dot', x=love.mouse.getX(),y=love.mouse.getY(),Vermelho=R,Verde=G,Azul=B}) | |
elseif current_shape == 'freehand' then | |
--? generate_freehand(mouse) | |
table.insert(pending.points, {x=love.mouse.getX(), y=love.mouse.getY()}) | |
elseif current_shape == 'line' then | |
elseif current_shape == 'circle' then | |
end | |
end | |
if mouse.x>UI.uprx and mouse.x<UI.uprx+19 and mouse.y>UI.upry and mouse.y<UI.upry+10 then R=R+1 end | |
if mouse.x>UI.downrx and mouse.x<UI.downrx+19 and mouse.y>UI.downry and mouse.y<UI.downry+10 then R=R-1 end | |
if mouse.x>UI.upgx and mouse.x<UI.upgx+19 and mouse.y>UI.upgy and mouse.y<UI.upgy+10 then G=G+1 end | |
if mouse.x>UI.downgx and mouse.x<UI.downgx+19 and mouse.y>UI.downgy and mouse.y<UI.downgy+10 then G=G-1 end | |
if mouse.x>UI.upbx and mouse.x<UI.upbx+19 and mouse.y>UI.upby and mouse.y<UI.upby+10 then B=B+1 end | |
if mouse.x>UI.downbx and mouse.x<UI.downbx+19 and mouse.y>UI.downby and mouse.y<UI.downby+10 then B=B-1 end | |
end | |
end | |
function love.draw() | |
draw_shapes() | |
draw_menu() | |
end | |
function draw_menu() | |
color(50,50,50) | |
love.graphics.rectangle("fill",UI.x,UI.y,UI.w,UI.h) | |
color(255,255,255) | |
local width, height, flags = love.window.getMode() | |
love.graphics.print(mouse.x,5,height-UI.status_height) | |
love.graphics.print("|",35,height-UI.status_height) | |
love.graphics.print(mouse.y,45,height-UI.status_height) | |
color(R,G,B) | |
love.graphics.rectangle("fill",UI.colorx,UI.colory,60,60) | |
color(0,0,0) | |
love.graphics.rectangle("fill",UI.px,UI.py,25,25) | |
color(255,255,255) | |
love.graphics.rectangle("fill",UI.bx,UI.by,25,25) | |
color(255,0,0) | |
love.graphics.rectangle("fill",UI.vx,UI.vy,25,25) | |
color(0,255,0) | |
love.graphics.rectangle("fill",UI.vex,UI.vey,25,25) | |
color(0,0,255) | |
love.graphics.rectangle("fill",UI.ax,UI.ay,25,25) | |
color(255,255,0) | |
love.graphics.rectangle("fill",UI.amx,UI.amy,25,25) | |
color(255,128,0) | |
love.graphics.rectangle("fill",UI.lx,UI.ly,25,25) | |
color(255,128,255) | |
love.graphics.rectangle("fill",UI.rx,UI.ry,25,25) | |
color(0,128,192) | |
love.graphics.rectangle("fill",UI.acx,UI.acy,25,25) | |
color(163,73,164) | |
love.graphics.rectangle("fill",UI.rox,UI.roy,25,25) | |
if current_shape == 'dot' then | |
color(255,255,255) | |
love.graphics.rectangle('fill',UI.dotx,UI.doty,20,20) | |
color(R,G,B) | |
love.graphics.circle('fill', UI.dotx+10,UI.doty+10, 4) | |
else | |
color(192,192,192) | |
love.graphics.rectangle('fill',UI.dotx,UI.doty,20,20) | |
color(0,0,0) | |
love.graphics.circle('fill', UI.dotx+10,UI.doty+10, 4) | |
end | |
if current_shape == 'freehand' then | |
color(255,255,255) | |
love.graphics.rectangle('fill',UI.freehandx,UI.freehandy,20,20) | |
color(R,G,B) | |
freehand_icon(UI.freehandx, UI.freehandy) | |
else | |
color(192,192,192) | |
love.graphics.rectangle('fill',UI.freehandx,UI.freehandy,20,20) | |
color(0,0,0) | |
freehand_icon(UI.freehandx, UI.freehandy) | |
end | |
if current_shape == 'line' then | |
color(255,255,255) | |
love.graphics.rectangle('fill',UI.linex,UI.liney,20,20) | |
color(R,G,B) | |
love.graphics.line(UI.linex+4,UI.liney+2, UI.linex+16,UI.liney+18) | |
else | |
color(192,192,192) | |
love.graphics.rectangle('fill',UI.linex,UI.liney,20,20) | |
color(0,0,0) | |
love.graphics.line(UI.linex+4,UI.liney+2, UI.linex+16,UI.liney+18) | |
end | |
if current_shape == 'horvert' then | |
color(255,255,255) | |
love.graphics.rectangle('fill',UI.horvertx,UI.horverty,20,20) | |
color(R,G,B) | |
horvert_icon(UI.horvertx, UI.horverty) | |
else | |
color(192,192,192) | |
love.graphics.rectangle('fill',UI.horvertx,UI.horverty,20,20) | |
color(0,0,0) | |
horvert_icon(UI.horvertx, UI.horverty) | |
end | |
if current_shape == 'circle' then | |
color(255,255,255) | |
love.graphics.rectangle('fill',UI.circlex,UI.circley,20,20) | |
color(R,G,B) | |
love.graphics.circle('line', UI.circlex+10,UI.circley+10, 8) | |
else | |
color(192,192,192) | |
love.graphics.rectangle('fill',UI.circlex,UI.circley,20,20) | |
color(0,0,0) | |
love.graphics.circle('line', UI.circlex+10,UI.circley+10, 8) | |
end | |
color(255,255,255) | |
love.graphics.print("Red",400,25) | |
love.graphics.print(R,400,45) | |
love.graphics.draw(img,up,UI.uprx,UI.upry) | |
love.graphics.draw(img,down,UI.downrx,UI.downry) | |
love.graphics.print("Green",440,25) | |
love.graphics.print(G,440,45) | |
love.graphics.draw(img,up,UI.upgx,UI.upgy) | |
love.graphics.draw(img,down,UI.downgx,UI.downgy) | |
love.graphics.print("Blue",485,25) | |
love.graphics.print(B,485,45) | |
love.graphics.draw(img,up,UI.upbx,UI.upby) | |
love.graphics.draw(img,down,UI.downbx,UI.downby) | |
end | |
function draw_freehand_bounds() | |
color(0,0,0) | |
love.graphics.rectangle("line",200,200,300,300) | |
end | |
pending_freehand = {} | |
function generate_freehand(mouse) | |
local iconside = 20 | |
local function g(a) return math.floor((a-200)/(300/iconside)) end | |
local function f(a) return tostring(g(a)) end | |
local function far_enough(a, b) return math.abs(g(a)-g(b)) > 1 end | |
if mouse.x > 200 and mouse.y > 200 and mouse.x < 500 and mouse.y < 500 then | |
if pending_freehand.x == nil then | |
-- initialize | |
pending_freehand = {x=mouse.x, y=mouse.y} | |
end | |
if far_enough(mouse.x, pending_freehand.x) or far_enough(mouse.y, pending_freehand.y) then | |
print('love.graphics.line(x+'..f(pending_freehand.x)..',y+'..f(pending_freehand.y)..',x+'..f(mouse.x)..',y+'..f(mouse.y)..')') | |
pending_freehand = {x=mouse.x, y=mouse.y} | |
end | |
end | |
end | |
function freehand_icon(x, y) | |
-- generated by generate_freehand | |
love.graphics.line(x+4,y+7,x+5,y+5) | |
love.graphics.line(x+5,y+5,x+7,y+4) | |
love.graphics.line(x+7,y+4,x+9,y+3) | |
love.graphics.line(x+9,y+3,x+10,y+5) | |
love.graphics.line(x+10,y+5,x+12,y+6) | |
love.graphics.line(x+12,y+6,x+13,y+8) | |
love.graphics.line(x+13,y+8,x+13,y+10) | |
love.graphics.line(x+13,y+10,x+14,y+12) | |
love.graphics.line(x+14,y+12,x+15,y+14) | |
love.graphics.line(x+15,y+14,x+15,y+16) | |
end | |
function horvert_icon(x, y) | |
love.graphics.line(x+2,y+4,x+6,y+4) | |
love.graphics.line(x+6,y+4,x+6,y+14) | |
love.graphics.line(x+6,y+14,x+14,y+14) | |
end | |
function draw_shapes() | |
color(255,255,255) | |
love.graphics.rectangle("fill",UI.x2,UI.y2,UI.w2,UI.h2) | |
local r = 4 | |
for i, v in ipairs(shapes_committed) do | |
color(v.Vermelho,v.Verde,v.Azul) | |
if v.shape == 'dot' then | |
love.graphics.circle("fill", v.x,v.y, 4) | |
elseif v.shape == 'line' then | |
love.graphics.line(v.x1, v.y1, v.x2, v.y2) | |
elseif v.shape == 'freehand' then | |
draw_freehand(v) | |
elseif v.shape == 'circle' then | |
love.graphics.circle('line', v.cx, v.cy, v.r) | |
end | |
end | |
--? draw_freehand_bounds() | |
if love.mouse.isDown("1") then | |
if pending.shape == 'line' then | |
color(pending.Vermelho, pending.Verde, pending.Azul) | |
love.graphics.line(pending.x1, pending.y1, mouse.x, mouse.y) | |
elseif pending.shape == 'horvert' then | |
color(pending.Vermelho, pending.Verde, pending.Azul) | |
if math.abs(mouse.x-pending.x1) > math.abs(mouse.y-pending.y1) then | |
love.graphics.line(pending.x1, pending.y1, mouse.x, pending.y1) | |
else | |
love.graphics.line(pending.x1, pending.y1, pending.x1, mouse.y) | |
end | |
elseif pending.shape == 'freehand' then | |
color(pending.Vermelho, pending.Verde, pending.Azul) | |
draw_freehand(pending) | |
elseif pending.shape == 'circle' then | |
color(pending.Vermelho, pending.Verde, pending.Azul) | |
love.graphics.circle('line', pending.cx, pending.cy, math.dist(pending.cx, pending.cy, mouse.x, mouse.y)) | |
end | |
end | |
end | |
function draw_freehand(v) | |
local prev | |
for _,p in ipairs(v.points) do | |
if prev then | |
love.graphics.line(prev.x,prev.y, p.x,p.y) | |
end | |
prev = p | |
end | |
end | |
function color(r, g, b) | |
-- "In versions prior to 11.0, color component values were within the range of 0 to 255 instead of 0 to 1." | |
-- https://love2d.org/wiki/love.graphics.setColor | |
love.graphics.setColor(r/255,g/255,b/255) | |
end | |
function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment