Skip to content

Commit e6c11cc

Browse files
authored
Merge pull request #1082 from anf3is/feat/chall-search
Add search bar for challenge selection screen
2 parents d3c7f0f + 917f5ad commit e6c11cc

4 files changed

Lines changed: 319 additions & 10 deletions

File tree

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
"Resource/UI/BaseModUI/ReactiveDropChallengeSelection.res"
2+
{
3+
"ReactiveDropChallengeSelection"
4+
{
5+
"ControlName" "Frame"
6+
"fieldName" "ReactiveDropChallengeSelection"
7+
8+
"xpos" "0"
9+
"ypos" "0"
10+
"zpos" "50"
11+
"wide" "f0"
12+
"tall" "f0"
13+
"autoResize" "0"
14+
"pinCorner" "0"
15+
"visible" "1"
16+
"enabled" "1"
17+
"tabPosition" "0"
18+
}
19+
20+
"Title"
21+
{
22+
"fieldName" "Title"
23+
"xpos" "c-266"
24+
"ypos" "56"
25+
"wide" "150"
26+
"tall" "19"
27+
"zpos" "5"
28+
"font" "DefaultExtraLarge"
29+
"textAlignment" "west"
30+
"ControlName" "Label"
31+
"labelText" "#rd_challenge_selection_title"
32+
"fgcolor_override" "224 224 224 255"
33+
}
34+
35+
"Divider1"
36+
{
37+
"ControlName" "ImagePanel"
38+
"fieldName" "Divider1"
39+
"xpos" "c-238"
40+
"ypos" "115"
41+
"zpos" "2"
42+
"wide" "450"
43+
"tall" "2"
44+
"autoResize" "0"
45+
"pinCorner" "0"
46+
"visible" "0"
47+
"enabled" "1"
48+
"tabPosition" "0"
49+
"image" "divider_gradient"
50+
"scaleImage" "1"
51+
}
52+
53+
"TxtSearch"
54+
{
55+
"ControlName" "ReactiveDropChallengeSelectionSearch"
56+
"fieldName" "TxtSearch"
57+
"xpos" "c-226"
58+
"ypos" "88"
59+
"wide" "160"
60+
"tall" "15"
61+
"visible" "1"
62+
"enabled" "1"
63+
}
64+
65+
"GplChallenges"
66+
{
67+
"ControlName" "GenericPanelList"
68+
"fieldName" "GplChallenges"
69+
"xpos" "c-226"
70+
"ypos" "115"
71+
"wide" "450"
72+
"tall" "185"
73+
"zpos" "1"
74+
"autoResize" "1"
75+
"pinCorner" "0"
76+
"visible" "1"
77+
"enabled" "1"
78+
"tabPosition" "1"
79+
"proportionalToParent" "1"
80+
81+
"bgcolor_override" "0 0 0 128"
82+
}
83+
84+
"Divider2"
85+
{
86+
"ControlName" "ImagePanel"
87+
"fieldName" "Divider2"
88+
"xpos" "c-238"
89+
"ypos" "297"
90+
"zpos" "2"
91+
"wide" "450"
92+
"tall" "2"
93+
"autoResize" "0"
94+
"pinCorner" "0"
95+
"visible" "0"
96+
"enabled" "1"
97+
"tabPosition" "0"
98+
"image" "divider_gradient"
99+
"scaleImage" "1"
100+
}
101+
102+
"LblName"
103+
{
104+
"ControlName" "Label"
105+
"fieldName" "LblName"
106+
"xpos" "c-140"
107+
"ypos" "315"
108+
"wide" "265"
109+
"tall" "18"
110+
"zpos" "1"
111+
"autoResize" "0"
112+
"pinCorner" "0"
113+
"visible" "1"
114+
"enabled" "1"
115+
"tabPosition" "0"
116+
"font" "DefaultLarge"
117+
"textAlignment" "north-west"
118+
}
119+
120+
"LblAuthor"
121+
{
122+
"ControlName" "Label"
123+
"fieldName" "LblAuthor"
124+
"xpos" "c+45"
125+
"ypos" "337"
126+
"wide" "180"
127+
"tall" "15"
128+
"zpos" "1"
129+
"autoResize" "0"
130+
"pinCorner" "0"
131+
"visible" "1"
132+
"enabled" "1"
133+
"tabPosition" "0"
134+
"Font" "DefaultMedium"
135+
"textAlignment" "north-east"
136+
"wrap" "0"
137+
"dulltext" "1"
138+
}
139+
140+
"LblDescription"
141+
{
142+
"ControlName" "Label"
143+
"fieldName" "LblDescription"
144+
"xpos" "c-140"
145+
"ypos" "355"
146+
"zpos" "1"
147+
"wide" "365"
148+
"tall" "75"
149+
"autoResize" "0"
150+
"pinCorner" "0"
151+
"visible" "1"
152+
"enabled" "1"
153+
"tabPosition" "0"
154+
"Font" "Default"
155+
"textAlignment" "north-west"
156+
"wrap" "1"
157+
"brighttext" "1"
158+
"dulltext" "0"
159+
}
160+
161+
"ImgIcon"
162+
{
163+
"ControlName" "ImagePanel"
164+
"fieldName" "ImgIcon"
165+
"xpos" "c-280"
166+
"ypos" "315"
167+
"zpos" "1"
168+
"wide" "123"
169+
"tall" "69"
170+
"autoResize" "0"
171+
"pinCorner" "0"
172+
"visible" "1"
173+
"enabled" "1"
174+
"tabPosition" "0"
175+
"scaleImage" "1"
176+
}
177+
178+
"BackButton"
179+
{
180+
"ControlName" "CNB_Button"
181+
"fieldName" "BackButton"
182+
"xpos" "c-264"
183+
"ypos" "r23"
184+
"wide" "117"
185+
"tall" "27"
186+
"zpos" "1"
187+
"visible" "1"
188+
"enabled" "1"
189+
"tabPosition" "0"
190+
"labelText" "#nb_back"
191+
"command" "BackButton"
192+
"textAlignment" "center"
193+
"font" "DefaultMedium"
194+
"fgcolor_override" "113 142 181 255"
195+
}
196+
}

