Skip to content

Commit

Permalink
dropdown menus implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
BenLubar committed Jul 25, 2023
1 parent 88135c4 commit 07cff46
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 10 deletions.
2 changes: 1 addition & 1 deletion reactivedrop/resource/ui/option_simple_dropdown.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"fieldName" "InteractiveArea"
"xpos" "100"
"ypos" "0"
"wide" "f100"
"wide" "90"
"tall" "12"
"bgcolor_override" "64 64 64 64"
}
Expand Down
219 changes: 210 additions & 9 deletions src/game/client/swarm/vgui/rd_vgui_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,124 @@ void CRD_VGUI_Settings_Panel_Base::NavigateTo()
BaseClass::NavigateTo();
}

class CRD_VGUI_Option_Dropdown : public vgui::EditablePanel
{
DECLARE_CLASS_SIMPLE( CRD_VGUI_Option_Dropdown, vgui::EditablePanel );
public:
CRD_VGUI_Option_Dropdown( CRD_VGUI_Option *parent, const char *panelName ) :
BaseClass{ parent, panelName }
{
m_hFont = vgui::INVALID_FONT;
MakePopup( false );
}

void PerformLayout() override
{
BaseClass::PerformLayout();

CRD_VGUI_Option *parent = assert_cast< CRD_VGUI_Option * >( GetParent() );

m_hFont = parent->m_pLblFieldName->GetFont();
SetFgColor( parent->m_pInteractiveArea->GetFgColor() );
SetBgColor( parent->m_pInteractiveArea->GetBgColor() );
SetPaintBackgroundEnabled( true );

int iMaxWidth = parent->m_pInteractiveArea->GetWide() - vgui::Label::Content * 2;
FOR_EACH_VEC( parent->m_Options, i )
{
iMaxWidth = MAX( iMaxWidth, parent->m_Options[i]->m_iWidth );
}

int x = 0, y = 0;
parent->m_pInteractiveArea->LocalToScreen( x, y );
SetPos( x, y );

SetWide( vgui::Label::Content * 2 + iMaxWidth );
SetTall( vgui::Label::Content + parent->m_Options.Count() * vgui::surface()->GetFontTall( m_hFont ) );

vgui::input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
OnCursorMoved( x, y );
}

void Paint() override
{
CRD_VGUI_Option *parent = assert_cast< CRD_VGUI_Option * >( GetParent() );
Assert( parent && parent->m_iActiveOption != -1 );
if ( !parent || parent->m_iActiveOption == -1 )
{
SetVisible( false );
return;
}

BaseClass::Paint();

int x = vgui::Label::Content;
int y = vgui::Label::Content / 2;
int iLineHeight = vgui::surface()->GetFontTall( m_hFont );

vgui::surface()->DrawSetTextFont( m_hFont );

FOR_EACH_VEC( parent->m_Options, i )
{
const wchar_t *wszLabel = parent->m_Options[i]->m_wszLabel;
bool bRecommended = parent->m_bHaveRecommended && i == parent->m_Recommended.m_iOption;
bool bCurrent = parent->m_bHaveCurrent && i == parent->m_Current.m_iOption;
bool bActive = parent->m_iActiveOption == i;

if ( bActive )
{
vgui::surface()->DrawSetColor( 255, 255, 255, 32 );
vgui::surface()->DrawFilledRect( 0, y, GetWide(), y + iLineHeight );
}

vgui::surface()->DrawSetTextPos( x, y );
if ( bRecommended )
vgui::surface()->DrawSetTextColor( 192, 224, 255, 255 );
else if ( bCurrent )
vgui::surface()->DrawSetTextColor( 255, 255, 255, 255 );
else
vgui::surface()->DrawSetTextColor( GetFgColor() );
vgui::surface()->DrawUnicodeString( wszLabel );

y += iLineHeight;
}
}

void OnMousePressed( vgui::MouseCode code ) override
{
// forward mouse presses to parent; don't process here
GetParent()->OnMousePressed( code );
}

void OnMouseReleased( vgui::MouseCode code ) override
{
GetParent()->OnMouseReleased( code );
}

void OnCursorMoved( int x, int y ) override
{
BaseClass::OnCursorMoved( x, y );

CRD_VGUI_Option *parent = assert_cast< CRD_VGUI_Option * >( GetParent() );
Assert( parent );
if ( !parent )
return;

int iLineHeight = vgui::surface()->GetFontTall( m_hFont );
int iOption = ( y - vgui::Label::Content / 2 ) / iLineHeight;
if ( iOption >= 0 && iOption < parent->m_Options.Count() && parent->m_iActiveOption != iOption )
{
parent->m_iActiveOption = iOption;
Repaint();

CBaseModPanel::GetSingleton().PlayUISound( UISOUND_FOCUS );
}
}

vgui::HFont m_hFont;
};

