local Vector2 = require("Vector2") local BezierCurve = {} local width = 5 local interval = 1/10 BezierCurve.maxDepth = -1 BezierCurve.randSeed = love.math.random() BezierCurve.__index = BezierCurve local function dist(x1,y1,x2,y2) return ((x1-x2)^2+(y1-y2)^2)^0.5 end local function linearBezier(p1, p2) return (1-t)*p1 + t*p2 end function BezierCurve.new(class, points) return setmetatable({ _curve = love.math.newBezierCurve(points or {100,180,250,250,200,500}), selectedPoint = false }, class) end function BezierCurve:draw(drawPoints, drawLines, drawFinal) love.graphics.setLineJoin("bevel") love.graphics.setLineStyle("smooth") if drawLines then love.graphics.setLineWidth(width*0.25) local p = {} for i=1, self._curve:getControlPointCount() do table.insert(p, Vector2(self._curve:getControlPoint(i))) end BezierCurve.stringArt(p, 0) end if drawFinal then love.graphics.setLineWidth(width) love.graphics.setColor(0.8,0,0) love.graphics.line(self._curve:render()) end if drawPoints then love.graphics.setColor(0,0,0.8) for i=1,self._curve:getControlPointCount() do local x,y = self._curve:getControlPoint(i) love.graphics.circle("fill",x,y,width*1.25) end end end function BezierCurve:mousemoved(x, y) if self.selectedPoint then self._curve:setControlPoint(self.selectedPoint, x, y) end end function BezierCurve:mousepressed(x, y, button) if button == 1 then local isCtrl = love.keyboard.isDown("lctrl", "rctrl") for i=1,self._curve:getControlPointCount() do if dist(x,y,self._curve:getControlPoint(i)) < width*1.25 then if isCtrl then self._curve:removeControlPoint(i) else self.selectedPoint = i end return end end if isCtrl then self._curve:insertControlPoint(x, y) end end end function BezierCurve:mousereleased(_, _, button) if button == 1 then self.selectedPoint = false end end function BezierCurve.stringArt(points, depth) if #points > 2 and (BezierCurve.maxDepth < 0 or depth < BezierCurve.maxDepth) then for t=0,1,interval do love.graphics.setColor(0.3,0.5,0.1) local p = {} for pointI=1, #points-1 do table.insert(p, (1-t)*points[pointI] + t*points[pointI+1]) end for pointI=1, #p-1 do love.graphics.line(p[pointI].x, p[pointI].y, p[pointI+1].x, p[pointI+1].y) end BezierCurve.stringArt(p, depth+1) end end end return BezierCurve