diff --git a/lua/bladw_announcement/client/admin_menu/cl_menu.lua b/lua/bladw_announcement/client/admin_menu/cl_menu.lua new file mode 100644 index 0000000..6da8559 --- /dev/null +++ b/lua/bladw_announcement/client/admin_menu/cl_menu.lua @@ -0,0 +1,191 @@ +local rndx = include("lib/rndx.lua") +local logo = Material("nocode/announcement/logo.png") + +BladW = BladW or {} +BladW.Announcement = BladW.Announcement or {} + +-- mêmes couleurs que les annonces +local COL_BG = Color(0, 0, 0, 200) +local COL_PANEL = Color(0, 0, 0, 160) +local COL_ACCENT = Color(76, 119, 200) +local COL_ACCENT_DIM = Color(60, 90, 150) +local COL_TEXT = Color(255, 255, 255) +local COL_RED = Color(255, 80, 80) +local COL_GRAY = Color(54, 54, 54, 255) +local COL_MUTED = Color(160, 160, 160) +local COL_WARN = Color(255, 200, 50) + +-- nb de caractères d'un champ (UTF-8, un accent = 1) +local function EntryLen(entry) + local v = entry:GetValue() + return utf8.len(v) or #v +end + +-- petit triangle warning dessiné à la main (comme ça pas besoin de font emoji) +local function DrawWarning(x, y, size) + draw.NoTexture() + surface.SetDrawColor(COL_WARN) + surface.DrawPoly({ + { x = x + size * 0.5, y = y }, + { x = x + size, y = y + size }, + { x = x, y = y + size }, + }) + draw.SimpleText("!", "DermaDefaultBold", x + size * 0.5, y + size * 0.62, Color(30, 30, 30), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) +end + +-- mon style pour les champs de texte +local function StyleEntry(entry, placeholder, default) + entry:SetFont("bladw_text_Medium") + entry:SetText(default or "") + entry:SetPlaceholderText(placeholder or "") + entry:SetTextColor(COL_TEXT) + entry:SetPaintBackground(false) + entry.Paint = function(self, w, h) + rndx.Draw(10, 0, 0, w, h, COL_PANEL, rndx.SHAPE_FIGMA) + local outline = self:IsEditing() and COL_ACCENT or Color(255, 255, 255, 60) + rndx.DrawOutlined(10, 0, 0, w, h, outline, 2, rndx.SHAPE_FIGMA) + self:DrawTextEntryText(COL_TEXT, COL_ACCENT, COL_TEXT) + end +end + +local function OpenAAdminMenu() + + -- si le menu est déjà ouvert je le vire + if IsValid(BladW_AdminMenu) then BladW_AdminMenu:Remove() end + + local selectedPreset = "" + local maxLen = (BladW.Announcement.Conf or {}).announcement_max_length or 120 + + local frame = vgui.Create("DFrame") + BladW_AdminMenu = frame + frame:SetSize(500, 460) + frame:Center() + frame:SetTitle("") + frame:ShowCloseButton(false) + frame:MakePopup() + + frame.Paint = function(self, w, h) + -- fond flou + sombre + contour blanc (comme la box d'annonce) + rndx.Draw(20, 0, 0, w, h, nil, rndx.SHAPE_FIGMA + rndx.BLUR) + rndx.Draw(20, 0, 0, w, h, COL_BG, rndx.SHAPE_FIGMA) + rndx.DrawOutlined(20, 0, 0, w, h, COL_TEXT, 3, rndx.SHAPE_FIGMA) + + -- logo + titre + rndx.DrawMaterial(0, w * 0.5 - 30, 20, 60, 60, COL_TEXT, logo) + draw.SimpleText("Envoyer une annonce", "bladw_text", w * 0.5, 94, COL_TEXT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + draw.SimpleText("Presets", "bladw_text_Medium", 40, 118, COL_TEXT, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER) + end + + -- ESC ferme mon menu sans laisser le menu pause s'afficher. + -- le moteur ouvre le menu pause sur ESC avant que je puisse l'intercepter, donc je le recache direct et je ferme. + frame.Think = function(self) + if gui.IsGameUIVisible() then + gui.HideGameUI() + self:Remove() + end + end + + -- bouton pour fermer + local close = vgui.Create("DButton", frame) + close:SetSize(30, 30) + close:SetPos(frame:GetWide() - 42, 14) + close:SetText("") + close.Paint = function(self, w, h) + rndx.Draw(8, 0, 0, w, h, self:IsHovered() and COL_RED or COL_GRAY, rndx.SHAPE_FIGMA) + draw.SimpleText("X", "bladw_text_Medium", w * 0.5, h * 0.5, COL_TEXT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end + close.DoClick = function() frame:Remove() end + + -- les champs (créés avant les boutons preset pour être captés dans leurs closures) + local titleEntry = vgui.Create("DTextEntry", frame) + titleEntry:SetPos(40, 240) + titleEntry:SetSize(420, 40) + StyleEntry(titleEntry, "Titre de l'annonce", "Annonce") + + local msgEntry = vgui.Create("DTextEntry", frame) + msgEntry:SetPos(40, 288) + msgEntry:SetSize(420, 40) + StyleEntry(msgEntry, "Message de l'annonce") + -- bord rouge quand ça dépasse la limite + msgEntry.Paint = function(self, w, h) + local over = EntryLen(self) > maxLen + rndx.Draw(10, 0, 0, w, h, COL_PANEL, rndx.SHAPE_FIGMA) + local outline = over and COL_RED or (self:IsEditing() and COL_ACCENT or Color(255, 255, 255, 60)) + rndx.DrawOutlined(10, 0, 0, w, h, outline, over and 3 or 2, rndx.SHAPE_FIGMA) + self:DrawTextEntryText(COL_TEXT, COL_ACCENT, COL_TEXT) + end + + -- ligne du bas : warning à gauche, compteur à droite + local status = vgui.Create("DPanel", frame) + status:SetPos(40, 332) + status:SetSize(420, 26) + status:SetPaintBackground(false) + status.Paint = function(self, w, h) + local len = EntryLen(msgEntry) + local over = len > maxLen + + if over then + DrawWarning(0, h * 0.5 - 8, 16) + draw.SimpleText("Trop de caractères", "bladw_text_Medium", 24, h * 0.5, COL_RED, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER) + end + + draw.SimpleText(len .. " / " .. maxLen, "bladw_text_Medium", w, h * 0.5, + over and COL_RED or COL_MUTED, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER) + end + + -- boutons preset : remplissent les champs et retiennent le preset choisi + local presets = vgui.Create("DIconLayout", frame) + presets:SetPos(40, 134) + presets:SetSize(420, 90) + presets:SetSpaceX(8) + presets:SetSpaceY(8) + + for key, preset in SortedPairs(BladW.Announcement.Presets or {}) do + local b = presets:Add("DButton") + b:SetSize(134, 34) + b:SetText("") + b.Paint = function(self, w, h) + local on = (selectedPreset == key) or self:IsHovered() + rndx.Draw(8, 0, 0, w, h, on and COL_ACCENT or COL_GRAY, rndx.SHAPE_FIGMA) + draw.SimpleText(preset.title or key, "bladw_text_Medium", w * 0.5, h * 0.5, COL_TEXT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end + b.DoClick = function() + selectedPreset = key + titleEntry:SetText(preset.title or "") + msgEntry:SetText(preset.text or "") + end + end + + -- bouton envoyer (grisé + bloqué si ça dépasse) + local send = vgui.Create("DButton", frame) + send:SetPos(40, 372) + send:SetSize(420, 50) + send:SetText("") + send.Paint = function(self, w, h) + local over = EntryLen(msgEntry) > maxLen + local col = over and COL_GRAY or (self:IsHovered() and COL_ACCENT or COL_ACCENT_DIM) + rndx.Draw(12, 0, 0, w, h, col, rndx.SHAPE_FIGMA) + draw.SimpleText("Envoyer", "bladw_text", w * 0.5, h * 0.5, over and COL_MUTED or COL_TEXT, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end + send.DoClick = function() + if EntryLen(msgEntry) > maxLen then + surface.PlaySound("buttons/button10.wav") + return + end + if msgEntry:GetValue() == "" and selectedPreset == "" then + surface.PlaySound("buttons/button10.wav") + return + end + + net.Start("bladWSendAnnouncement") + net.WriteString(selectedPreset) + net.WriteString(titleEntry:GetValue()) + net.WriteString(msgEntry:GetValue()) + net.SendToServer() + + frame:Remove() + end + +end + +return OpenAAdminMenu