CRD_VGUI_Option::CRD_VGUI_Option( vgui::Panel *parent, const char *panelName, const char *szLabel, Mode_t eMode ) :
BaseClass{ parent, panelName },
m_eMode{ eMode }
Expand All @@ -219,6 +337,7 @@ CRD_VGUI_Option::CRD_VGUI_Option( vgui::Panel *parent, const char *panelName, co
m_pTextEntry->AddActionSignalTarget( this );
m_pTextEntry->SetAllowNumericInputOnly( true );
}
m_pDropdown = NULL;

m_bHaveCurrent = false;
m_bHaveRecommended = false;
Expand Down Expand Up @@ -349,13 +468,25 @@ void CRD_VGUI_Option::NavigateTo()

void CRD_VGUI_Option::OnKillFocus()
{
vgui::Panel *pNewFocus = vgui::ipanel()->GetPanel( vgui::input()->GetCalculatedFocus(), GetModuleName() );
if ( m_pDropdown && pNewFocus == m_pDropdown )
{
RequestFocus();
return;
}

BaseClass::OnKillFocus();

if ( m_bSliderActive )
{
ToggleSliderActive( false );
}

if ( m_pDropdown )
{
m_pDropdown->SetVisible( false );
}

m_iActiveOption = -1;
}

Expand Down Expand Up @@ -623,7 +754,7 @@ void CRD_VGUI_Option::Paint()
{
HUD_SHEET_DRAW_RECT( x0, y0, x0 + y1, y0 + y1, Controls, UV_radio );

// TODO
Assert( !"TODO: slider with options" );

x0 += y1;
}
Expand Down Expand Up @@ -679,6 +810,28 @@ void CRD_VGUI_Option::Paint()
}
}

void CRD_VGUI_Option::OnKeyCodeTyped( vgui::KeyCode code )
{
if ( code == KEY_ESCAPE )
{
if ( m_eMode == MODE_DROPDOWN && m_iActiveOption != -1 )
{
Assert( m_pDropdown );
m_iActiveOption = -1;
m_pDropdown->SetVisible( false );
return;
}

if ( m_bSliderActive )
{
if ( OnActivateButton( false ) )
return;
}
}

BaseClass::OnKeyCodeTyped( code );
}

void CRD_VGUI_Option::OnKeyCodePressed( vgui::KeyCode code )
{
if ( m_pTextEntry && m_pTextEntry->HasFocus() )
Expand All @@ -690,11 +843,6 @@ void CRD_VGUI_Option::OnKeyCodePressed( vgui::KeyCode code )

switch ( GetBaseButtonCode( code ) )
{
case KEY_ESCAPE:
if ( !m_bSliderActive )
break;

// fallthrough
case KEY_SPACE:
case KEY_ENTER:
case KEY_PAD_ENTER:
Expand Down Expand Up @@ -869,6 +1017,9 @@ void CRD_VGUI_Option::SetCurrentOption( int iCurrent )
{
Assert( m_eMode == MODE_RADIO || m_eMode == MODE_DROPDOWN );

KeyValues *pKV = new KeyValues( "CurrentOptionChanged" );
pKV->SetPtr( "panel", this );

#ifdef DBGFLAG_ASSERT
bool bHaveNegativeOne = false;
#endif
Expand All @@ -879,6 +1030,8 @@ void CRD_VGUI_Option::SetCurrentOption( int iCurrent )
m_bHaveCurrent = true;
m_Current.m_iOption = i;

PostActionSignal( pKV );

return;
}

Expand All @@ -892,6 +1045,8 @@ void CRD_VGUI_Option::SetCurrentOption( int iCurrent )

Assert( iCurrent == ( bHaveNegativeOne ? -2 : -1 ) );
m_bHaveCurrent = false;

PostActionSignal( pKV );
}

void CRD_VGUI_Option::SetRecommendedOption( int iRecommended )
Expand Down Expand Up @@ -970,6 +1125,10 @@ void CRD_VGUI_Option::SetCurrentSliderValue( float flValue )

m_pTextEntry->SetText( VarArgs( "%.*f", iDigits, flValue ) );
}

KeyValues *pKV = new KeyValues( "CurrentOptionChanged" );
pKV->SetPtr( "panel", this );
PostActionSignal( pKV );
}