src/game/client/swarm/gameui/swarm/rd_challenge_selection.cpp

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#include "cbase.h"
2+
3+
#include "asw_util_shared.h"
24
#include "rd_challenge_selection.h"
35
#include "rd_challenges_shared.h"
46
#include <vgui_controls/ImagePanel.h>
57
#include <vgui/ILocalize.h>
68
#include <vgui/ISurface.h>
79
#include "nb_header_footer.h"
810
#include "nb_button.h"
11+
#include "strtools.h"
912
#include "vfooterpanel.h"
1013
#include "rd_workshop.h"
1114
#include "filesystem.h"
@@ -14,6 +17,47 @@
1417
// memdbgon must be the last include file in a .cpp file!!!
1518
#include "tier0/memdbgon.h"
1619

20+
bool NameHasSearch( const char *szTitle, const char *szSearch )
21+
{
22+
if ( szSearch[0] == '\0' )
23+
{
24+
return true;
25+
}
26+
27+
if ( szTitle[0] == '#' )
28+
{
29+
wchar_t wszLocalized[RD_CHALLENGE_TITLE_LEN];
30+
char szLocalized[RD_CHALLENGE_TITLE_LEN];
31+
32+
TryLocalize( szTitle, wszLocalized, RD_CHALLENGE_TITLE_LEN );
33+
V_UnicodeToUTF8( wszLocalized, szLocalized, RD_CHALLENGE_TITLE_LEN );
34+
35+
return Q_stristr( szLocalized, szSearch ) != NULL;
36+
}
37+
38+
return Q_stristr( szTitle, szSearch ) != NULL;
39+
}
40+
41+
BaseModUI::ReactiveDropChallengeSelectionSearch::ReactiveDropChallengeSelectionSearch( vgui::Panel *parent, const char *panelName, ReactiveDropChallengeSelection *pSelection ) : BaseClass( parent, panelName )
42+
{
43+
SetMaximumCharCount( RD_CHALLENGE_TITLE_LEN );
44+
m_pSelection = pSelection;
45+
}
46+
47+
void BaseModUI::ReactiveDropChallengeSelectionSearch::OnKeyTyped( wchar_t unichar )
48+
{
49+
const int nBefore = GetTextLength();
50+
BaseClass::OnKeyTyped( unichar );
51+
const int nAfter = GetTextLength();
52+
53+
char szSearchText[RD_CHALLENGE_TITLE_LEN];
54+
GetText( szSearchText, RD_CHALLENGE_TITLE_LEN );
55+
56+
const bool bIncrSearch = nBefore != 0 && nAfter > nBefore;
57+
58+
m_pSelection->PopulateChallenges( szSearchText, bIncrSearch );
59+
}
60+
1761
BaseModUI::ReactiveDropChallengeSelectionListItem::ReactiveDropChallengeSelectionListItem( vgui::Panel *parent, const char *panelName ) : BaseClass( parent, panelName )
1862
{
1963
SetProportional( true );
@@ -219,6 +263,13 @@ const CReactiveDropWorkshop::WorkshopItem_t &BaseModUI::ReactiveDropChallengeSel
219263
BaseModUI::ReactiveDropChallengeSelection::ReactiveDropChallengeSelection( vgui::Panel *parent, const char *panelName, bool bDeathmatch ) : BaseClass( parent, panelName )
220264
{
221265
SetProportional( true );
266+
SetMouseInputEnabled( true );
267+
SetKeyBoardInputEnabled( true );
268+
269+
if ( engine->IsConnected() )
270+
{
271+
MakePopup( false );
272+
}
222273

223274
m_pHeaderFooter = new CNB_Header_Footer( this, "HeaderFooter" );
224275
m_pHeaderFooter->SetTitle( "" );
@@ -237,6 +288,8 @@ BaseModUI::ReactiveDropChallengeSelection::ReactiveDropChallengeSelection( vgui:
237288
m_lblDescription = new vgui::Label( this, "LblDescription", "" );
238289
m_lblAuthor = new vgui::Label( this, "LblAuthor", "" );
239290

291+
m_pTxtSearch = new ReactiveDropChallengeSelectionSearch( this, "TxtSearch", this );
292+
240293
m_bIgnoreSelectionChange = false;
241294

242295
m_bDeathmatch = bDeathmatch;
@@ -309,7 +362,7 @@ void BaseModUI::ReactiveDropChallengeSelection::OnMessage( const KeyValues *para
309362
}
310363
}
311364

312-
void BaseModUI::ReactiveDropChallengeSelection::PopulateChallenges()
365+
void BaseModUI::ReactiveDropChallengeSelection::PopulateChallenges( const char* szSearch, bool bIncrSearch )
313366
{
314367
m_gplChallenges->RemoveAllPanelItems();
315368
ReactiveDropChallengeSelectionListItem *pDisabled = m_gplChallenges->AddPanelItem<ReactiveDropChallengeSelectionListItem>( "ReactiveDropChallengeSelectionListItem" );
@@ -319,16 +372,55 @@ void BaseModUI::ReactiveDropChallengeSelection::PopulateChallenges()
319372
Assert( g_ReactiveDropWorkshop.m_bStartingUp == false );
320373
g_ReactiveDropWorkshop.m_bStartingUp = true;
321374

322-
int iCount = ReactiveDropChallenges::Count();
323-
for ( int i = 0; i < iCount; i++ )
375+
const char* szChallenges[RD_MAX_CHALLENGES];
376+
int nChallenges = 0;
377+
378+
// Find valid challenges
379+
if ( bIncrSearch )
324380
{
325-
const RD_Challenge_t *pChallenge = ReactiveDropChallenges::GetSummary( i );
326-
if ( m_bDeathmatch ? pChallenge->AllowDeathmatch : pChallenge->AllowCoop )
381+
for ( int i = 0; i < m_nChallengesPrev; i++ )
327382
{
328-
ReactiveDropChallengeSelectionListItem *pItem = m_gplChallenges->AddPanelItem<ReactiveDropChallengeSelectionListItem>( "ReactiveDropChallengeSelectionListItem" );
329-
pItem->PopulateChallenge( ReactiveDropChallenges::Name( i ) );
330-
GetControllerFocus()->AddToFocusList( pItem, true, true );
383+
const char *pChallengeName = m_szChallengesPrev[i];
384+
const char *szTitle = ReactiveDropChallenges::DisplayName(pChallengeName);
385+
386+
if ( NameHasSearch(szTitle, szSearch) )
387+
{
388+
szChallenges[nChallenges] = pChallengeName;
389+
m_szChallengesPrev[nChallenges] = pChallengeName;
390+
nChallenges++;
391+
}
331392
}
393+
m_nChallengesPrev = nChallenges;
394+
}
395+
else
396+
{
397+
const int nRDChallenges = ReactiveDropChallenges::Count();
398+
Assert( nRDChallenges <= RD_MAX_CHALLENGES );
399+
for ( int i = 0; i < nRDChallenges; i++ )
400+
{
401+
const RD_Challenge_t *pChallenge = ReactiveDropChallenges::GetSummary( i );
402+
if ( m_bDeathmatch ? pChallenge->AllowDeathmatch : pChallenge->AllowCoop )
403+
{
404+
const char *pChallengeName = ReactiveDropChallenges::Name( i );
405+
const char *szTitle = pChallenge->Title;
406+
407+
if ( !szSearch || NameHasSearch(szTitle, szSearch) )
408+
{
409+
szChallenges[nChallenges] = pChallengeName;
410+
m_szChallengesPrev[nChallenges] = pChallengeName;
411+
nChallenges++;
412+
}
413+
}
414+
}
415+
m_nChallengesPrev = nChallenges;
416+
}
417+
418+
// Add valid challenges to the panel list
419+
for ( int j = 0; j < nChallenges; j++ )
420+
{
421+
ReactiveDropChallengeSelectionListItem *pItem = m_gplChallenges->AddPanelItem<ReactiveDropChallengeSelectionListItem>( "ReactiveDropChallengeSelectionListItem" );
422+
pItem->PopulateChallenge( szChallenges[j] );
423+
GetControllerFocus()->AddToFocusList( pItem, true, true );
332424
}
333425

334426
g_ReactiveDropWorkshop.m_bStartingUp = false;

0 commit comments

Comments
 (0)