This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 8064ba84d8
commit 73479cff9e
7338 changed files with 1718883 additions and 14 deletions

View File

@@ -0,0 +1,192 @@
--[[
| 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/
--]]
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TDLib = sui.TDLib
local draw_material = sui.draw_material
local lerp_color = sui.lerp_color
local GetColor = SUI.GetColor
local RoundedBox = TDLib.RoundedBox
local CircleAvatar = TDLib.LibClasses.CircleAvatar
local CircleClick2 = TDLib.LibClasses.CircleClick2
local PLAYER_LINE_NAME = SUI.CreateFont("PlayerLineName", "Roboto Bold", 17)
local PLAYER_LINE_RANK = SUI.CreateFont("PlayerLineRank", "Roboto Bold", 13)
local PLAYER_LINE_STEAMID = SUI.CreateFont("PlayerLineSteamID", "Roboto Medium", 12)
local PANEL = {}
function PANEL:Init()
local size = SUI.Scale(34)
self:Dock(TOP)
self:SetTall(size)
self.size = size
end
local rank_Paint = function(s, w, h)
RoundedBox(s.rect, SUI.Scale(10), 0, 0, w, h, s.col)
end
function PANEL:SetInfo(info)
local size = self.size
local container
do
local w = SUI.Scale(280) + size
local _container = self:Add("Panel")
_container:Dock(LEFT)
_container:SetMouseInputEnabled(false)
_container:SetWide(w)
container = _container:Add("Panel")
container:SetSize(w, size)
function _container:PerformLayout()
container:Center()
end
end
do
local avatar = container:Add("Panel")
avatar:Dock(LEFT)
avatar:DockMargin(0, 0, 5, 0)
avatar:SetWide(size)
avatar:SetMouseInputEnabled(false)
CircleAvatar(avatar)
avatar:SetSteamID(util.SteamIDTo64(info.steamid), size)
end
do
local top_container = container:Add("Panel")
top_container:Dock(TOP)
top_container:DockMargin(0, 0, 0, 2)
local name = top_container:Add("SAM.Label")
name:Dock(LEFT)
name:SetFont(PLAYER_LINE_NAME)
self.name = name
local pname = info.name
if not pname or pname == "" then
name:SetTextColor(GetColor("player_list_names_2"))
self:SetName("N/A")
else
name:SetTextColor(GetColor("player_list_names"))
self:SetName(pname)
end
if info.rank then
local rank_bg = top_container:Add("Panel")
rank_bg:Dock(LEFT)
rank_bg:DockMargin(5, 0, 0, 0)
rank_bg.rect = {}
rank_bg.col = info.rank_bg or GetColor("player_list_rank")
rank_bg.Paint = rank_Paint
local rank = rank_bg:Add("SAM.Label")
rank:Dock(FILL)
rank:DockMargin(SUI.Scale(8), 0, 0, 0)
rank:SetTextColor(GetColor("player_list_rank_text"))
rank:SetFont(PLAYER_LINE_RANK)
rank.bg = rank_bg
self.rank = rank
self:SetRank(info.rank)
rank_bg:SetSize(rank:GetTextSize() + SUI.Scale(8) * 2)
end
top_container:SizeToChildren(true, true)
end
local steamid = container:Add("SAM.Label")
steamid:Dock(TOP)
steamid:SetTextColor(GetColor("player_list_steamid"))
steamid:SetFont(PLAYER_LINE_STEAMID)
steamid:SetText(info.steamid)
steamid:SizeToContents()
steamid:SetAutoStretchVertical(true)
self.container = container
end
function PANEL:SetName(new_name)
local name = self.name
name:SetText(new_name)
name:SizeToContents()
if name:GetWide() > 160 then
name:SetWide(158)
end
end
function PANEL:SetRank(new_rank)
local rank = self.rank
rank:SetText(new_rank)
rank:SizeToContents()
rank.bg:SetSize(rank:GetTextSize() + SUI.Scale(8) * 2)
end
function PANEL:Actions()
local container
do
local size = self.size
local _container = self:Add("Panel")
_container:Dock(RIGHT)
_container:SetWide(size)
container = _container:Add("Panel")
container:SetSize(size, size)
function _container:PerformLayout()
container:Center()
end
end
local actions_button = container:Add("SAM.Button")
actions_button:SetText("")
actions_button:ClearPaint()
function container:PerformLayout(w, h)
actions_button:SetSize(h, h)
actions_button:Center()
end
local image = actions_button:Add("SAM.Image")
image:Dock(FILL)
image:SetImage("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sam/dots_verticle.png")
local current_icon_color = Color(GetColor("actions_button_icon"):Unpack())
function image:Draw(w, h)
if not h then return end
if actions_button.Hovered then
lerp_color(current_icon_color, GetColor("actions_button_icon_hover"))
else
lerp_color(current_icon_color, GetColor("actions_button_icon"))
end
draw_material(nil, w / 2, h / 2, SUI.ScaleEven(20), current_icon_color)
end
CircleClick2(actions_button, Color(62, 62, 62), 10)
actions_button:Center()
return actions_button
end
sui.register("PlayerLine", PANEL, "Panel")

View File

@@ -0,0 +1,76 @@
--[[
| 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/
--]]
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TEXT_FONT = SUI.CreateFont("ComboBox", "Roboto Regular", 16)
local GetColor = SUI.GetColor
local draw_material = sui.draw_material
local PANEL = {}
PANEL.NoOverrideClear = true
sui.scaling_functions(PANEL)
function PANEL:Init()
self:ScaleInit()
self.DropButton:Remove()
self:SetFont(TEXT_FONT)
self:SetSize(34, 22)
self:SetIsMenu(true)
local image = self:Add(NAME .. ".Image")
image:Dock(FILL)
image:SetImage("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sui/arrow.png")
image.Draw = self.Paint
end
function PANEL:OpenMenu(pControlOpener)
if pControlOpener and pControlOpener == self.TextEntry then return end
if #self.Choices == 0 then return end
if IsValid(self.Menu) then
self.Menu:Remove()
self.Menu = nil
end
self.Menu = vgui.Create(NAME .. ".Menu", self)
self.Menu:SetInternal(self)
for k, v in ipairs(self.Choices) do
self.Menu:AddOption(v, function()
self:ChooseOption(v, k)
end)
end
local x, y = self:LocalToScreen(0, self:GetTall())
self.Menu:SetMinimumWidth(self:GetWide())
self.Menu:Open(x, y, false, self)
end
function PANEL:Paint(w, h, from_image)
local text_color = GetColor("menu_option_hover_text")
if from_image then
local size = SUI.ScaleEven(10)
draw_material(nil, w - (size / 2) - 6, h / 2, size, text_color)
else
local col = GetColor("menu")
self:RoundedBox("Background", 4, 0, 0, w, h, col)
self:SetTextColor(text_color)
end
end
function PANEL:PerformLayout()
end
sui.register("ComboBox", PANEL, "DComboBox")

326
lua/sui/vgui/sui_frame.lua Normal file
View File

