Files
wnsrc/gamemodes/sandbox/gamemode/spawnmenu/spawnmenu.lua
lifestorm c6d9b6f580 Upload
2024-08-05 18:40:29 +03:00

407 lines
12 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local spawnmenu_border = CreateConVar( "spawnmenu_border", "0.1", { FCVAR_ARCHIVE }, "Amount of empty space around the Sandbox spawn menu." )
include( "toolmenu.lua" )
include( "contextmenu.lua" )
include( "creationmenu.lua" )
local PANEL = {}
function PANEL:Init()
self:Dock( FILL )
self.HorizontalDivider = vgui.Create( "DHorizontalDivider", self )
self.HorizontalDivider:Dock( FILL )
self.HorizontalDivider:SetLeftWidth( ScrW() ) -- It will be automatically resized by DHorizontalDivider to account for GetRightMin/GetLeftMin
self.HorizontalDivider:SetDividerWidth( 6 )
self.HorizontalDivider:SetCookieName( "SpawnMenuDiv" )
self.HorizontalDivider:SetRightMin( 300 )
if ( ScrW() >= 1024 ) then self.HorizontalDivider:SetRightMin( 460 ) end
self.ToolMenu = vgui.Create( "ToolMenu", self.HorizontalDivider )
self.HorizontalDivider:SetRight( self.ToolMenu )
self.CreateMenu = vgui.Create( "CreationMenu", self.HorizontalDivider )
self.HorizontalDivider:SetLeft( self.CreateMenu )
self.m_bHangOpen = false
self:SetMouseInputEnabled( true )
self.ToolToggle = vgui.Create( "DImageButton", self )
self.ToolToggle:SetImage( "gui/spawnmenu_toggle" )
self.ToolToggle:SetSize( 16, 16 )
self.ToolToggle.DoClick = function()
self.ToolMenu:SetVisible( !self.ToolMenu:IsVisible() )
self:InvalidateLayout()
if ( self.ToolMenu:IsVisible() ) then
self.ToolToggle:SetImage( "gui/spawnmenu_toggle" )
self.CreateMenu:Dock( NODOCK ) -- What an ugly hack
self.HorizontalDivider:SetRight( self.ToolMenu )
self.HorizontalDivider:SetLeft( self.CreateMenu )
else
self.ToolToggle:SetImage( "gui/spawnmenu_toggle_back" )
self.HorizontalDivider:SetRight( nil ) -- What an ugly hack
self.HorizontalDivider:SetLeft( nil )
self.CreateMenu:SetParent( self.HorizontalDivider )
self.CreateMenu:Dock( FILL )
end
end
end
function PANEL:OpenCreationMenuTab( name )
self.CreateMenu:SwitchToName( name )
end
function PANEL:GetToolMenu()
return self.ToolMenu
end
function PANEL:GetCreationMenu()
return self.CreateMenu
end
--[[---------------------------------------------------------
Name: OnClick
-----------------------------------------------------------]]
function PANEL:OnMousePressed()
self:Close()
end
--[[---------------------------------------------------------
Name: HangOpen
-----------------------------------------------------------]]
function PANEL:HangOpen( bHang )
self.m_bHangOpen = bHang
end
--[[---------------------------------------------------------
Name: HangingOpen
-----------------------------------------------------------]]
function PANEL:HangingOpen()
return self.m_bHangOpen
end
--[[---------------------------------------------------------
Name: Paint
-----------------------------------------------------------]]
function PANEL:Open()
RestoreCursorPosition()
self.m_bHangOpen = false
-- If the context menu is open, try to close it..
if ( IsValid( g_ContextMenu ) && g_ContextMenu:IsVisible() ) then
g_ContextMenu:Close( true )
end
if ( self:IsVisible() ) then return end
CloseDermaMenus()
self:MakePopup()
self:SetVisible( true )
self:SetKeyboardInputEnabled( false )
self:SetMouseInputEnabled( true )
self:SetAlpha( 255 )
achievements.SpawnMenuOpen()
if ( IsValid( self.StartupTool ) && self.StartupTool.Name ) then
self.StartupTool:SetSelected( true )
spawnmenu.ActivateTool( self.StartupTool.Name, true )
self.StartupTool = nil
end
end
--[[---------------------------------------------------------
Name: Paint
-----------------------------------------------------------]]
function PANEL:Close( bSkipAnim )
if ( self.m_bHangOpen ) then
self.m_bHangOpen = false
return
end
if ( self:IsVisible() ) then RememberCursorPosition() end
CloseDermaMenus()
self:SetKeyboardInputEnabled( false )
self:SetMouseInputEnabled( false )
self:SetVisible( false )
end
function PANEL:PerformLayout()
local MarginX = math.Clamp( ( ScrW() - 1024 ) * spawnmenu_border:GetFloat(), 25, 256 )
local MarginY = math.Clamp( ( ScrH() - 768 ) * spawnmenu_border:GetFloat(), 25, 256 )
-- At this size we can't spare any space for emptiness
if ( ScrW() < 1024 || ScrH() < 768 ) then
MarginX = 0
MarginY = 0
end
self:DockPadding( 0, 0, 0, 0 )
self.HorizontalDivider:DockMargin( MarginX, MarginY, MarginX, MarginY )
self.HorizontalDivider:SetLeftMin( self.HorizontalDivider:GetWide() / 3 )
self.ToolToggle:AlignRight( 6 )
self.ToolToggle:AlignTop( 6 )
end
function PANEL:StartKeyFocus( pPanel )
self.m_pKeyFocus = pPanel
self:SetKeyboardInputEnabled( true )
self:HangOpen( true )
end
function PANEL:EndKeyFocus( pPanel )
if ( self.m_pKeyFocus != pPanel ) then return end
self:SetKeyboardInputEnabled( false )
end
function PANEL:OnSizeChanged( newW, newH )
local divW = self.HorizontalDivider:GetWide()
local divL = self.HorizontalDivider:GetLeftWidth()
self:InvalidateLayout( true )
local divWnew = self.HorizontalDivider:GetWide()
if ( divW > divL && divW < divWnew ) then
local ratio = divL / divW
self.HorizontalDivider:SetLeftWidth( ratio * divWnew )
end
end
vgui.Register( "SpawnMenu", PANEL, "EditablePanel" )
--[[---------------------------------------------------------
Called to create the spawn menu..
-----------------------------------------------------------]]
local function CreateSpawnMenu()
if ( !hook.Run( "SpawnMenuEnabled" ) ) then return end
-- If we have an old spawn menu remove it.
if ( IsValid( g_SpawnMenu ) ) then
g_SpawnMenu:Remove()
g_SpawnMenu = nil
end
hook.Run( "PreReloadToolsMenu" )
-- Start Fresh
spawnmenu.ClearToolMenus()
-- Add defaults for the gamemode. In sandbox these defaults
-- are the Main/Postprocessing/Options tabs.
-- They're added first in sandbox so they're always first
hook.Run( "AddGamemodeToolMenuTabs" )
-- Use this hook to add your custom tools
-- This ensures that the default tabs are always
-- first.
hook.Run( "AddToolMenuTabs" )
-- Use this hook to add your custom tools
-- We add the gamemode tool menu categories first
-- to ensure they're always at the top.
hook.Run( "AddGamemodeToolMenuCategories" )
hook.Run( "AddToolMenuCategories" )
-- Add the tabs to the tool menu before trying
-- to populate them with tools.
hook.Run( "PopulateToolMenu" )
g_SpawnMenu = vgui.Create( "SpawnMenu" )
if ( IsValid( g_SpawnMenu ) ) then
g_SpawnMenu:SetVisible( false )
hook.Run( "SpawnMenuCreated", g_SpawnMenu )
end
CreateContextMenu()
hook.Run( "PostReloadToolsMenu" )
end
-- Hook to create the spawnmenu at the appropriate time (when all sents and sweps are loaded)
hook.Add( "OnGamemodeLoaded", "CreateSpawnMenu", CreateSpawnMenu )
concommand.Add( "spawnmenu_reload", CreateSpawnMenu )
function GM:OnSpawnMenuOpen()
-- Let the gamemode decide whether we should open or not..
if ( !hook.Call( "SpawnMenuOpen", self ) ) then return end
if ( IsValid( g_SpawnMenu ) ) then
g_SpawnMenu:Open()
menubar.ParentTo( g_SpawnMenu )
end
hook.Call( "SpawnMenuOpened", self )
end
function GM:OnSpawnMenuClose()
if ( IsValid( g_SpawnMenu ) ) then g_SpawnMenu:Close() end
hook.Call( "SpawnMenuClosed", self )
end
--[[---------------------------------------------------------
Name: HOOK SpawnMenuKeyboardFocusOn
Called when text entry needs keyboard focus
-----------------------------------------------------------]]
local function SpawnMenuKeyboardFocusOn( pnl )
if ( IsValid( g_SpawnMenu ) && IsValid( pnl ) && pnl:HasParent( g_SpawnMenu ) ) then
g_SpawnMenu:StartKeyFocus( pnl )
end
if ( IsValid( g_ContextMenu ) && IsValid( pnl ) && pnl:HasParent( g_ContextMenu ) ) then
g_ContextMenu:StartKeyFocus( pnl )
end
end
hook.Add( "OnTextEntryGetFocus", "SpawnMenuKeyboardFocusOn", SpawnMenuKeyboardFocusOn )
--[[---------------------------------------------------------
Name: HOOK SpawnMenuKeyboardFocusOff
Called when text entry stops needing keyboard focus
-----------------------------------------------------------]]
local function SpawnMenuKeyboardFocusOff( pnl )
if ( IsValid( g_SpawnMenu ) && IsValid( pnl ) && pnl:HasParent( g_SpawnMenu ) ) then
g_SpawnMenu:EndKeyFocus( pnl )
end
if ( IsValid( g_ContextMenu ) && IsValid( pnl ) && pnl:HasParent( g_ContextMenu ) ) then
g_ContextMenu:EndKeyFocus( pnl )
end
end
hook.Add( "OnTextEntryLoseFocus", "SpawnMenuKeyboardFocusOff", SpawnMenuKeyboardFocusOff )
--[[---------------------------------------------------------
Name: HOOK SpawnMenuOpenGUIMousePressed
Don't do context screen clicking if spawnmenu is open
-----------------------------------------------------------]]
local function SpawnMenuOpenGUIMousePressed()
if ( !IsValid( g_SpawnMenu ) ) then return end
if ( !g_SpawnMenu:IsVisible() ) then return end
return true
end
hook.Add( "GUIMousePressed", "SpawnMenuOpenGUIMousePressed", SpawnMenuOpenGUIMousePressed )
--[[---------------------------------------------------------
Name: HOOK SpawnMenuOpenGUIMousePressed
Close spawnmenu if it's open
-----------------------------------------------------------]]
local function SpawnMenuOpenGUIMouseReleased()
if ( !IsValid( g_SpawnMenu ) ) then return end
if ( !g_SpawnMenu:IsVisible() ) then return end
g_SpawnMenu:Close()
return true
end
hook.Add( "GUIMouseReleased", "SpawnMenuOpenGUIMouseReleased", SpawnMenuOpenGUIMouseReleased )
--[[---------------------------------------------------------
Handle spawn menu language switching
- The spawn menu needs to be recreated ("refreshed") after a language switch
- We SHOULDN'T refresh it if the user has unsaved changes to their spawn list (these would be lost!)
- We SHOULDN'T refresh it if the user has the spawn menu open (that would be bad user experience)
- But, we SHOULD refresh it if the user saves or reverts any changes and closes the spawn menu
- What if the user switches BACK to the original language they were using? Surely, a refresh is not needed now?
- No, in this case we should still refresh the spawn menu because some text and labels do actually update during use of the spawn menu and might be left "dirty"
-----------------------------------------------------------]]
local function SpawnMenuLanguageChanged()
if ( !IsValid( g_SpawnMenu ) ) then return end
if ( g_SpawnMenu.m_UnsavedModifications || g_SpawnMenu:IsVisible() ) then
-- If there are unsaved modifications, or the spawn menu is somehow open, mark the spawn menu for recreation when the opportunity arises
g_SpawnMenu.m_NeedsLanguageRefresh = true
else
-- If there are no unsaved modifications, and the spawn menu isn't open, we can go ahead and safely refresh the spawn menu
CreateSpawnMenu()
end
end
-- When gmod_language changes, call SpawnMenuLanguageChanged
cvars.AddChangeCallback( "gmod_language", SpawnMenuLanguageChanged, "spawnmenu_reload" )
local function ProtectSpawnMenuChanges()
if ( !IsValid( g_SpawnMenu ) ) then return end
-- Mark the spawn menu as having unsaved modifications
g_SpawnMenu.m_UnsavedModifications = true
end
hook.Add( "SpawnlistContentChanged", "ProtectSpawnMenuChanges", ProtectSpawnMenuChanges )
local function SpawnMenuChangesFinished()
if ( !IsValid( g_SpawnMenu ) ) then return end
-- Mark the spawn menu as no longer having unsaved modifications
g_SpawnMenu.m_UnsavedModifications = nil
end
hook.Add( "OnRevertSpawnlist", "SpawnMenuChangesFinished", SpawnMenuChangesFinished )
hook.Add( "OnSaveSpawnlist", "SpawnMenuChangesFinished", SpawnMenuChangesFinished )
local function SpawnMenuLanguageRefresh()
if ( !IsValid( g_SpawnMenu ) ) then return end
-- When the spawn menu is closed, check if it needs a language refresh. If it has no unsaved modifications, refresh it!
if ( !g_SpawnMenu.m_UnsavedModifications && g_SpawnMenu.m_NeedsLanguageRefresh ) then
g_SpawnMenu.m_NeedsLanguageRefresh = nil
CreateSpawnMenu()
end
end
hook.Add( "OnSpawnMenuClose", "SpawnMenuLanguageRefresh", SpawnMenuLanguageRefresh )