-- 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 .` -- maximize window love.window.setMode(0, 0) 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 Geometry') -- the window has 3 major parts: menu, drawing area and status bar status_height = 20 menux, menuy = 5, 5 menuw, menuh = width-10, 100 shapex, shapey = 5, 110 shapew, shapeh = width-10, height-status_height-115 -- state that affects the shape currently being drawn current_mode = 'line' -- valid modes: dot, line, radius, center, arcbegin, arcend current_red = 0 -- red component of current color (green and blue are always 0) current_radius = 100 current_end_angle = nil pending = {} -- shapes drawn in the past shapes_committed = {} function love.draw() draw_shapes() draw_menu() end -- ### Rendering shapes -- This section takes current_mode largely for granted. function draw_shapes() love.graphics.setColor(1,1,1) love.graphics.rectangle('fill', shapex,shapey, shapew,shapeh) for i, v in ipairs(shapes_committed) do love.graphics.setColor(v.R, 0, 0) if v.shape == 'line' then love.graphics.line(v.x1,v.y1, v.x2,v.y2) elseif v.shape == 'point' then love.graphics.circle('fill', v.x,v.y, 2) elseif v.shape == 'arc' then love.graphics.arc('line', 'open', v.cx,v.cy, v.r, v.s,v.e, 360) end end if pending.shape == 'arc' then love.graphics.setColor(0.75, 0.75, 0.75) love.graphics.circle('line', pending.cx,pending.cy, pending.r) end if love.mouse.isDown('1') then if pending.shape == 'line' then love.graphics.setColor(pending.R, 0, 0) love.graphics.line(pending.x1,pending.y1, love.mouse.getX(),love.mouse.getY()) elseif pending.shape == 'radius' then love.graphics.setColor(0.75, 0.75, 0.75) love.graphics.line(pending.x1,pending.y1, love.mouse.getX(),love.mouse.getY()) elseif pending.shape == 'arc' then if pending.s then current_end_angle = angle_with_hint(pending.cx,pending.cy, love.mouse.getX(),love.mouse.getY(), current_end_angle) love.graphics.setColor(pending.R, 0, 0) love.graphics.arc('line', 'open', pending.cx,pending.cy, pending.r, pending.s, current_end_angle, 360) end end end end -- Summary of mouse events: -- drawing lines: press(x1,y1) -> release(x2,y2) -- setting radius: press -> release(radius) -- drawing arcs: press(center), press(start_angle) -> press(end_angle) -- (current_mode changes here from 'center' to 'arcbegin' to 'arcend') function love.mousepressed(x, y, button) menu_pressed(x, y, button) if button == 1 then if x>shapex and xshapey and yshapex and xshapey and y hint+math.pi/10 do result = result-math.pi*2 end while result < hint-math.pi/10 do result = result+math.pi*2 end end return result end -- result is from -π/2 to 3π/2, approximately adding math.atan2 from Lua 5.3 -- (LÖVE is Lua 5.1) function angle(x1,y1, x2,y2) local result = math.atan((y2-y1)/(x2-x1)) if x2 < x1 then result = result+math.pi end return result end function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end -- ### Menu area and widgets -- Here we update current_mode. events = {} function draw_menu() events = {} love.graphics.setColor(0.2, 0.2, 0.2) love.graphics.rectangle('fill', menux,menuy, menuw,menuh) local width, height, flags = love.window.getMode() love.graphics.setColor(1, 1, 1) love.graphics.print(love.mouse.getX(), 5, height-status_height) love.graphics.print("|", 35,height-status_height) love.graphics.print(love.mouse.getY(), 45, height-status_height) button('color', {x=25,y=25, w=50,h=50, color={current_red,0,0}, onpress1 = function() current_red = 1 - current_red end}) button('point', {x=100,y=25, w=50,h=50, color = (current_mode == 'point' and {1,1,1} or {0.75,0.75,0.75}), icon = function() love.graphics.setColor(current_mode == 'point' and current_red or 0, 0, 0) love.graphics.circle('fill', 100+50/2,25+50/2, 2) end, onpress1 = function() current_mode = 'point' end}) button('line', {x=175,y=25, w=50,h=50, color = (current_mode == 'line' and {1,1,1} or {0.75,0.75,0.75}), icon = function() love.graphics.setColor(current_mode == 'line' and current_red or 0, 0, 0) love.graphics.line(175+5,25, 175+50-5,25+50) end, onpress1 = function() current_mode = 'line' end}) button('radius', {x=250,y=25, w=50,h=50, color = (current_mode == 'radius' and {1,1,1} or {0.75,0.75,0.75}), icon = function() local y = 25+50/2 love.graphics.setColor(current_mode == 'radius' and current_red or 0, 0, 0) love.graphics.circle('fill', 250+10,y, 2) love.graphics.line(250+10,y, 250+40,y) love.graphics.circle('fill', 250+40,y, 2) love.graphics.setColor(0.5, 0.5, 0.5) love.graphics.arc('line', 'open', 250+10,y, 30, 1/2,-1/2) end, onpress1 = function() current_mode = 'radius' end}) local arc_pressed = one_of(current_mode, {'center', 'arcbegin', 'arcend'}) button('arc', {x=325,y=25, w=50,h=50, color = (arc_pressed and {1,1,1} or {0.75,0.75,0.75}), icon = function() local y = 25+50/2 love.graphics.setColor(0.5, 0.5, 0.5) love.graphics.line(325+10,y, 325+40,y) love.graphics.setColor(arc_pressed and current_red or 0, 0, 0) love.graphics.arc('line', 'open', 325+10,y, 30, 1/2,-1/2) end, onpress1 = function() current_mode = 'center' end}) end -- draw button and queue up event handlers function button(name, params) love.graphics.setColor(params.color[1], params.color[2], params.color[3]) love.graphics.rectangle('fill', params.x,params.y, params.w,params.h) if params.icon then params.icon() end table.insert(events, params) end -- process button event handlers function menu_pressed(x, y, button) for _,ev in ipairs(events) do if x>ev.x and xev.y and y