@@ -0,0 +1,326 @@
--[[
| 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/
--]]
local math = math
local gui = gui
local draw = draw
local surface = surface
local ScrW = ScrW
local ScrH = ScrH
local IsValid = IsValid
local ipairs = ipairs
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TDLib = sui.TDLib
local FRAME_FONT = SUI.CreateFont("Frame", "Roboto", 18)
local Panel = FindMetaTable("Panel")
local PANEL = {}
AccessorFunc(PANEL, "m_bHeaderHeight", "HeaderHeight", FORCE_NUMBER)
AccessorFunc(PANEL, "m_bTitleFont", "TitleFont", FORCE_STRING)
AccessorFunc(PANEL, "m_bSizable", "Sizable", FORCE_BOOL)
AccessorFunc(PANEL, "m_iMinWidth", "MinWidth", FORCE_NUMBER)
AccessorFunc(PANEL, "m_iMinHeight", "MinHeight", FORCE_NUMBER)
local header_Think = function(s)
local parent = s.parent
local sw, sh = ScrW(), ScrH()
if s.dragging then
local x, y = input.GetCursorPos()
x, y = math.Clamp(x, 1, sw - 1), math.Clamp(y, 1, sh - 1)
x, y = x - s.dragging[1], y - s.dragging[2]
parent:SetPos(x, y)
parent:InvalidateLayout(true)
parent:OnPosChanged()
else
local x, y, w, h = parent:GetBounds()
parent:SetPos(math.Clamp(x, 5, sw - w - 5), math.Clamp(y, 5, sh - h - 5))
end
end
local header_OnMousePressed = function(s)
local parent = s.parent
s.dragging = {gui.MouseX() - parent.x, gui.MouseY() - parent.y}
s:MouseCapture(true)
end
local header_OnMouseReleased = function(s)
s.dragging = nil
s:MouseCapture(false)
end
local title_SetBGColor = function(s, c)
s:SetVisible(c and true or false)
end
local title_update_color = function(s)
s:SetTextColor(SUI.GetColor("title"))
end
local close_DoClick = function(s)
s.frame:Remove()
end
function PANEL:Init()
local header_buttons = {}
self.header_buttons = header_buttons
self:Center()
self:SetHeaderHeight(28)
local header = self:Add("PANEL")
header:Dock(TOP)
header.Paint = self.HeaderPaint
header:SetCursor("sizeall")
header.parent = self
header.Think = header_Think
header.OnMousePressed = header_OnMousePressed
header.OnMouseReleased = header_OnMouseReleased
self.header = header
local title = header:Add(NAME .. ".Label")
title:Dock(LEFT)
title:DockMargin(6, 2, 0, 2)
title:SetText("")
title:SetTextColor(SUI.GetColor("title"))
title:SizeToContents()
title.SetBGColor = title_SetBGColor
hook.Add(NAME .. ".ThemeChanged", title, title_update_color)
self.title = title
self.close = self:AddHeaderButton("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sui/close.png", "close", close_DoClick)
self.close.frame = self
self:SetSize(SUI.Scale(520), SUI.Scale(364))
self:SetTitleFont(FRAME_FONT)
SUI.OnScaleChanged(self, self.ScaleChanged)
function self:PerformLayout(w, h)
if IsValid(title) then
title:SizeToContents()
end
if IsValid(header) then
header:SetTall(SUI.Scale(self:GetHeaderHeight()))
end
for k, v in ipairs(header_buttons) do
if IsValid(v) then
v:SetWide(v:GetTall())
local margin = SUI.Scale(4)
v.image:DockMargin(margin, margin, margin, margin)
end
end
end
end
function PANEL:SetSize(w, h)
self.real_w, self.real_h = w, h
self:ScaleChanged()
end
function PANEL:HeaderPaint(w, h)
draw.RoundedBoxEx(3, 0, 0, w, h, SUI.GetColor("header"), true, true)
end
local SetSize = Panel.SetSize
PANEL.RealSetSize = SetSize
function PANEL:ScaleChanged()
if self.sizing then return end
local new_w, new_h = SUI.Scale(self.real_w), SUI.Scale(self.real_h)
self.x, self.y = self.x + (self:GetWide() / 2 - new_w / 2), self.y + (self:GetTall() / 2 - new_h / 2)
SetSize(self, new_w, new_h)
self:InvalidateLayout(true)
end
function PANEL:Paint(w, h)
if SUI.GetColor("frame_blur") then
TDLib.BlurPanel(self)
end
self:RoundedBox("Background", 3, 0, 0, w, h, SUI.GetColor("frame"))
end
function PANEL:SetTitleFont(font)
self.m_bTitleFont = font
self.title:SetFont(font)
end
function PANEL:SetTitle(text)
self.title:SetText(text)
self.title:SizeToContents()
end
function PANEL:AddHeaderButton(image_name, name, callback)
local button = self.header:Add("DButton")
button:SetText("")
button:Dock(RIGHT)
button:DockMargin(0, 2, #self.header:GetChildren() == 1 and 4 or 2, 2)
local hover = name .. "_hover"
local press = name .. "_press"
local circle = {}
button.Paint = function(s, w, h)
if s:IsHovered() then
TDLib.DrawCircle(circle, w / 2, h / 2, w / 2, SUI.GetColor(hover))
end
if s.Depressed then
TDLib.DrawCircle(circle, w / 2, h / 2, w / 2, SUI.GetColor(press))
end
end
button.DoClick = callback
local image = button:Add(NAME .. ".Image")
image:Dock(FILL)
image:SetMouseInputEnabled(false)
image:SetImage(image_name)
button.image = image
table.insert(self.header_buttons, button)
return button
end
function PANEL:OnMousePressed(_, checking)
if not self.m_bSizable then return end
local x, y = self:LocalToScreen(0, 0)
local w, h = self:GetSize()
if gui.MouseX() > (x + w - 20) and gui.MouseY() > (y + h - 20) then
if not checking then
self.sizing = {gui.MouseX() - w, gui.MouseY() - h}
self:MouseCapture(true)
end
self:SetCursor("sizenwse")
return
end
if checking then
self:SetCursor("arrow")
end
end
function PANEL:OnMouseReleased()
if not self.m_bSizable then return end
self:MouseCapture(false)
SUI.CallScaleChanged()
self.sizing = nil
end
function PANEL:Think()
if not self.m_bSizable then return end
self:OnMousePressed(nil, true)
if not self.sizing then return end
local sw, sh = ScrW(), ScrH()
local cx, cy = input.GetCursorPos()
local mousex = math.Clamp(cx, 1, sw - 1)
local mousey = math.Clamp(cy, 1, sh - 1)
local x = mousex - self.sizing[1]
x = math.Clamp(x, self.m_iMinWidth, sw - 10)
local y = mousey - self.sizing[2]
y = math.Clamp(y, self.m_iMinHeight, sh - 10)
self.real_w, self.real_h = x, y
SetSize(self, x, y)
self:InvalidateLayout(true)
self:SetCursor("sizenwse")
end
function PANEL:OnPosChanged()
end
local SetVisible = Panel.SetVisible
local Remove = Panel.Remove
local anim_speed = 0.2
local show = function(s)
local w, h = s.real_w, s.real_h
if s.anim_scale then
w, h = SUI.Scale(w), SUI.Scale(h)
end
SetVisible(s, true)
SetSize(s, w * 1.1, h * 1.1)
s:Center()
s:Stop()
s:SizeTo(w, h, anim_speed, 0, -1)
s:MoveTo((ScrW() / 2) - (w / 2), (ScrH() / 2) - (h / 2), anim_speed, 0, -1)
s:AlphaTo(255, anim_speed + 0.02, 0)
s:MakePopup()
end
local remove = function(s, hide)
if not hide and not s:IsVisible() then
Remove(s)
return
end
local w, h = s.real_w, s.real_h
if s.anim_scale then
w, h = SUI.Scale(w), SUI.Scale(h)
end
w, h = w * 1.1, h * 1.1
s:Stop()
s:SizeTo(w, h, anim_speed, 0, -1)
s:MoveTo((ScrW() / 2) - (w / 2), (ScrH() / 2) - (h / 2), anim_speed, 0, -1)
s:SetMouseInputEnabled(false)
s:SetKeyboardInputEnabled(false)
s:AlphaTo(0, anim_speed + 0.02, 0, function()
if hide then
SetVisible(s, false)
else
Remove(s)
end
end)
end
local hide = function(s)
remove(s, true)
end
function PANEL:AddAnimations(w, h, no_scale)
self.anim_scale = not no_scale
self.real_w, self.real_h = w, h
self:SetAlpha(0)
show(self)
self.Remove = remove
self.Hide = hide
self.Show = show
end
sui.register("Frame", PANEL, "EditablePanel")

334
lua/sui/vgui/sui_image.lua Normal file
View File

@@ -0,0 +1,334 @@
--[[
| 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/
--]]
local table = table
local file = file
local coroutine = coroutine
local surface = surface
local UnPredictedCurTime = UnPredictedCurTime
local pairs = pairs
local color_white = color_white
local sui = sui
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local read_gif = include("sui/libs/gif_loader.lua")
local generate_png = include("sui/libs/png_encoder.lua")
local images_path = (NAME .. "/images/"):lower()
file.CreateDir(images_path)
local get_image_path = function(url)
return images_path .. (url:gsub("%W", "_") .. ".png")
end
local Write = file.Write
local gif_to_png; do
local internal_gif_to_png = function(file_path, chunk)
local gif = read_gif(chunk)
local frames = gif:get_frames()
local w, h = gif.width, gif.height
local path = file_path .. "/"
file.CreateDir(path)
for frame_id = 1, #frames do
local frame = frames[frame_id]
local data = frame.data
local png = generate_png(w, h, data)
Write(("%s%d_%d.png"):format(path, frame_id, frame.delay), png)
coroutine.yield()
end
end
local delay = 0.01
local next_run = 0
local coroutines = {}
local callbacks = {}
gif_to_png = function(file_path, data, callback)
local co = coroutine.create(internal_gif_to_png)
local i = table.insert(coroutines, co)
callbacks[i] = callback
coroutine.resume(co, file_path, data)
next_run = UnPredictedCurTime()
end
hook.Add("Think", NAME .. "ProcessGIFs", function()
local co = coroutines[1]
if not co then return end
if UnPredictedCurTime() < next_run then return end
if coroutine.status(co) == "suspended" then
coroutine.resume(co)
else
callbacks[1]()
table.remove(coroutines, 1)
table.remove(callbacks, 1)
end
next_run = UnPredictedCurTime() + delay
end)
hook.Add(NAME .. "ImagesCleared", "ClearCoroutines", function()
table.Empty(coroutines)
table.Empty(callbacks)
end)
end
local download_image, is_downloading_image; do
-- https://stackoverflow.com/questions/25959386/how-to-check-if-a-file-is-a-valid-image
local valid_images = {
["\xff\xd8\xff"] = "jpeg",
["\x89PNG\r\n\x1a\n"] = "png",
["GIF87a"] = "gif",
["GIF89a"] = "gif",
}
local get_image_type = function(data)
for k, v in pairs(valid_images) do
if data:StartWith(k) then
return v
end
end
return false
end
local downloading_images = {}
local process_callbacks = function(url)
local callbacks = downloading_images[url] or {}
downloading_images[url] = nil
for _, func in ipairs(callbacks) do
func()
end
end
download_image = function(url, callback)
if downloading_images[url] then
table.insert(downloading_images[url], callback)
return
end
downloading_images[url] = {callback}
http.Fetch(url, function(data)
local image_type = get_image_type(data)
if not image_type then
downloading_images[url] = nil
return
end
local image_path = get_image_path(url)
if image_type == "gif" then
gif_to_png(image_path, data, function()
process_callbacks(url)
end)
else
file.Write(image_path, data)
process_callbacks(url)
end
end, function(err)
print("(SUI) Failed to download an image, error: " .. err)
downloading_images[url] = nil
end)
end
is_downloading_image = function(url)
return downloading_images[url] ~= nil
end
hook.Add(NAME .. "ImagesCleared", "ClearDownloadingImages", function()
table.Empty(downloading_images)
end)
end
local images_panels = {}
local PANEL = {}
local err_mat = SUI.Material("error")
function PANEL:Init()
self:SetMouseInputEnabled(false)
self.minus = 0
self.rotation = 0
self.image = err_mat
self.image_col = color_white
table.insert(images_panels, self)
end
function PANEL:OnRemove()
for k, v in ipairs(images_panels) do
if v == self then
table.remove(images_panels, k)
return
end
end
end
function PANEL:SetMinus(minus)
self.minus = minus
end
function PANEL:SetRotation(rotation)
self.rotation = rotation
end
function PANEL:SetImageColor(col)
self.image_col = col
end
local cached_files = {}
local get_files = function(image_path)
local f = cached_files[image_path]
if f then return f end
cached_files[image_path] = file.Find(image_path .. "/*", "DATA")
return cached_files[image_path]
end
function PANEL:SetImage(url)
self.image = err_mat
self.pos = nil
self.delay = nil
self.images = nil
self.delays = nil
self.url = url
if url:sub(1, 4) ~= "http" then
self.image = SUI.Material(url)
return
end
local image_path = get_image_path(url)
if not file.Exists(image_path, "DATA") or is_downloading_image(url) then
download_image(url, function()
if self:IsValid() then
self:SetImage(url)
end
end)
return
end
local is_gif = file.IsDir(image_path, "DATA")
if is_gif then
local images = {}
local delays = {}
local files = get_files(image_path)
for i = 1, #files do
local v = files[i]
local id, delay = v:match("(.*)_(.*)%.png")
id = tonumber(id)
local img_path = "../data/" .. image_path .. "/" .. v
images[id] = img_path
delays[id] = delay
end
self.frame = 1
self.delay = (UnPredictedCurTime() * 100) + delays[1]
self.images = images
self.delays = delays
self.max_images = #files
else
self.image = SUI.Material("../data/" .. image_path)
end
end
local SetMaterial = surface.SetMaterial
function PANEL:PaintGIF(w, h, images)
local frame = self.frame
-- SUI.Material() caches materials by default
local mat = SUI.Material(images[frame], true)
if not mat then
if frame > 1 then
mat = SUI.Material(images[frame - 1])
else
mat = err_mat
end
SetMaterial(mat)
return
end
SetMaterial(mat)
local curtime = UnPredictedCurTime() * 100
if curtime < self.delay then return end
frame = frame + 1
if frame > self.max_images then
frame = 1
end
self.frame = frame
self.delay = curtime + self.delays[frame]
end
local PaintGIF = PANEL.PaintGIF
local SetDrawColor = surface.SetDrawColor
local DrawTexturedRectRotated = surface.DrawTexturedRectRotated
function PANEL:Paint(w, h)
SetDrawColor(self.image_col)
local images = self.images
if images then
PaintGIF(self, w, h, images)
else
SetMaterial(self.image)
end
if self.Draw then
self:Draw(w, h, true)
else
local minus = self.minus
DrawTexturedRectRotated(w * 0.5, h * 0.5, w - minus, h - minus, self.rotation)
end
end
sui.register("Image", PANEL, "PANEL")
function SUI.ClearImages()
local files, dirs = file.Find(images_path .. "/*", "DATA")
for _, f in ipairs(files) do
file.Delete(images_path .. f)
end
for _, d in ipairs(dirs) do
for _, f in ipairs(file.Find(images_path .. d .. "/*", "DATA")) do
file.Delete(images_path .. (d .. "/" .. f))
end
file.Delete(images_path .. d)
end
table.Empty(SUI.materials)
table.Empty(cached_files)
hook.Call(NAME .. "ImagesCleared")
for k, v in ipairs(images_panels) do
if v.url then
v:SetImage(v.url)
end
end
end

220
lua/sui/vgui/sui_label.lua Normal file
View File

@@ -0,0 +1,220 @@
--[[
| 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/
--]]
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local MOUSE_LEFT = MOUSE_LEFT
local SysTime = SysTime
local PANEL = {}
AccessorFunc(PANEL, "m_colText", "TextColor")
AccessorFunc(PANEL, "m_colTextStyle", "TextStyleColor")
AccessorFunc(PANEL, "m_FontName", "Font")
AccessorFunc(PANEL, "m_bDoubleClicking", "DoubleClickingEnabled", FORCE_BOOL)
AccessorFunc(PANEL, "m_bAutoStretchVertical", "AutoStretchVertical", FORCE_BOOL)
AccessorFunc(PANEL, "m_bIsMenuComponent", "IsMenu", FORCE_BOOL)
AccessorFunc(PANEL, "m_bBackground", "PaintBackground", FORCE_BOOL)
AccessorFunc(PANEL, "m_bBackground", "DrawBackground", FORCE_BOOL)
AccessorFunc(PANEL, "m_bDisabled", "Disabled", FORCE_BOOL)
AccessorFunc(PANEL, "m_bIsToggle", "IsToggle", FORCE_BOOL)
AccessorFunc(PANEL, "m_bToggle", "Toggle", FORCE_BOOL)
AccessorFunc(PANEL, "m_bBright", "Bright", FORCE_BOOL)
AccessorFunc(PANEL, "m_bDark", "Dark", FORCE_BOOL)
AccessorFunc(PANEL, "m_bHighlight", "Highlight", FORCE_BOOL)
PANEL:SetIsToggle(false)
PANEL:SetToggle(false)
PANEL:SetDisabled(false)
PANEL:SetDoubleClickingEnabled(true)
local Panel = FindMetaTable("Panel")
local SetMouseInputEnabled = Panel.SetMouseInputEnabled
local SetPaintBackgroundEnabled = Panel.SetPaintBackgroundEnabled
local SetPaintBorderEnabled = Panel.SetPaintBorderEnabled
local InvalidateLayout = Panel.InvalidateLayout
local SetFGColor = Panel.SetFGColor
function PANEL:Init()
SetMouseInputEnabled(self, false)
SetPaintBackgroundEnabled(self, false)
SetPaintBorderEnabled(self, false)
end
function PANEL:AllowScale()
SUI.OnScaleChanged(self, self.ScaleChanged)
end
function PANEL:ScaleChanged()
self:SizeToContents()
end
function PANEL:SetFont(font)
if self.m_FontName == font then return end
self.m_FontName = font
self:SetFontInternal(self.m_FontName)
end
function PANEL:SetTextColor(col)
if self.m_colText == col then return end
self.m_colText = col
SetFGColor(self, col.r, col.g, col.b, col.a)
end
PANEL.SetColor = PANEL.SetTextColor
function PANEL:GetColor()
return self.m_colText or self.m_colTextStyle
end
function PANEL:Toggle()
if not self:GetIsToggle() then return end
self:SetToggle(not self:GetToggle())
self:OnToggled(self:GetToggle())
end
function PANEL:SetDisabled(bDisabled)
self.m_bDisabled = bDisabled
InvalidateLayout(self)
end
function PANEL:SetEnabled(bEnabled)
self:SetDisabled(not bEnabled)
end
function PANEL:IsEnabled()
return not self:GetDisabled()
end
function PANEL:ApplySchemeSettings()
local col = self:GetColor()
if not col then return end
self:SetFGColor(col.r, col.g, col.b, col.a)
end
function PANEL:AutoStretchVerticalThink()
self:SizeToContentsY()
end
function PANEL:SetAutoStretchVertical(enable)
self.m_bAutoStretchVertical = enable
self.Think = enable and self.AutoStretchVerticalThink or nil
end
function PANEL:OnCursorEntered()
InvalidateLayout(self, true)
end
function PANEL:OnCursorExited()
InvalidateLayout(self, true)
end
function PANEL:OnMousePressed(mousecode)
if self:GetDisabled() then return end
if mousecode == MOUSE_LEFT and not dragndrop.IsDragging() and self.m_bDoubleClicking then
if self.LastClickTime and SysTime() - self.LastClickTime < 0.2 then
self:DoDoubleClickInternal()
self:DoDoubleClick()
return
end
self.LastClickTime = SysTime()
end
if self:IsSelectable() and mousecode == MOUSE_LEFT and input.IsShiftDown() then
return self:StartBoxSelection()
end
self:MouseCapture(true)
self.Depressed = true
self:OnDepressed()
InvalidateLayout(self, true)
self:DragMousePress(mousecode)
end
function PANEL:OnMouseReleased(mousecode)
self:MouseCapture(false)
if self:GetDisabled() then return end
if not self.Depressed and dragndrop.m_DraggingMain ~= self then return end
if self.Depressed then
self.Depressed = nil
self:OnReleased()
InvalidateLayout(self, true)
end
if self:DragMouseRelease(mousecode) then return end
if self:IsSelectable() and mousecode == MOUSE_LEFT then
local canvas = self:GetSelectionCanvas()
if canvas then
canvas:UnselectAll()
end
end
if not self.Hovered then return end
self.Depressed = true
if mousecode == MOUSE_RIGHT then
self:DoRightClick()
end
if mousecode == MOUSE_LEFT then
self:DoClickInternal()
self:DoClick()
end
if mousecode == MOUSE_MIDDLE then
self:DoMiddleClick()
end
self.Depressed = nil
end
function PANEL:OnReleased()
end
function PANEL:OnDepressed()
end
function PANEL:OnToggled(bool)
end
function PANEL:DoClick()
self:Toggle()
end
function PANEL:DoRightClick()
end
function PANEL:DoMiddleClick()
end
function PANEL:DoClickInternal()
end
function PANEL:DoDoubleClick()
end
function PANEL:DoDoubleClickInternal()
end
sui.register("Label", PANEL, "Label")

View File

@@ -0,0 +1,81 @@
--[[
| 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/
--]]
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local LABEL_FONT = SUI.CreateFont("LabelPanel", "Roboto", 18)
local PANEL = {}
local add = function(s, c)
if IsValid(s.pnl) then
s.pnl:Remove()
end
local pnl = vgui.Create(c, s)
s.pnl = pnl
return pnl
end
function PANEL:Init()
self.title = ""
local label = self:Add(NAME .. ".Label")
label:Dock(LEFT)
self.label = label
self:SetFont(LABEL_FONT)
self:Dock(TOP)
self:InvalidateLayout(true)
self.Add = add
end
function PANEL:SetPanel(pnl)
if IsValid(self.pnl) then
self.pnl:Remove()
end
pnl:SetParent(self)
self.pnl = pnl
end
function PANEL:SetLabel(lbl)
self.title = lbl
self:InvalidateLayout(true)
end
function PANEL:SetFont(font)
self.font = font
self.label:SetFont(font)
end
function PANEL:PerformLayout(w, h)
local label = self.label
local pnl = self.pnl
local pnl_w, pnl_h = 0, 0
if pnl then
pnl_w, pnl_h = pnl:GetSize()
end
label:SetWide(w - pnl_w - 4)
label:SetText(sui.wrap_text(self.title, self.font, w - pnl_w - 4))
local _, _h = label:GetTextSize()
self:SetTall(math.max(_h, pnl_h))
if pnl then
pnl:SetPos(w - pnl_w, h / 2 - pnl_h / 2)
end
end
sui.register("LabelPanel", PANEL, "PANEL")

View File

@@ -0,0 +1,45 @@
--[[
| 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/
--]]
local surface = surface
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local NUMBER_SLIDER_FONT = SUI.CreateFont("NumberSlider", "Roboto Regular", 14)
local PANEL = {}
sui.scaling_functions(PANEL)
function PANEL:Init()
self:ScaleInit()
local slider = vgui.Create(NAME .. ".Slider", self, "NumberSlider")
slider:Dock(FILL)
self.slider = slider
local label = self:Add(NAME .. ".Label")
label:Dock(RIGHT)
label:DockMargin(3, 0, 0, 0)
label:SetFont(NUMBER_SLIDER_FONT)
self.label = label
function label:Think()
self:SetText(slider:GetValue())
self:SizeToContents()
end
self:SetSize(100, 12)
self:InvalidateLayout(true)
end
sui.register("NumberSlider", PANEL, "Panel")

View File

@@ -0,0 +1,19 @@
--[[
| 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/
--]]
local PANEL = {}
sui.scaling_functions(PANEL)
function PANEL:Init()
self:ScaleInit()
end
sui.register("Panel", PANEL, "Panel")

View File

@@ -0,0 +1,171 @@
--[[
| 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/
--]]
local draw = draw
local surface = surface
local vgui = vgui
local TYPE_MATERIAL = TYPE_MATERIAL
local RealFrameTime = RealFrameTime
local IsValid = IsValid
local Lerp = Lerp
local pairs = pairs
local TypeID = TypeID
local TDLib_Classes = sui.TDLib.LibClasses
local TextColor = TDLib_Classes.TextColor
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local PROPERTY_SHEET_FONT = SUI.CreateFont("PropertySheet", "Roboto Regular", 18)
local PANEL = {}
AccessorFunc(PANEL, "m_FontName", "Font", FORCE_STRING)
function PANEL:Init()
self.tabs = {}
self:SetFont(PROPERTY_SHEET_FONT)
local tab_scroller = self:Add("DHorizontalScroller")
tab_scroller:Dock(TOP)
self.tabs_tall = 26
self.tab_scroller = tab_scroller
self:ScaleChanged()
SUI.OnScaleChanged(self, self.ScaleChanged)
end
function PANEL:ScaleChanged()
self.tab_scroller:SetTall(SUI.Scale(self.tabs_tall))
for k, v in pairs(self.tab_scroller.Panels) do
if v:IsValid() then
if v.Material then
v:SetWide(self.tab_scroller:GetTall())
else
v:SizeToContentsX()
end
end
end
self:InvalidateLayout(true)
end
function PANEL:Paint(w, h)
self:RoundedBox("Background", 1, 0, 0, w, self.tab_scroller:GetTall(), SUI.GetColor("property_sheet_bg"))
end
function PANEL:PaintOver(w, h)
local active_tab = self:GetActiveTab()
if not IsValid(active_tab) then return end
local tab_scroller = self.tab_scroller
local offset = tab_scroller:GetTall() - SUI.Scale(1)
local x = active_tab:LocalToScreen(0) - self:LocalToScreen(0)
if not self.activeTabX then
self.activeTabX = x
self.activeTabW = active_tab:GetWide()
end
local delta = RealFrameTime() * 6
if delta then
self.activeTabX = Lerp(delta, self.activeTabX, x)
self.activeTabW = Lerp(delta, self.activeTabW, active_tab:GetWide())
end
self:RoundedBox("Background2", 1, self.activeTabX, tab_scroller.y + offset, self.activeTabW, SUI.Scale(1), SUI.GetColor("property_sheet_tab_active"))
end
local tab_Paint = function(s, w, h)
s.circle_click_color = SUI.GetColor("property_sheet_tab_click")
if s.property_sheet:GetActiveTab() == s then
TextColor(s, SUI.GetColor("property_sheet_tab_active"))
else
TextColor(s, SUI.GetColor("property_sheet_tab"))
end
end
local tab_DoClick = function(s)
s.parent:SetActiveTab(s)
end
local image_paint = function(s, w, h)
surface.SetDrawColor(color_white)
surface.SetMaterial(s.Material)
surface.DrawTexturedRectRotated(w * 0.5, h * 0.5, w - 10, h - 10, 0)
end
function PANEL:AddSheet(name, load_func)
local tab = vgui.Create("DButton")
if TypeID(name) == TYPE_MATERIAL then
tab:SetText("")
tab.Material = name
tab.Paint = image_paint
tab:SetWide(self.tab_scroller:GetTall())
else
tab:SetFont(self:GetFont())
tab:SetText(name)
tab:SetTextInset(10, 0)
tab:SizeToContentsX()
tab.Paint = tab_Paint
end
tab.parent = self
tab.DoClick = tab_DoClick
tab.load_func = load_func
tab.property_sheet = self
tab.On = TDLib_Classes.On
TDLib_Classes.CircleClick(tab)
self.tab_scroller:AddPanel(tab)
if not self:GetActiveTab() then
self:SetActiveTab(tab)
end
table.insert(self.tabs, tab)
return tab
end
function PANEL:GetActiveTab()
return self.active_tab
end
function PANEL:SetActiveTab(new_tab)
if IsValid(new_tab) and not IsValid(new_tab.panel) then
local panel = new_tab.load_func(self)
panel:SetParent(self)
panel:SetVisible(false)
panel.tab = new_tab
new_tab.panel = panel
end
if self.active_tab and IsValid(self.active_tab.panel) then
self.active_tab.panel:SetVisible(false)
end
if IsValid(new_tab) then
new_tab.panel:SetVisible(true)
end
self.active_tab = new_tab
end
sui.register("PropertySheet", PANEL, "EditablePanel")

View File

@@ -0,0 +1,140 @@
--[[
| 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/
--]]
local ScrW, ScrH = ScrW, ScrH
local DisableClipping = DisableClipping
local SetDrawColor = surface.SetDrawColor
local DrawRect = surface.DrawRect
local BlurPanel = sui.TDLib.BlurPanel
local lerp_color = sui.lerp_color
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local GetColor = SUI.GetColor
local PANEL = {}
function PANEL:SetCallback(callback)
self.callback = callback
end
function PANEL:Init()
self:SetSize(0, 0)
local bottom = self:Add("Panel")
bottom:Dock(BOTTOM)
bottom:DockMargin(4, 10, 4, 4)
bottom:SetZPos(100)
local save = bottom:Add(NAME .. ".Button")
save:SetText("SAVE")
save:Dock(RIGHT)
save:SetEnabled(false)
self.save = save
function save.DoClick()
self.callback()
self:Remove()
end
local cancel = bottom:Add(NAME .. ".Button")
cancel:Dock(RIGHT)
cancel:DockMargin(0, 0, 4, 0)
cancel:SetContained(false)
cancel:SetColors(GetColor("query_box_cancel"), GetColor("query_box_cancel_text"))
cancel:SetText("CANCEL")
self.cancel = cancel
function cancel.DoClick()
self:Remove()
end
bottom:SetSize(save:GetWide() * 2 + 4, SUI.Scale(30))
local body = self:Add("Panel")
body:Dock(FILL)
body:DockMargin(4, 4, 4, 4)
body:DockPadding(3, 3, 3, 3)
body:InvalidateLayout(true)
body:InvalidateParent(true)
local added = 1
function body.OnChildAdded(s, child)
added = added + 1
child:Dock(TOP)
child:SetZPos(added)
child:InvalidateLayout(true)
s:InvalidateLayout(true)
end
self.body = body
function self:Add(name)
return body:Add(name)
end
local old_Paint = self.Paint
local trans = Color(0, 0, 0, 0)
local new_col = Color(70, 70, 70, 100)
function self:Paint(w, h)
lerp_color(trans, new_col)
local x, y = self:LocalToScreen(0, 0)
DisableClipping(true)
BlurPanel(self)
SetDrawColor(trans)
DrawRect(x * -1, y * -1, ScrW(), ScrH())
DisableClipping(false)
old_Paint(self, w, h)
end
end
function PANEL:ChildrenHeight()
local body = self.body
self.header:InvalidateLayout(true)
local height = self.header:GetTall()
body:InvalidateLayout(true)
self:InvalidateLayout(true)
height = height + select(2, body:ChildrenSize())
height = height + SUI.Scale(30) + 14 + 6
return height
end
function PANEL:Paint(w, h)
if GetColor("frame_blur") then
BlurPanel(self)
end
self:RoundedBox("Background", 8, 0, 0, w, h, GetColor("query_box_bg"))
end
function PANEL:Done()
self:InvalidateChildren(true)
self.size_to_children = function()
local h = self:ChildrenHeight()
self:RealSetSize(self:GetWide(), h)
self.real_h = h
end
self:Center()
self:MakePopup()
self:DoModal(true)
timer.Simple(0.08, function()
self:AddAnimations(self:GetWide(), self:ChildrenHeight(), true)
end)
end
sui.register("QueryBox", PANEL, NAME .. ".Frame")

View File

@@ -0,0 +1,208 @@
--[[
| 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/
--]]
local math = math
local table = table
local pairs = pairs
local RealFrameTime = RealFrameTime
local TDLib = sui.TDLib
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local RoundedBox = sui.TDLib.LibClasses.RoundedBox
local Panel = {}
AccessorFunc(Panel, "m_bFromBottom", "FromBottom", FORCE_BOOL)
AccessorFunc(Panel, "m_bVBarPadding", "VBarPadding", FORCE_NUMBER)
Panel:SetVBarPadding(0)
Panel.NoOverrideClear = true
-- VBar
local starting_scroll_speed = 3
local vbar_OnMouseWheeled = function(s, delta)
s.scroll_speed = s.scroll_speed + (14 * RealFrameTime() --[[ slowly increase scroll speed ]])
s:AddScroll(delta * -s.scroll_speed)
end
-- default set scroll clamps amount
local vbar_SetScroll = function(s, amount)
if not s.Enabled then s.Scroll = 0 return end
s.scroll_target = amount
s:InvalidateLayout()
end
-- ¯\_(ツ)_/¯ https://github.com/Facepunch/garrysmod/blob/cd3d894288b847e3d081570129963d4089e36261/garrysmod/lua/vgui/dvscrollbar.lua#L234
local vbar_OnCursorMoved = function(s, _, y)
if s.Dragging then
y = y - s.HoldPos
y = y / (s:GetTall() - s:GetWide() * 2 - s.btnGrip:GetTall())
s.scroll_target = y * s.CanvasSize
end
end
local vbar_Think = function(s)
local frame_time = RealFrameTime() * 14
local scroll_target = s.scroll_target
s.Scroll = Lerp(frame_time, s.Scroll, scroll_target)
if not s.Dragging then
s.scroll_target = Lerp(frame_time, scroll_target, math.Clamp(scroll_target, 0, s.CanvasSize))
end
-- now start slowing it down!!!
s.scroll_speed = Lerp(frame_time / 14, s.scroll_speed, starting_scroll_speed)
end
local vbar_Paint = function(s, w, h)
TDLib.RoundedBox(s.vertices, 3, 0, 0, w, h, SUI.GetColor("scroll"))
end
local vbarGrip_Paint = function(s, w, h)
TDLib.RoundedBox(s.vertices, 3, 0, 0, w, h, SUI.GetColor("scroll_grip"))
end
local vbar_PerformLayout = function(s, w, h)
local scroll = s:GetScroll() / s.CanvasSize
local bar_size = math.max(s:BarScale() * h, 10)
local track = (h - bar_size) + 1
scroll = scroll * track
s.btnGrip.y = scroll
s.btnGrip:SetSize(w, bar_size)
end
--
function Panel:Init()
local canvas = self:GetCanvas()
canvas:SUI_TDLib()
local children = {}
function canvas:OnChildAdded(child)
table.insert(children, child)
end
function canvas:OnChildRemoved(child)
for i = 1, #children do
local v = children[i]
if v == child then
table.remove(children, i)
return
end
end
end
canvas.GetChildren = function()
return children
end
canvas.children = children
local vbar = self.VBar
vbar:SetHideButtons(true)
vbar.btnUp:SetVisible(false)
vbar.btnDown:SetVisible(false)
vbar.vertices = {}
vbar.scroll_target = 0
vbar.scroll_speed = starting_scroll_speed
vbar.OnMouseWheeled = vbar_OnMouseWheeled
vbar.SetScroll = vbar_SetScroll
vbar.OnCursorMoved = vbar_OnCursorMoved
vbar.Think = vbar_Think
vbar.Paint = vbar_Paint
vbar.PerformLayout = vbar_PerformLayout
vbar.btnGrip.vertices = {}
vbar.btnGrip.Paint = vbarGrip_Paint
self:ScaleChanged()
SUI.OnScaleChanged(self, self.ScaleChanged)
end
function Panel:OnChildAdded(child)
self:AddItem(child)
self:ChildAdded(child)
end
function Panel:ChildAdded()
end
function Panel:ScaleChanged()
local w = SUI.Scale(4)
self.VBar:SetWide(w)
self.VBar.btnDown:SetSize(w, 0)
self.VBar.btnUp:SetSize(w, 0)
end
function Panel:Paint(w, h)
local outline = SUI.GetColor("scroll_panel_outline")
if outline then
TDLib.DrawOutlinedBox(3, 0, 0, w, h, SUI.GetColor("scroll_panel"), outline, 1)
else
RoundedBox(self, "Background", 3, 0, 0, w, h, SUI.GetColor("scroll_panel"))
end
end
function Panel:ScrollToBottom()
local vbar = self.VBar
for k, anim in pairs(vbar.m_AnimList or {}) do
anim:Think(vbar, 1)
vbar.m_AnimList[k] = nil
end
self:InvalidateParent(true)
self:InvalidateChildren(true)
vbar:SetScroll(vbar.CanvasSize)
end
function Panel:PerformLayoutInternal(w, h)
w = w or self:GetWide()
h = h or self:GetTall()
local canvas = self.pnlCanvas
self:Rebuild()
local vbar = self.VBar
vbar:SetUp(h, canvas:GetTall())
if vbar.Enabled then
w = w - vbar:GetWide() - self.m_bVBarPadding
end
canvas:SetWide(w)
self:Rebuild()
end
function Panel:Think()
local canvas = self.pnlCanvas
local vbar = self.VBar
if vbar.Enabled then
canvas.y = -vbar.Scroll
else
if self:GetFromBottom() then
canvas._y = Lerp(14 * RealFrameTime(), canvas._y or canvas.y, self:GetTall() - canvas:GetTall())
else
canvas._y = Lerp(14 * RealFrameTime(), canvas._y or canvas.y, -vbar.Scroll)
end
canvas.y = canvas._y
end
end
sui.register("ScrollPanel", Panel, "DScrollPanel")

View File

@@ -0,0 +1,91 @@
--[[
| 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/
--]]
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TDLib = sui.TDLib
local Panel = {}
sui.scaling_functions(Panel)
AccessorFunc(Panel, "m_bValue", "Value", FORCE_NUMBER)
AccessorFunc(Panel, "m_bMin", "Min", FORCE_NUMBER)
AccessorFunc(Panel, "m_bMax", "Max", FORCE_NUMBER)
AccessorFunc(Panel, "m_bDecimals", "Decimals", FORCE_NUMBER)
function Panel:Init()
self:ScaleInit()
self:SetMin(0)
self:SetMax(10)
self:SetValue(1)
self:SetDecimals(1)
self:SetSize(100, 12)
self.rounded_box = {}
self.Knob.circle = {}
self.Knob.Paint = self.KnobPaint
self:SetTrapInside(true)
end
function Panel:SetMinMax(min, max)
self:SetMin(min)
self:SetMax(max)
end
function Panel:TranslateValues(x, y)
self:SetValue(self:GetMin() + (x * self:GetRange()))
return self:GetFraction(), y
end
function Panel:GetFraction()
return (self:GetValue() - self:GetMin()) / self:GetRange()
end
function Panel:SetValue(val)
val = math.Clamp(val, self:GetMin(), self:GetMax())
val = math.Round(val, self:GetDecimals())
self.m_bValue = val
self:SetSlideX((val - self:GetMin()) / self:GetRange())
self:OnValueChanged(val)
end
function Panel:OnValueChanged(val)
end
function Panel:GetRange()
return self:GetMax() - self:GetMin()
end
function Panel:Paint(w, h)
local _h = SUI.Scale(2)
TDLib.RoundedBox(self.rounded_box, 3, 0, h / 2 - _h / 2, w, _h, SUI.GetColor("slider_track"))
end
function Panel:KnobPaint(w, h)
if self.Depressed then
TDLib.DrawCircle(self.circle, w / 2, h / 2, h / 1.1, SUI.GetColor("slider_pressed"))
elseif self.Hovered then
TDLib.DrawCircle(self.circle, w / 2, h / 2, h / 1.1, SUI.GetColor("slider_hover"))
end
TDLib.DrawCircle(self.circle, w / 2, h / 2, h / 2, SUI.GetColor("slider_knob"))
end
function Panel:PerformLayout(w, h)
self.Knob:SetSize(SUI.Scale(12), SUI.Scale(12))
DSlider.PerformLayout(self, w, h)
end
sui.register("Slider", Panel, "DSlider")

View File

@@ -0,0 +1,389 @@
--[[
| 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/
--]]
local sui = sui
local surface = surface
local utf8 = sui.utf8
local draw = draw
local math = math
local IsValid = IsValid
local tostring = tostring
local tonumber = tonumber
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local GetColor = SUI.GetColor
local TEXT_ENTRY_FONT = SUI.CreateFont("TextEntry", "Roboto Regular", 16)
local Panel = {}
sui.scaling_functions(Panel)
AccessorFunc(Panel, "m_FontName", "Font", FORCE_STRING)
AccessorFunc(Panel, "m_Editable", "Editable", FORCE_BOOL)
AccessorFunc(Panel, "m_Placeholder", "Placeholder", FORCE_STRING)
AccessorFunc(Panel, "m_MaxChars", "MaxChars", FORCE_NUMBER)
AccessorFunc(Panel, "m_Numeric", "Numeric", FORCE_BOOL)
AccessorFunc(Panel, "m_NoBar", "NoBar", FORCE_BOOL)
AccessorFunc(Panel, "m_BarColor", "BarColor")
AccessorFunc(Panel, "m_Background", "Background")
AccessorFunc(Panel, "m_Radius", "Radius")
AccessorFunc(Panel, "m_NoEnter", "NoEnter")
Panel:SetRadius(3)
function Panel:Init()
self:ScaleInit()
self:SetupTransition("TextEntryReady", 0.9, function()
return self:IsEditing() or self:GetBarColor() ~= nil
end)
self:SetUpdateOnType(true)
self:SetCursor("beam")
self:SetFont(TEXT_ENTRY_FONT)
self:SetPlaceholder("Placeholder text")
self:SetSize(200, 22)
self.allowed_numeric_characters = "1234567890.-"
self.history = {}
self.history_pos = 1
self.can_use_history = true
self:OnScaleChange()
end
function Panel:SetCaretPos(pos)
DTextEntry.SetCaretPos(self, math.Clamp(pos, 0, utf8.len(self:GetText())))
end
function Panel:SetValue(value)
self:SetText(value)
self:OnValueChange(value)
end
function Panel:AllowInput(ch)
if self:CheckNumeric(ch) then return true end
if sui.wspace_chs[ch] or sui.cntrl_chs[ch] then
return true
end
local max_chars = self:GetMaxChars()
if max_chars and #self:GetText() >= max_chars then
surface.PlaySound("resource/warning.wav")
return true
end
end
function Panel:AddValue(v, i, j)
local original_text = self:GetText()
local start
if i then
start = original_text:sub(1, i)
else
start = utf8.sub(original_text, 1, self:GetCaretPos())
end
local text = start .. v
local caret_pos = utf8.len(text)
local _end
if j then
_end = original_text:sub(j)
else
_end = utf8.sub(original_text, utf8.len(start) + 1)
end
text = text .. _end
local max_chars = self:GetMaxChars()
if max_chars then
text = text:sub(1, max_chars)
end
self:SetValue(text)
self:SetCaretPos(caret_pos)
end
function Panel:OnKeyCodeTyped(code)
if self.no_down then
self.no_down = nil
return
end
if code == KEY_UP or code == KEY_DOWN then
if not self:UpdateFromHistory(code) then
return true
end
local lines, caret_line = self:GetNumLines()
if lines == 1 then
return true
end
--
-- this fixes a weird issue
-- make the text entry has at least 2 lines, go up then go down, you won't be able to go up again
--
if code == KEY_DOWN and lines == caret_line + 1 then
self.no_down = true
gui.InternalKeyCodeTyped(KEY_DOWN)
end
end
self:OnKeyCode(code)
if code == KEY_ENTER then
if IsValid(self.Menu) then
self.Menu:Remove()
end
if not self:GetNoEnter() then
self:FocusNext()
self:OnEnter()
end
end
end
function Panel:DisallowFloats(disallow)
if not isbool(disallow) then
disallow = true
end
if disallow then
self.allowed_numeric_characters = self.allowed_numeric_characters:gsub("%.", "", 1)
elseif not self.allowed_numeric_characters:find(".", 1, true) then
self.allowed_numeric_characters = self.allowed_numeric_characters .. "."
end
end
function Panel:DisallowNegative(disallow)
if not isbool(disallow) then
disallow = true
end
if disallow then
self.allowed_numeric_characters = self.allowed_numeric_characters:gsub("%-", "", 1)
elseif not self.allowed_numeric_characters:find("-", 1, true) then
self.allowed_numeric_characters = self.allowed_numeric_characters .. "-"
end
end
function Panel:CheckNumeric(value)
if not self:GetNumeric() then return false end
if not self.allowed_numeric_characters:find(value, 1, true) then
return true
end
local new_value = ""
local current_value = tostring(self:GetText())
local caret_pos = self:GetCaretPos()
for i = 0, #current_value do
new_value = new_value .. current_value:sub(i, i)
if i == caret_pos then
new_value = new_value .. value
end
end
if #current_value ~= 0 and not tonumber(new_value) then
return true
end
return false
end
function Panel:AddHistory(txt)
if not txt or txt == "" then return end
local history = self.history
if history[#history] ~= txt then
table.insert(history, txt)
end
end
function Panel:UpdateFromHistory(code)
if not self.can_use_history then return end
local lines, caret_line = self:GetNumLines()
if code == KEY_UP then
if caret_line > 1 then return true end -- enable the caret to move up and down
if self.history_pos <= 1 then return end
self.history_pos = self.history_pos - 1
elseif code == KEY_DOWN then
if caret_line ~= lines then return true end
if self.history_pos >= #self.history then
self:SetValue("")
self:SetCaretPos(0)
self.history_pos = #self.history + 1
return
end
self.history_pos = self.history_pos + 1
end
local text = self.history[self.history_pos]
if not text then return end
self:SetValue(text)
self:SetCaretPos(utf8.len(text))
end
function Panel:OnTextChanged()
self.history_pos = #self.history + 1
local text = self:GetText()
self.can_use_history = text == "" and true or false
if self:GetUpdateOnType() then
self:UpdateConvarValue()
self:OnValueChange(text)
end
self:OnChange()
end
function Panel:OnScaleChange()
self:InvalidateLayout()
self:InvalidateLayout(true)
end
function Panel:Paint(w, h)
self:RoundedBox("Background", self:GetRadius(), 0, 0, w, h, GetColor("text_entry_bg") or self:GetBackground())
local text_entry_3 = GetColor("text_entry_3")
if self:GetText() == "" then
local old_text = self:GetText()
self:SetText(self:GetPlaceholder())
self:DrawTextEntryText(GetColor("text_entry_2"), text_entry_3, text_entry_3)
self:SetText(old_text)
else
self:DrawTextEntryText(GetColor("text_entry"), text_entry_3, text_entry_3)
end
if not self:GetNoBar() then
local bar_color = self:GetBarColor()
self:RoundedBox("Bar1", 0, 0, h - 1, w, 1, GetColor("text_entry_bar_color"))
local bar = math.Round(w * self.TextEntryReady)
if bar > 0 then
self:RoundedBox("Bar2", 0, (w / 2) - (bar / 2), h - 1, bar, 1, bar_color or text_entry_3)
end
end
end
-- https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/vgui2/vgui_controls/TextEntry.cpp#L969
function Panel:GetNumLines(wide)
local num_lines = 1
wide = wide or self:GetWide() - 2
local vbar = self:GetChildren()[1]
if vbar then
wide = wide - vbar:GetWide()
end
local char_width
local x = 3
local word_start_index = 1
local word_start_len
local word_length = 0
local has_word = false
local just_started_new_line = true
local word_started_on_new_line = true
local start_char = 1
surface.SetFont(self:GetFont())
local i = start_char
local text, n = utf8.force(self:GetText())
local caret_line = 0
local caret_pos = self:GetCaretPos()
local caret_i = 1
while i <= n do
local ch_len = utf8.char_bytes(text:byte(i))
local ch = text:sub(i, i + ch_len - 1)
if ch ~= " " then
if not has_word then
word_start_index = i
word_start_len = ch_len
has_word = true
word_started_on_new_line = just_started_new_line
word_length = 0
end
else
has_word = false
end
char_width = surface.GetTextSize(ch)
just_started_new_line = false
if (x + char_width) >= wide then
x = 3
just_started_new_line = true
has_word = false
if word_started_on_new_line then
num_lines = num_lines + 1
else
num_lines = num_lines + 1
i = (word_start_index + word_start_len) - ch_len
end
word_length = 0
end
x = x + char_width
word_length = word_length + char_width
if caret_i == caret_pos then
caret_line = num_lines
end
i = i + ch_len
caret_i = caret_i + 1
end
return num_lines, caret_line
end
function Panel:SetCheck(func, col)
function self:OnValueChange(text)
if func(text) == false then
self.valid = false
self:SetBarColor(GetColor("close_hover"))
self:SetNoEnter(true)
else
self.valid = true
self:SetBarColor(col)
self:SetNoEnter(false)
end
end
self:SetValue(self:GetText())
end
sui.register("TextEntry", Panel, "DTextEntry")

View File

@@ -0,0 +1,99 @@
--[[
| 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/
--]]
local math = math
local table = table
local ipairs = ipairs
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local Panel = {}
AccessorFunc(Panel, "horizontalMargin", "HorizontalMargin", FORCE_NUMBER)
AccessorFunc(Panel, "verticalMargin", "VerticalMargin", FORCE_NUMBER)
AccessorFunc(Panel, "columns", "Columns", FORCE_NUMBER)
AccessorFunc(Panel, "Wide2", "Wide2", FORCE_NUMBER)
function Panel:Init()
self:SetHorizontalMargin(0)
self:SetVerticalMargin(0)
self.Rows = {}
self.Cells = {}
end
function Panel:AddCell(pnl)
local cols = self:GetColumns()
local idx = math.floor(#self.Cells / cols) + 1
local rows = self.Rows[idx]
if not rows then
rows = self:CreateRow()
self.Rows[idx] = rows
end
local margin = self:GetHorizontalMargin()
local dockl, dockt, _, dockb = pnl:GetDockMargin()
pnl:SetParent(rows)
pnl:Dock(LEFT)
pnl:DockMargin(dockl, dockt, #rows.Items + 1 < cols and self:GetHorizontalMargin() or 0, dockb)
pnl:SetWide(((self:GetWide2() or self:GetWide()) - margin * (cols - 1)) / cols)
table.insert(rows.Items, pnl)
table.insert(self.Cells, pnl)
self:CalculateRowHeight(rows)
end
function Panel:CreateRow()
local row = self:Add("Panel")
row:Dock(TOP)
row:DockMargin(0, 0, 0, self:GetVerticalMargin())
row.Items = {}
return row
end
function Panel:CalculateRowHeight(row)
local height = 0
for k, v in ipairs(row.Items) do
local _, t, _, b = v:GetDockMargin()
height = math.max(height, v:GetTall() + t + b)
end
row:SetTall(height)
end
function Panel:Skip()
local cell = vgui.Create("Panel")
self:AddCell(cell)
end
function Panel:CalculateRowHeights()
for _, row in ipairs(self.Rows) do
self:CalculateRowHeight(row)
end
end
function Panel:Clear()
for _, row in ipairs(self.Rows) do
for _, cell in ipairs(row.Items) do
cell:Remove()
end
row:Remove()
end
self.Cells, self.Rows = {}, {}
end
Panel.OnRemove = Panel.Clear
sui.register("ThreeGrid", Panel, NAME .. ".ScrollPanel")

View File

@@ -0,0 +1,48 @@
--[[
| 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/
--]]
local Lerp = Lerp
local FrameTime = FrameTime
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TDLib = sui.TDLib
local Panel = {}
sui.scaling_functions(Panel)
function Panel:Init()
self:ScaleInit()
local rounded_box = {}
local switch_circle = {}
function self:Paint(w, h)
local is_checked = self:GetChecked()
local _h = SUI.Scale(14)
TDLib.RoundedBox(rounded_box, _h, 0, h / 2 - _h / 2, w, _h, is_checked and SUI.GetColor("toggle_button_active") or SUI.GetColor("toggle_button"))
local size = h - 2
do
local pos = is_checked and (w - (size / 2)) or (h / 2 - 1)
if self.pos then
self.pos = Lerp(FrameTime() * 12, self.pos, pos)
else
self.pos = pos
end
end
TDLib.DrawCircle(switch_circle, self.pos, h / 2, size / 2, is_checked and SUI.GetColor("toggle_button_switch_active") or SUI.GetColor("toggle_button_switch"))
end
self:SetSize(34, 20)
end
sui.register("ToggleButton", Panel, "DCheckBox")

View File

@@ -0,0 +1,147 @@
--[[
| 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/
--]]
local draw = draw
local render = render
local TDLib = sui.TDLib
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local lerp_color = sui.lerp_color
local contrast_color = sui.contrast_color
local BUTTON_FONT = SUI.CreateFont("Button", "Roboto Medium", 16)
local color_white = color_white
local color_transparent = Color(0, 0, 0, 0)
local PANEL = {}
AccessorFunc(PANEL, "m_Background", "Background")
AccessorFunc(PANEL, "m_bContained", "Contained", FORCE_BOOL)
sui.TDLib.Install(PANEL)
sui.scaling_functions(PANEL)
PANEL:ClearPaint()
PANEL:SetContained(true)
local Panel = FindMetaTable("Panel")
local SetMouseInputEnabled = Panel.SetMouseInputEnabled
local IsMouseInputEnabled = Panel.IsMouseInputEnabled
local SetCursor = Panel.SetCursor
local SetContentAlignment = Panel.SetContentAlignment
function PANEL:Init()
self:ScaleInit()
self.vertices, self.vertices_2 = {}, {}
SetMouseInputEnabled(self, true)
SetCursor(self, "hand")
SetContentAlignment(self, 5)
self:SetSize(90, 30)
self:SetFont(BUTTON_FONT)
self:CircleClick(nil, 7)
self.OldPaint, self.Paint = self.Paint, self.Paint2
self.cur_col = Color(0, 0, 0, 0)
end
function PANEL:SetEnabled(b)
SetMouseInputEnabled(self, b)
end
function PANEL:IsEnabled()
return IsMouseInputEnabled(self)
end
function PANEL:ContainedPaint(w, h)
local enabled = self:IsEnabled()
local col
if enabled then
col = self:GetBackground() or SUI.GetColor("button")
self:SetTextColor(SUI.GetColor("button_text"))
else
col = SUI.GetColor("button_disabled")
self:SetTextColor(SUI.GetColor("button_disabled_text"))
end
self:RoundedBox("Background", 4, 0, 0, w, h, col)
if not enabled then return end
self.circle_click_color = SUI.GetColor("button_click")
if self.Hovered or self.Selected then
self:RoundedBox("Hover", 4, 0, 0, w, h, SUI.GetColor("button_hover"))
end
end
function PANEL:SetColors(hover_color, text_color)
self.hover = hover_color
self.text_color = text_color
end
function PANEL:Paint2(w, h)
if self:GetContained() then
self:ContainedPaint(w, h)
self:OldPaint(w, h)
return
end
render.ClearStencil()
render.SetStencilEnable(true)
render.SetStencilWriteMask(1)
render.SetStencilTestMask(1)
render.SetStencilFailOperation(STENCILOPERATION_REPLACE)
render.SetStencilPassOperation(STENCILOPERATION_ZERO)
render.SetStencilZFailOperation(STENCILOPERATION_ZERO)
render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_NEVER)
render.SetStencilReferenceValue(1)
TDLib.RoundedBox(self.vertices, 4, 0, 0, w, h, color_white)
render.SetStencilFailOperation(STENCILOPERATION_ZERO)
render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
render.SetStencilZFailOperation(STENCILOPERATION_ZERO)
render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
render.SetStencilReferenceValue(1)
local cur_col = self.cur_col
if self.Selected then
lerp_color(cur_col, SUI.GetColor("button2_selected"))
elseif self.Hovered then
lerp_color(cur_col, self.hover or SUI.GetColor("button2_hover"))
else
lerp_color(cur_col, color_transparent)
end
TDLib.RoundedBox(self.vertices_2, 4, 0, 0, w, h, cur_col)
if self.text_color then
self.circle_click_color = self.text_color
self:SetTextColor(self.text_color)
else
local col = contrast_color(cur_col)
self.circle_click_color = col
self:SetTextColor(col)
end
self:OldPaint(w, h)
render.SetStencilEnable(false)
render.ClearStencil()
end
sui.register("Button", PANEL, NAME .. ".Label")

View File

@@ -0,0 +1,254 @@
--[[
| 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/
--]]
local sui = sui
local draw_material = sui.draw_material
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local GetColor = SUI.GetColor
local RoundedBox = sui.TDLib.LibClasses.RoundedBox
local TextColor = sui.TDLib.LibClasses.TextColor
local TABS_FONT = SUI.CreateFont("CategoryListTabs", "Roboto Bold", 13)
local ITEMS_FONT = SUI.CreateFont("CategoryListItems", "Roboto Medium", 14)
local Panel = {}
local item_OnRemove = function(s)
local parent = s.parent
local items = parent.items
for k, v in ipairs(items) do
if v == s then
table.remove(items, k)
break
end
end
if #items == 0 then
local category = s.category
category:Remove()
parent.categories[category.name] = nil
end
end
local item_DoClick = function(s)
local parent = s.parent
parent:select_item(s)
end
function Panel:Init()
local categories = {}
local items = {}
self.categories = categories
self.items = items
self:SetVBarPadding(1)
local get_category = function(name)
local category = categories[name]
if category then return category end
local expanded = false
category = self:Add("Panel")
category:Dock(TOP)
category:DockMargin(0, 0, 0, 3)
category.name = name
local header = category:Add("DButton")
header:Dock(TOP)
header:DockMargin(0, 0, 0, 3)
header:SetFont(TABS_FONT)
header:SetContentAlignment(4)
header:SetTextInset(6, 0)
header:SetText(name)
header:SizeToContentsY(SUI.Scale(14))
local cur_col
local cur_col_text = Color(GetColor("collapse_category_header_text"):Unpack())
function header:Paint(w, h)
if expanded then
cur_col = GetColor("collapse_category_header_active")
cur_col_text = GetColor("collapse_category_header_text_active")
elseif self.Hovered then
cur_col = GetColor("collapse_category_header_hover")
cur_col_text = GetColor("collapse_category_header_text_hover")
else
cur_col = GetColor("collapse_category_header")
cur_col_text = GetColor("collapse_category_header_text")
end
RoundedBox(self, "Background", 3, 0, 0, w, h, cur_col)
TextColor(self, cur_col_text)
end
local image = header:Add(NAME .. ".Image")
image:Dock(FILL)
image:SetImage("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sui/arrow.png")
function image:Draw(w, h)
local size = SUI.ScaleEven(10)
draw_material(nil, w - (size / 2) - 6, h / 2, size, cur_col_text, expanded and 180)
end
local current_h
function category.RefreshHeight()
local h
if expanded then
local _
_, h = category:ChildrenSize()
if self.searching and h == header:GetTall() then
h = 0
end
else
h = header:GetTall()
end
if current_h == h then return end
if h > 0 then
category:SetVisible(true)
end
current_h = h
category:Stop()
category:SizeTo(-1, h, 0.2, 0, -1, function()
if h == 0 then
category:SetVisible(false)
end
end)
end
function category.SetExpanded(_, set_expanded)
if expanded == set_expanded then return end
if sam.isbool(set_expanded) then
expanded = set_expanded
else
expanded = not expanded
end
category.RefreshHeight()
if expanded then
self:OnCategoryExpanded(category)
end
self:InvalidateLayout(true)
end
header.DoClick = category.SetExpanded
category:SetTall(header:GetTall())
categories[name] = category
return category
end
function self:add_item(name, category_name)
local category = get_category(category_name)
local item = category:Add("DButton")
item:Dock(TOP)
item:DockMargin(0, 0, 0, 3)
item:SetFont(ITEMS_FONT)
item:SetText(name)
item:SizeToContentsY(SUI.Scale(3 * 2))
item.name = name
item.parent = self
item.category = category
local cur_col
local cur_col_text = Color(GetColor("collapse_category_item_text"):Unpack())
function item:Paint(w, h)
if self.selected then
cur_col = GetColor("collapse_category_item_active")
cur_col_text = GetColor("collapse_category_item_text_active")
elseif self.Hovered then
cur_col = GetColor("collapse_category_item_hover")
cur_col_text = GetColor("collapse_category_item_text_hover")
else
cur_col = GetColor("collapse_category_item")
cur_col_text = GetColor("collapse_category_item_text")
end
RoundedBox(self, "Background", 4, 0, 0, w, h, cur_col)
TextColor(self, cur_col_text)
end
item.DoClick = item_DoClick
item.OnRemove = item_OnRemove
table.insert(items, item)
return item
end
end
function Panel:OnCategoryExpanded(category)
end
function Panel:select_item(item)
if self.selected_item ~= item then
if IsValid(self.selected_item) then
self.selected_item.selected = false
end
item.selected = true
self.selected_item = item
self:item_selected(item)
end
end
function Panel:item_selected()
end
function Panel:Search(text, names)
local items = self.items
self.searching = true
for i = 1, #items do
local item = items[i]
local category = item.category
category:SetExpanded(true)
if not names then
if item.name:find(text, nil, true) then
item:SetVisible(true)
else
item:SetVisible(false)
end
else
local found = false
for _, name in ipairs(item.names) do
if name:find(text, nil, true) then
found = true
item:SetVisible(true)
end
end
if not found then
item:SetVisible(false)
end
end
if text == "" then
category:SetExpanded(false)
end
category:RefreshHeight()
category:InvalidateLayout(true)
end
self.searching = false
end
sui.register("CollapseCategory", Panel, NAME .. ".ScrollPanel")

View File

@@ -0,0 +1,142 @@
--[[
| 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/
--]]
local IsValid = IsValid
local TDLib_Classes = sui.TDLib.LibClasses
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local GetColor = SUI.GetColor
local Panel = {}
function Panel:Init()
self.tabs = {}
local tab_scroller = self:Add(NAME .. ".ScrollPanel")
tab_scroller:Dock(LEFT)
function tab_scroller:Paint(w, h)
self:RoundedBox("Background", 1, 0, 0, w, h, GetColor("column_sheet_bar"))
end
self.tabs_wide = 48
self.tab_scroller = tab_scroller
self:ScaleChanged()
SUI.OnScaleChanged(self, self.ScaleChanged)
end
function Panel:ScaleChanged()
local tabs_wide = SUI.Scale(self.tabs_wide)
self.tab_scroller:SetWide(tabs_wide)
self:InvalidateLayout(true)
local tabs = self.tabs
for i = 1, #self.tabs do
tabs[i].img:SetMinus(SUI.Scale(20))
end
end
function Panel:Paint(w, h)
self:RoundedBox("Background", 1, 0, 0, w, h, GetColor("column_sheet"))
end
local tab_DoClick = function(s)
s.parent:SetActiveTab(s)
end
local tab_Paint = function(s, w, h)
local cur_col
if s.active then
cur_col = GetColor("column_sheet_tab_active")
elseif s.Hovered then
cur_col = GetColor("column_sheet_tab_hover")
else
cur_col = GetColor("column_sheet_tab")
end
s:RoundedBox("Backgrounds", 0, 0, 0, w, h, cur_col)
end
local tab_OnRemove = function(s)
table.RemoveByValue(s.parent.tabs, s)
end
function Panel:AddSheet(mat, load_func)
local tab = self.tab_scroller:Add(NAME .. ".Button")
tab:Dock(TOP)
tab:SetText("")
tab:SetTall(self.tabs_wide)
tab.On = TDLib_Classes.On
tab.DoClick = tab_DoClick
tab.Paint = tab_Paint
tab:On("OnRemove", tab_OnRemove)
tab.parent = self
tab.load_func = load_func
local img = tab:Add(NAME .. ".Image")
img:Dock(FILL)
img:SetImage(mat)
img:SetMinus(SUI.Scale(20))
tab.img = img
self.tab_scroller:AddItem(tab)
if not self:GetActiveTab() then
self:SetActiveTab(tab)
end
table.insert(self.tabs, tab)
return tab
end
function Panel:GetActiveTab()
return self.active_tab
end
function Panel:SetActiveTab(new_tab)
if new_tab == self.active_tab then return end
if not IsValid(new_tab.panel) then
local panel = new_tab.load_func(self)
panel:SetParent(self)
panel:SetVisible(false)
panel:SetAlpha(0)
panel.tab = new_tab
new_tab.panel = panel
end
local old_active_tab = self.active_tab
local delay = 0
if old_active_tab and IsValid(old_active_tab.panel) then
old_active_tab.active = false
delay = 0.2
old_active_tab.panel:AlphaTo(0, delay, 0, function(_, p)
if p:IsValid() then
p:SetVisible(false)
end
end)
end
new_tab.active = true
new_tab.panel:SetVisible(true)
new_tab.panel:AlphaTo(255, 0.2, delay)
self.active_tab = new_tab
end
sui.register("ColumnSheet", Panel, "EditablePanel")

146
lua/sui/vgui/sui_zmenu.lua Normal file
View File

@@ -0,0 +1,146 @@
--[[
| 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/
--]]
local BSHADOWS = sui.BSHADOWS
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local GetColor = SUI.GetColor
local RoundedBox = sui.TDLib.LibClasses.RoundedBox
local TextColor = sui.TDLib.LibClasses.TextColor
local OPTION_FONT = SUI.CreateFont("MenuOption", "Roboto Medium", 15, 500)
local PANEL = {}
AccessorFunc(PANEL, "m_bIsMenuComponent", "IsMenu")
AccessorFunc(PANEL, "m_bDeleteSelf", "DeleteSelf")
AccessorFunc(PANEL, "m_iMinimumWidth", "MinimumWidth")
AccessorFunc(PANEL, "m_SetInternal", "Internal")
PANEL:SetIsMenu(true)
PANEL:SetDeleteSelf(true)
local pad = 4
local max_height = 300
local PerformLayout = function(s)
local w, h = s:ChildrenSize()
if h > SUI.Scale(max_height) then
h = SUI.Scale(max_height)
end
s:SetSize(math.max(s:GetMinimumWidth(), w), h)
end
function PANEL:Init()
self:GetCanvas():DockPadding(0, pad, 0, pad)
self:SetMinimumWidth(SUI.Scale(100))
self:SetKeyboardInputEnabled(false)
self:SetTall(pad * 2)
self:SetAlpha(0)
self.tall = pad * 2
RegisterDermaMenuForClose(self)
self:On("PerformLayoutInternal", PerformLayout)
end
function PANEL:Paint(w, h)
local x, y = self:LocalToScreen()
BSHADOWS.BeginShadow()
self:RoundedBox("Background", pad, x, y, w, h, GetColor("menu"))
BSHADOWS.EndShadow(1, 3, 3)
self:MoveToFront()
end
function PANEL:Open(x, y)
self:SizeToChildren(true, false)
local w, h = self:GetSize()
if h > SUI.Scale(max_height) then
h = SUI.Scale(max_height)
end
local internal = self:GetInternal()
internal:On("OnRemove", function()
self:Remove()
end)
if not x then
x, y = internal:LocalToScreen(0, 0)
y = y + (internal:GetTall() + 2)
end
if y + h > ScrH() then
y = y - h
end
if x + w > ScrW() then
x = x - w
end
if y < 1 then
y = 1
end
if x < 1 then
x = 1
end
self:SetPos(x, y)
self:MakePopup()
self:AlphaTo(255, 0.23)
self:SetDrawOnTop(true)
self:MoveToFront()
end
local option_OnMouseReleased = function(s, mousecode)
if s.Depressed and mousecode == MOUSE_LEFT then
CloseDermaMenus()
end
DButton.OnMouseReleased(s, mousecode)
end
function PANEL:AddOption(str, callback)
local option = self:Add("DButton")
option:Dock(TOP)
option:SetFont(OPTION_FONT)
option:SetText(str)
option:SizeToContentsX(20)
option:SizeToContentsY(10)
option:InvalidateLayout(true)
option.OnMouseReleased = option_OnMouseReleased
function option:Paint(w, h)
RoundedBox(self, "Background", 0, 0, 0, w, h, self.Hovered and GetColor("menu_option_hover") or GetColor("menu_option"))
TextColor(self, self.Hovered and GetColor("menu_option_hover_text") or GetColor("menu_option_text"))
end
option.DoClick = callback
self.tall = self.tall + option:GetTall()
self:SetTall(self.tall)
return option
end
function PANEL:AddSpacer()
local spacer = self:Add("Panel")
spacer:Dock(TOP)
spacer:DockMargin(0, 1, 0, 1)
spacer:SetTall(2)
function spacer:Paint(w, h)
RoundedBox(self, "Background", 0, 0, 0, w, h, GetColor("menu_spacer"))
end
spacer:InvalidateLayout(true)
end
sui.register("Menu", PANEL, NAME .. ".ScrollPanel")