Files
wnsrc/gamemodes/helix/plugins/willardinterface/derma/cl_notice.lua
lifestorm ba1fc01b16 Upload
2024-08-04 23:12:27 +03:00

285 lines
6.4 KiB
Lua

--[[
| 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 animationTime = 0.75
-- notice manager
-- this manages positions/animations for notice panels
local PANEL = {}
AccessorFunc(PANEL, "padding", "Padding", FORCE_NUMBER)
function PANEL:Init()
self:SetSize(ScrW() * 0.4, ScrH())
self:SetZPos(-99999)
self:SetMouseInputEnabled(false)
self:SetKeyboardInputEnabled(false)
self.notices = {}
self.padding = 4
end
function PANEL:GetAll()
return self.notices
end
function PANEL:Clear()
for _, v in ipairs(self.notices) do
self:RemoveNotice(v)
end
end
function PANEL:AddNotice(text, bError)
if (IsValid(ix.gui.characterMenu) and !ix.gui.characterMenu.bClosing) then
return
end
local panel = self:Add("ixNotice")
panel:SetText(text)
panel:SetError(bError or text:utf8sub(#text, #text) == "!")
panel:SizeToContents()
panel.currentY = -panel:GetTall()
panel:SetPos(self.padding, panel.currentY)
-- setup duration timer
panel:CreateAnimation(ix.option.Get("noticeDuration", 8), {
index = 2,
target = {duration = 1},
bIgnoreConfig = true,
OnComplete = function(animation, this)
self:RemoveNotice(this)
end
})
table.insert(self.notices, 1, panel)
self:Organize()
-- remove old notice if we've hit the limit of notices
if (#self.notices > ix.option.Get("noticeMax", 4)) then
for i = #self.notices, 1, -1 do
local notice = self.notices[i]
if (IsValid(notice) and !notice.bClosing) then
self:RemoveNotice(notice)
break
end
end
end
return panel
end
function PANEL:RemoveNotice(panel)
panel.bClosing = true
panel:CreateAnimation(animationTime, {
index = 3,
target = {outAnimation = 0},
easing = "outQuint",
OnComplete = function(animation, this)
local toRemove
for k, v in ipairs(self.notices) do
if (v == this) then
toRemove = k
break
end
end
if (toRemove) then
table.remove(self.notices, toRemove)
end
this:SetText("") -- (hack) text remains for a frame after remove is called, so let's make sure we don't draw it
this:Remove()
end
})
end
-- update target Y positions and animations
function PANEL:Organize()
local currentTarget = self.padding
for _, v in ipairs(self.notices) do
v:CreateAnimation(animationTime, {
index = 1,
target = {currentY = currentTarget},
easing = "outElastic",
Think = function(animation, panel)
panel:SetPos(
self:GetWide() - panel:GetWide() - self.padding,
math.min(panel.currentY + 1, currentTarget) -- easing eventually hits subpixel movement so we level it off
)
end
})
currentTarget = currentTarget + self.padding + v:GetTall()
end
end
function PANEL:Think()
if IsValid(ix.gui.menu) and ix.gui.menu:IsVisible() then
self:SetPos(ScrW() - ScrW() * 0.4, SScaleMin(50 / 3))
else
self:SetPos(ScrW() - ScrW() * 0.4, 0)
end
end
vgui.Register("ixNoticeManager", PANEL, "Panel")
-- notice panel
-- these do not manage their own enter/exit animations or lifetime
DEFINE_BASECLASS("DLabel")
PANEL = {}
AccessorFunc(PANEL, "bError", "Error", FORCE_BOOL)
AccessorFunc(PANEL, "padding", "Padding", FORCE_NUMBER)
function PANEL:Init()
self:SetSize(256, 36)
self:SetContentAlignment(5)
self:SetExpensiveShadow(1, Color(0, 0, 0, 150))
self:SetFont("ixNoticeFont")
self:SetTextColor(color_white)
self:SetDrawOnTop(true)
self:DockPadding(0, 0, 0, 0)
self:DockMargin(0, 0, 0, 0)
self.bError = false
self.bHovered = false
self.errorAnimation = 0
self.padding = 8
self.currentY = 0
self.duration = 0
self.outAnimation = 1
self.alpha = 255
LocalPlayer():EmitSound("Helix.Notify")
end
function PANEL:SetError(bValue)
self.bError = tobool(bValue)
if (bValue) then
self.errorAnimation = 1
self:CreateAnimation(animationTime, {
index = 5,
target = {errorAnimation = 0},
easing = "outQuint"
})
end
end
function PANEL:SizeToContents()
local contentWidth, contentHeight = self:GetContentSize()
contentWidth = contentWidth + self.padding * 2
contentHeight = contentHeight + self.padding * 2
local manager = ix.gui.notices
local maxWidth = math.min(IsValid(manager) and (manager:GetWide() - manager:GetPadding() * 2) or ScrW(), contentWidth)
if (contentWidth > maxWidth) then
self:SetWide(maxWidth)
self:SetTextInset(self.padding * 2, 0)
self:SetWrap(true)
self:SizeToContentsY()
self:SetWide(self:GetContentSize())
else
self:SetSize(contentWidth, contentHeight)
end
end
function PANEL:SizeToContentsY()
BaseClass.SizeToContentsY(self)
self:SetTall(self:GetTall() + self.padding * 2)
end
function PANEL:OnMouseHover()
self:CreateAnimation(animationTime * 0.5, {
index = 4,
target = {alpha = 0},
easing = "outQuint",
Think = function(animation, panel)
panel:SetAlpha(panel.alpha)
end
})
end
function PANEL:OnMouseLeave()
self:CreateAnimation(animationTime * 0.5, {
index = 4,
target = {alpha = 255},
easing = "outQuint",
Think = function(animation, panel)
panel:SetAlpha(panel.alpha)
end
})
end
function PANEL:Paint(width, height)
if (self.outAnimation < 1) then
local x, y = self:LocalToScreen(0, 0)
render.SetScissorRect(x, y, x + self:GetWide(), y + (self:GetTall() * self.outAnimation), true)
end
local x, y = self:LocalToScreen(0, 0)
local mouseX, mouseY = gui.MousePos()
if (mouseX >= x and mouseX <= x + width and
mouseY >= y and mouseY <= y + height) then
if (!self.bHovered) then
self.bHovered = true
self:OnMouseHover()
end
elseif (self.bHovered) then
self.bHovered = false
self:OnMouseLeave()
end
ix.util.DrawBlur(self)
if (self.errorAnimation > 0) then
local color = derma.GetColor("Error", self)
surface.SetDrawColor(
color.r * self.errorAnimation,
color.g * self.errorAnimation,
color.b * self.errorAnimation,
self.errorAnimation * 255 + ((1 - self.errorAnimation) * 66)
)
else
surface.SetDrawColor(0, 0, 0, 66)
end
surface.DrawRect(0, 0, width, height)
surface.SetDrawColor(self.bError and derma.GetColor("Error", self) or ix.config.Get("color"))
surface.DrawRect(0, height - 1, width * self.duration, 1)
end
function PANEL:PaintOver(width, height)
render.SetScissorRect(0, 0, 0, 0, false)
end
vgui.Register("ixNotice", PANEL, "DLabel")
if (IsValid(ix.gui.notices)) then
ix.gui.notices:Remove()
ix.gui.notices = vgui.Create("ixNoticeManager")
else
ix.gui.notices = vgui.Create("ixNoticeManager")
end