SneakySquid icon

FPS Graph

SneakySquid | PRO | 07/17/24 12:41:03 PM UTC (Edited) | 0 ⭐ | 558 👁️ | Never ⏰ | []
Lua |

5.41 KB

|

None

|

0 👍

/

0 👎

local fps = {}
 
do
    cvars.RemoveChangeCallback("fps_graph", "fps_graph")
    cvars.RemoveChangeCallback("fps_graph_width", "fps_graph_width")
    cvars.RemoveChangeCallback("fps_graph_points", "fps_graph_points")
 
    fps.X, fps.Y = 20, 20
    fps.W, fps.H = 0, 150
    fps.PointDistance = 0
 
    fps.max = GetConVar("fps_max")
    fps.graph = CreateClientConVar("fps_graph", "0", nil, nil, "Draw the FPS counter and/or graph, = 1 draws counter, = 2 draws bar graph and counter, = 3 draws line graph and counter.")
    fps.graph_points = CreateClientConVar("fps_graph_points", "60", nil, nil, "The number of points/bars the FPS graph will have.")
    fps.graph_width = CreateClientConVar("fps_graph_width", "500", nil, nil, "The FPS graph's target width. Will change to match the points.")
 
    fps.Gradient = Material("vgui/gradient-d")
    fps.Cache = setmetatable({}, {__index = function() return 0 end})
 
    fps.NextCount = 0
    fps.SinceLastUpdate = 0
    fps.LastFrameNumber = FrameNumber()
end
 
local function CountFrames()
    if (SysTime() < fps.NextCount) then return end
    fps.NextCount = SysTime() + 1
 
    local frames = FrameNumber()
    local diff = frames - fps.LastFrameNumber
    local limit = math.max(fps.max:GetInt(), 60)
 
    table.insert(fps.Cache, 1, math.Clamp(diff / limit, 0, 1))
 
    if (#fps.Cache > fps.graph_points:GetInt() + 1) then
        table.remove(fps.Cache)
    end
 
    fps.SinceLastUpdate = diff
    fps.LastFrameNumber = frames
end
 
local function DrawCounter()
    local x, y = fps.X, fps.Y
    local w, h = fps.W, fps.H
    local FPS = string.format("%i FPS", fps.SinceLastUpdate)
 
    if (fps.graph:GetInt() == 1) then
        draw.SimpleText(FPS, "DebugOverlay", x, y)
    else
        local mult = fps.Cache[1]
        local tx = x + w + 2
        local ty = y + (h - (h * mult))
 
        draw.SimpleText(FPS, "DebugOverlay", tx, ty, _, _, TEXT_ALIGN_CENTER)
    end
end
 
local function DrawBarGraph()
    local x, y = fps.X, fps.Y
    local w, h = fps.W, fps.H
 
    local pd = fps.PointDistance
    local points = fps.graph_points:GetInt()
 
    render.SetScissorRect(x, y, x + w, y + h, true)
        surface.SetDrawColor(0, 0, 0, 200)
        surface.DrawRect(x, y, w, h)
 
        for i = 1, points do
            local mult = fps.Cache[i]
 
            local bh = math.floor(h * mult)
            local bx = (x + w) - (i * pd)
            local by = y + (h - bh)
 
            surface.SetDrawColor(Color(255 - 255 * mult, 255 * mult, 0))
            surface.DrawRect(bx, by, pd, bh)
        end
    render.SetScissorRect(0, 0, 0, 0, false)
end
 
local function DrawLineGraph()
    local x, y = fps.X, fps.Y
    local w, h = fps.W, fps.H
 
    local pd = fps.PointDistance
    local points = fps.graph_points:GetInt()
 
    render.SetScissorRect(x, y, x + w, y + h, true)
        surface.SetDrawColor(0, 0, 0, 200)
        surface.DrawRect(x, y, w, h)
 
        render.ClearStencil()
 
        render.SetStencilEnable(true)
            render.SetStencilTestMask(0xFF)
            render.SetStencilWriteMask(0xFF)
            render.SetStencilReferenceValue(0x01)
 
            render.SetStencilCompareFunction(STENCIL_ALWAYS)
            render.SetStencilPassOperation(STENCIL_REPLACE)
 
            local first = fps.Cache[1]
 
            local pph = math.floor(h * first)
            local ppx = (x + w) - 1
            local ppy = y + (h - pph)
 
            for i = 2, points + 1 do
                local mult = fps.Cache[i]
 
                local ph = math.floor(h * mult)
                local px = ((x + w) - ((i - 1) * pd)) - 1
                local py = y + (h - ph)
 
                surface.SetDrawColor(0, 255, 0)
                surface.DrawLine(ppx, ppy, px, py)
 
                ppx, ppy = px, py
            end
 
            render.SetStencilCompareFunction(STENCIL_LESSEQUAL)
            render.SetStencilFailOperation(STENCIL_KEEP)
 
            surface.SetMaterial(fps.Gradient)
            surface.SetDrawColor(255, 0, 0)
            surface.DrawTexturedRect(x, y, w, h)
        render.SetStencilEnable(false)
    render.SetScissorRect(0, 0, 0, 0, false)
end
 
local function GraphChanged(_, old, new)
    old, new = tonumber(old) or 0, tonumber(new) or 0
 
    if (new > 0) then
        if (old <= 0) then
            fps.SinceLastUpdate = 0
            fps.LastFrameNumber = FrameNumber()
        end
 
        hook.Add("PreRender", "FPS Counter", CountFrames)
 
        if (new >= 1) then
            hook.Add("PostDrawHUD", "FPS Counter", DrawCounter)
 
            if (new == 2) then
                hook.Add("PostDrawHUD", "FPS Graph", DrawBarGraph)
            elseif (new >= 3) then
                hook.Add("PostDrawHUD", "FPS Graph", DrawLineGraph)
            else
                hook.Remove("PostDrawHUD", "FPS Graph")
            end
        end
    else
        table.Empty(fps.Cache)
 
        hook.Remove("PreRender", "FPS Counter")
        hook.Remove("PostDrawHUD", "FPS Counter")
        hook.Remove("PostDrawHUD", "FPS Graph")
    end
end
cvars.AddChangeCallback("fps_graph", GraphChanged, "fps_graph")
 
local function FindClosest(width, points)
    local low = width % points
    local high = (width + low) % points
 
    return low <= high and width - low or width + high
end
 
local function WidthChanged(_, _, new)
    local points = fps.graph_points:GetInt()
    fps.W = FindClosest(new, points)
    fps.PointDistance = fps.W / points
end
cvars.AddChangeCallback("fps_graph_width", WidthChanged, "fps_graph_width")
 
local function PointsChanged(_, old, new)
    old, new = tonumber(old) or 0, tonumber(new) or 60
 
    local target = fps.graph_width:GetInt()
    fps.W = FindClosest(target, new)
    fps.PointDistance = fps.W / new
 
    if (old < new) then return end
 
    local diff = old - new
 
    if (#fps.Cache - diff > new) then
        for i = 1, diff do
            table.remove(fps.Cache)
        end
    end
end
cvars.AddChangeCallback("fps_graph_points", PointsChanged, "fps_graph_points")
 
GraphChanged(_, _, fps.graph:GetInt())
WidthChanged(_, _, fps.graph_width:GetInt())

Comments