SneakySquid icon

Lines!

SneakySquid | PRO | 07/17/24 12:38:54 PM UTC (Edited) | 0 ⭐ | 1070 👁️ | Never ⏰ | []
Lua |

3.61 KB

|

None

|

0 👍

/

0 👎

LINE_CORNER_NONE = 0
LINE_CORNER_MITER = 1
LINE_CORNER_ROUND = 2
 
do
    local plotting = false
    local plots, quads = {}, {}
    local plot_count, quad_count = 0, 0
 
    local thickness = 0
    local min_angle = 0
    local corner_type = 0
 
    function draw.StartLine(_thickness, _min_angle, _corner_type)
        assert(not plotting, "how come your mom lets you have 2 lines")
 
        plotting = true
        plot_count, quad_count = 0, 0
 
        thickness = (tonumber(_thickness) or 10) / 2
        min_angle = math.pi - math.rad(tonumber(_min_angle) or 20)
        corner_type = tonumber(_corner_type) or 0
    end
 
    function draw.AddLinePoint(x, y)
        assert(plotting, "better start a line boy")
 
        if not y then
            y = x.y
            x = x.x
        end
 
        plot_count = plot_count + 1
        plots[plot_count] = Vector(x, y)
    end
 
    function draw.EndLine()
        assert(plotting, "cut me point 2 g fam")
        plotting = false
 
        assert(plot_count > 1, "A minimum of 2 points are required to draw a line.")
 
        for i = 1, plot_count - 1 do
            local a, b = plots[i], plots[i + 1]
 
            local ab = b - a
            ab:Normalize()
 
            local ab_right = Vector(-ab.y, ab.x)
 
            quad_count = quad_count + 1
            quads[quad_count] = {
                a + ab_right * thickness,
                a - ab_right * thickness,
                b - ab_right * thickness,
                b + ab_right * thickness,
            }
        end
 
        if plot_count >= 3 then
            for i = 2, plot_count - 1 do
                local a, b, c = unpack(plots, i - 1, i + 1)
 
                local left_quad = quads[i - 1]
                local right_quad = quads[i]
 
                local ab, bc do
                    ab = b - a
                    bc = c - b
 
                    ab:Normalize()
                    bc:Normalize()
                end
 
                local angle = math.acos(ab:Dot(bc))
                local bc_right = Vector(-bc.y, bc.x)
 
                local is_left = false
                if ab:Dot(bc_right) > 0 then
                    is_left = true
                end
 
                if corner_type == LINE_CORNER_MITER then
                    local height = thickness / math.cos(angle / 2)
                    local joint_direction = bc - ab
                    joint_direction:Normalize()
 
                    if is_left then
                        joint_direction = -joint_direction
                    end
 
                    if angle <= min_angle then
                        left_quad[3] = b - joint_direction * height
                        left_quad[4] = b + joint_direction * height
 
                        right_quad[1] = left_quad[4]
                        right_quad[2] = left_quad[3]
                    end
                elseif corner_type == LINE_CORNER_ROUND then
                    local bd = (is_left and left_quad[4] or right_quad[2]) - b
                    bd:Normalize()
 
                    local step = 1 / thickness
                    local theta = (0.5 * math.pi - math.atan2(bd.y, bd.x)) % math.tau
 
                    mesh.Begin(MATERIAL_POLYGON, 1)
                        for a = theta, theta + angle + step, step do
                            local sin, cos = math.sin(a), math.cos(a)
                            local pos = b + Vector(sin, cos) * thickness
 
                            mesh.Position(pos)
                            mesh.AdvanceVertex()
                        end
 
                        mesh.Position(b)
                        mesh.AdvanceVertex()
                    mesh.End()
                end
            end
        end
 
        mesh.Begin(MATERIAL_QUADS, quad_count)
            for i, quad in ipairs(quads) do
                mesh.Quad(unpack(quad))
            end
        mesh.End()
    end
end
 
 
--[[
 
    EXAMPLE
 
]]--
 
 
local plots = {}
for i = 1, 20 do
    if #plots == 0 then
        table.insert(plots, Vector(ScrW() / 2, ScrH() / 2))
    else
        local rand_direction = Vector(math.Rand(-1, 1), math.Rand(-1, 1))
        rand_direction:Normalize()
 
        local last_plot = plots[#plots]
        table.insert(plots, last_plot + rand_direction * math.random(100, 400))
    end
end
 
hook.Add("PostRender", "", function()
    cam.Start2D()
        surface.SetDrawColor(255, 255 ,255)
        render.SetMaterial(Material("vgui/white"))
 
        draw.StartLine(50, 15, math.floor(CurTime() % 3))
            for i, plot in ipairs(plots) do
                draw.AddLinePoint(plot)
            end
        draw.EndLine()
    cam.End2D()
end)

Comments