From de8af2af39323e546fd3472b90d53128d927b4ee Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Thu, 31 Oct 2024 15:23:49 -0400 Subject: [PATCH 1/6] Allow addons to add options to SpawnIcon and ContentIcon derma menu --- .../creationmenu/content/contenticon.lua | 14 +++++++++++ garrysmod/lua/derma/derma_menus.lua | 23 ++++++++++++++++++- garrysmod/lua/vgui/spawnicon.lua | 15 ++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua index b73281181b..ac40220b24 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua @@ -94,8 +94,22 @@ function PANEL:DoRightClick() return hook.Run( "SpawnlistOpenGenericMenu", pCanvas ) end + local openedMenus = GetOpenDermaMenus() + local menuCount = #openedMenus + self:OpenMenu() + local menu = openedMenus[ menuCount + 1 ] + + -- + -- Allow addons to easily add their own options to the opened menu + -- + if ( IsValid( menu ) ) then + + hook.Run( "OnContentIconOpenMenu", self, menu ) + + end + end function PANEL:DoClick() diff --git a/garrysmod/lua/derma/derma_menus.lua b/garrysmod/lua/derma/derma_menus.lua index 9945b3a651..eea4862918 100644 --- a/garrysmod/lua/derma/derma_menus.lua +++ b/garrysmod/lua/derma/derma_menus.lua @@ -1,6 +1,26 @@ local tblOpenMenus = {} +function GetOpenDermaMenus() + + -- + -- Clear the table of any removed derma menus + -- Each option in a derma menu is another derma menu itself + -- + for k, menu in ipairs( tblOpenMenus ) do + + if ( !IsValid( menu ) ) then + + table.remove( tblOpenMenus, k ) + + end + + end + + return tblOpenMenus + +end + function RegisterDermaMenuForClose( dmenu ) table.insert( tblOpenMenus, dmenu ) @@ -30,9 +50,10 @@ function CloseDermaMenus() end + tblOpenMenus[ k ] = nil + end - tblOpenMenus = {} hook.Run( "CloseDermaMenus" ) end diff --git a/garrysmod/lua/vgui/spawnicon.lua b/garrysmod/lua/vgui/spawnicon.lua index 3d3a672e8c..caa140b448 100644 --- a/garrysmod/lua/vgui/spawnicon.lua +++ b/garrysmod/lua/vgui/spawnicon.lua @@ -28,8 +28,23 @@ function PANEL:DoRightClick() if ( IsValid( pCanvas ) && pCanvas:NumSelectedChildren() > 0 && self:IsSelected() ) then return hook.Run( "SpawnlistOpenGenericMenu", pCanvas ) end + + local openedMenus = GetOpenDermaMenus() + local menuCount = #openedMenus self:OpenMenu() + + local menu = openedMenus[ menuCount + 1 ] + + -- + -- Allow addons to easily add their own options to the opened menu + -- + if ( IsValid( menu ) ) then + + hook.Run( "OnSpawnIconOpenMenu", self, menu ) + + end + end function PANEL:DoClick() From dacb2277130f5217d494e8efcf7f949df107a920 Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Thu, 31 Oct 2024 16:55:27 -0400 Subject: [PATCH 2/6] Add sub category headers for NPCs, Entities, and Vehicles --- .../content/contenttypes/entities.lua | 72 ++++++++++++++--- .../content/contenttypes/npcs.lua | 72 ++++++++++++++--- .../content/contenttypes/vehicles.lua | 78 +++++++++++++++---- .../content/contenttypes/weapons.lua | 66 +++++++++++++--- .../lua/includes/modules/scripted_ents.lua | 1 + garrysmod/lua/includes/modules/weapons.lua | 1 + 6 files changed, 244 insertions(+), 46 deletions(-) diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua index 9804f5bcbd..0db7f7ceba 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua @@ -9,24 +9,33 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br -- Add this list into the tormoil local SpawnableEntities = list.Get( "SpawnableEntities" ) + if ( SpawnableEntities ) then + for k, v in pairs( SpawnableEntities ) do local Category = v.Category or "Other" - if ( !isstring( Category ) ) then Category = tostring( Category ) end - Categorised[ Category ] = Categorised[ Category ] or {} + Category = tostring( Category ) + + local SubCategory = v.SubCategory or "Other" + SubCategory = tostring( SubCategory ) v.SpawnName = k - table.insert( Categorised[ Category ], v ) + + Categorised[ Category ] = Categorised[ Category ] or {} + Categorised[ Category ][ SubCategory ] = Categorised[ Category ][ SubCategory ] or {} + + table.insert( Categorised[ Category ][ SubCategory ], v ) end + end -- -- Add a tree node for each category -- local CustomIcons = list.Get( "ContentCategoryIcons" ) - for CategoryName, v in SortedPairs( Categorised ) do + for CategoryName, subCategories in SortedPairs( Categorised ) do -- Add a node to the tree local node = tree:AddNode( CategoryName, CustomIcons[ CategoryName ] or "icon16/bricks.png" ) @@ -42,14 +51,55 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br self.PropPanel:SetVisible( false ) self.PropPanel:SetTriggerSpawnlistChange( false ) - for k, ent in SortedPairsByMemberValue( v, "PrintName" ) do + local createOtherHeader = false + + for subCategoryName, tab in SortedPairs( subCategories ) do + + if ( subCategoryName == "Other" ) then continue end + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( subCategoryName ) + + self.PropPanel:Add( label ) + + for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.SpawnName, + material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), + admin = ent.AdminOnly + } ) + + end + + createOtherHeader = true + + end + + if ( subCategories.Other ) then + + if ( createOtherHeader ) then + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( "Other" ) + + self.PropPanel:Add( label ) + + end + + for k, ent in SortedPairsByMemberValue( subCategories.Other, "PrintName" ) do - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.SpawnName, - material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), - admin = ent.AdminOnly - } ) + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.SpawnName, + material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), + admin = ent.AdminOnly + } ) + + end end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua index a8a37fffcb..281dfb613a 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua @@ -6,20 +6,28 @@ hook.Add( "PopulateNPCs", "AddNPCContent", function( pnlContent, tree, browseNod -- Categorize them local Categories = {} + for k, v in pairs( NPCList ) do local Category = v.Category or "Other" - if ( !isstring( Category ) ) then Category = tostring( Category ) end + Category = tostring( Category ) + + local SubCategory = v.SubCategory or "Other" + SubCategory = tostring( SubCategory ) local Tab = Categories[ Category ] or {} - Tab[ k ] = v + local subCategoryTab = Tab[ SubCategory ] or {} + + subCategoryTab[ k ] = v + + Tab[ SubCategory ] = subCategoryTab Categories[ Category ] = Tab end -- Create an icon for each one and put them on the panel local CustomIcons = list.Get( "ContentCategoryIcons" ) - for CategoryName, v in SortedPairs( Categories ) do + for CategoryName, subCategories in SortedPairs( Categories ) do -- Add a node to the tree local node = tree:AddNode( CategoryName, CustomIcons[ CategoryName ] or "icon16/monkey.png" ) @@ -35,15 +43,57 @@ hook.Add( "PopulateNPCs", "AddNPCContent", function( pnlContent, tree, browseNod self.PropPanel:SetVisible( false ) self.PropPanel:SetTriggerSpawnlistChange( false ) - for name, ent in SortedPairsByMemberValue( v, "Name" ) do + local createOtherHeader = false + + for subCategoryName, tab in SortedPairs( subCategories ) do + + if ( subCategoryName == "Other" ) then continue end + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( subCategoryName ) + + self.PropPanel:Add( label ) + + for name, ent in SortedPairsByMemberValue( tab, "Name" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", self.PropPanel, { + nicename = ent.Name or name, + spawnname = name, + material = ent.IconOverride or "entities/" .. name .. ".png", + weapon = ent.Weapons, + admin = ent.AdminOnly + } ) + + end + + createOtherHeader = true + + end + + if ( subCategories.Other ) then + + if ( createOtherHeader ) then + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( "Other" ) + + self.PropPanel:Add( label ) + + end + + for name, ent in SortedPairsByMemberValue( subCategories.Other, "Name" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", self.PropPanel, { + nicename = ent.Name or name, + spawnname = name, + material = ent.IconOverride or "entities/" .. name .. ".png", + weapon = ent.Weapons, + admin = ent.AdminOnly + } ) - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", self.PropPanel, { - nicename = ent.Name or name, - spawnname = name, - material = ent.IconOverride or "entities/" .. name .. ".png", - weapon = ent.Weapons, - admin = ent.AdminOnly - } ) + end end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua index 4d5b157564..5f33b616ee 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua @@ -1,35 +1,44 @@ hook.Add( "PopulateVehicles", "AddEntityContent", function( pnlContent, tree, browseNode ) - local Categorised = {} - -- Add this list into the tormoil local Vehicles = list.Get( "Vehicles" ) + local Categorised = {} + if ( Vehicles ) then + for k, v in pairs( Vehicles ) do local Category = v.Category or "Other" - if ( !isstring( Category ) ) then Category = tostring( Category ) end - Categorised[ Category ] = Categorised[ Category ] or {} + Category = tostring( Category ) + + local SubCategory = v.SubCategory or "Other" + SubCategory = tostring( SubCategory ) v.ClassName = k v.PrintName = v.Name v.ScriptedEntityType = "vehicle" - table.insert( Categorised[ Category ], v ) + + Categorised[ Category ] = Categorised[ Category ] or {} + Categorised[ Category ][ SubCategory ] = Categorised[ Category ][ SubCategory ] or {} + + table.insert( Categorised[ Category ][ SubCategory ], v ) end + end -- -- Add a tree node for each category -- local CustomIcons = list.Get( "ContentCategoryIcons" ) - for CategoryName, v in SortedPairs( Categorised ) do + + for CategoryName, subCategories in SortedPairs( Categorised ) do -- Add a node to the tree local node = tree:AddNode( CategoryName, CustomIcons[ CategoryName ] or "icon16/bricks.png" ) - -- When we click on the node - populate it using this function + -- When we click on the node - populate it using this function node.DoPopulate = function( self ) -- If we've already populated it - forget it. @@ -40,14 +49,55 @@ hook.Add( "PopulateVehicles", "AddEntityContent", function( pnlContent, tree, br self.PropPanel:SetVisible( false ) self.PropPanel:SetTriggerSpawnlistChange( false ) - for k, ent in SortedPairsByMemberValue( v, "PrintName" ) do + local createOtherHeader = false + + for subCategoryName, tab in SortedPairs( subCategories ) do + + if ( subCategoryName == "Other" ) then continue end + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( subCategoryName ) + + self.PropPanel:Add( label ) + + for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", + admin = ent.AdminOnly + } ) + + end + + createOtherHeader = true + + end + + if ( subCategories.Other ) then + + if ( createOtherHeader ) then + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( "Other" ) + + self.PropPanel:Add( label ) + + end + + for k, ent in SortedPairsByMemberValue( subCategories.Other, "PrintName" ) do - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", - admin = ent.AdminOnly - } ) + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", + admin = ent.AdminOnly + } ) + + end end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua index 853614ea0e..5133611767 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua @@ -9,10 +9,15 @@ local function BuildWeaponCategories() if ( !weapon.Spawnable ) then continue end local Category = weapon.Category or "Other" - if ( !isstring( Category ) ) then Category = tostring( Category ) end + Category = tostring( Category ) + + local SubCategory = weapon.SubCategory or "Other" + SubCategory = tostring( SubCategory ) Categorised[ Category ] = Categorised[ Category ] or {} - table.insert( Categorised[ Category ], weapon ) + Categorised[ Category ][ SubCategory ] = Categorised[ Category ][ SubCategory ] or {} + + table.insert( Categorised[ Category ][ SubCategory ], weapon ) end @@ -37,15 +42,56 @@ local function AddCategory( tree, cat ) self.PropPanel:SetVisible( false ) self.PropPanel:SetTriggerSpawnlistChange( false ) - local weps = BuildWeaponCategories()[ cat ] - for k, ent in SortedPairsByMemberValue( weps, "PrintName" ) do + local subCategories = BuildWeaponCategories()[ cat ] + local createOtherHeader = false + + for subCategoryName, weps in SortedPairs( subCategories ) do + + if ( subCategoryName == "Other" ) then continue end + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( subCategoryName ) - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), - admin = ent.AdminOnly - } ) + self.PropPanel:Add( label ) + + for k, ent in SortedPairsByMemberValue( weps, "PrintName" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), + admin = ent.AdminOnly + } ) + + end + + createOtherHeader = true + + end + + if ( subCategories.Other ) then + + if ( createOtherHeader ) then + + local label = vgui.Create( "ContentHeader" ) + + label:SetText( "Other" ) + + self.PropPanel:Add( label ) + + end + + for name, ent in SortedPairsByMemberValue( subCategories.Other, "Name" ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", self.PropPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), + admin = ent.AdminOnly + } ) + + end end diff --git a/garrysmod/lua/includes/modules/scripted_ents.lua b/garrysmod/lua/includes/modules/scripted_ents.lua index 23903b9860..1664690019 100644 --- a/garrysmod/lua/includes/modules/scripted_ents.lua +++ b/garrysmod/lua/includes/modules/scripted_ents.lua @@ -127,6 +127,7 @@ function Register( t, name ) Category = t.Category, -- Optional information + SubCategory = t.SubCategory, NormalOffset = t.NormalOffset, DropToFloor = t.DropToFloor, Author = t.Author, diff --git a/garrysmod/lua/includes/modules/weapons.lua b/garrysmod/lua/includes/modules/weapons.lua index a3624703d2..85dd1a9eaa 100644 --- a/garrysmod/lua/includes/modules/weapons.lua +++ b/garrysmod/lua/includes/modules/weapons.lua @@ -59,6 +59,7 @@ function Register( t, name ) ClassName = name, PrintName = t.PrintName or name, Category = t.Category or "Other", + SubCategory = t.SubCategory, Spawnable = t.Spawnable, AdminOnly = t.AdminOnly, ScriptedEntityType = t.ScriptedEntityType, From 3dee6f736da740e97ea0221ed6e4fa688e978c80 Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Thu, 31 Oct 2024 18:10:01 -0400 Subject: [PATCH 3/6] Allow spawn list custom ordering for NPCs, Entities, and Vehicles --- .../content/contenttypes/entities.lua | 57 ++++++++++------- .../content/contenttypes/npcs.lua | 62 ++++++++++++------- .../content/contenttypes/vehicles.lua | 55 ++++++++++------ .../content/contenttypes/weapons.lua | 55 ++++++++++------ 4 files changed, 145 insertions(+), 84 deletions(-) diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua index 0db7f7ceba..76dfd16626 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/entities.lua @@ -3,6 +3,39 @@ list.Set( "ContentCategoryIcons", "Half-Life: Source", "games/16/hl1.png" ) list.Set( "ContentCategoryIcons", "Half-Life 2", "games/16/hl2.png" ) list.Set( "ContentCategoryIcons", "Portal", "games/16/portal.png" ) +local function BuildContentList( tab, propPanel ) + + local orderedList = {} + + for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do + + local order = isnumber( ent.SpawnListOrder ) and ent.SpawnListOrder + + if ( order ) then + + table.insert( orderedList, order, ent ) + + else + + table.insert( orderedList, ent ) + + end + + end + + for k, ent in SortedPairs( orderedList ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", propPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.SpawnName, + material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), + admin = ent.AdminOnly + } ) + + end + +end + hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, browseNode ) local Categorised = {} @@ -11,7 +44,6 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br local SpawnableEntities = list.Get( "SpawnableEntities" ) if ( SpawnableEntities ) then - for k, v in pairs( SpawnableEntities ) do local Category = v.Category or "Other" @@ -28,7 +60,6 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br table.insert( Categorised[ Category ][ SubCategory ], v ) end - end -- @@ -63,16 +94,7 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br self.PropPanel:Add( label ) - for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.SpawnName, - material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), - admin = ent.AdminOnly - } ) - - end + BuildContentList( tab, self.PropPanel ) createOtherHeader = true @@ -90,16 +112,7 @@ hook.Add( "PopulateEntities", "AddEntityContent", function( pnlContent, tree, br end - for k, ent in SortedPairsByMemberValue( subCategories.Other, "PrintName" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.SpawnName, - material = ent.IconOverride or ( "entities/" .. ent.SpawnName .. ".png" ), - admin = ent.AdminOnly - } ) - - end + BuildContentList( subCategories.Other, self.PropPanel ) end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua index 281dfb613a..44ba4da93f 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/npcs.lua @@ -1,4 +1,42 @@ +local function BuildContentList( tab, propPanel ) + + local orderedList = {} + + for name, ent in SortedPairsByMemberValue( tab, "Name" ) do + + local order = isnumber( ent.SpawnListOrder ) and ent.SpawnListOrder + local data = { name = name, ent = ent } + + if ( order ) then + + table.insert( orderedList, order, data ) + + else + + table.insert( orderedList, data ) + + end + + end + + for k, data in SortedPairs( orderedList ) do + + local ent = data.ent + local name = data.name + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", propPanel, { + nicename = ent.Name or name, + spawnname = name, + material = ent.IconOverride or "entities/" .. name .. ".png", + weapon = ent.Weapons, + admin = ent.AdminOnly + } ) + + end + +end + hook.Add( "PopulateNPCs", "AddNPCContent", function( pnlContent, tree, browseNode ) -- Get a list of available NPCs @@ -55,17 +93,7 @@ hook.Add( "PopulateNPCs", "AddNPCContent", function( pnlContent, tree, browseNod self.PropPanel:Add( label ) - for name, ent in SortedPairsByMemberValue( tab, "Name" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", self.PropPanel, { - nicename = ent.Name or name, - spawnname = name, - material = ent.IconOverride or "entities/" .. name .. ".png", - weapon = ent.Weapons, - admin = ent.AdminOnly - } ) - - end + BuildContentList( tab, self.PropPanel ) createOtherHeader = true @@ -83,17 +111,7 @@ hook.Add( "PopulateNPCs", "AddNPCContent", function( pnlContent, tree, browseNod end - for name, ent in SortedPairsByMemberValue( subCategories.Other, "Name" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "npc", self.PropPanel, { - nicename = ent.Name or name, - spawnname = name, - material = ent.IconOverride or "entities/" .. name .. ".png", - weapon = ent.Weapons, - admin = ent.AdminOnly - } ) - - end + BuildContentList( subCategories.Other, self.PropPanel ) end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua index 5f33b616ee..1fbfc2c750 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/vehicles.lua @@ -1,4 +1,37 @@ +local function BuildContentList( tab, propPanel ) + + local orderedList = {} + + for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do + + local order = isnumber( ent.SpawnListOrder ) and ent.SpawnListOrder + + if ( order ) then + + table.insert( orderedList, order, ent ) + + else + + table.insert( orderedList, ent ) + + end + + end + + for k, ent in SortedPairs( orderedList ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", propPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", + admin = ent.AdminOnly + } ) + + end + +end + hook.Add( "PopulateVehicles", "AddEntityContent", function( pnlContent, tree, browseNode ) -- Add this list into the tormoil @@ -61,16 +94,7 @@ hook.Add( "PopulateVehicles", "AddEntityContent", function( pnlContent, tree, br self.PropPanel:Add( label ) - for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", - admin = ent.AdminOnly - } ) - - end + BuildContentList( tab, self.PropPanel ) createOtherHeader = true @@ -88,16 +112,7 @@ hook.Add( "PopulateVehicles", "AddEntityContent", function( pnlContent, tree, br end - for k, ent in SortedPairsByMemberValue( subCategories.Other, "PrintName" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "entity", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or "entities/" .. ent.ClassName .. ".png", - admin = ent.AdminOnly - } ) - - end + BuildContentList( subCategories.Other, self.PropPanel ) end diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua index 5133611767..75183518f9 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenttypes/weapons.lua @@ -24,6 +24,39 @@ local function BuildWeaponCategories() return Categorised end +local function BuildContentList( tab, propPanel ) + + local orderedList = {} + + for k, ent in SortedPairsByMemberValue( tab, "PrintName" ) do + + local order = isnumber( ent.SpawnListOrder ) and ent.SpawnListOrder + + if ( order ) then + + table.insert( orderedList, order, ent ) + + else + + table.insert( orderedList, ent ) + + end + + end + + for k, ent in SortedPairs( orderedList ) do + + spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", propPanel, { + nicename = ent.PrintName or ent.ClassName, + spawnname = ent.ClassName, + material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), + admin = ent.AdminOnly + } ) + + end + +end + local function AddCategory( tree, cat ) local CustomIcons = list.Get( "ContentCategoryIcons" ) @@ -55,16 +88,7 @@ local function AddCategory( tree, cat ) self.PropPanel:Add( label ) - for k, ent in SortedPairsByMemberValue( weps, "PrintName" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), - admin = ent.AdminOnly - } ) - - end + BuildContentList( weps, self.PropPanel ) createOtherHeader = true @@ -82,16 +106,7 @@ local function AddCategory( tree, cat ) end - for name, ent in SortedPairsByMemberValue( subCategories.Other, "Name" ) do - - spawnmenu.CreateContentIcon( ent.ScriptedEntityType or "weapon", self.PropPanel, { - nicename = ent.PrintName or ent.ClassName, - spawnname = ent.ClassName, - material = ent.IconOverride or ( "entities/" .. ent.ClassName .. ".png" ), - admin = ent.AdminOnly - } ) - - end + BuildContentList( subCategories.Other, self.PropPanel ) end From dbdaec15f7eaa3b079cbc19b5c63323f21ce85c1 Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Thu, 31 Oct 2024 18:11:11 -0400 Subject: [PATCH 4/6] Almost forgot these --- garrysmod/lua/includes/modules/scripted_ents.lua | 1 + garrysmod/lua/includes/modules/weapons.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/garrysmod/lua/includes/modules/scripted_ents.lua b/garrysmod/lua/includes/modules/scripted_ents.lua index 1664690019..f6c38f937c 100644 --- a/garrysmod/lua/includes/modules/scripted_ents.lua +++ b/garrysmod/lua/includes/modules/scripted_ents.lua @@ -127,6 +127,7 @@ function Register( t, name ) Category = t.Category, -- Optional information + SpawnListOrder = t.SpawnListOrder, SubCategory = t.SubCategory, NormalOffset = t.NormalOffset, DropToFloor = t.DropToFloor, diff --git a/garrysmod/lua/includes/modules/weapons.lua b/garrysmod/lua/includes/modules/weapons.lua index 85dd1a9eaa..7b43a78ce3 100644 --- a/garrysmod/lua/includes/modules/weapons.lua +++ b/garrysmod/lua/includes/modules/weapons.lua @@ -59,6 +59,7 @@ function Register( t, name ) ClassName = name, PrintName = t.PrintName or name, Category = t.Category or "Other", + SpawnListOrder = t.SpawnListOrder, SubCategory = t.SubCategory, Spawnable = t.Spawnable, AdminOnly = t.AdminOnly, From 8b8094c8eda5c39cf7f4628a63cdcc6ca40229c4 Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Fri, 1 Nov 2024 15:37:01 -0400 Subject: [PATCH 5/6] Get the correct derma menu properly --- .../creationmenu/content/contenticon.lua | 22 ++++++++++++++---- garrysmod/lua/derma/derma_menus.lua | 12 ++++------ garrysmod/lua/vgui/spawnicon.lua | 23 +++++++++++++++---- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua index ac40220b24..f2e8b61e24 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua @@ -90,20 +90,34 @@ end function PANEL:DoRightClick() local pCanvas = self:GetSelectionCanvas() + if ( IsValid( pCanvas ) && pCanvas:NumSelectedChildren() > 0 && self:IsSelected() ) then return hook.Run( "SpawnlistOpenGenericMenu", pCanvas ) end - local openedMenus = GetOpenDermaMenus() - local menuCount = #openedMenus + local oldMenuCount = #GetOpenDermaMenus() self:OpenMenu() - local menu = openedMenus[ menuCount + 1 ] + local openedMenus = GetOpenDermaMenus() + local newMenuCount = #openedMenus + + local menuIndex = newMenuCount == oldMenuCount and oldMenuCount or oldMenuCount + 1 + local menu = openedMenus[ menuIndex ] + + if ( !IsValid( menu ) ) then return end -- - -- Allow addons to easily add their own options to the opened menu + -- Get the correct derma menu + -- Each option in a derma menu is a derma menu itself -- + while ( IsValid( menu.ParentMenu ) ) do + + menuIndex = menuIndex - 1 + menu = openedMenus[ menuIndex ] + + end + if ( IsValid( menu ) ) then hook.Run( "OnContentIconOpenMenu", self, menu ) diff --git a/garrysmod/lua/derma/derma_menus.lua b/garrysmod/lua/derma/derma_menus.lua index eea4862918..bbcb35e95c 100644 --- a/garrysmod/lua/derma/derma_menus.lua +++ b/garrysmod/lua/derma/derma_menus.lua @@ -3,21 +3,19 @@ local tblOpenMenus = {} function GetOpenDermaMenus() - -- - -- Clear the table of any removed derma menus - -- Each option in a derma menu is another derma menu itself - -- + local fixedCopy = {} + for k, menu in ipairs( tblOpenMenus ) do - if ( !IsValid( menu ) ) then + if ( IsValid( menu ) ) then - table.remove( tblOpenMenus, k ) + table.insert( fixedCopy, menu ) end end - return tblOpenMenus + return fixedCopy end diff --git a/garrysmod/lua/vgui/spawnicon.lua b/garrysmod/lua/vgui/spawnicon.lua index caa140b448..48d1f9a628 100644 --- a/garrysmod/lua/vgui/spawnicon.lua +++ b/garrysmod/lua/vgui/spawnicon.lua @@ -28,17 +28,30 @@ function PANEL:DoRightClick() if ( IsValid( pCanvas ) && pCanvas:NumSelectedChildren() > 0 && self:IsSelected() ) then return hook.Run( "SpawnlistOpenGenericMenu", pCanvas ) end - - local openedMenus = GetOpenDermaMenus() - local menuCount = #openedMenus + + local oldMenuCount = #GetOpenDermaMenus() self:OpenMenu() - local menu = openedMenus[ menuCount + 1 ] + local openedMenus = GetOpenDermaMenus() + local newMenuCount = #openedMenus + + local menuIndex = newMenuCount == oldMenuCount and oldMenuCount or oldMenuCount + 1 + local menu = openedMenus[ menuIndex ] + + if ( !IsValid( menu ) ) then return end -- - -- Allow addons to easily add their own options to the opened menu + -- Get the correct derma menu + -- Each option in a derma menu is a derma menu itself -- + while ( IsValid( menu.ParentMenu ) ) do + + menuIndex = menuIndex - 1 + menu = openedMenus[ menuIndex ] + + end + if ( IsValid( menu ) ) then hook.Run( "OnSpawnIconOpenMenu", self, menu ) From 4087c7dadf95f07a17c5c17b8568dc7cc8aed0f3 Mon Sep 17 00:00:00 2001 From: Zaurzo <wafflesfordaysyt@gmail.com> Date: Fri, 1 Nov 2024 17:06:34 -0400 Subject: [PATCH 6/6] Better way to get the correct derma menu --- .../creationmenu/content/contenticon.lua | 20 ++++++------------- garrysmod/lua/vgui/spawnicon.lua | 20 ++++++------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua index f2e8b61e24..561553ed6e 100644 --- a/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua +++ b/garrysmod/gamemodes/sandbox/gamemode/spawnmenu/creationmenu/content/contenticon.lua @@ -100,30 +100,22 @@ function PANEL:DoRightClick() self:OpenMenu() local openedMenus = GetOpenDermaMenus() - local newMenuCount = #openedMenus - local menuIndex = newMenuCount == oldMenuCount and oldMenuCount or oldMenuCount + 1 + local menuIndex = #openedMenus == oldMenuCount and oldMenuCount or oldMenuCount + 1 local menu = openedMenus[ menuIndex ] if ( !IsValid( menu ) ) then return end - -- - -- Get the correct derma menu - -- Each option in a derma menu is a derma menu itself - -- - while ( IsValid( menu.ParentMenu ) ) do - - menuIndex = menuIndex - 1 - menu = openedMenus[ menuIndex ] + local parent = menu.ParentMenu - end - - if ( IsValid( menu ) ) then + if ( IsValid( parent ) ) then - hook.Run( "OnContentIconOpenMenu", self, menu ) + menu = parent end + hook.Run( "OnContentIconOpenMenu", self, menu ) + end function PANEL:DoClick() diff --git a/garrysmod/lua/vgui/spawnicon.lua b/garrysmod/lua/vgui/spawnicon.lua index 48d1f9a628..5f0782a396 100644 --- a/garrysmod/lua/vgui/spawnicon.lua +++ b/garrysmod/lua/vgui/spawnicon.lua @@ -34,30 +34,22 @@ function PANEL:DoRightClick() self:OpenMenu() local openedMenus = GetOpenDermaMenus() - local newMenuCount = #openedMenus - local menuIndex = newMenuCount == oldMenuCount and oldMenuCount or oldMenuCount + 1 + local menuIndex = #openedMenus == oldMenuCount and oldMenuCount or oldMenuCount + 1 local menu = openedMenus[ menuIndex ] if ( !IsValid( menu ) ) then return end - -- - -- Get the correct derma menu - -- Each option in a derma menu is a derma menu itself - -- - while ( IsValid( menu.ParentMenu ) ) do - - menuIndex = menuIndex - 1 - menu = openedMenus[ menuIndex ] + local parent = menu.ParentMenu - end - - if ( IsValid( menu ) ) then + if ( IsValid( parent ) ) then - hook.Run( "OnSpawnIconOpenMenu", self, menu ) + menu = parent end + hook.Run( "OnSpawnIconOpenMenu", self, menu ) + end function PANEL:DoClick()