basic chatbox functionality
This commit is contained in:
parent
5cfe0c8ea5
commit
27d4dda2a2
5 changed files with 280 additions and 7 deletions
180
lua/cbox/cl_chatbox.lua
Normal file
180
lua/cbox/cl_chatbox.lua
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
local DisableClipping = DisableClipping
|
||||||
|
local ScrW = ScrW
|
||||||
|
local ScrH = ScrH
|
||||||
|
|
||||||
|
local render = render
|
||||||
|
local string = string
|
||||||
|
local surface = surface
|
||||||
|
|
||||||
|
local render_UpdateScreenEffectTexture = render.UpdateScreenEffectTexture
|
||||||
|
local surface_DrawRect = surface.DrawRect
|
||||||
|
local surface_DrawTexturedRect = surface.DrawTexturedRect
|
||||||
|
local surface_SetDrawColor = surface.SetDrawColor
|
||||||
|
local surface_SetMaterial = surface.SetMaterial
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
---@param height number
|
||||||
|
---@return number
|
||||||
|
local function _ScreenScaleH(height)
|
||||||
|
return height * (ScrH() / 480)
|
||||||
|
end
|
||||||
|
local ScreenScaleH = ScreenScaleH or _ScreenScaleH
|
||||||
|
|
||||||
|
---@return number x
|
||||||
|
---@return number y
|
||||||
|
---@return number w
|
||||||
|
---@return number h
|
||||||
|
local function GetDefaultBounds()
|
||||||
|
return ScreenScaleH(10), ScreenScaleH(275), ScreenScaleH(320), ScreenScaleH(120)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Add a new chatbox tab
|
||||||
|
---@param key string Internal unique name
|
||||||
|
---@param name string Display name
|
||||||
|
---@param icon string Path to icon
|
||||||
|
---@param callback fun(): Panel What to do when the tab is created
|
||||||
|
function cbox.chatbox.AddTab(key, name, icon, callback)
|
||||||
|
cbox.chatbox.tabs[key] = {
|
||||||
|
name = name,
|
||||||
|
icon = icon,
|
||||||
|
callback = callback,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local MATERIAL_BLUR = Material("pp/blurscreen")
|
||||||
|
|
||||||
|
local oldSkin = SKIN
|
||||||
|
SKIN = derma.GetDefaultSkin()
|
||||||
|
local CLOSE_BUTTON = GWEN.CreateTextureNormal(32, 452, 29, 17)
|
||||||
|
local CLOSE_BUTTON_HOVER = GWEN.CreateTextureNormal(64, 452, 29, 17)
|
||||||
|
local CLOSE_BUTTON_DOWN = GWEN.CreateTextureNormal(96, 452, 29, 17)
|
||||||
|
SKIN = oldSkin
|
||||||
|
|
||||||
|
local COLOR_DISABLED = Color(255, 255, 255, 50)
|
||||||
|
|
||||||
|
local function CreateChatbox()
|
||||||
|
if IsValid(cbox.chatbox.panels.frame) then
|
||||||
|
cbox.chatbox.panels.frame:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
local frame = vgui.Create("DFrame", nil, "cbox.chatbox")
|
||||||
|
frame:SetCookieName("cbox_chatbox")
|
||||||
|
frame:SetDeleteOnClose(false)
|
||||||
|
frame:SetSizable(true)
|
||||||
|
frame:SetScreenLock(true)
|
||||||
|
frame:DockPadding(4, 4, 4, 4)
|
||||||
|
|
||||||
|
frame.btnMinim:SetVisible(false)
|
||||||
|
frame.btnMaxim:SetVisible(false)
|
||||||
|
frame.lblTitle:SetVisible(false)
|
||||||
|
|
||||||
|
function frame:Paint(w, h)
|
||||||
|
if CHATBOX_BLUR:GetBool() then
|
||||||
|
local x, y = self:LocalToScreen(0, 0)
|
||||||
|
|
||||||
|
surface_SetMaterial(MATERIAL_BLUR)
|
||||||
|
surface_SetDrawColor(255, 255, 255, 255)
|
||||||
|
|
||||||
|
for i = 0.33, 1, 0.33 do
|
||||||
|
MATERIAL_BLUR:SetFloat("$blur", 5 * i)
|
||||||
|
MATERIAL_BLUR:Recompute()
|
||||||
|
render_UpdateScreenEffectTexture()
|
||||||
|
surface_DrawTexturedRect(x * -1, y * -1, ScrW(), ScrH())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local color = string.Explode(" ", CHATBOX_COLOR:GetString())
|
||||||
|
surface_SetDrawColor(tonumber(color[1]), tonumber(color[2]), tonumber(color[3]), CHATBOX_ALPHA:GetInt())
|
||||||
|
surface_DrawRect(0, 0, w, h)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
||||||
|
for id, tab in next, cbox.chatbox.tabs do
|
||||||
|
local function catch(err)
|
||||||
|
cbox.utils.RealmError(("Failed to create tab %q:"):format(id), err)
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok, ret = xpcall(tab.callback, catch)
|
||||||
|
if not ok then continue end
|
||||||
|
if not ispanel(ret) then
|
||||||
|
cbox.utils.RealmError(("Got non-panel for tab %q!"):format(id))
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
tabs:AddSheet(tab.name, ret, tab.icon)
|
||||||
|
end
|
||||||
|
|
||||||
|
frame.btnClose:SetZPos(99)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not IsValid(cbox.chatbox.panels.frame) then
|
||||||
|
CreateChatbox()
|
||||||
|
end
|
||||||
|
|
||||||
|
---Opens the chatbox
|
||||||
|
---@param alt? boolean Was this request to open made by messagemode2 (team chat)
|
||||||
|
function cbox.chatbox.Open(alt)
|
||||||
|
alt = alt ~= nil and alt or false
|
||||||
|
|
||||||
|
if not IsValid(cbox.chatbox.panels.frame) then
|
||||||
|
CreateChatbox()
|
||||||
|
end
|
||||||
|
|
||||||
|
cbox.chatbox.panels.frame:SetVisible(true)
|
||||||
|
cbox.chatbox.panels.frame:MakePopup()
|
||||||
|
cbox.chatbox.panels.input:RequestFocus()
|
||||||
|
|
||||||
|
hook.Run("StartChat")
|
||||||
|
end
|
||||||
|
|
||||||
|
---Closes the chatbox
|
||||||
|
function cbox.chatbox.Close()
|
||||||
|
cbox.chatbox.panels.frame:Close()
|
||||||
|
|
||||||
|
hook.Run("FinishChat")
|
||||||
|
|
||||||
|
cbox.chatbox.panels.input:SetText("")
|
||||||
|
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)
|
||||||
|
|
||||||
|
concommand.Add("cbox_chatbox_reload", function()
|
||||||
|
CreateChatbox()
|
||||||
|
end, nil, "Reloads the chatbox")
|
|
@ -11,8 +11,11 @@ function cbox.hooks.GetTable()
|
||||||
return hookTable
|
return hookTable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@alias ValidHooks
|
||||||
|
---| '"PreChatAddText"' # Runs before the true chat.AddText is called, allows modification to arguments
|
||||||
|
|
||||||
---Adds a hook
|
---Adds a hook
|
||||||
---@param name "PreChatAddText"
|
---@param name ValidHooks
|
||||||
---@param identifier string
|
---@param identifier string
|
||||||
---@param callback function
|
---@param callback function
|
||||||
function cbox.hooks.Add(name, identifier, callback)
|
function cbox.hooks.Add(name, identifier, callback)
|
||||||
|
@ -21,7 +24,7 @@ function cbox.hooks.Add(name, identifier, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Removes a hook
|
---Removes a hook
|
||||||
---@param name "PreChatAddText"
|
---@param name ValidHooks
|
||||||
---@param identifier string
|
---@param identifier string
|
||||||
function cbox.hooks.Remove(name, identifier)
|
function cbox.hooks.Remove(name, identifier)
|
||||||
if not hookTable[name] then return end
|
if not hookTable[name] then return end
|
||||||
|
|
|
@ -6,8 +6,15 @@ include("cbox/sh_utils.lua")
|
||||||
|
|
||||||
if SERVER then
|
if SERVER then
|
||||||
AddCSLuaFile("cbox/cl_hooks.lua")
|
AddCSLuaFile("cbox/cl_hooks.lua")
|
||||||
|
AddCSLuaFile("cbox/cl_chatbox.lua")
|
||||||
|
|
||||||
|
local tab_files = file.Find("cbox/tabs/*", "LUA")
|
||||||
|
for _, name in ipairs(tab_files) do
|
||||||
|
AddCSLuaFile("cbox/tabs/" .. name)
|
||||||
|
end
|
||||||
elseif CLIENT then
|
elseif CLIENT then
|
||||||
include("cbox/cl_hooks.lua")
|
include("cbox/cl_hooks.lua")
|
||||||
|
include("cbox/cl_chatbox.lua")
|
||||||
end
|
end
|
||||||
|
|
||||||
local module_files = file.Find("cbox/modules/*", "LUA")
|
local module_files = file.Find("cbox/modules/*", "LUA")
|
||||||
|
@ -21,7 +28,7 @@ for _, name in ipairs(module_files) do
|
||||||
include(full_path)
|
include(full_path)
|
||||||
end
|
end
|
||||||
elseif name:StartsWith("sv_") and SERVER then
|
elseif name:StartsWith("sv_") and SERVER then
|
||||||
cbox.utils.RealmPrint("Loading module:", name)
|
cbox.utils.RealmPrint("Loading module:", name)
|
||||||
include(full_path)
|
include(full_path)
|
||||||
else
|
else
|
||||||
if SERVER then
|
if SERVER then
|
||||||
|
|
|
@ -40,7 +40,7 @@ function utils.ParseColorString(str, alpha)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Prints to console with realm prefix
|
---Prints to console with realm prefix
|
||||||
---@vararg any
|
---@param ... any
|
||||||
function utils.RealmPrint(...)
|
function utils.RealmPrint(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
for i, arg in ipairs(args) do
|
for i, arg in ipairs(args) do
|
||||||
|
@ -65,7 +65,7 @@ function utils.RealmPrint(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Prints to console with the "shared" prefix
|
---Prints to console with the "shared" prefix
|
||||||
---@vararg any
|
---@param ... any
|
||||||
function utils.SharedPrint(...)
|
function utils.SharedPrint(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
for i, arg in ipairs(args) do
|
for i, arg in ipairs(args) do
|
||||||
|
@ -82,7 +82,7 @@ function utils.SharedPrint(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Prints to console with realm prefix, but in red
|
---Prints to console with realm prefix, but in red
|
||||||
---@vararg any
|
---@param ... any
|
||||||
function utils.RealmError(...)
|
function utils.RealmError(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
for i, arg in ipairs(args) do
|
for i, arg in ipairs(args) do
|
||||||
|
@ -107,7 +107,7 @@ function utils.RealmError(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Prints to console with the "shared" prefix, but in red
|
---Prints to console with the "shared" prefix, but in red
|
||||||
---@vararg any
|
---@param ... any
|
||||||
function utils.SharedError(...)
|
function utils.SharedError(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
for i, arg in ipairs(args) do
|
for i, arg in ipairs(args) do
|
||||||
|
|
83
lua/cbox/tabs/chat.lua
Normal file
83
lua/cbox/tabs/chat.lua
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
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)
|
||||||
|
cbox.chatbox.panels.history = history
|
||||||
|
|
||||||
|
function history:PerformLayout()
|
||||||
|
-- TODO: configurable font
|
||||||
|
history:SetFontInternal("ChatFont")
|
||||||
|
end
|
||||||
|
|
||||||
|
local input_wrapper = vgui.Create("EditablePanel", wrapper)
|
||||||
|
input_wrapper:SetHeight(20)
|
||||||
|
input_wrapper:Dock(BOTTOM)
|
||||||
|
|
||||||
|
local input = vgui.Create("DTextEntry", input_wrapper)
|
||||||
|
input:Dock(FILL)
|
||||||
|
cbox.chatbox.panels.input = input
|
||||||
|
|
||||||
|
local mode_switch = vgui.Create("DButton", input_wrapper)
|
||||||
|
mode_switch:SetText("Say")
|
||||||
|
mode_switch:SizeToContents()
|
||||||
|
mode_switch:Dock(LEFT)
|
||||||
|
cbox.chatbox.panels.mode_switch = mode_switch
|
||||||
|
|
||||||
|
function mode_switch:DoClick()
|
||||||
|
-- TODO
|
||||||
|
end
|
||||||
|
function mode_switch:DoRightClick()
|
||||||
|
-- TODO
|
||||||
|
end
|
||||||
|
|
||||||
|
function input:OnKeyCodeTyped(key)
|
||||||
|
if key == KEY_ESCAPE then
|
||||||
|
cbox.chatbox.Close()
|
||||||
|
gui.HideGameUI()
|
||||||
|
elseif key == KEY_BACKQUOTE then
|
||||||
|
gui.HideGameUI()
|
||||||
|
elseif key == KEY_ENTER then
|
||||||
|
local text = self:GetText():Trim()
|
||||||
|
if text ~= "" then
|
||||||
|
RunConsoleCommand("say", text)
|
||||||
|
end
|
||||||
|
|
||||||
|
cbox.chatbox.Close()
|
||||||
|
elseif key == KEY_TAB then
|
||||||
|
if #self:GetText() == 0 then
|
||||||
|
-- TODO: mode switch
|
||||||
|
else
|
||||||
|
-- TODO: autocomplete
|
||||||
|
end
|
||||||
|
else
|
||||||
|
hook.Run("ChatTextChanged", self:GetText())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
end)
|
||||||
|
|
||||||
|
hook.Add("OnChatAddText", "cbox.chatbox.history", function(args)
|
||||||
|
local history = cbox.chatbox.panels.history
|
||||||
|
for _, arg in ipairs(args) do
|
||||||
|
if IsColor(arg) then
|
||||||
|
history:InsertColorChange(arg.r, arg.g, arg.b, 255)
|
||||||
|
elseif isstring(arg) then
|
||||||
|
history:AppendText(arg)
|
||||||
|
elseif isentity(arg) then
|
||||||
|
if IsValid(arg) and arg:IsPlayer() then
|
||||||
|
local col = hook.Run("GetTeamColor", arg)
|
||||||
|
history:InsertColorChange(col.r, col.g, col.b, 255)
|
||||||
|
history:AppendText(arg:Name())
|
||||||
|
else
|
||||||
|
local col = cbox.utils.colors.BRAND
|
||||||
|
history:InsertColorChange(col.r, col.g, col.b, 255)
|
||||||
|
history:AppendText("???")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
history:AppendText("\n")
|
||||||
|
end)
|
Loading…
Reference in a new issue