Skip to content

Commit

Permalink
make config menu more readable (#50)
Browse files Browse the repository at this point in the history
* make config menu more readable

* use static width for config panel

* new config option UseGamemodeMapPrefixes

* fix linter errors

* remove shadowing

* fix grammer

* update wording to be clear current map will not always appear in votes

* delay round end rtv print

* avoid creating new table for map prefix check

* make UseGamemodePrefixes optional

* dont invalidate config if there are extra fields

* update map icon style

* fix icon animations snapping due to perform layout

* rate limit thumb downloading

* fix net

* remove unused var

* comment
  • Loading branch information
plally authored Feb 4, 2024
1 parent d8fe617 commit 140e2bb
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 124 deletions.
4 changes: 4 additions & 0 deletions lua/includes/modules/schemavalidator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ end

---@class SchemaTypeObject: SchemaType
---@field ValidateField fun(self: SchemaTypeObject, key: any, value: any): (boolean, string)
---@field HasField fun(self: SchemaTypeObject, key: any): boolean
---@field fields { [string]: SchemaType }

---@param tbl { [string]: SchemaType }
Expand All @@ -90,6 +91,9 @@ function SchemaValidator.Object( tbl )
Optional = function( self )
return SchemaValidator.Optional( self )
end,
HasField = function( self, key )
return self.fields[key] ~= nil
end,
ValidateField = function( self, key, value )
local fieldType = self.fields[key]
if not fieldType then
Expand Down
38 changes: 21 additions & 17 deletions lua/mapvote/client/modules/admin_menu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,21 @@ local function updateconfigKey( key )
end

local configMenuOptions = {
{ "Map Limit", schema.fields.MapLimit, "MapLimit" },
{ "Time Limit", schema.fields.TimeLimit, "TimeLimit" },
{ "Allow Current Map", schema.fields.AllowCurrentMap, "AllowCurrentMap" },
{ "RTV Percent Players Required 0-1", schema.fields.RTVPercentPlayersRequired, "RTVPercentPlayersRequired" },
{ "RTV Wait", schema.fields.RTVWait, "RTVWait" },
{ "Sort Maps", schema.fields.SortMaps, "SortMaps" },
{ "Default Map", schema.fields.DefaultMap, "DefaultMap" },
{ "Enable Cooldown", schema.fields.EnableCooldown, "EnableCooldown" },
{ "Maps Before Revote", schema.fields.MapsBeforeRevote, "MapsBeforeRevote" },
{ "RTV Player Count", schema.fields.RTVPlayerCount, "RTVPlayerCount" },
{ "Minimum Players Before Reset", schema.fields.MinimumPlayersBeforeReset, "MinimumPlayersBeforeReset" },
{ "Time To Reset", schema.fields.TimeToReset, "TimeToReset" },
{ "Map Prefixes", schema.fields.MapPrefixes, "MapPrefixes" },
{ "Player RTV Cooldown", schema.fields.PlyRTVCooldownSeconds, "PlyRTVCooldownSeconds" },
{ seperator = true, text = "Voting" },
{ "The amount of maps in a vote", schema.fields.MapLimit, "MapLimit" },
{ "The length of a vote in seconds", schema.fields.TimeLimit, "TimeLimit" },
{ "Should the current map have a chance to appear in votes", schema.fields.AllowCurrentMap, "AllowCurrentMap" },
{ "Should the maps in a vote be sorted", schema.fields.SortMaps, "SortMaps" },
{ seperator = true, text = "RTV" },
{ "Percentage of players who need to RTV between 0 and 1", schema.fields.RTVPercentPlayersRequired, "RTVPercentPlayersRequired" },
{ "The time RTV is disabled after a map change in seonds", schema.fields.RTVWait, "RTVWait" },
{ "How long should a player wait between RTV commands", schema.fields.PlyRTVCooldownSeconds, "PlyRTVCooldownSeconds" },
{ "Minimum players required to enable RTVing", schema.fields.RTVPlayerCount, "RTVPlayerCount" },
{ seperator = true, text = "Maps" },
{ "Map prefixes automatically enabled, comma seperated list", schema.fields.MapPrefixes, "MapPrefixes" },
{ "Use map prefixes from gamemode.txt", schema.fields.UseGamemodeMapPrefixes, "UseGamemodeMapPrefixes" },
{ "Disable a map after its played", schema.fields.EnableCooldown, "EnableCooldown" },
{ "The amount of maps that need to be played before a map is enabled again", schema.fields.MapsBeforeRevote, "MapsBeforeRevote" },
}

MapVote._mapconfigFrame = nil
Expand All @@ -34,7 +35,7 @@ function MapVote.openconfig()
return
end
local frame = vgui.Create( "MapVote_Frame" ) --[[@as DFrame]]
frame:SetSize( 800, 600 )
frame:SetSize( 1000, ScrH() * 0.9 )
frame:Center()
frame:MakePopup()
frame:SetTitle( "MapVote Config" )
Expand All @@ -43,6 +44,7 @@ function MapVote.openconfig()
local configMenu = vgui.Create( "MapVote_ConfigPanel", frame ) --[[@as ConfigPanel]]
configMenu:SetSize( 800, 600 )
configMenu:Dock( FILL )
configMenu:DockMargin( 10, 10, 10, 10 )

---@diagnostic disable-next-line: duplicate-set-field
frame.OnClose = function( _ )
Expand All @@ -55,7 +57,9 @@ function MapVote.openconfig()
MapVote.Net.sendConfigRequest( function()
configMenu:Clear()
for _, option in pairs( configMenuOptions ) do
if IsValid( configMenu ) and configMenu.AddConfigItem then
if option.seperator then
configMenu:AddSeperator( option.text )
elseif IsValid( configMenu ) and configMenu.AddConfigItem then
configMenu:AddConfigItem( option[1], option[2], updateconfigKey( option[3] ), MapVote.config[option[3]] )
end
end
Expand Down Expand Up @@ -110,7 +114,7 @@ function MapVote.addMapRow( map )
local row = vgui.Create( "Panel" ) --[[@as Panel]]
row:SetSize( 800, 128 )

local mapIcon = vgui.Create( "MapVote_MapIcon", row ) --[[@as MapIcon]]
local mapIcon = vgui.Create( "MapVote_MapIcon", row )
mapIcon:SetSize( 128, 128 )
mapIcon:SetMap( map )
mapIcon:Dock( LEFT )
Expand Down
7 changes: 5 additions & 2 deletions lua/mapvote/client/modules/net.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ net.Receive( "MapVote_VoteCancelled", function()
end )

net.Receive( "RTV_Delay", function()
chat.AddText( Color( 102, 255, 51 ), "[RTV]", Color( 255, 255, 255 ),
" The vote has been rocked, map vote will begin on round end" )
-- this timer makes sure the message shows up after the RTV message
timer.Simple( 0.2, function()
chat.AddText( Color( 102, 255, 51 ), "[RTV]", Color( 255, 255, 255 ),
" The vote has been rocked, map vote will begin on round end" )
end )
end )


Expand Down
60 changes: 52 additions & 8 deletions lua/mapvote/client/vgui/config_panel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
local PANEL = {}

function PANEL:Init()
self.largestLabelWidth = 0
end

function PANEL:Paint( w, h )
Expand All @@ -21,13 +22,39 @@ function PANEL:configRow( displayName )
optionPanel:Dock( TOP )

local label = vgui.Create( "DLabel", optionPanel ) --[[@as DLabel]]
label:SetText( displayName .. ": " )
label:SetText( displayName )
label:Dock( LEFT )
label:SetSize( 200, 35 )
label:SetFont( MapVote.style.configLabelFont )
label:SetFont( "MapVote_ConfigItem" )
label:SizeToContents()
self.largestLabelWidth = math.max( self.largestLabelWidth, label:GetWide() )
optionPanel.label = label
return optionPanel
end

function PANEL:PerformLayout()
for _, child in pairs( self:GetCanvas():GetChildren() ) do
if child.label then
child.label:SetWide( self.largestLabelWidth + 50 )
end
end
end

surface.CreateFont( "MapVote_ConfigItem", {
font = "Arial",
size = 20,
weight = 600,
antialias = true,
shadow = false
} )

function PANEL:AddSeperator( text )
local seperator = vgui.Create( "MapVote_Seperator", self )
seperator:SetText( text )
seperator:Dock( TOP )
seperator:DockMargin( 5, 15, 5, 5 )
self:AddItem( seperator )
end

---@param displayName string
---@param itemType SchemaType
function PANEL:AddConfigItem( displayName, itemType, action, startingValue )
Expand Down Expand Up @@ -58,9 +85,11 @@ function PANEL:AddConfigItem( displayName, itemType, action, startingValue )
end
end
elseif itemType.name == "bool" then
entryPanel = vgui.Create( "DCheckBox", optionPanel ) --[[@as DCheckBox]]
entryPanel:SetSize( 25, 25 )
entryPanel:SetValue( startingValue or false )
entryPanel = vgui.Create( "MapVote_Switch", optionPanel )
entryPanel:SetOn( startingValue or false )
entryPanel.ColorOff = MapVote.style.colorSecondaryFG
entryPanel.ColorOn = MapVote.style.colorGreen
entryPanel.ColorSwitch = MapVote.style.colorPrimaryBG
---@diagnostic disable-next-line: duplicate-set-field
entryPanel.OnChange = function( _, val )
local ok, err = itemType:Validate( val )
Expand Down Expand Up @@ -89,7 +118,7 @@ function PANEL:AddConfigItem( displayName, itemType, action, startingValue )
entryPanel:SetSize( 100, 25 )
elseif itemType.name == "string" then
entryPanel = vgui.Create( "MapVote_TextEntry", optionPanel ) --[[@as DTextEntry]]
entryPanel:SetSize( 100, 25 )
entryPanel:SetSize( 300, 25 )
entryPanel:SetValue( startingValue or "" )

---@diagnostic disable-next-line: duplicate-set-field
Expand All @@ -108,7 +137,22 @@ function PANEL:AddConfigItem( displayName, itemType, action, startingValue )
entryPanel = vgui.Create( "MapVote_TextEntry", optionPanel ) --[[@as DTextEntry]]
entryPanel:SetSize( 100, 25 )
entryPanel:SetValue( startingValue or "" )
entryPanel:SetEnabled( false )
entryPanel:SetEnabled( true )
entryPanel.OnValueChanged = function( _, val )
val = string.Split( val, "," )
for i = #val, 1, -1 do
val[i] = string.Trim( val[i] )
if val[i] == "" then
table.remove( val, i )
end
end
local ok, err = itemType:Validate( val )
errLabel:SetText( err or "" )
errLabel:Dock( LEFT )
if ok then
action( val )
end
end
else
error( "Unknown type " .. itemType.name )
end
Expand Down
64 changes: 20 additions & 44 deletions lua/mapvote/client/vgui/frame.lua
Original file line number Diff line number Diff line change
@@ -1,33 +1,6 @@
---@class MapVote_Frame : DFrame
local PANEL = {}

local function disableColor( c )
return Color( c.r / 2, c.g / 2, c.b / 2 )
end

local function drawCircle( x, y, radius, seg )
draw.NoTexture()
local cir = {}

table.insert( cir, { x = x, y = y, u = 0.5, v = 0.5 } )
for i = 0, seg do
local a = math.rad( (i / seg) * -360 )
table.insert( cir,
{
x = x + math.sin( a ) * radius,
y = y + math.cos( a ) * radius,
} )
end

local a = math.rad( 0 ) -- This is needed for non absolute segment counts
table.insert( cir,
{
x = x + math.sin( a ) * radius,
y = y + math.cos( a ) * radius,
} )

surface.DrawPoly( cir )
end
function surface.DrawTexturedRectRotatedPoint( x, y, w, h, rot, x0, y0 )
local c = math.cos( math.rad( rot ) )
local s = math.sin( math.rad( rot ) )
Expand All @@ -42,6 +15,14 @@ function PANEL:SetHideOnClose( hide )
self.hideOnClose = hide
end

surface.CreateFont( "MapVote_CloseButton", {
font = "Marlett",
size = 20,
weight = 1,
extended = true,
symbol = true
} )

function PANEL:Init()
local blur = MapVote.style.frameBlur or 0
if blur > 0 then
Expand All @@ -50,32 +31,27 @@ function PANEL:Init()
self.blurMat:Recompute()
end

local circleSegments = 30
self.btnClose:SetSize( 25, 25 )
---@diagnostic disable-next-line: duplicate-set-field
self.btnClose.Paint = function( _, w, h )
local r = (w - 13) / 2
surface.SetDrawColor( MapVote.style.colorCloseButton )
drawCircle( w / 2, h / 2 + 2, r, circleSegments )
surface.SetDrawColor( MapVote.style.colorTextPrimary )
surface.DrawTexturedRectRotatedPoint( w / 2, h / 2 + 2, r * 1.5, 2, 45, 0, 0 )
surface.DrawTexturedRectRotatedPoint( w / 2, h / 2 + 2, r * 1.5, 2, 315, 0, 0 )
self.btnClose.Paint = function( selfClose, w, h )
if selfClose.Hovered then
draw.RoundedBox( 0, 0, 0, w, h, MapVote.style.colorCloseButton )
end
surface.SetTextColor( Color( 255, 255, 255, 200 ) )
surface.SetFont( "MapVote_CloseButton" )
local tw, th = surface.GetTextSize( "r" )
surface.SetTextPos( w / 2 - tw / 2, h / 2 - th / 2 )
surface.DrawText( "r" )
end

self.btnMaxim:SetSize( 25, 25 )
---@diagnostic disable-next-line: duplicate-set-field
self.btnMaxim.Paint = function( _, w, h )
local r = (w - 13) / 2
surface.SetDrawColor( disableColor( MapVote.style.colorGreen ) )
drawCircle( w / 2, h / 2 + 2, r, circleSegments )
self.btnMaxim.Paint = function()
end

self.btnMinim:SetSize( 25, 25 )
---@diagnostic disable-next-line: duplicate-set-field
self.btnMinim.Paint = function( _, w, h )
local r = (w - 13) / 2
surface.SetDrawColor( disableColor( MapVote.style.colorYellow ) )
drawCircle( w / 2, h / 2 + 2, r, circleSegments )
self.btnMinim.Paint = function()
end
self.btnClose.DoClick = function()
if self.hideOnClose then
Expand Down Expand Up @@ -104,7 +80,7 @@ function PANEL:ApplyBlur()
render.UpdateScreenEffectTexture()

local x, y = self:LocalToScreen( 0, 0 )
surface.DrawTexturedRect( -x, -y, ScrW(), ScrH())
surface.DrawTexturedRect( -x, -y, ScrW(), ScrH() )
end

local basePanel = baseclass.Get( "Panel" )
Expand Down
19 changes: 15 additions & 4 deletions lua/mapvote/client/vgui/map_icon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ local PANEL = {}
function PANEL:Init()
self.button = vgui.Create( "DImageButton", self ) --[[@as DImageButton]]
self.button:Dock( FILL )
self.button:DockMargin( 2, 2, 2, 0 )
self.button:DockMargin( 1, 1, 1, 0 )
self.button.DoClick = function()
self:DoClick()
end

self.label = vgui.Create( "DLabel", self ) --[[@as DLabel]]
self.label:Dock( BOTTOM )
self.label:SetContentAlignment( 5 )
self.infoRow = vgui.Create( "Panel", self.button ) --[[@as DPanel]]
self.infoRow:Dock( BOTTOM )
self.infoRow:SetTall( 20 )
self.infoRow.Paint = function( _, w, h )
surface.SetDrawColor( Color( MapVote.style.colorSecondaryFG.r, MapVote.style.colorSecondaryFG.g, MapVote.style.colorSecondaryFG.b, 230 ) )
surface.DrawRect( 0, 0, w, h )
end

self.label = vgui.Create( "DLabel", self.infoRow ) --[[@as DLabel]]
self.label:Dock( LEFT )
self.label:DockMargin( 5, 0, 0, 0 )
self.label:SetContentAlignment( 4 )
self.label:SetFont( "DermaDefaultBold" )
end

Expand All @@ -26,6 +35,8 @@ end

function PANEL:SetMap( map )
self.label:SetText( map )
self.label:SizeToContents()
self.label:SetWide( math.min( self.label:GetWide(), self:GetWide() - 5 ) )

MapVote.ThumbDownloader:QueueDownload( map, function( filepath )
MapVote.TaskManager.AddFunc( function()
Expand Down
20 changes: 12 additions & 8 deletions lua/mapvote/client/vgui/mapvote_panel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ function PANEL:PerformLayout()
-- This is expensive, but must be done so avatar positions dont get misaligned when parent panel is being minimized and resized
for _, map in ipairs( self.maps ) do
for i, voter in ipairs( map.voters ) do
local newX, newY, willOverflow = self:CalculateDesiredAvatarIconPosition( map, i )
voter:SetPos( newX, newY )
voter:SetVisible( not willOverflow )
if not voter.inAnimation then
local newX, newY, willOverflow = self:CalculateDesiredAvatarIconPosition( map, i )
voter:SetPos( newX, newY )
voter:SetVisible( not willOverflow )
end
end
end
end
Expand Down Expand Up @@ -83,8 +85,10 @@ function PANEL:SetVote( identifier, mapIndex )
local voter = oldMapData.voters[i]
local newX, newY, willOverflow = self:CalculateDesiredAvatarIconPosition( oldMapData, i )
voter:SetVisible( true )
voter:MoveTo( newX, newY, 0.2, nil, nil, function( _, pnl )
voter.inAnimation = true
voter:MoveTo( newX, newY, 0.3, nil, 1, function( _, pnl )
pnl:SetVisible( not willOverflow )
pnl.inAnimation = false
end )
end

Expand All @@ -103,10 +107,10 @@ function PANEL:SetVote( identifier, mapIndex )

local newX, newY, willOverflow = self:CalculateDesiredAvatarIconPosition( mapData )
panel:SetVisible( true )
panel:MoveTo( newX, newY, 0.2, nil, nil, function()
if willOverflow then
panel:SetVisible( not willOverflow )
end
panel.inAnimation = true
panel:MoveTo( newX, newY, 0.3, nil, 1, function( _, pnl )
pnl:SetVisible( not willOverflow )
pnl.inAnimation = false
end )
end

Expand Down
Loading

0 comments on commit 140e2bb

Please sign in to comment.