void CRD_VGUI_Option::SetRecommendedSliderValue( float flValue )
Expand Down Expand Up @@ -1428,6 +1587,20 @@ bool CRD_VGUI_Option::OnMovementButton( int iDirection, bool bVertical )
return true;
}

if ( bVertical && m_pDropdown && m_pDropdown->IsVisible() )
{
int iNewOption = clamp<int>( m_iActiveOption + iDirection, 0, m_Options.Count() - 1 );
if ( iNewOption != m_iActiveOption )
{
m_iActiveOption = iNewOption;
m_pDropdown->Repaint();

CBaseModPanel::GetSingleton().PlayUISound( UISOUND_FOCUS );
}

return true;
}

return false;
}

Expand Down Expand Up @@ -1494,12 +1667,15 @@ void CRD_VGUI_Option::SelectActiveRadioButton()

m_bHaveCurrent = true;
if ( m_eMode == MODE_SLIDER )
m_Current.m_flValue = m_Options[m_iActiveOption]->m_iValue;
SetCurrentSliderValue( m_Options[m_iActiveOption]->m_iValue );
else
m_Current.m_iOption = m_iActiveOption;
SetCurrentOption( m_Options[m_iActiveOption]->m_iValue );

if ( m_eMode == MODE_DROPDOWN )
{
m_pDropdown->SetVisible( false );
m_iActiveOption = -1;
}

CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );

Expand Down Expand Up @@ -1559,7 +1735,32 @@ void CRD_VGUI_Option::ToggleDropdownActive()
Assert( m_eMode == MODE_DROPDOWN );
Assert( m_iActiveOption == -1 );

Assert( !"TODO: ToggleDropdownActive" );
if ( !m_pDropdown )
{
m_pDropdown = new CRD_VGUI_Option_Dropdown( this, "Dropdown" );
m_pDropdown->MakeReadyForUse();
}

if ( m_bHaveCurrent )
{
Assert( m_Current.m_iOption >= 0 && m_Current.m_iOption < m_Options.Count() );
m_iActiveOption = m_Current.m_iOption;
}
else if ( m_bHaveRecommended )
{
Assert( m_Recommended.m_iOption >= 0 && m_Recommended.m_iOption < m_Options.Count() );
m_iActiveOption = m_Recommended.m_iOption;
}
else
{
Assert( m_Options.Count() );
m_iActiveOption = 0;
}

m_pDropdown->SetVisible( true );
m_pDropdown->MoveToFront();
m_pDropdown->InvalidateLayout();
m_pDropdown->Repaint();
}

CON_COMMAND( rd_settings, "Opens the settings screen." )
Expand Down
6 changes: 6 additions & 0 deletions src/game/client/swarm/vgui/rd_vgui_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace BaseModUI
class CNB_Header_Footer;
class CRD_VGUI_Main_Menu_Top_Bar;
class CRD_VGUI_Microphone_Tester;
class CRD_VGUI_Option_Dropdown;
class CRD_VGUI_Settings_Panel_Base;
class CRD_VGUI_Settings_Controls;
class CRD_VGUI_Settings_Options;
Expand Down Expand Up @@ -91,6 +92,7 @@ class CRD_VGUI_Option : public vgui::EditablePanel
void PerformLayout() override;
void OnThink() override;
void Paint() override;
void OnKeyCodeTyped( vgui::KeyCode code ) override;
void OnKeyCodePressed( vgui::KeyCode code ) override;
void OnMousePressed( vgui::MouseCode code ) override;
void OnMouseReleased( vgui::MouseCode code ) override;
Expand Down Expand Up @@ -183,6 +185,9 @@ class CRD_VGUI_Option : public vgui::EditablePanel
vgui::Label *m_pLblFieldName;
vgui::Label *m_pLblHint;
vgui::TextEntry *m_pTextEntry;
CRD_VGUI_Option_Dropdown *m_pDropdown;

friend class CRD_VGUI_Option_Dropdown;

static bool s_bCVarChanged;
static float s_flLastRepeatLEFT, s_flLastRepeatRIGHT;
Expand Down Expand Up @@ -455,6 +460,7 @@ class CRD_VGUI_Settings_Video : public CRD_VGUI_Settings_Panel_Base

void Activate() override;
BaseModUI::BaseModHybridButton *GetButton( BaseModUI::CRD_VGUI_Settings *pSettings ) override { return pSettings->m_pBtnVideo; }
MESSAGE_FUNC_PTR( OnCurrentOptionChanged, "CurrentOptionChanged", panel );

CRD_VGUI_Option *m_pSettingScreenResolution;
CRD_VGUI_Option *m_pSettingDisplayMode;
Expand Down
Loading

0 comments on commit 07cff46

Please sign in to comment.