--[[ | 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/ --]] AddCSLuaFile() PANEL.Base = "Panel" function PANEL:Init() self.CurrentSearch = "" self.OldResults = -1 self.RebuildResults = false self:Dock( TOP ) self:SetHeight( 20 ) self:DockMargin( 0, 0, 0, 3 ) self.Search = self:Add( "DTextEntry" ) self.Search:Dock( FILL ) self.Search:SetPlaceholderText( "#spawnmenu.search" ) self.Search.OnEnter = function() self:RefreshResults() end self.Search.OnFocusChanged = function( _, b ) if ( b ) then self.ContentPanel:SwitchPanel( self.PropPanel ) end end self.Search:SetTooltip( "#spawnmenu.enter_search" ) local btn = self.Search:Add( "DImageButton" ) btn:SetImage( "icon16/magnifier.png" ) btn:SetText( "" ) btn:Dock( RIGHT ) btn:DockMargin( 4, 2, 4, 2 ) btn:SetSize( 16, 16 ) btn:SetTooltip( "#spawnmenu.press_search" ) btn.DoClick = function() self:RefreshResults() end self.Search.OnKeyCode = function( p, code ) if ( code == KEY_F1 ) then hook.Run( "OnSpawnMenuClose" ) end if ( code == KEY_ESCAPE ) then hook.Run( "OnSpawnMenuClose" ) end end self.PropPanel = vgui.Create( "ContentContainer", self ) self.PropPanel:SetVisible( false ) self.PropPanel:SetTriggerSpawnlistChange( false ) -- Some sort of placeholder local Header = self:Add( "ContentHeader" ) Header:SetText( "#spawnmenu.enter_search" ) self.PropPanel:Add( Header ) end function PANEL:Paint() -- This is a bit of a hack, if there was a request to rebuild the results from the search indexer -- Do it when the player next sees the search panel, in case they got the spawnmenu closed -- Think hook causes unexpected 1 frame duplication of all the elements if ( self.RebuildResults ) then self.RebuildResults = false self:RefreshResults( self.CurrentSearch ) end end function PANEL:SetSearchType( stype, hookname ) self.m_strSearchType = stype hook.Add( hookname, "AddSearchContent_" .. hookname, function( pnlContent, tree, node ) self.ContentPanel = pnlContent end ) hook.Add( "SearchUpdate", "SearchUpdate_" .. hookname, function() if ( !g_SpawnMenu:IsVisible() ) then self.RebuildResults = true return end self:RefreshResults( self.CurrentSearch ) end ) -- This stuff is only for the primary search if ( hookname != "PopulateContent" ) then return end g_SpawnMenu.SearchPropPanel = self.PropPanel hook.Add( "StartSearch", "StartSearch", function() if ( g_SpawnMenu:IsVisible() ) then return hook.Run( "OnSpawnMenuClose" ) end hook.Run( "OnSpawnMenuOpen" ) hook.Run( "OnTextEntryGetFocus", self.Search ) self.Search:RequestFocus() self.Search:SetText( "" ) -- -- If we don't call this we'd have to press F1 twice to close it! -- It's in a timer because of some good reason that! -- timer.Simple( 0.1, function() g_SpawnMenu:HangOpen( false ) end ) self.ContentPanel:SwitchPanel( self.PropPanel ) end ) end function PANEL:RefreshResults( str ) if ( !str ) then -- User tried to search for something self.CurrentSearch = self.Search:GetText() str = self.CurrentSearch self.OldResults = -1 else -- Don't force open the search when you click away from search while this function is called from cl_search_models.lua if ( self.ContentPanel.SelectedPanel != self.PropPanel ) then return end end if ( !str or str == "" ) then return end local results = search.GetResults( str, self.m_strSearchType, GetConVarNumber( "sbox_search_maxresults" ) ) for id, result in ipairs( results ) do if ( !IsValid( result.icon ) ) then ErrorNoHalt( "Failed to create icon for " .. ( result.words && isstring( result.words[ 1 ] ) && result.words[ 1 ] || result.text ).. "\n" ) continue end result.icon:SetParent( vgui.GetWorldPanel() ) -- Don't parent the icons to search panel prematurely end -- I know this is not perfect, but this is the best I am willing to do with how the search library was set up if ( self.OldResults == #results ) then -- No updates, don't rebuild for id, result in ipairs( results ) do if ( IsValid( result.icon ) ) then result.icon:Remove() end -- Kill all icons end return end self.OldResults = #results self.PropPanel:Clear() local Header = self:Add( "ContentHeader" ) Header:SetText( #results .. " Results for \"" .. str .. "\"" ) self.PropPanel:Add( Header ) for k, v in ipairs( results ) do self:AddSearchResult( v.text, v.func, v.icon ) end self.PropPanel:SetParent( self.ContentPanel ) self.ContentPanel:SwitchPanel( self.PropPanel ) end function PANEL:AddSearchResult( text, func, icon ) if ( !IsValid( icon ) ) then return end icon:SetParent( self.PropPanel ) self.PropPanel:Add( icon ) end