Compare commits
2 commits
fad1e8eba6
...
fe2785825b
Author | SHA1 | Date | |
---|---|---|---|
fe2785825b | |||
631874aebc |
3 changed files with 266 additions and 40 deletions
|
@ -1,12 +1,32 @@
|
|||
local DisableClipping = DisableClipping
|
||||
local ScrW = ScrW
|
||||
local ScrH = ScrH
|
||||
local Color = Color
|
||||
|
||||
local STENCIL_EQUAL = STENCIL_EQUAL
|
||||
local STENCIL_KEEP = STENCIL_KEEP
|
||||
local STENCIL_NEVER = STENCIL_NEVER
|
||||
local STENCIL_REPLACE = STENCIL_REPLACE
|
||||
|
||||
local draw = draw
|
||||
local math = math
|
||||
local render = render
|
||||
local string = string
|
||||
local surface = surface
|
||||
|
||||
local draw_NoTexture = draw.NoTexture
|
||||
local math_rad = math.rad
|
||||
local math_sin = math.sin
|
||||
local math_cos = math.cos
|
||||
local render_ClearStencil = render.ClearStencil
|
||||
local render_SetStencilCompareFunction = render.SetStencilCompareFunction
|
||||
local render_SetStencilEnable = render.SetStencilEnable
|
||||
local render_SetStencilFailOperation = render.SetStencilFailOperation
|
||||
local render_SetStencilPassOperation = render.SetStencilPassOperation
|
||||
local render_SetStencilReferenceValue = render.SetStencilReferenceValue
|
||||
local render_SetStencilTestMask = render.SetStencilTestMask
|
||||
local render_SetStencilWriteMask = render.SetStencilWriteMask
|
||||
local render_SetStencilZFailOperation = render.SetStencilZFailOperation
|
||||
local render_UpdateScreenEffectTexture = render.UpdateScreenEffectTexture
|
||||
local surface_DrawPoly = surface.DrawPoly
|
||||
local surface_DrawRect = surface.DrawRect
|
||||
local surface_DrawTexturedRect = surface.DrawTexturedRect
|
||||
local surface_SetDrawColor = surface.SetDrawColor
|
||||
|
@ -16,10 +36,10 @@ cbox.chatbox = cbox.chatbox or {}
|
|||
cbox.chatbox.tabs = cbox.chatbox.tabs or {}
|
||||
cbox.chatbox.panels = cbox.chatbox.panels or {}
|
||||
|
||||
|
||||
local CHATBOX_COLOR = CreateClientConVar("cbox_chatbox_color", "160 160 160", true, false, "Chatbox background color")
|
||||
local CHATBOX_ALPHA = CreateClientConVar("cbox_chatbox_alpha", "128", true, false, "Chatbox background alpha")
|
||||
local CHATBOX_BLUR = CreateClientConVar("cbox_chatbox_blur", "0", true, false, "Chatbox background is blurred")
|
||||
local CHATBOX_FADE = CreateClientConVar("cbox_chatbox_fade", "1", true, false, "Chatbox fades in and out")
|
||||
|
||||
---@param height number
|
||||
---@return number
|
||||
|
@ -51,6 +71,55 @@ end
|
|||
|
||||
local MATERIAL_BLUR = Material("pp/blurscreen")
|
||||
|
||||
local function add_rounded_poly(poly, x, y, rad, seg, offset)
|
||||
offset = offset or 0
|
||||
|
||||
for i = 0, seg do
|
||||
local r = math_rad(((i + offset) / seg) * -90)
|
||||
poly[#poly + 1] = {
|
||||
x = x + math_sin(r) * rad,
|
||||
y = y + math_cos(r) * rad,
|
||||
u = math_sin(r) / 2 + 0.5,
|
||||
v = math_cos(r) / 2 + 0.5,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function RoundedBoxPoly(x, y, w, h, rad, seg)
|
||||
local poly = {}
|
||||
|
||||
add_rounded_poly(poly, x + rad, y + rad, rad, seg, seg)
|
||||
|
||||
poly[#poly + 1] = {
|
||||
x = x + (w - rad),
|
||||
y = y,
|
||||
u = 0.5,
|
||||
v = 0.5,
|
||||
}
|
||||
|
||||
add_rounded_poly(poly, x + (w - rad), y + rad, rad, seg, seg * 2)
|
||||
|
||||
poly[#poly + 1] = {
|
||||
x = x + w,
|
||||
y = y + (h - rad),
|
||||
u = 0.5,
|
||||
v = 0.5,
|
||||
}
|
||||
|
||||
add_rounded_poly(poly, x + (w - rad), y + (h - rad), rad, seg, seg * 3)
|
||||
|
||||
poly[#poly + 1] = {
|
||||
x = x + rad,
|
||||
y = y + h,
|
||||
u = 0.5,
|
||||
v = 0.5,
|
||||
}
|
||||
|
||||
add_rounded_poly(poly, x + rad, y + (h - rad), rad, seg)
|
||||
|
||||
surface_DrawPoly(poly)
|
||||
end
|
||||
|
||||
local function CreateChatbox()
|
||||
if IsValid(cbox.chatbox.panels.frame) then
|
||||
cbox.chatbox.panels.frame:Remove()
|
||||
|
@ -61,15 +130,85 @@ local function CreateChatbox()
|
|||
frame:SetDeleteOnClose(false)
|
||||
frame:SetSizable(true)
|
||||
frame:SetScreenLock(true)
|
||||
frame:DockPadding(4, 4, 4, 4)
|
||||
frame:DockPadding(8, 8, 8, 8)
|
||||
|
||||
frame.btnMinim:SetVisible(false)
|
||||
frame.btnMaxim:SetVisible(false)
|
||||
frame.lblTitle:SetVisible(false)
|
||||
local dx, dy, dw, dh = GetDefaultBounds()
|
||||
|
||||
-- TODO: make this configurable
|
||||
frame:SetMinWidth(dw)
|
||||
frame:SetMinWidth(dh)
|
||||
|
||||
-- TODO: save resizing/moving
|
||||
frame:SetPos(dx, dy)
|
||||
frame:SetSize(dw, dh)
|
||||
|
||||
frame:SetVisible(false)
|
||||
|
||||
function frame:PerformLayout() end
|
||||
|
||||
frame.btnClose:Remove()
|
||||
frame.btnMinim:Remove()
|
||||
frame.btnMaxim:Remove()
|
||||
frame.lblTitle:Remove()
|
||||
|
||||
function frame:CrossFade(anim, delta, out)
|
||||
if anim.Finished then
|
||||
if out then
|
||||
self:Close()
|
||||
else
|
||||
self:MakePopup()
|
||||
end
|
||||
end
|
||||
|
||||
if anim.Started then
|
||||
if out then
|
||||
self:SetAlpha(255)
|
||||
else
|
||||
self:SetAlpha(0)
|
||||
end
|
||||
end
|
||||
|
||||
self:SetAlpha(out and 255 * (1 - delta) or 255 * delta)
|
||||
end
|
||||
|
||||
frame.animFade = Derma_Anim("Fade", frame, frame.CrossFade)
|
||||
|
||||
frame.oldThink = frame.Think
|
||||
|
||||
function frame:Think()
|
||||
self:oldThink()
|
||||
|
||||
self.animFade:Run()
|
||||
|
||||
-- TODO: save position and size
|
||||
end
|
||||
|
||||
function frame:Paint(w, h)
|
||||
local alpha = CHATBOX_ALPHA:GetInt()
|
||||
|
||||
-- Reset everything to known good
|
||||
render_SetStencilWriteMask( 0xFF )
|
||||
render_SetStencilTestMask( 0xFF )
|
||||
render_SetStencilReferenceValue( 0 )
|
||||
render_SetStencilPassOperation( STENCIL_KEEP )
|
||||
render_SetStencilZFailOperation( STENCIL_KEEP )
|
||||
render_ClearStencil()
|
||||
|
||||
-- Enable stencils
|
||||
render_SetStencilEnable( true )
|
||||
-- Set everything up everything draws to the stencil buffer instead of the screen
|
||||
render_SetStencilReferenceValue( 1 )
|
||||
render_SetStencilCompareFunction( STENCIL_NEVER )
|
||||
render_SetStencilFailOperation( STENCIL_REPLACE )
|
||||
|
||||
draw_NoTexture()
|
||||
surface_SetDrawColor(255, 255, 255)
|
||||
RoundedBoxPoly(0, 0, w, h, 8, 24)
|
||||
|
||||
-- Only draw things that are in the stencil buffer
|
||||
render_SetStencilCompareFunction( STENCIL_EQUAL )
|
||||
render_SetStencilFailOperation( STENCIL_KEEP )
|
||||
|
||||
if CHATBOX_BLUR:GetBool() and alpha ~= 255 then
|
||||
local x, y = self:LocalToScreen(0, 0)
|
||||
|
||||
|
@ -84,32 +223,26 @@ local function CreateChatbox()
|
|||
end
|
||||
end
|
||||
|
||||
local color = string.Explode(" ", CHATBOX_COLOR:GetString())
|
||||
surface_SetDrawColor(tonumber(color[1]), tonumber(color[2]), tonumber(color[3]), alpha)
|
||||
local r, g, b = CHATBOX_COLOR:GetString():match("(%d+) (%d+) (%d+)")
|
||||
surface_SetDrawColor(r, g, b, alpha)
|
||||
surface_DrawRect(0, 0, w, h)
|
||||
|
||||
-- Let everything render normally again
|
||||
render_SetStencilEnable(false)
|
||||
end
|
||||
|
||||
local dx, dy, dw, dh = GetDefaultBounds()
|
||||
|
||||
-- TODO: make this configurable
|
||||
frame:SetMinWidth(dw)
|
||||
frame:SetMinWidth(dh)
|
||||
|
||||
-- TODO: save resizing/moving
|
||||
frame:SetPos(dx, dy)
|
||||
frame:SetSize(dw, dh)
|
||||
|
||||
frame:SetVisible(false)
|
||||
|
||||
cbox.chatbox.panels.frame = frame
|
||||
|
||||
local tabs = vgui.Create("DPropertySheet", frame, "cbox.chatbox.tabs")
|
||||
tabs:Dock(FILL)
|
||||
tabs:SetPadding(0)
|
||||
|
||||
function tabs:Paint(w, h)
|
||||
surface_SetDrawColor(0, 0, 0, 72)
|
||||
surface_DrawRect(0, 20, w, h - 20)
|
||||
function tabs:Paint(w, h) end
|
||||
|
||||
function tabs:OnActiveTabChanged( old, new )
|
||||
if new:GetPanel().cbox_id == "\1chat" then
|
||||
cbox.chatbox.panels.input:RequestFocus()
|
||||
end
|
||||
end
|
||||
|
||||
for id, tab in next, cbox.chatbox.tabs do
|
||||
|
@ -124,14 +257,30 @@ local function CreateChatbox()
|
|||
continue
|
||||
end
|
||||
|
||||
tabs:AddSheet(tab.name, ret, tab.icon)
|
||||
local sheet = tabs:AddSheet(tab.name, ret, tab.icon)
|
||||
sheet.Panel.cbox_id = id
|
||||
end
|
||||
|
||||
frame.btnClose:SetZPos(99)
|
||||
end
|
||||
|
||||
if not IsValid(cbox.chatbox.panels.frame) then
|
||||
local function Init()
|
||||
local tab_files = file.Find("cbox/tabs/*", "LUA")
|
||||
for _, name in ipairs(tab_files) do
|
||||
cbox.utils.RealmPrint("Loading chatbox tab:", name)
|
||||
include("cbox/tabs/" .. name)
|
||||
end
|
||||
|
||||
if not IsValid(cbox.chatbox.panels.frame) then
|
||||
CreateChatbox()
|
||||
end
|
||||
|
||||
hook.Add("PlayerBindPress", "cbox.chatbox", function(ply, bind, pressed)
|
||||
if bind ~= "messagemode" and bind ~= "messagemode2" then return end
|
||||
if not pressed then return end
|
||||
|
||||
cbox.chatbox.Open(bind == "messagemode2")
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
---Opens the chatbox
|
||||
|
@ -139,12 +288,37 @@ end
|
|||
function cbox.chatbox.Open(alt)
|
||||
alt = alt ~= nil and alt or false
|
||||
|
||||
if not IsValid(cbox.chatbox.panels.frame) then
|
||||
local frame = cbox.chatbox.panels.frame
|
||||
|
||||
if not IsValid(frame) then
|
||||
CreateChatbox()
|
||||
end
|
||||
|
||||
cbox.chatbox.panels.frame:SetVisible(true)
|
||||
cbox.chatbox.panels.frame:MakePopup()
|
||||
frame:SetVisible(true)
|
||||
|
||||
if frame.animFade and CHATBOX_FADE:GetBool() then
|
||||
frame.animFade:Start(0.1, false)
|
||||
else
|
||||
frame:MakePopup()
|
||||
end
|
||||
|
||||
if not IsValid(cbox.chatbox.panels.input) then
|
||||
-- attempt to reinit
|
||||
if IsValid(frame) then
|
||||
frame:Remove()
|
||||
end
|
||||
Init()
|
||||
end
|
||||
|
||||
if not IsValid(cbox.chatbox.panels.input) then
|
||||
cbox.utils.RealmError("Input isn't valid, chat tab failed to load, bailing!")
|
||||
if IsValid(frame) then
|
||||
frame:Remove()
|
||||
end
|
||||
hook.Remove("PlayerBindPress", "cbox.chatbox")
|
||||
return
|
||||
end
|
||||
|
||||
cbox.chatbox.panels.input:RequestFocus()
|
||||
|
||||
hook.Run("StartChat")
|
||||
|
@ -152,7 +326,13 @@ end
|
|||
|
||||
---Closes the chatbox
|
||||
function cbox.chatbox.Close()
|
||||
cbox.chatbox.panels.frame:Close()
|
||||
local frame = cbox.chatbox.panels.frame
|
||||
|
||||
if frame.animFade and CHATBOX_FADE:GetBool() then
|
||||
frame.animFade:Start(0.1, true)
|
||||
else
|
||||
frame:Close()
|
||||
end
|
||||
|
||||
hook.Run("FinishChat")
|
||||
|
||||
|
@ -160,14 +340,15 @@ function cbox.chatbox.Close()
|
|||
hook.Run("ChatTextChanged", "")
|
||||
end
|
||||
|
||||
hook.Add("PlayerBindPress", "cbox.chatbox", function(ply, bind, pressed)
|
||||
if bind ~= "messagemode" and bind ~= "messagemode2" then return end
|
||||
|
||||
cbox.chatbox.Open(bind == "messagemode2")
|
||||
|
||||
return true
|
||||
end)
|
||||
hook.Add("Initialize", "cbox.chatbox", Init)
|
||||
|
||||
concommand.Add("cbox_chatbox_reload", function()
|
||||
CreateChatbox()
|
||||
end, nil, "Reloads the chatbox")
|
||||
|
||||
concommand.Add("_cbox_chatbox_fullreload", function()
|
||||
if IsValid(cbox.chatbox.panels.frame) then
|
||||
cbox.chatbox.panels.frame:Remove()
|
||||
end
|
||||
Init()
|
||||
end, nil, "Fully reinitializes the chatbox, use only in extreme breakage.")
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
local Color = Color
|
||||
|
||||
local surface = surface
|
||||
|
||||
local surface_DrawRect = surface.DrawRect
|
||||
local surface_SetDrawColor = surface.SetDrawColor
|
||||
|
||||
local INPUT_TEXT_COLOR = Color(221, 221, 221)
|
||||
local INPUT_HIGHLIGHT_COLOR = Color(192, 28, 0, 140)
|
||||
|
||||
cbox.chatbox.AddTab("\1chat", "Chat", "icon16/comments.png", function()
|
||||
local wrapper = vgui.Create("EditablePanel")
|
||||
|
||||
-- TODO: custom richtext panel
|
||||
local history = vgui.Create("RichText", wrapper)
|
||||
history:Dock(FILL)
|
||||
function history:Paint(w, h)
|
||||
surface_SetDrawColor(0, 0, 0, 128)
|
||||
surface_DrawRect(0, 0, w, h)
|
||||
end
|
||||
cbox.chatbox.panels.history = history
|
||||
|
||||
function history:PerformLayout()
|
||||
|
@ -13,18 +27,35 @@ cbox.chatbox.AddTab("\1chat", "Chat", "icon16/comments.png", function()
|
|||
|
||||
local input_wrapper = vgui.Create("EditablePanel", wrapper)
|
||||
input_wrapper:SetHeight(20)
|
||||
input_wrapper:DockMargin(0, 8, 0, 0)
|
||||
input_wrapper:Dock(BOTTOM)
|
||||
|
||||
local input = vgui.Create("DTextEntry", input_wrapper)
|
||||
input:DockMargin(4, 0, 0, 0)
|
||||
input:Dock(FILL)
|
||||
input:SetFont("ChatFont")
|
||||
cbox.chatbox.panels.input = input
|
||||
|
||||
function input:Paint(w, h)
|
||||
surface_SetDrawColor(0, 0, 0, 128)
|
||||
surface_DrawRect(0, 0, w, h)
|
||||
|
||||
self:DrawTextEntryText(INPUT_TEXT_COLOR, INPUT_HIGHLIGHT_COLOR, INPUT_TEXT_COLOR)
|
||||
end
|
||||
|
||||
local mode_switch = vgui.Create("DButton", input_wrapper)
|
||||
mode_switch:SetFont("ChatFont")
|
||||
mode_switch:SetTextColor(INPUT_TEXT_COLOR)
|
||||
mode_switch:SetText("Say")
|
||||
mode_switch:SizeToContents()
|
||||
mode_switch:Dock(LEFT)
|
||||
cbox.chatbox.panels.mode_switch = mode_switch
|
||||
|
||||
function mode_switch:Paint(w, h)
|
||||
surface_SetDrawColor(0, 0, 0, 128)
|
||||
surface_DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
function mode_switch:DoClick()
|
||||
-- TODO
|
||||
end
|
||||
|
|
14
lua/cbox/tabs/settings.lua
Normal file
14
lua/cbox/tabs/settings.lua
Normal file
|
@ -0,0 +1,14 @@
|
|||
local surface = surface
|
||||
|
||||
local surface_DrawRect = surface.DrawRect
|
||||
local surface_SetDrawColor = surface.SetDrawColor
|
||||
|
||||
cbox.chatbox.AddTab("zzzzzzzsettings", "Settings", "icon16/cog.png", function()
|
||||
local wrapper = vgui.Create("EditablePanel")
|
||||
function wrapper:Paint(w, h)
|
||||
surface_SetDrawColor(0, 0, 0, 128)
|
||||
surface_DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
return wrapper
|
||||
end)
|
Loading…
Reference in a new issue