This commit is contained in:
lifestorm
2024-08-05 18:40:29 +03:00
parent c4d91bf369
commit 324f19217d
8040 changed files with 1853423 additions and 21 deletions

View File

@@ -0,0 +1,924 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
--[[
Three's Derma Lib
Made by Threebow
You are free to use this anywhere you like, or sell any addons
made using this, as long as I am properly accredited.
]]
local pairs = pairs
local ipairs = ipairs
local Color = Color
local render = render
local SysTime = SysTime
local Lerp, RealFrameTime = Lerp, RealFrameTime
local RoundedBox, RoundedBoxEx, NoTexture = draw.RoundedBox, draw.RoundedBoxEx, draw.NoTexture
local SetDrawColor, DrawRect = surface.SetDrawColor, surface.DrawRect
local DrawPoly = surface.DrawPoly
local sui = sui
local Panel = FindMetaTable("Panel")
--[[
Constants
]]
local BLUR = CreateMaterial("SUI.TDLib.Blur", "gmodscreenspace", {
["$basetexture"] = "_rt_fullframefb",
["$blur"] = (1 / 3) * 7,
})
local COL_WHITE_1 = Color(255, 255, 255)
local COL_WHITE_2 = Color(255, 255, 255, 30)
--[[
credits to http://slabode.exofire.net/circle_draw.shtml
]]
local calculate_circle do
local cos = math.cos
local sin = math.sin
local round = math.Round
local sqrt = math.sqrt
local pi = math.pi
calculate_circle = function(circle, x_centre, y_centre, r)
if circle.x == x_centre and circle.y == y_centre and circle.r == r then return end
local step = (2 * pi) / round(6 * sqrt(r))
local i = 0
for theta = 2 * pi, 0, -step do
local x = x_centre + r * cos(theta)
local y = y_centre - r * sin(theta)
i = i + 1
circle[i] = {
x = x,
y = y
}
end
for i = i + 1, #circle do
circle[i] = nil
end
circle.x = x_centre
circle.y = y_centre
circle.r = r
end
end
--[[
void DrawArc(float cx, float cy, float r, float start_angle, float arc_angle, int num_segments)
{
float theta = arc_angle / float(num_segments - 1);//theta is now calculated from the arc angle instead, the - 1 bit comes from the fact that the arc is open
float tangetial_factor = tanf(theta);
float radial_factor = cosf(theta);
float x = r * cosf(start_angle);//we now start at the start angle
float y = r * sinf(start_angle);
glBegin(GL_LINE_STRIP);//since the arc is not a closed curve, this is a strip now
for(int ii = 0; ii < num_segments; ii++)
{
glVertex2f(x + cx, y + cy);
float tx = -y;
float ty = x;
x += tx * tangetial_factor;
y += ty * tangetial_factor;
x *= radial_factor;
y *= radial_factor;
}
glEnd();
}
]]
local copy_color = function(color)
return Color(color.r, color.g, color.b, color.a)
end
local color_alpha = function(color, a)
color.a = a
return color
end
--[[
Collection of various utilities
]]
local TDLibUtil = {}
function TDLibUtil.DrawCircle(circle, x, y, r, color)
calculate_circle(circle, x, y, r)
SetDrawColor(color)
NoTexture()
DrawPoly(circle)
end
local DrawCircle = TDLibUtil.DrawCircle
do
local SetMaterial = surface.SetMaterial
local UpdateScreenEffectTexture, DrawTexturedRect, SetScissorRect = render.UpdateScreenEffectTexture, surface.DrawTexturedRect, render.SetScissorRect
local scrW, scrH = ScrW(), ScrH()
hook.Add("OnScreenSizeChanged", "SUI.TDLib", function()
scrW, scrH = ScrW(), ScrH()
end)
function TDLibUtil.BlurPanel(s)
local x, y = s:LocalToScreen(0, 0)
SetDrawColor(255, 255, 255)
SetMaterial(BLUR)
for i = 1, 2 do
UpdateScreenEffectTexture()
DrawTexturedRect(x * -1, y * -1, scrW, scrH)
end
end
function TDLibUtil.DrawBlur(x, y, w, h)
SetDrawColor(255, 255, 255)
SetMaterial(BLUR)
SetScissorRect(x, y, x + w, y + h, true)
for i = 1, 2 do
UpdateScreenEffectTexture()
DrawTexturedRect(-1, -1, scrW, scrH)
end
SetScissorRect(0, 0, 0, 0, false)
end
end
local LibClasses = {}
do
local on_funcs = {}
function LibClasses:On(name, func)
local old_func = self[name]
if not old_func then
self[name] = func
return self
end
local name_2 = name .. "_funcs"
-- we gotta avoid creating 13535035 closures
if not on_funcs[name] then
on_funcs[name] = function(s, a1, a2, a3, a4)
local funcs = s[name_2]
local i, n = 0, #funcs
::loop::
i = i + 1
if i <= n then
funcs[i](s, a1, a2, a3, a4)
goto loop
end
end
end
if not self[name_2] then
self[name] = on_funcs[name]
self[name_2] = {
old_func,
func
}
else
table.insert(self[name_2], func)
end
return self
end
end
do
local UnPredictedCurTime = UnPredictedCurTime
local transition_func = function(s)
local transitions = s.transitions
local i, n = 0, #transitions
::loop::
i = i + 1
if i <= n then
local v = transitions[i]
local name = v.name
local v2 = s[name]
if v.func(s) then
if v.start_0 then
v.start_1, v.start_0 = UnPredictedCurTime(), nil
end
if v2 ~= 1 then
s[name] = Lerp((UnPredictedCurTime() - v.start_1) / v.time, v2, 1)
end
else
if v.start_1 then
v.start_0, v.start_1 = UnPredictedCurTime(), nil
end
if v2 ~= 0 then
s[name] = Lerp((UnPredictedCurTime() - v.start_0) / v.time, v2, 0)
end
end
goto loop
end
end
function LibClasses:SetupTransition(name, time, func)
self[name] = 0
local transition = {
name = name,
time = time,
func = func,
start_0 = 0,
start_1 = 0,
}
if self.transitions then
for k, v in ipairs(self.transitions) do
if v.name == name then
self.transitions[k] = transition
return self
end
end
table.insert(self.transitions, transition)
else
self.transitions = {transition}
self:On("Think", transition_func)
end
return self
end
end
function LibClasses:ClearPaint()
self.Paint = nil
self.Paint_funcs = nil
local SetPaintBackgroundEnabled = self.SetPaintBackgroundEnabled
if SetPaintBackgroundEnabled then
SetPaintBackgroundEnabled(self, false)
end
return self
end
function LibClasses:RoundedBox(id, r, x, y, w, h, c)
self.colors = self.colors or {}
local colors = self.colors
local id_c = colors[id]
if not id_c then
id_c = Color(c:Unpack())
colors[id] = id_c
end
sui.lerp_color(id_c, c)
RoundedBox(r, x, y, w, h, id_c)
end
do
local SetFGColor = Panel.SetFGColor
local set_color = function(s, col)
s.m_colText = col
SetFGColor(s, col.r, col.g, col.b, col.a)
end
local paint = function(s)
local col = s.sui_textcolor
sui.lerp_color(col, s.new_col)
set_color(s, col)
end
function LibClasses:TextColor(c, use_paint)
local col = self.sui_textcolor
if not col then
col = Color(c:Unpack())
self.sui_textcolor = col
if use_paint then
self:On("Paint", paint)
end
end
if use_paint then
self.new_col = c
else
sui.lerp_color(col, c)
self:SetTextColor(col)
end
end
end
do
local fade_hover_Paint = function(s, w, h)
if s.FadeHovers ~= 0 then
color_alpha(s.fadehover_color, s.fadehover_old_alpha * s.FadeHovers)
if s.fadehover_radius > 0 then
RoundedBox(s.fadehover_radius, 0, 0, w, h, s.fadehover_color)
else
SetDrawColor(s.fadehover_color)
DrawRect(0, 0, w, h)
end
end
end
function LibClasses:FadeHover(color, time, radius, func)
color = copy_color(color or COL_WHITE_2)
self.fadehover_color = color
self.fadehover_radius = radius or 0
self.fadehover_old_alpha = color.a
self:SetupTransition("FadeHovers", time or 0.8, func or TDLibUtil.HoverFunc)
self:On("Paint", fade_hover_Paint)
return self
end
end
function LibClasses:BarHover(color, height, time)
color = color or COL_WHITE_1
height = height or 2
time = time or 1.6
self:SetupTransition("BarHovers", time, TDLibUtil.HoverFunc)
self:On("Paint", function(s, w, h)
if s.BarHovers ~= 0 then
local bar = Round(w * s.BarHovers)
SetDrawColor(color)
DrawRect((w / 2) - (bar / 2), h - height, bar, height)
end
end)
return self
end
do
local paint = function(s, w, h)
draw.RoundedBox(0, 0, 0, w, h, s.SUI_GetColor("line"))
end
function LibClasses:Line(dock, m1, m2, m3, m4)
self.making_line = true
local line = self:Add("SAM.Panel")
line:Dock(dock or TOP)
if self.line_margin then
line:DockMargin(unpack(self.line_margin))
else
line:DockMargin(m1 or 0, m2 or 0, m3 or 0, m4 or 10)
end
line.no_scale = true
line:SetTall(1)
line.Paint = paint
self.making_line = false
return line
end
function LibClasses:LineMargin(m1, m2, m3, m4)
self.line_margin = {m1 or 0, m2 or 0, m3 or 0, m4 or 0}
return self
end
end
do
local background_Paint_1 = function(s)
s:SetBGColor(s.background_color)
end
local background_Paint_2 = function(s, w, h)
RoundedBoxEx(s.background_radius, 0, 0, w, h, s.background_color, true, true, true, true)
end
local background_Paint_3 = function(s, w, h)
RoundedBoxEx(s.background_radius, 0, 0, w, h, s.background_color, s.background_r_tl, s.background_r_tr, s.background_r_bl, s.background_r_br)
end
function LibClasses:Background(color, radius, r_tl, r_tr, r_bl, r_br)
self.background_color = color
if isnumber(radius) and radius ~= 0 then
self.background_radius = radius
if isbool(r_tl) or isbool(r_tr) or isbool(r_bl) or isbool(r_br) then
self.background_r_tl = r_tl
self.background_r_tr = r_tr
self.background_r_bl = r_bl
self.background_r_br = r_br
self:On("Paint", background_Paint_3)
else
self:On("Paint", background_Paint_2)
end
else
self:SetPaintBackgroundEnabled(true)
self:On("ApplySchemeSettings", background_Paint_1)
self:On("PerformLayout", background_Paint_1)
end
return self
end
end
function LibClasses:CircleClick(color, speed, target_radius)
self.circle_click_color = color or COL_WHITE_2
speed = speed or 5
target_radius = isnumber(target_radius) and target_radius or false
local radius, alpha, click_x, click_y = 0, -1, 0, 0
local circle = {}
self:On("Paint", function(s, w)
if alpha >= 0 then
DrawCircle(circle, click_x, click_y, radius, ColorAlpha(self.circle_click_color, alpha))
local frame_time = RealFrameTime()
radius, alpha = Lerp(frame_time * speed, radius, target_radius or w), Lerp(frame_time * speed, alpha, -1)
end
end)
self:On("DoClick", function()
click_x, click_y = self:CursorPos()
radius, alpha = 0, self.circle_click_color.a
end)
return self
end
do
local min = math.min
function LibClasses:CircleClick2(color, speed, target_radius, start_radius)
color = color or COL_WHITE_2
local _color = Color(color:Unpack())
speed = speed or 5
target_radius = isnumber(target_radius) and target_radius or false
local radius, alpha = 0, -1
local circle = {}
self:On("Paint", function(s, w, h)
if alpha >= 0 then
_color.a = alpha
DrawCircle(circle, w / 2, h / 2, radius, _color)
local frame_time = RealFrameTime()
radius, alpha = Lerp(frame_time * speed, radius, target_radius or min(w, h) / 2), Lerp(frame_time * speed, alpha, -1)
end
end)
self:On("DoClick", function()
radius, alpha = start_radius or 0, color.a
end)
return self
end
end
-- https://github.com/Facepunch/garrysmod/pull/1520#issuecomment-410458090
function LibClasses:Outline(color, width)
color = color or COL_WHITE_1
width = width or 1
self:On("Paint", function(s, w, h)
SetDrawColor(color)
DrawRect(0, 0, w, width)
DrawRect(0, h - width, w, width)
DrawRect(0, width, width, h - (width * 2))
DrawRect(w - width, width, width, h - (width * 2))
end)
return self
end
function LibClasses:LinedCorners(color, len)
color = color or COL_WHITE_1
len = len or 15
self:On("Paint", function(s, w, h)
SetDrawColor(color)
DrawRect(0, 0, len, 1)
DrawRect(0, 1, 1, len - 1)
DrawRect(w - len, h - 1, len, 1)
DrawRect(w - 1, h - len, 1, len - 1)
end)
return self
end
function LibClasses:SideBlock(color, size, side)
color = color or COL_WHITE_1
size = size or 3
side = side or LEFT
self:On("Paint", function(s, w, h)
SetDrawColor(color)
if side == LEFT then
DrawRect(0, 0, size, h)
elseif side == TOP then
DrawRect(0, 0, w, size)
elseif size == RIGHT then
DrawRect(w - size, 0, size, h)
elseif side == BOTTOM then
DrawRect(0, h - size, w, size)
end
end)
return self
end
function LibClasses:Blur()
self:On("Paint", TDLibUtil.BlurPanel)
return self
end
do
local STENCILOPERATION_REPLACE = STENCILOPERATION_REPLACE
local STENCILOPERATION_ZERO = STENCILOPERATION_ZERO
local STENCILCOMPARISONFUNCTION_NEVER = STENCILCOMPARISONFUNCTION_NEVER
local STENCILCOMPARISONFUNCTION_EQUAL = STENCILCOMPARISONFUNCTION_EQUAL
local ClearStencil = render.ClearStencil
local SetStencilEnable = render.SetStencilEnable
local SetStencilWriteMask = render.SetStencilWriteMask
local SetStencilTestMask = render.SetStencilTestMask
local SetStencilFailOperation = render.SetStencilFailOperation
local SetStencilPassOperation = render.SetStencilPassOperation
local SetStencilZFailOperation = render.SetStencilZFailOperation
local SetStencilCompareFunction = render.SetStencilCompareFunction
local SetStencilReferenceValue = render.SetStencilReferenceValue
local color_white = color_white
local avatar_setplayer = function(s, ply, size)
s.avatar:SetPlayer(ply, size)
end
local avatar_setsteamid = function(s, steamid, size)
s.avatar:SetSteamID(steamid, size)
end
function LibClasses:CircleAvatar()
local avatar = self:Add("AvatarImage")
avatar:Dock(FILL)
avatar:SetPaintedManually(true)
self.avatar = avatar
self.SetSteamID = avatar_setsteamid
self.SetPlayer = avatar_setplayer
local circle = {}
local PaintManual = avatar.PaintManual
self.Paint = function(s, w, h)
ClearStencil()
SetStencilEnable(true)
SetStencilWriteMask(1)
SetStencilTestMask(1)
SetStencilFailOperation(STENCILOPERATION_REPLACE)
SetStencilPassOperation(STENCILOPERATION_ZERO)
SetStencilZFailOperation(STENCILOPERATION_ZERO)
SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_NEVER)
SetStencilReferenceValue(1)
local a = w / 2
DrawCircle(circle, a, a, a, color_white)
SetStencilFailOperation(STENCILOPERATION_ZERO)
SetStencilPassOperation(STENCILOPERATION_REPLACE)
SetStencilZFailOperation(STENCILOPERATION_ZERO)
SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
SetStencilReferenceValue(1)
PaintManual(avatar)
SetStencilEnable(false)
end
return self
end
end
do
function LibClasses:AnimationThinkInternal()
local systime = SysTime()
if self.Term and self.Term <= systime then
self:Remove()
return
end
local m_AnimList = self.m_AnimList
if not m_AnimList then return end
for i = #m_AnimList, 1, -1 do
local anim = m_AnimList[i]
if systime >= anim.StartTime then
local frac = math.TimeFraction(anim.StartTime, anim.EndTime, systime)
frac = math.Clamp(frac, 0, 1)
local Think = anim.Think
if Think then
Think(anim, self, frac ^ (1.0 - (frac - 0.5)))
end
if frac == 1 then
local OnEnd = anim.OnEnd
if OnEnd then
OnEnd(anim, self)
end
m_AnimList[i] = nil
end
end
end
end
local sort = function(a, b)
return a.EndTime > b.EndTime
end
function LibClasses:NewAnimation(length, delay, ease, callback)
delay = delay or 0
ease = ease or -1
if self.m_AnimQueue then
delay = delay + self:AnimTail()
self.m_AnimQueue = false
else
delay = delay + SysTime()
end
local anim = {
StartTime = delay,
EndTime = delay + length,
Ease = ease,
OnEnd = callback
}
self:SetAnimationEnabled(true)
if self.m_AnimList == nil then
self.m_AnimList = {}
end
table.insert(self.m_AnimList, anim)
table.sort(self.m_AnimList, sort)
self.AnimationThink = self.AnimationThinkInternal
return anim
end
local MoveThink = function(anim, panel, frac)
if not anim.startx then
anim.startx = panel.x
anim.starty = panel.y
end
local x = Lerp(frac, anim.startx, anim.x)
local y = Lerp(frac, anim.starty, anim.y)
panel:SetPos(x, y)
end
function LibClasses:MoveTo(x, y, length, delay, ease, callback)
if self.x == x and self.y == y then return end
local anim = self:NewAnimation(length, delay, ease, callback)
anim.x = x
anim.y = y
anim.Think = MoveThink
end
local SetSize = Panel.SetSize
local SizeThink = function(anim, panel, frac)
if not anim.startw then
anim.startw, anim.starth = panel:GetSize()
end
local w, h
if anim.sizew and anim.sizeh then
w = Lerp(frac, anim.startw, anim.w)
h = Lerp(frac, anim.starth, anim.h)
SetSize(panel, w, h)
elseif anim.sizew then
w = Lerp(frac, anim.startw, anim.w)
SetSize(panel, w, panel.starth)
else
h = Lerp(frac, anim.starth, anim.h)
SetSize(panel, panel.startw, h)
end
if panel:GetDock() > 0 then
panel:InvalidateParent()
end
end
function LibClasses:SizeTo(w, h, length, delay, ease, callback)
local anim = self:NewAnimation(length, delay, ease, callback)
if w ~= -1 then
anim.sizew = true
end
if h ~= -1 then
anim.sizeh = true
end
anim.w, anim.h = w, h
anim.Think = SizeThink
return anim
end
local SetVisible = Panel.SetVisible
local IsVisible = Panel.IsVisible
local is_visible = function(s)
local state = s.visible_state
if state ~= nil then
return state
else
return IsVisible(s)
end
end
function LibClasses:AnimatedSetVisible(visible, cb)
if visible == is_visible(self) then
if cb then
cb()
end
return
end
if visible then
SetVisible(self, true)
end
self.visible_state = visible
self:Stop()
self:AlphaTo(visible and 255 or 0, 0.2, 0, function()
SetVisible(self, visible)
self:InvalidateParent(true)
if cb then
cb()
end
end)
self:InvalidateParent(true)
end
function LibClasses:AnimatedToggleVisible()
self:AnimatedSetVisible(not is_visible(self))
end
function LibClasses:AnimatedIsVisible()
return is_visible(self)
end
end
function Panel:SUI_TDLib()
for k, v in pairs(LibClasses) do
self[k] = v
end
return self
end
TDLibUtil.Install = Panel.SUI_TDLib
local count = 0
TDLibUtil.Start = function()
count = count + 1
for k, v in pairs(LibClasses) do
if not Panel["SUI_OLD" .. k] then
local old = Panel[k]
if old == nil then
old = v
end
Panel[k], Panel["SUI_OLD" .. k] = v, old
end
end
end
TDLibUtil.End = function()
count = count - 1
if count > 0 then return end
for k, v in pairs(LibClasses) do
local old = Panel["SUI_OLD" .. k]
if old == v then
Panel[k] = nil
else
Panel[k] = old
end
Panel["SUI_OLD" .. k] = nil
end
end
TDLibUtil.HoverFunc = function(p)
return p:IsHovered() and not p:GetDisabled()
end
TDLibUtil.DrawOutlinedBox = function(radius, x, y, w, h, bg, outline, thickness)
thickness = thickness or 2
draw.RoundedBox(radius, x, y, w, h, outline)
draw.RoundedBox(radius, x + thickness, y + thickness, w - (thickness * 2), h - (thickness * 2), bg)
end
do
local cos, sin, sqrt = math.cos, math.sin, math.sqrt
local clamp, floor = math.Clamp, math.floor
local min, max = math.min, math.max
local calc_ellipse_points = function(rx, ry)
local points = sqrt(((rx * ry) / 2) * 6)
return max(points, 8)
end
local M_PI = 3.14159265358979323846
calc_rect = function(c, r, x, y, w, h)
if
(c.r == r) and
(c.x == x and c.y == y) and
(c.w == w and c.h == h)
then return end
r = clamp(r, 0, min(w, h) / 2)
local rx, ry = r, r
if w >= 0.02 then
rx = min(rx, w / 2.0 - 0.01)
end
if h >= 0.02 then
ry = min(ry, h / 2.0 - 0.01)
end
local points = max(calc_ellipse_points(rx, ry) / 4, 1)
points = floor(points)
local half_pi = M_PI / 2
local angle_shift = half_pi / (points + 1)
local phi = 0
for i = 1, points + 2 do
c[i] = {
x = x + rx * (1 - cos(phi)),
y = y + ry * (1 - sin(phi))
}
phi = phi + angle_shift
end
phi = half_pi
for i = points + 3, 2 * (points + 2) do
c[i] = {
x = x + w - rx * (1 + cos(phi)),
y = y + ry * (1 - sin(phi))
}
phi = phi + angle_shift
end
phi = 2 * half_pi
for i = (2 * (points + 2)) + 1, 3 * (points + 2) do
c[i] = {
x = x + w - rx * (1 + cos(phi)),
y = y + h - ry * (1 + sin(phi))
}
phi = phi + angle_shift
end
phi = 3 * half_pi
for i = (3 * (points + 2)) + 1, 4 * (points + 2) do
c[i] = {
x = x + rx * (1 - cos(phi)),
y = y + h - ry * (1 + sin(phi))
}
phi = phi + angle_shift
end
local last = (points + 2) * 4 + 1
c[last] = c[1]
for i = last + 1, #c do
c[i] = nil
end
c.r = r
c.x, c.y = x, y
c.w, c.h = w, h
end
TDLibUtil.RoundedBox = function(c, r, x, y, w, h, color)
calc_rect(c, r, x, y, w, h)
SetDrawColor(color)
NoTexture()
DrawPoly(c)
end
end
TDLibUtil.LibClasses = LibClasses
sui.TDLib = TDLibUtil