mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-02-09 21:54:19 +00:00
2534 lines
84 KiB
C++
2534 lines
84 KiB
C++
#include "gamepadui_interface.h"
|
|
#include "gamepadui_button.h"
|
|
#include "gamepadui_frame.h"
|
|
#include "gamepadui_scrollbar.h"
|
|
#include "gamepadui_image.h"
|
|
#include "gamepadui_genericconfirmation.h"
|
|
|
|
#include "ienginevgui.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include "vgui/ISurface.h"
|
|
#include "vgui/IVGui.h"
|
|
#include "vgui/IInput.h"
|
|
|
|
#include "vgui_controls/ComboBox.h"
|
|
|
|
#include "KeyValues.h"
|
|
#include "filesystem.h"
|
|
#include "utlbuffer.h"
|
|
#include "inputsystem/iinputsystem.h"
|
|
#include "materialsystem/materialsystem_config.h"
|
|
|
|
#if defined( USE_SDL )
|
|
#include "SDL.h"
|
|
#endif
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
const int MAX_OPTIONS_TABS = 7;
|
|
|
|
#define GAMEPADUI_OPTIONS_FILE GAMEPADUI_RESOURCE_FOLDER "options.res"
|
|
|
|
class GamepadUIOptionButton;
|
|
class GamepadUIWheelyWheel;
|
|
void OnResolutionsNeedUpdate( IConVar *var, const char *pOldValue, float flOldValue );
|
|
|
|
extern CUtlSymbolTable g_ButtonSoundNames;
|
|
|
|
ConVar _gamepadui_water_detail( "_gamepadui_water_detail", "0" );
|
|
ConVar _gamepadui_shadow_detail( "_gamepadui_shadow_detail", "0" );
|
|
ConVar _gamepadui_antialiasing( "_gamepadui_antialiasing", "0" );
|
|
ConVar _gamepadui_aspectratio( "_gamepadui_aspectratio", "0", FCVAR_NONE, "", OnResolutionsNeedUpdate );
|
|
ConVar _gamepadui_displaymode( "_gamepadui_displaymode", "0", FCVAR_NONE, "", OnResolutionsNeedUpdate );
|
|
ConVar _gamepadui_resolution( "_gamepadui_resolution", "0" );
|
|
ConVar _gamepadui_sound_quality( "_gamepadui_sound_quality", "0" );
|
|
ConVar _gamepadui_closecaptions( "_gamepadui_closecaptions", "0" );
|
|
#ifdef HL2_RETAIL
|
|
ConVar _gamepadui_hudaspect( "_gamepadui_hudaspect", "0" );
|
|
#endif
|
|
ConVar _gamepadui_skill( "_gamepadui_skill", "0" );
|
|
|
|
struct GamepadUITab
|
|
{
|
|
GamepadUIButton *pTabButton;
|
|
CUtlVector< GamepadUIOptionButton* > pButtons;
|
|
GamepadUIScrollState ScrollState;
|
|
bool bAlternating;
|
|
bool bHorizontal;
|
|
CUtlVector<CUtlSymbol> KeysToUnbind;
|
|
};
|
|
|
|
class GamepadUIOptionsPanel : public GamepadUIFrame
|
|
{
|
|
DECLARE_CLASS_SIMPLE( GamepadUIOptionsPanel, GamepadUIFrame );
|
|
|
|
public:
|
|
GamepadUIOptionsPanel( vgui::Panel *pParent, const char* pPanelName );
|
|
~GamepadUIOptionsPanel();
|
|
|
|
void OnThink() OVERRIDE;
|
|
void Paint() OVERRIDE;
|
|
void LayoutCurrentTab();
|
|
void OnCommand( char const* pCommand ) OVERRIDE;
|
|
|
|
void UpdateGradients() OVERRIDE;
|
|
|
|
void LoadOptionTabs( const char* pszOptionsFile );
|
|
|
|
void ApplySchemeSettings( vgui::IScheme *pScheme ) OVERRIDE;
|
|
|
|
void SetOptionDescription( GamepadUIString *pStr ) { m_strOptionDescription = pStr; }
|
|
|
|
void SetActiveTab( int nTab );
|
|
int GetActiveTab();
|
|
void OnMouseWheeled( int delta ) OVERRIDE;
|
|
|
|
void UpdateResolutions();
|
|
void ClearBindings();
|
|
void FillInBindings();
|
|
void ApplyKeyBindings();
|
|
|
|
void OnKeyBound( const char *pKey );
|
|
|
|
void OnKeyCodePressed( vgui::KeyCode code );
|
|
|
|
MESSAGE_FUNC_HANDLE( OnGamepadUIButtonNavigatedTo, "OnGamepadUIButtonNavigatedTo", button );
|
|
|
|
static GamepadUIOptionsPanel *GetInstance()
|
|
{
|
|
return s_pOptionsPanel;
|
|
}
|
|
|
|
GamepadUIWheelyWheel *GetResolutionButton()
|
|
{
|
|
return m_pResolutionButton;
|
|
}
|
|
|
|
private:
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flTabsOffsetX, "Tabs.OffsetX", "0", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flTabsOffsetY, "Tabs.OffsetY", "0", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flOptionsFade, "Options.Fade", "80", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flScrollBarOffsetX, "Options.Scrollbar.OffsetX", "716", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flScrollBarOffsetY, "Options.Scrollbar.OffsetY", "128", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flScrollBarHeight, "Options.Scrollbar.Height", "256", SchemeValueTypes::ProportionalFloat );
|
|
|
|
GamepadUITab m_Tabs[ MAX_OPTIONS_TABS ];
|
|
int m_nTabCount = 0;
|
|
|
|
GamepadUIWheelyWheel* m_pResolutionButton = NULL;
|
|
|
|
GamepadUIGlyph m_leftGlyph;
|
|
GamepadUIGlyph m_rightGlyph;
|
|
|
|
GamepadUIString *m_strOptionDescription = NULL;
|
|
vgui::HFont m_hDescFont = vgui::INVALID_FONT;
|
|
|
|
GamepadUIScrollBar *m_pScrollBar;
|
|
|
|
static GamepadUIOptionsPanel *s_pOptionsPanel;
|
|
};
|
|
|
|
GamepadUIOptionsPanel* GamepadUIOptionsPanel::s_pOptionsPanel = NULL;
|
|
|
|
ConVar gamepadui_last_options_tab( "gamepadui_last_options_tab", "0", FCVAR_ARCHIVE );
|
|
|
|
class GamepadUIOptionButton : public GamepadUIButton
|
|
{
|
|
DECLARE_CLASS_SIMPLE( GamepadUIOptionButton, GamepadUIButton );
|
|
public:
|
|
GamepadUIOptionButton( vgui::Panel *pParent, vgui::Panel *pActionSignalTarget, const char *pSchemeFile, const char *pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
{
|
|
}
|
|
|
|
GamepadUIOptionButton( vgui::Panel *pParent, vgui::Panel *pActionSignalTarget, const char *pSchemeFile, const char *pCommand, const wchar_t *pText, const wchar_t *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
{
|
|
}
|
|
|
|
virtual bool ShowDescriptionAtFooter() { return true; }
|
|
|
|
void SetArmed( bool state ) OVERRIDE
|
|
{
|
|
BaseClass::SetArmed( state );
|
|
|
|
if (state && ShowDescriptionAtFooter())
|
|
{
|
|
Assert( GamepadUIOptionsPanel::GetInstance() != NULL );
|
|
GamepadUIOptionsPanel::GetInstance()->SetOptionDescription( &m_strButtonDescription );
|
|
m_bDescriptionHide = true;
|
|
}
|
|
}
|
|
|
|
void SetHorizontal( bool bHorz )
|
|
{
|
|
m_bHorizontal = bHorz;
|
|
}
|
|
|
|
bool IsHorizontal()
|
|
{
|
|
return m_bHorizontal;
|
|
}
|
|
|
|
private:
|
|
bool m_bHorizontal = false;
|
|
};
|
|
|
|
class GamepadUIHeaderButton : public GamepadUIOptionButton
|
|
{
|
|
DECLARE_CLASS_SIMPLE( GamepadUIHeaderButton, GamepadUIOptionButton );
|
|
public:
|
|
GamepadUIHeaderButton( vgui::Panel *pParent, vgui::Panel *pActionSignalTarget, const char *pSchemeFile, const char *pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
{
|
|
}
|
|
|
|
GamepadUIHeaderButton( vgui::Panel *pParent, vgui::Panel *pActionSignalTarget, const char *pSchemeFile, const char *pCommand, const wchar_t *pText, const wchar_t *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
{
|
|
}
|
|
|
|
void NavigateTo()
|
|
{
|
|
switch (m_LastNavDirection)
|
|
{
|
|
case ND_UP: NavigateUp(); break;
|
|
case ND_DOWN: NavigateDown(); break;
|
|
case ND_LEFT: NavigateLeft(); break;
|
|
case ND_RIGHT: NavigateRight(); break;
|
|
case ND_BACK: NavigateBack(); break;
|
|
}
|
|
}
|
|
|
|
void ApplySchemeSettings( vgui::IScheme* pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
if (m_bCenter)
|
|
{
|
|
m_CenterX = true;
|
|
}
|
|
}
|
|
|
|
void SetCentered( bool bHorz )
|
|
{
|
|
m_bCenter = bHorz;
|
|
}
|
|
|
|
bool IsCentered()
|
|
{
|
|
return m_bCenter;
|
|
}
|
|
|
|
private:
|
|
bool m_bCenter = false;
|
|
};
|
|
|
|
class GamepadUICheckButton : public GamepadUIOptionButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUICheckButton, GamepadUIOptionButton );
|
|
|
|
GamepadUICheckButton( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char *pSchemeFile, const char* pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
{
|
|
}
|
|
|
|
virtual void ApplySchemeSettings( vgui::IScheme* pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
m_hIconFont = pScheme->GetFont( "Button.Check.Font", true );
|
|
}
|
|
|
|
virtual void Paint()
|
|
{
|
|
BaseClass::Paint();
|
|
|
|
vgui::surface()->DrawSetTextColor( m_colTextColor );
|
|
vgui::surface()->DrawSetTextFont( m_hIconFont );
|
|
vgui::surface()->DrawSetTextPos( m_flCheckOffsetX, m_flHeight / 2 - m_flCheckHeight / 2 );
|
|
vgui::surface()->DrawPrintText( L"j", 1 );
|
|
vgui::surface()->DrawSetTextPos( m_flCheckOffsetX, m_flHeight / 2 - m_flCheckHeight / 2 );
|
|
vgui::surface()->DrawPrintText( L"k", 1 );
|
|
}
|
|
|
|
private:
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flCheckOffsetX, "Button.Check.OffsetX", "10", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flCheckHeight, "Button.Check.Height", "18", SchemeValueTypes::ProportionalFloat );
|
|
|
|
vgui::HFont m_hIconFont = vgui::INVALID_FONT;
|
|
};
|
|
|
|
struct GamepadUIOption
|
|
{
|
|
GamepadUIString strOptionText;
|
|
int nValue = 0;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
int nWidth;
|
|
int nHeight;
|
|
};
|
|
void *pData;
|
|
} userdata;
|
|
};
|
|
|
|
class GamepadUIKeyButton : public GamepadUIOptionButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUIKeyButton, GamepadUIOptionButton );
|
|
|
|
GamepadUIKeyButton( const char *pszBinding, vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char *pSchemeFile, const char* pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_szBinding( pszBinding )
|
|
{
|
|
}
|
|
|
|
void Paint() OVERRIDE
|
|
{
|
|
BaseClass::Paint();
|
|
|
|
if ( m_bBeingBound )
|
|
{
|
|
vgui::surface()->DrawSetColor( m_colBinding );
|
|
vgui::surface()->DrawFilledRect( m_flWidth - m_flTextOffsetX - m_flBindingWidth, m_flHeight / 2 - m_flBindingHeight / 2, m_flWidth - m_flTextOffsetX, m_flHeight / 2 + m_flBindingHeight / 2 );
|
|
}
|
|
else
|
|
{
|
|
ButtonState state = GetCurrentButtonState();
|
|
|
|
wchar_t wszBuffer[ 128 ];
|
|
V_UTF8ToUnicode( m_szKey.String(), wszBuffer, sizeof( wszBuffer ) );
|
|
V_wcsupr( wszBuffer );
|
|
|
|
int nTextSizeX, nTextSizeY;
|
|
vgui::surface()->DrawSetTextFont(state == ButtonStates::Out ? m_hTextFont : m_hTextFontOver);
|
|
vgui::surface()->GetTextSize(state == ButtonStates::Out ? m_hTextFont : m_hTextFontOver, wszBuffer, nTextSizeX, nTextSizeY);
|
|
|
|
vgui::surface()->DrawSetTextPos( m_flWidth - m_flTextOffsetX - nTextSizeX, m_flHeight / 2 - nTextSizeY / 2 );
|
|
vgui::surface()->DrawPrintText( wszBuffer, V_wcslen( wszBuffer ) );
|
|
}
|
|
}
|
|
|
|
void ApplySchemeSettings(vgui::IScheme* pScheme)
|
|
{
|
|
BaseClass::ApplySchemeSettings(pScheme);
|
|
|
|
// Move the depressed sound to play after key capture
|
|
// (This would be more fitting for the release sound, but this class reuses the slider res file, which doesn't normally use a release sound)
|
|
m_sCaptureSoundName = m_sDepressedSoundName;
|
|
m_sDepressedSoundName = UTL_INVAL_SYMBOL;
|
|
}
|
|
|
|
ButtonState GetCurrentButtonState() OVERRIDE
|
|
{
|
|
if ( m_bBeingBound )
|
|
return ButtonStates::Pressed;
|
|
if ( s_bBeingBound )
|
|
return ButtonStates::Out;
|
|
return BaseClass::GetCurrentButtonState();
|
|
}
|
|
|
|
void OnMouseDoublePressed(vgui::MouseCode code) OVERRIDE
|
|
{
|
|
if ( !s_bBeingBound )
|
|
StartCapture();
|
|
}
|
|
|
|
void OnKeyCodePressed( vgui::KeyCode code )
|
|
{
|
|
ButtonCode_t buttonCode = GetBaseButtonCode( code );
|
|
switch ( buttonCode )
|
|
{
|
|
case KEY_ENTER:
|
|
if ( !s_bBeingBound )
|
|
StartCapture();
|
|
break;
|
|
case KEY_DELETE:
|
|
if ( !s_bBeingBound )
|
|
ClearKey();
|
|
break;
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OnThink() OVERRIDE
|
|
{
|
|
BaseClass::OnThink();
|
|
|
|
if ( m_bBeingBound )
|
|
{
|
|
ButtonCode_t code = BUTTON_CODE_INVALID;
|
|
if ( GamepadUI::GetInstance().GetEngineClient()->CheckDoneKeyTrapping( code ) )
|
|
{
|
|
OnKeyBound( code );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StartCapture()
|
|
{
|
|
m_bBeingBound = true;
|
|
s_bBeingBound = true;
|
|
g_pInputSystem->SetNovintPure( true );
|
|
GamepadUI::GetInstance().GetEngineClient()->StartKeyTrapMode();
|
|
vgui::surface()->SetCursor( vgui::dc_none );
|
|
SetCursor( vgui::dc_none );
|
|
vgui::input()->GetCursorPos( m_iMouseX, m_iMouseY );
|
|
}
|
|
|
|
void EndCapture()
|
|
{
|
|
m_bBeingBound = false;
|
|
s_bBeingBound = false;
|
|
vgui::input()->SetMouseCapture( NULL );
|
|
RequestFocus();
|
|
g_pInputSystem->SetNovintPure( false );
|
|
vgui::surface()->SetCursor( vgui::dc_arrow );
|
|
SetCursor( vgui::dc_arrow );
|
|
vgui::input()->SetCursorPos ( m_iMouseX, m_iMouseY );
|
|
}
|
|
|
|
void OnKeyBound( ButtonCode_t code )
|
|
{
|
|
EndCapture();
|
|
|
|
const char *pKey = g_pInputSystem->ButtonCodeToString( code );
|
|
GamepadUIOptionsPanel *pOptions = GamepadUIOptionsPanel::GetInstance();
|
|
if ( pOptions )
|
|
pOptions->OnKeyBound( pKey );
|
|
m_szKey = pKey;
|
|
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sCaptureSoundName ) );
|
|
}
|
|
|
|
const char *GetKeyBinding() { return m_szBinding.String(); }
|
|
|
|
const char *GetKey() { return m_szKey.String(); }
|
|
void SetKey( const char *pKey ) { m_szKey = pKey; }
|
|
|
|
void ClearKey() { m_szKey = ""; }
|
|
|
|
protected:
|
|
CUtlString m_szBinding;
|
|
CUtlString m_szKey;
|
|
|
|
bool m_bBeingBound = false;
|
|
static bool s_bBeingBound;
|
|
int m_iMouseX, m_iMouseY;
|
|
|
|
CUtlSymbol m_sCaptureSoundName = UTL_INVAL_SYMBOL;
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flBindingWidth, "Button.Binding.Width", "160", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flBindingHeight, "Button.Binding.Height", "11", SchemeValueTypes::ProportionalFloat );
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( Color, m_colBinding, "Button.Binding", "0 0 0 255", SchemeValueTypes::Color );
|
|
};
|
|
|
|
bool GamepadUIKeyButton::s_bBeingBound = false;
|
|
|
|
class GamepadUIConvarButton : public GamepadUIOptionButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUIConvarButton, GamepadUIOptionButton );
|
|
|
|
GamepadUIConvarButton( const char *pszCvar, const char* pszCvarDepends, bool bInstantApply, vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char *pSchemeFile, const char* pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_cvar( pszCvar )
|
|
, m_szDependentCVar( pszCvarDepends )
|
|
, m_bInstantApply( bInstantApply )
|
|
{
|
|
}
|
|
|
|
virtual void UpdateConVar() = 0;
|
|
virtual bool IsDirty() = 0;
|
|
virtual void SetToDefault() = 0;
|
|
virtual bool IsConVarEnabled() const { return true; }
|
|
|
|
const char *GetDependentCVar() const
|
|
{
|
|
return m_szDependentCVar.String();
|
|
}
|
|
|
|
const char *GetConVarName() const
|
|
{
|
|
return m_cvar.GetName();
|
|
}
|
|
|
|
protected:
|
|
ConVarRef m_cvar;
|
|
CUtlString m_szDependentCVar;
|
|
bool m_bInstantApply = false;
|
|
};
|
|
|
|
class GamepadUIWheelyWheel : public GamepadUIConvarButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUIWheelyWheel, GamepadUIConvarButton );
|
|
|
|
GamepadUIWheelyWheel( const char *pszCvar, const char *pszCvarDepends, bool bInstantApply, bool bSignOnly, vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char *pSchemeFile, const char* pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pszCvar, pszCvarDepends, bInstantApply, pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_bSignOnly( bSignOnly )
|
|
{
|
|
}
|
|
|
|
void OnKeyCodePressed( vgui::KeyCode code )
|
|
{
|
|
ButtonCode_t buttonCode = GetBaseButtonCode( code );
|
|
switch ( buttonCode )
|
|
{
|
|
case KEY_LEFT:
|
|
case KEY_XBUTTON_LEFT:
|
|
|
|
#ifdef HL2_RETAIL // Steam input and Steam Controller are not supported in SDK2013 (Madi)
|
|
case STEAMCONTROLLER_DPAD_LEFT:
|
|
#endif
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sDepressedSoundName ) );
|
|
DecrementValue();
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
case KEY_XBUTTON_RIGHT:
|
|
|
|
#ifdef HL2_RETAIL
|
|
case STEAMCONTROLLER_DPAD_RIGHT:
|
|
#endif
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sDepressedSoundName ) );
|
|
IncrementValue();
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OnMousePressed( vgui::MouseCode code )
|
|
{
|
|
GamepadUIString& strOption = m_Options[ m_nSelectedItem ].strOptionText;
|
|
|
|
int x, y;
|
|
GetPos( x, y );
|
|
|
|
int nTextW, nTextH;
|
|
vgui::surface()->GetTextSize( m_hTextFont, strOption.String(), nTextW, nTextH );
|
|
|
|
int nScrollerSize = vgui::surface()->GetCharacterWidth( m_hTextFont, L'<' ) + vgui::surface()->GetCharacterWidth( m_hTextFont, L' ' );
|
|
int nTextLen = (nTextW + 2 * nScrollerSize);
|
|
int nTextStart = x + m_flWidth - m_flTextOffsetX - nTextLen;
|
|
int nTextHalfwayPoint = x + m_flWidth - m_flTextOffsetX - (nTextLen / 2);
|
|
|
|
// Give some room to roughly press the scroller's left side
|
|
nTextStart -= m_flClickPadding;
|
|
|
|
// Change value based on what side the player clicked on
|
|
int mx, my;
|
|
g_pVGuiInput->GetCursorPos( mx, my );
|
|
if (mx > nTextHalfwayPoint)
|
|
{
|
|
// Right side
|
|
IncrementValue();
|
|
}
|
|
else if (mx > nTextStart)
|
|
{
|
|
// Left side
|
|
DecrementValue();
|
|
}
|
|
else
|
|
return; // Don't play sound
|
|
|
|
BaseClass::OnMousePressed( code );
|
|
}
|
|
|
|
void IncrementValue()
|
|
{
|
|
if (m_DangerousOptions.Count())
|
|
{
|
|
int nNewItem = 0;
|
|
if ( m_Options.Count() )
|
|
nNewItem = ( m_nSelectedItem + 1) % m_Options.Count();
|
|
|
|
int nIndex = m_DangerousOptions.Find( nNewItem );
|
|
if (nIndex != m_DangerousOptions.InvalidIndex())
|
|
{
|
|
ShowWarning( nIndex, true );
|
|
return;
|
|
}
|
|
}
|
|
|
|
IncrementValueInner();
|
|
}
|
|
|
|
void DecrementValue()
|
|
{
|
|
if (m_DangerousOptions.Count())
|
|
{
|
|
int nNewItem = m_nSelectedItem - 1;
|
|
if ( nNewItem < 0 )
|
|
nNewItem = Max( 0, m_Options.Count() - 1);
|
|
|
|
int nIndex = m_DangerousOptions.Find( nNewItem );
|
|
if (nIndex != m_DangerousOptions.InvalidIndex())
|
|
{
|
|
ShowWarning( nIndex, false );
|
|
return;
|
|
}
|
|
}
|
|
|
|
DecrementValueInner();
|
|
}
|
|
|
|
void IncrementValueInner()
|
|
{
|
|
if ( m_Options.Count() )
|
|
m_nSelectedItem = ( m_nSelectedItem + 1 ) % m_Options.Count();
|
|
if ( m_bInstantApply )
|
|
UpdateConVar();
|
|
}
|
|
|
|
void DecrementValueInner()
|
|
{
|
|
if ( --m_nSelectedItem < 0 )
|
|
m_nSelectedItem = Max( 0, m_Options.Count() - 1 );
|
|
if ( m_bInstantApply )
|
|
UpdateConVar();
|
|
}
|
|
|
|
void ShowWarning( int nIndex, bool bIncrement )
|
|
{
|
|
new GamepadUIGenericConfirmationPanel( GamepadUIOptionsPanel::GetInstance(), "OptionWarning", GamepadUIString( "#GameUI_Confirm" ).String(), m_DangerousOptionsText[nIndex].String(),
|
|
[this, bIncrement]() {
|
|
bIncrement ? this->IncrementValueInner() : this->DecrementValueInner();
|
|
}, true, true );
|
|
}
|
|
|
|
void AddDangerousOption( int option, const char *pszText )
|
|
{
|
|
m_DangerousOptions.AddToTail( option );
|
|
m_DangerousOptionsText.AddToTail( GamepadUIString( pszText ) );
|
|
}
|
|
|
|
void UpdateConVar() OVERRIDE
|
|
{
|
|
if ( IsDirty() )
|
|
{
|
|
if ( m_bSignOnly )
|
|
m_cvar.SetValue( abs( m_cvar.GetFloat() ) * m_Options[m_nSelectedItem].nValue );
|
|
else
|
|
m_cvar.SetValue( m_Options[ m_nSelectedItem ].nValue );
|
|
}
|
|
}
|
|
|
|
|
|
bool IsDirty() OVERRIDE
|
|
{
|
|
return m_cvar.IsValid() && GetCvarValue() != m_Options[m_nSelectedItem].nValue;
|
|
}
|
|
|
|
virtual void Paint()
|
|
{
|
|
BaseClass::Paint();
|
|
|
|
if ( m_nSelectedItem >= m_Options.Count() )
|
|
return;
|
|
|
|
GamepadUIString& strOption = m_Options[ m_nSelectedItem ].strOptionText;
|
|
ButtonState state = GetCurrentButtonState();
|
|
|
|
int nTextW, nTextH;
|
|
vgui::surface()->GetTextSize( m_hTextFont, strOption.String(), nTextW, nTextH );
|
|
|
|
int nScrollerSize = vgui::surface()->GetCharacterWidth( m_hTextFont, L'<' ) + vgui::surface()->GetCharacterWidth( m_hTextFont, L' ' );
|
|
|
|
int nTextY = m_flHeight / 2 - nTextH / 2 + m_flTextOffsetY;
|
|
|
|
vgui::surface()->DrawSetTextFont( m_hTextFont );
|
|
if ( state != ButtonStates::Out )
|
|
{
|
|
vgui::surface()->DrawSetTextPos( m_flWidth - m_flTextOffsetX - nTextW - 2 * nScrollerSize, nTextY );
|
|
vgui::surface()->DrawPrintText( L"< ", 2 );
|
|
}
|
|
vgui::surface()->DrawSetTextPos( m_flWidth - m_flTextOffsetX - nTextW - nScrollerSize, nTextY );
|
|
vgui::surface()->DrawPrintText( strOption.String(), strOption.Length() );
|
|
if ( state != ButtonStates::Out )
|
|
{
|
|
vgui::surface()->DrawSetTextPos( m_flWidth - m_flTextOffsetX - nScrollerSize, nTextY );
|
|
vgui::surface()->DrawPrintText( L" >", 2 );
|
|
}
|
|
}
|
|
|
|
void ClearOptions()
|
|
{
|
|
m_Options.RemoveAll();
|
|
}
|
|
|
|
void AddOptionItem( GamepadUIOption option )
|
|
{
|
|
m_Options.AddToTail( option );
|
|
}
|
|
|
|
int GetOptionCount()
|
|
{
|
|
return m_Options.Count();
|
|
}
|
|
|
|
int GetCvarValue()
|
|
{
|
|
if ( m_bSignOnly )
|
|
return (int)Sign( m_cvar.GetFloat() );
|
|
else
|
|
return m_cvar.GetInt();
|
|
}
|
|
|
|
void SetToDefault() OVERRIDE
|
|
{
|
|
if ( m_cvar.IsValid() )
|
|
{
|
|
const int nCurrentValue = GetCvarValue();
|
|
for ( int i = 0; i < m_Options.Count(); i++)
|
|
{
|
|
if ( m_Options[ i ].nValue == nCurrentValue )
|
|
m_nSelectedItem = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
GamepadUIOption *GetOption( int nIndex )
|
|
{
|
|
if ( nIndex < 0 || nIndex >= m_Options.Count() )
|
|
return NULL;
|
|
return &m_Options[ nIndex ];
|
|
}
|
|
|
|
bool IsConVarEnabled() const OVERRIDE
|
|
{
|
|
return !!m_Options[m_nSelectedItem].nValue;
|
|
}
|
|
|
|
private:
|
|
|
|
bool m_bSignOnly = false;
|
|
int m_nSelectedItem = 0;
|
|
CUtlVector< GamepadUIOption > m_Options;
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flClickPadding, "Button.Wheel.ClickPadding", "24", SchemeValueTypes::ProportionalFloat );
|
|
|
|
CUtlVector< int > m_DangerousOptions;
|
|
CUtlVector< GamepadUIString > m_DangerousOptionsText;
|
|
|
|
};
|
|
|
|
class GamepadUISlideySlide : public GamepadUIConvarButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUISlideySlide, GamepadUIConvarButton );
|
|
|
|
GamepadUISlideySlide( const char *pszCvar, const char* pszCvarDepends, bool bInstantApply, float flMin, float flMax, float flStep, int nTextPrecision, vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char *pSchemeFile, const char* pCommand, const char *pText, const char *pDescription )
|
|
: BaseClass( pszCvar, pszCvarDepends, bInstantApply, pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_flMin( flMin )
|
|
, m_flMax( flMax )
|
|
, m_flStep( flStep )
|
|
, nTextPrecision( nTextPrecision )
|
|
{
|
|
SetUseCaptureMouse( true );
|
|
}
|
|
|
|
void OnKeyCodePressed( vgui::KeyCode code )
|
|
{
|
|
ButtonCode_t buttonCode = GetBaseButtonCode( code );
|
|
switch ( buttonCode )
|
|
{
|
|
case KEY_LEFT:
|
|
case KEY_XBUTTON_LEFT:
|
|
|
|
#ifdef HL2_RETAIL // Steam input and Steam Controller are not supported in SDK2013 (Madi)
|
|
case STEAMCONTROLLER_DPAD_LEFT:
|
|
#endif
|
|
{
|
|
float flValue = Clamp( m_flValue - (m_bFineAdjust ? m_flMouseStep : m_flStep), m_flMin, m_flMax );
|
|
if (flValue != m_flValue)
|
|
{
|
|
if (m_sSliderSoundName != UTL_INVAL_SYMBOL)
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sSliderSoundName ) );
|
|
m_flValue = flValue;
|
|
if ( m_bInstantApply )
|
|
UpdateConVar();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
case KEY_XBUTTON_RIGHT:
|
|
|
|
#ifdef HL2_RETAIL
|
|
case STEAMCONTROLLER_DPAD_RIGHT:
|
|
#endif
|
|
{
|
|
float flValue = Clamp( m_flValue + (m_bFineAdjust ? m_flMouseStep : m_flStep), m_flMin, m_flMax );
|
|
if (flValue != m_flValue)
|
|
{
|
|
if (m_sSliderSoundName != UTL_INVAL_SYMBOL)
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sSliderSoundName ) );
|
|
m_flValue = flValue;
|
|
if ( m_bInstantApply )
|
|
UpdateConVar();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_RSHIFT:
|
|
case KEY_LSHIFT:
|
|
{
|
|
m_bFineAdjust = true;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OnKeyCodeReleased( vgui::KeyCode code )
|
|
{
|
|
ButtonCode_t buttonCode = GetBaseButtonCode( code );
|
|
switch ( buttonCode )
|
|
{
|
|
case KEY_RSHIFT:
|
|
case KEY_LSHIFT:
|
|
{
|
|
m_bFineAdjust = false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodeReleased( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OnMousePressed( vgui::MouseCode code )
|
|
{
|
|
int x, y;
|
|
GetPos( x, y );
|
|
|
|
int mx, my;
|
|
g_pVGuiInput->GetCursorPos( mx, my );
|
|
|
|
int iSliderEnd = x + m_flWidth - m_flTextOffsetX;
|
|
int iSliderStart = iSliderEnd - m_flSliderWidth;
|
|
|
|
// Allow some wiggle room
|
|
if (mx > iSliderStart-4 && mx < iSliderEnd+4)
|
|
{
|
|
// Start influencing the slider value
|
|
BaseClass::OnMousePressed( code );
|
|
}
|
|
}
|
|
|
|
void SetMouseStep( float flStep )
|
|
{
|
|
m_flMouseStep = flStep;
|
|
}
|
|
|
|
void OnThink()
|
|
{
|
|
if (IsSelected())
|
|
{
|
|
int x, y;
|
|
GetPos( x, y );
|
|
|
|
int mx, my;
|
|
g_pVGuiInput->GetCursorPos( mx, my );
|
|
|
|
int iSliderEnd = x + m_flWidth - m_flTextOffsetX;
|
|
int iSliderStart = iSliderEnd - m_flSliderWidth;
|
|
|
|
// Set the slider value to whichever step is closest to the cursor
|
|
float flProgress = RemapValClamped( mx, iSliderStart, iSliderEnd, m_flMin, m_flMax );
|
|
|
|
float flRemainder = fmodf( flProgress, m_flMouseStep );
|
|
flProgress -= flRemainder;
|
|
|
|
if ((flRemainder / m_flMouseStep) > 0.5f)
|
|
flProgress += m_flMouseStep;
|
|
|
|
if (flProgress != m_flValue)
|
|
{
|
|
if (m_sSliderSoundName != UTL_INVAL_SYMBOL && m_flLastSliderSoundTime < GamepadUI::GetInstance().GetTime())
|
|
{
|
|
vgui::surface()->PlaySound( g_ButtonSoundNames.String( m_sSliderSoundName ) );
|
|
m_flLastSliderSoundTime = GamepadUI::GetInstance().GetTime() + 0.04f; // Arbitrary sound cooldown
|
|
}
|
|
m_flValue = flProgress;
|
|
if ( m_bInstantApply )
|
|
UpdateConVar();
|
|
}
|
|
}
|
|
|
|
BaseClass::OnThink();
|
|
}
|
|
|
|
void ApplySchemeSettings(vgui::IScheme* pScheme)
|
|
{
|
|
BaseClass::ApplySchemeSettings(pScheme);
|
|
|
|
const char *pSliderSound = pScheme->GetResourceString( "Slider.Sound.Adjust" );
|
|
if (pSliderSound && *pSliderSound)
|
|
m_sSliderSoundName = g_ButtonSoundNames.AddString( pSliderSound );
|
|
}
|
|
|
|
void UpdateConVar() OVERRIDE
|
|
{
|
|
if ( IsDirty() )
|
|
m_cvar.SetValue( m_flValue );
|
|
}
|
|
|
|
bool IsDirty() OVERRIDE
|
|
{
|
|
return m_cvar.IsValid() && m_cvar.GetFloat() != m_flValue;
|
|
}
|
|
|
|
float GetMultiplier() const
|
|
{
|
|
return ( m_flValue - m_flMin ) / ( m_flMax - m_flMin );
|
|
}
|
|
|
|
virtual void Paint()
|
|
{
|
|
BaseClass::Paint();
|
|
|
|
if ( nTextPrecision >= 0 )
|
|
{
|
|
wchar_t szValue[ 256 ];
|
|
V_snwprintf( szValue, sizeof( szValue ), L"%.*f", nTextPrecision, m_flValue );
|
|
|
|
int w, h;
|
|
vgui::surface()->GetTextSize( m_hTextFont, szValue, w, h );
|
|
vgui::surface()->DrawSetTextPos( m_flWidth - 2 * m_flTextOffsetX - m_flSliderWidth - w, m_flHeight / 2 - h / 2 );
|
|
vgui::surface()->DrawPrintText( szValue, V_wcslen( szValue ) );
|
|
}
|
|
|
|
vgui::surface()->DrawSetColor( m_colSliderBacking );
|
|
vgui::surface()->DrawFilledRect( m_flWidth - m_flTextOffsetX - m_flSliderWidth, m_flHeight / 2 - m_flSliderHeight / 2, m_flWidth - m_flTextOffsetX, m_flHeight / 2 + m_flSliderHeight / 2 );
|
|
|
|
float flFill = m_flSliderWidth * ( 1.0f - GetMultiplier() );
|
|
|
|
vgui::surface()->DrawSetColor( m_colSliderFill );
|
|
vgui::surface()->DrawFilledRect( m_flWidth - m_flTextOffsetX - m_flSliderWidth, m_flHeight / 2 - m_flSliderHeight / 2, m_flWidth - m_flTextOffsetX - flFill, m_flHeight / 2 + m_flSliderHeight / 2 );
|
|
}
|
|
|
|
void SetToDefault() OVERRIDE
|
|
{
|
|
if ( m_cvar.IsValid() )
|
|
m_flValue = m_cvar.GetFloat();
|
|
}
|
|
|
|
void RunAnimations( ButtonState state ) OVERRIDE
|
|
{
|
|
BaseClass::RunAnimations( state );
|
|
|
|
GAMEPADUI_RUN_ANIMATION_COMMAND( m_colSliderBacking, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GAMEPADUI_RUN_ANIMATION_COMMAND( m_colSliderFill, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
}
|
|
|
|
private:
|
|
|
|
float m_flValue = 0.0f;
|
|
|
|
float m_flMin = 0.0f;
|
|
float m_flMax = 1.0f;
|
|
float m_flStep = 0.1f;
|
|
|
|
int nTextPrecision = -1;
|
|
|
|
CUtlSymbol m_sSliderSoundName = UTL_INVAL_SYMBOL;
|
|
float m_flLastSliderSoundTime = 0.0f;
|
|
|
|
float m_flMouseStep = 0.1f;
|
|
bool m_bFineAdjust = false;
|
|
|
|
GAMEPADUI_BUTTON_ANIMATED_PROPERTY( Color, m_colSliderBacking, "Slider.Backing", "255 255 255 22", SchemeValueTypes::Color );
|
|
GAMEPADUI_BUTTON_ANIMATED_PROPERTY( Color, m_colSliderFill, "Slider.Fill", "255 255 255 255", SchemeValueTypes::Color );
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flSliderWidth, "Slider.Width", "160", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flSliderHeight, "Slider.Height", "11", SchemeValueTypes::ProportionalFloat );
|
|
|
|
};
|
|
|
|
class GamepadUISkillySkill : public GamepadUIOptionButton
|
|
{
|
|
public:
|
|
DECLARE_CLASS_SIMPLE( GamepadUISkillySkill, GamepadUIOptionButton );
|
|
|
|
GamepadUISkillySkill( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const char* pText, const char* pDescription, const char *pImage, int nSkill )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_Image( pImage )
|
|
, m_nSkill( nSkill )
|
|
{
|
|
}
|
|
|
|
GamepadUISkillySkill( vgui::Panel* pParent, vgui::Panel* pActionSignalTarget, const char* pSchemeFile, const char* pCommand, const wchar* pText, const wchar* pDescription, const char *pImage, int nSkill )
|
|
: BaseClass( pParent, pActionSignalTarget, pSchemeFile, pCommand, pText, pDescription )
|
|
, m_Image( pImage )
|
|
, m_nSkill( nSkill )
|
|
{
|
|
}
|
|
|
|
void RunAnimations( ButtonState state ) OVERRIDE
|
|
{
|
|
BaseClass::RunAnimations( state );
|
|
|
|
GAMEPADUI_RUN_ANIMATION_COMMAND( m_colTitleBackground, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GAMEPADUI_RUN_ANIMATION_COMMAND( m_colDescriptionBackground, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
GAMEPADUI_RUN_ANIMATION_COMMAND( m_colImage, vgui::AnimationController::INTERPOLATOR_LINEAR );
|
|
}
|
|
|
|
ButtonState GetCurrentButtonState() OVERRIDE
|
|
{
|
|
if ( _gamepadui_skill.GetInt() == m_nSkill )
|
|
return ButtonState::Pressed;
|
|
|
|
return BaseClass::GetCurrentButtonState();
|
|
}
|
|
|
|
void NavigateTo() OVERRIDE
|
|
{
|
|
BaseClass::NavigateTo();
|
|
|
|
_gamepadui_skill.SetValue( m_nSkill );
|
|
}
|
|
|
|
void DoClick() OVERRIDE
|
|
{
|
|
BaseClass::DoClick();
|
|
|
|
_gamepadui_skill.SetValue( m_nSkill );
|
|
}
|
|
|
|
void Paint() OVERRIDE
|
|
{
|
|
PaintButton();
|
|
|
|
int nTextSizeX, nTextSizeY;
|
|
vgui::surface()->GetTextSize(GetCurrentButtonState() == ButtonStates::Out ? m_hTextFont : m_hTextFontOver, m_strButtonText.String(), nTextSizeX, nTextSizeY);
|
|
int y2 = m_flTextOffsetY + m_flHeight / 2 + nTextSizeY / 2;
|
|
|
|
vgui::surface()->DrawSetColor(m_colTitleBackground);
|
|
vgui::surface()->DrawFilledRect(0, m_flTextOffsetY + m_flHeight / 2 - nTextSizeY / 2, nTextSizeX + m_flTextOffsetX * 2, y2);
|
|
|
|
vgui::surface()->DrawSetColor(m_colDescriptionBackground);
|
|
vgui::surface()->DrawFilledRect(0, y2, m_flWidth, m_flHeight + m_flExtraHeight);
|
|
|
|
vgui::surface()->DrawSetColor( m_colImage );
|
|
vgui::surface()->DrawSetTexture( m_Image );
|
|
vgui::surface()->DrawTexturedRect( m_flWidth / 2 - m_flImageWidth / 2, 0, m_flWidth / 2 + m_flImageWidth / 2, m_flImageHeight );
|
|
vgui::surface()->DrawSetTexture( 0 );
|
|
|
|
PaintText();
|
|
|
|
PaintBorders();
|
|
}
|
|
|
|
virtual bool ShowDescriptionAtFooter() { return false; }
|
|
|
|
private:
|
|
GamepadUIImage m_Image;
|
|
|
|
int m_nSkill = 0;
|
|
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flImageWidth, "Button.Image.Width", "40", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_PANEL_PROPERTY( float, m_flImageHeight, "Button.Image.Height", "40", SchemeValueTypes::ProportionalFloat );
|
|
GAMEPADUI_BUTTON_ANIMATED_PROPERTY( Color, m_colImage, "Button.Image", "255 255 255 255", SchemeValueTypes::Color );
|
|
GAMEPADUI_BUTTON_ANIMATED_PROPERTY( Color, m_colTitleBackground, "Button.Title.Background", "0 0 0 0", SchemeValueTypes::Color );
|
|
GAMEPADUI_BUTTON_ANIMATED_PROPERTY( Color, m_colDescriptionBackground, "Button.Description.Background", "0 0 0 0", SchemeValueTypes::Color );
|
|
};
|
|
|
|
struct AAMode_t
|
|
{
|
|
GamepadUIString strName;
|
|
int m_nNumSamples;
|
|
int m_nQualityLevel;
|
|
};
|
|
|
|
int g_nNumAAModes = 0;
|
|
AAMode_t g_AAModes[16];
|
|
|
|
void InitAAModes()
|
|
{
|
|
static bool s_bAAModesInitialized = false;
|
|
if ( s_bAAModesInitialized )
|
|
return;
|
|
s_bAAModesInitialized = true;
|
|
|
|
g_nNumAAModes = 0;
|
|
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_None";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 1;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 0;
|
|
g_nNumAAModes++;
|
|
|
|
if ( materials->SupportsMSAAMode(2) )
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_2X";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 2;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 0;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsMSAAMode(4) )
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_4X";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 4;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 0;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsMSAAMode(6) )
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_6X";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 6;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 0;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsCSAAMode(4, 2) ) // nVidia CSAA "8x"
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_8X_CSAA";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 4;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 2;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsCSAAMode(4, 4) ) // nVidia CSAA "16x"
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_16X_CSAA";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 4;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 4;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsMSAAMode(8) )
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_8X";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 8;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 0;
|
|
g_nNumAAModes++;
|
|
}
|
|
|
|
if ( materials->SupportsCSAAMode(8, 2) ) // nVidia CSAA "16xQ"
|
|
{
|
|
g_AAModes[g_nNumAAModes].strName = "#GameUI_16XQ_CSAA";
|
|
g_AAModes[g_nNumAAModes].m_nNumSamples = 8;
|
|
g_AAModes[g_nNumAAModes].m_nQualityLevel = 2;
|
|
g_nNumAAModes++;
|
|
}
|
|
}
|
|
|
|
struct RatioToAspectMode_t
|
|
{
|
|
int anamorphic;
|
|
float aspectRatio;
|
|
};
|
|
RatioToAspectMode_t g_RatioToAspectModes[] =
|
|
{
|
|
{ 0, 4.0f / 3.0f },
|
|
{ 1, 16.0f / 9.0f },
|
|
{ 2, 16.0f / 10.0f },
|
|
{ 2, 1.0f },
|
|
};
|
|
|
|
int GetScreenAspectMode( int width, int height )
|
|
{
|
|
float aspectRatio = (float)width / (float)height;
|
|
|
|
// just find the closest ratio
|
|
float closestAspectRatioDist = 99999.0f;
|
|
int closestAnamorphic = 0;
|
|
for (int i = 0; i < ARRAYSIZE(g_RatioToAspectModes); i++)
|
|
{
|
|
float dist = fabs( g_RatioToAspectModes[i].aspectRatio - aspectRatio );
|
|
if (dist < closestAspectRatioDist)
|
|
{
|
|
closestAspectRatioDist = dist;
|
|
closestAnamorphic = g_RatioToAspectModes[i].anamorphic;
|
|
}
|
|
}
|
|
|
|
return closestAnamorphic;
|
|
}
|
|
|
|
void OnResolutionsNeedUpdate( IConVar *var, const char *pOldValue, float flOldValue )
|
|
{
|
|
GamepadUIOptionsPanel* pOptionsPanel = GamepadUIOptionsPanel::GetInstance();
|
|
if ( pOptionsPanel )
|
|
pOptionsPanel->UpdateResolutions();
|
|
}
|
|
|
|
static int GetSDLDisplayIndex()
|
|
{
|
|
#if defined( USE_SDL )
|
|
static ConVarRef sdl_displayindex( "sdl_displayindex" );
|
|
|
|
Assert( sdl_displayindex.IsValid() );
|
|
return sdl_displayindex.IsValid() ? sdl_displayindex.GetInt() : 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static int GetSDLDisplayIndexFullscreen()
|
|
{
|
|
#if defined( USE_SDL )
|
|
static ConVarRef sdl_displayindex_fullscreen( "sdl_displayindex_fullscreen" );
|
|
|
|
Assert( sdl_displayindex_fullscreen.IsValid() );
|
|
return sdl_displayindex_fullscreen.IsValid() ? sdl_displayindex_fullscreen.GetInt() : -1;
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int GetCurrentWaterDetail()
|
|
{
|
|
ConVarRef r_waterforceexpensive( "r_waterforceexpensive" );
|
|
ConVarRef r_waterforcereflectentities( "r_waterforcereflectentities" );
|
|
|
|
if ( r_waterforcereflectentities.GetBool() )
|
|
return 2;
|
|
|
|
if ( r_waterforceexpensive.GetBool() )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GetCurrentShadowDetail()
|
|
{
|
|
ConVarRef r_shadowrendertotexture( "r_shadowrendertotexture" );
|
|
ConVarRef r_flashlightdepthtexture( "r_flashlightdepthtexture" );
|
|
|
|
if ( r_flashlightdepthtexture.GetBool() )
|
|
return 2;
|
|
|
|
if ( r_shadowrendertotexture.GetBool() )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GetCurrentAntialiasing()
|
|
{
|
|
ConVarRef mat_antialias( "mat_antialias" );
|
|
ConVarRef mat_aaquality( "mat_aaquality" );
|
|
int nAASamples = mat_antialias.GetInt();
|
|
int nAAQuality = mat_aaquality.GetInt();
|
|
|
|
// Run through the AA Modes supported by the device
|
|
for ( int nAAMode = 0; nAAMode < g_nNumAAModes; nAAMode++ )
|
|
{
|
|
// If we found the mode that matches what we're looking for, return the index
|
|
if ( ( g_AAModes[nAAMode].m_nNumSamples == nAASamples) && ( g_AAModes[nAAMode].m_nQualityLevel == nAAQuality) )
|
|
{
|
|
return nAAMode;
|
|
}
|
|
}
|
|
|
|
return 0; // Didn't find what we're looking for, so no AA
|
|
}
|
|
|
|
int GetCurrentAspectRatio()
|
|
{
|
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
|
return GetScreenAspectMode( config.m_VideoMode.m_Width, config.m_VideoMode.m_Height );
|
|
}
|
|
|
|
int GetCurrentDisplayMode()
|
|
{
|
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
|
if ( config.Windowed() )
|
|
{
|
|
#ifdef HL2_RETAIL // SDK2013 does not natively support borderless windowed (Madi)
|
|
if ( config.NoWindowBorder() )
|
|
return 1;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HL2_RETAIL
|
|
return 2 + GetSDLDisplayIndex();
|
|
#else
|
|
// TODO FIXME: SDK2013 uses the inverse here...1 is "windowed" and 0 is "fullscreen" in materialsystem.
|
|
// but our values mean the opposite in gamepadUI code. (Madi)
|
|
return 1 + GetSDLDisplayIndex();
|
|
#endif
|
|
}
|
|
|
|
|
|
int GetCurrentSoundQuality()
|
|
{
|
|
ConVarRef snd_pitchquality( "snd_pitchquality" );
|
|
ConVarRef dsp_slow_cpu( "dsp_slow_cpu" );
|
|
|
|
if ( snd_pitchquality.GetInt() )
|
|
return 2;
|
|
|
|
if ( !dsp_slow_cpu.GetBool() )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int GetCurrentCloseCaptions()
|
|
{
|
|
ConVarRef closecaption( "closecaption" );
|
|
ConVarRef cc_subtitles( "cc_subtitles" );
|
|
|
|
if ( closecaption.GetBool() )
|
|
return cc_subtitles.GetBool() ? 1 : 2;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HL2_RETAIL
|
|
int GetCurrentHudAspectRatio()
|
|
{
|
|
ConVarRef hud_aspect( "hud_aspect" );
|
|
float flHudAspect = hud_aspect.GetFloat();
|
|
if ( flHudAspect > 0.0f )
|
|
{
|
|
if ( flHudAspect < 1.4f )
|
|
return 1;
|
|
else if (flHudAspect < 1.7f)
|
|
return 3;
|
|
else
|
|
return 2;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int GetCurrentSkill()
|
|
{
|
|
ConVarRef skill( "skill" );
|
|
return skill.GetInt();
|
|
}
|
|
|
|
void FlushPendingAntialiasing()
|
|
{
|
|
ConVarRef mat_antialias( "mat_antialias" );
|
|
ConVarRef mat_aaquality( "mat_aaquality" );
|
|
|
|
int nAAMode = Clamp( _gamepadui_antialiasing.GetInt(), 0, Max( 0, g_nNumAAModes - 1 ) );
|
|
if ( mat_antialias.GetInt() != g_AAModes[ nAAMode ].m_nNumSamples )
|
|
mat_antialias.SetValue( g_AAModes[ nAAMode ].m_nNumSamples );
|
|
|
|
if ( mat_aaquality.GetInt() != g_AAModes[ nAAMode ].m_nQualityLevel )
|
|
mat_aaquality.SetValue( g_AAModes[ nAAMode ].m_nQualityLevel );
|
|
}
|
|
|
|
void FlushPendingWaterDetail()
|
|
{
|
|
ConVarRef r_waterforceexpensive( "r_waterforceexpensive" );
|
|
ConVarRef r_waterforcereflectentities( "r_waterforcereflectentities" );
|
|
|
|
bool bForceExpensive = _gamepadui_water_detail.GetInt() > 0;
|
|
bool bForceReflect = _gamepadui_water_detail.GetInt() > 1;
|
|
|
|
if ( r_waterforceexpensive.GetBool() != bForceExpensive )
|
|
r_waterforceexpensive.SetValue( bForceExpensive );
|
|
|
|
if ( r_waterforcereflectentities.GetBool() != bForceReflect )
|
|
r_waterforcereflectentities.SetValue(bForceReflect);
|
|
}
|
|
|
|
void FlushPendingShadowDetail()
|
|
{
|
|
ConVarRef r_shadowrendertotexture( "r_shadowrendertotexture" );
|
|
ConVarRef r_flashlightdepthtexture( "r_flashlightdepthtexture" );
|
|
|
|
bool bShadowRenderToTexture = _gamepadui_shadow_detail.GetInt() > 0;
|
|
bool bFlashlightDepthTexture = _gamepadui_shadow_detail.GetInt() > 1;
|
|
|
|
if ( r_shadowrendertotexture.GetBool() != bShadowRenderToTexture )
|
|
r_shadowrendertotexture.SetValue( bShadowRenderToTexture );
|
|
|
|
if ( r_flashlightdepthtexture.GetBool() != bFlashlightDepthTexture )
|
|
r_flashlightdepthtexture.SetValue( bFlashlightDepthTexture );
|
|
}
|
|
|
|
void FlushPendingResolution()
|
|
{
|
|
GamepadUIOptionsPanel *pOptions = GamepadUIOptionsPanel::GetInstance();
|
|
if ( !pOptions )
|
|
return;
|
|
|
|
GamepadUIWheelyWheel *pResButton = pOptions->GetResolutionButton();
|
|
if ( !pResButton )
|
|
return;
|
|
|
|
GamepadUIOption *pOption = pResButton->GetOption( _gamepadui_resolution.GetInt() );
|
|
if ( !pOption )
|
|
return;
|
|
|
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
|
bool bDirty = false;
|
|
|
|
if ( GetCurrentDisplayMode() != _gamepadui_displaymode.GetInt() )
|
|
bDirty = true;
|
|
|
|
if ( pOption->userdata.nWidth != config.m_VideoMode.m_Width || pOption->userdata.nHeight != config.m_VideoMode.m_Height )
|
|
bDirty = true;
|
|
|
|
if ( !bDirty )
|
|
return;
|
|
|
|
const int nWidth = pOption->userdata.nWidth;
|
|
const int nHeight = pOption->userdata.nHeight;
|
|
#ifdef HL2_RETAIL
|
|
const int nWindowed = _gamepadui_displaymode.GetInt() < 2 ? 1 : 0;
|
|
const int nBorderless = _gamepadui_displaymode.GetInt() == 1 ? 1 : 0;
|
|
#else
|
|
// TODO FIXME: SDK2013 uses the inverse here...1 is "windowed" and 0 is "fullscreen" in materialsystem.
|
|
// but our values mean the opposite in gamepadUI code. (Madi)
|
|
const int nWindowed = _gamepadui_displaymode.GetInt() == 1 ? 0 /* fullscreen*/ : 1 /* windowed */;
|
|
#endif
|
|
|
|
char szCmd[ 256 ];
|
|
|
|
#ifdef HL2_RETAIL
|
|
Q_snprintf( szCmd, sizeof( szCmd ), "mat_setvideomode %i %i %i %i\n", nWidth, nHeight, nWindowed, nBorderless );
|
|
#else
|
|
Q_snprintf( szCmd, sizeof( szCmd ), "mat_setvideomode %i %i %i\n", nWidth, nHeight, nWindowed );
|
|
#endif
|
|
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( szCmd );
|
|
}
|
|
|
|
void FlushPendingSoundQuality()
|
|
{
|
|
ConVarRef snd_pitchquality( "snd_pitchquality" );
|
|
ConVarRef dsp_slow_cpu( "dsp_slow_cpu" );
|
|
ConVarRef dsp_enhance_stereo( "dsp_enhance_stereo" );
|
|
ConVarRef snd_surround_speakers( "snd_surround_speakers" );
|
|
|
|
int nSoundQuality = _gamepadui_sound_quality.GetInt();
|
|
switch ( nSoundQuality )
|
|
{
|
|
default:
|
|
case 2:
|
|
// Headphones at high quality get enhanced stereo turned on
|
|
dsp_enhance_stereo.SetValue( snd_surround_speakers.GetInt() == 0 );
|
|
snd_pitchquality.SetValue( true );
|
|
dsp_slow_cpu.SetValue( false );
|
|
break;
|
|
case 1:
|
|
snd_pitchquality.SetValue( false );
|
|
dsp_slow_cpu.SetValue( false );
|
|
break;
|
|
case 0:
|
|
snd_pitchquality.SetValue( false );
|
|
dsp_slow_cpu.SetValue( true );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FlushPendingCloseCaptions()
|
|
{
|
|
ConVarRef closecaption( "closecaption" );
|
|
ConVarRef cc_subtitles( "cc_subtitles" );
|
|
|
|
int nCloseCaptions = _gamepadui_closecaptions.GetInt();
|
|
bool bCloseCaptionConvarValue = false;
|
|
switch ( nCloseCaptions )
|
|
{
|
|
default:
|
|
case 2:
|
|
cc_subtitles.SetValue( false );
|
|
bCloseCaptionConvarValue = true;
|
|
break;
|
|
case 1:
|
|
cc_subtitles.SetValue(true);
|
|
bCloseCaptionConvarValue = true;
|
|
break;
|
|
case 0:
|
|
cc_subtitles.SetValue(false);
|
|
bCloseCaptionConvarValue = false;
|
|
break;
|
|
}
|
|
|
|
// Stuff the close caption change to the console so that it can be
|
|
// sent to the server (FCVAR_USERINFO) so that you don't have to restart
|
|
// the level for the change to take effect.
|
|
char szCmd[ 64 ];
|
|
Q_snprintf( szCmd, sizeof( szCmd ), "closecaption %i\n", bCloseCaptionConvarValue ? 1 : 0 );
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( szCmd );
|
|
}
|
|
|
|
#ifdef HL2_RETAIL
|
|
void FlushPendingHudAspectRatio()
|
|
{
|
|
ConVarRef hud_aspect( "hud_aspect" );
|
|
|
|
int nHudAspect = _gamepadui_hudaspect.GetInt();
|
|
switch ( nHudAspect )
|
|
{
|
|
default:
|
|
case 0:
|
|
hud_aspect.SetValue( 0.0f );
|
|
break;
|
|
case 1:
|
|
hud_aspect.SetValue( 4.0f / 3.0f );
|
|
break;
|
|
case 2:
|
|
hud_aspect.SetValue( 16.0f / 9.0f );
|
|
break;
|
|
case 3:
|
|
hud_aspect.SetValue( 16.0f / 10.0f );
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void FlushPendingSkill()
|
|
{
|
|
ConVarRef skill( "skill" );
|
|
skill.SetValue( _gamepadui_skill.GetInt() );
|
|
}
|
|
|
|
void UpdateHelperConvars()
|
|
{
|
|
_gamepadui_water_detail.SetValue( GetCurrentWaterDetail() );
|
|
_gamepadui_shadow_detail.SetValue( GetCurrentShadowDetail() );
|
|
_gamepadui_antialiasing.SetValue( GetCurrentAntialiasing() );
|
|
_gamepadui_aspectratio.SetValue( GetCurrentAspectRatio() );
|
|
_gamepadui_displaymode.SetValue( GetCurrentDisplayMode() );
|
|
_gamepadui_sound_quality.SetValue( GetCurrentSoundQuality() );
|
|
_gamepadui_closecaptions.SetValue( GetCurrentCloseCaptions() );
|
|
#ifdef HL2_RETAIL
|
|
_gamepadui_hudaspect.SetValue( GetCurrentHudAspectRatio() );
|
|
#endif
|
|
_gamepadui_skill.SetValue( GetCurrentSkill() );
|
|
}
|
|
|
|
void FlushHelperConVars()
|
|
{
|
|
FlushPendingWaterDetail();
|
|
FlushPendingShadowDetail();
|
|
FlushPendingAntialiasing();
|
|
FlushPendingResolution();
|
|
FlushPendingSoundQuality();
|
|
FlushPendingCloseCaptions();
|
|
#ifdef HL2_RETAIL
|
|
FlushPendingHudAspectRatio();
|
|
#endif
|
|
FlushPendingSkill();
|
|
}
|
|
|
|
GamepadUIOptionsPanel::GamepadUIOptionsPanel( vgui::Panel* pParent, const char* pPanelName )
|
|
: BaseClass( pParent, pPanelName )
|
|
{
|
|
s_pOptionsPanel = this;
|
|
|
|
vgui::HScheme Scheme = vgui::scheme()->LoadSchemeFromFileEx( GamepadUI::GetInstance().GetSizingVPanel(), GAMEPADUI_DEFAULT_PANEL_SCHEME, "SchemePanel" );
|
|
SetScheme( Scheme );
|
|
|
|
GetFrameTitle() = GamepadUIString( "#GameUI_Options" );
|
|
SetFooterButtons( FooterButtons::Apply | FooterButtons::Back );
|
|
|
|
Activate();
|
|
|
|
InitAAModes();
|
|
UpdateHelperConvars();
|
|
|
|
LoadOptionTabs( GAMEPADUI_OPTIONS_FILE );
|
|
FillInBindings();
|
|
|
|
SetActiveTab( GetActiveTab() );
|
|
|
|
UpdateGradients();
|
|
|
|
m_pScrollBar = new GamepadUIScrollBar(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemescrollbar.res",
|
|
NULL, false );
|
|
}
|
|
|
|
GamepadUIOptionsPanel::~GamepadUIOptionsPanel()
|
|
{
|
|
if (s_pOptionsPanel == this)
|
|
{
|
|
s_pOptionsPanel = NULL;
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnThink()
|
|
{
|
|
BaseClass::OnThink();
|
|
|
|
LayoutCurrentTab();
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::Paint()
|
|
{
|
|
BaseClass::Paint();
|
|
|
|
if ( !m_nTabCount )
|
|
return;
|
|
|
|
const int nLastTabX = m_flTabsOffsetX + m_nTabCount * m_Tabs[0].pTabButton->GetWide();
|
|
|
|
const int nTabSize = m_Tabs[0].pTabButton->GetTall();
|
|
const int nGlyphSize = nTabSize * 0.90f;
|
|
const int nGlyphOffsetX = nGlyphSize / 4.0f;
|
|
const int nGlyphOffsetY = nTabSize - nGlyphSize;
|
|
|
|
if ( m_leftGlyph.SetupGlyph( nGlyphSize, "menu_lb", true ) )
|
|
m_leftGlyph.PaintGlyph( m_flTabsOffsetX - nGlyphSize - nGlyphOffsetX, m_flTabsOffsetY + nGlyphOffsetY / 2, nGlyphSize, 255 );
|
|
|
|
if ( m_rightGlyph.SetupGlyph( nGlyphSize, "menu_rb", true ) )
|
|
m_rightGlyph.PaintGlyph( nLastTabX + nGlyphOffsetX, m_flTabsOffsetY + nGlyphOffsetY / 2, nGlyphSize, 255 );
|
|
|
|
// Draw description
|
|
if (m_strOptionDescription != NULL)
|
|
{
|
|
int nParentW, nParentH;
|
|
GetParent()->GetSize( nParentW, nParentH );
|
|
|
|
float flX = m_flFooterButtonsOffsetX + m_nFooterButtonWidth + m_flFooterButtonsSpacing;
|
|
float flY = nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight;
|
|
|
|
vgui::surface()->DrawSetTextColor( Color( 255, 255, 255, 255 ) );
|
|
vgui::surface()->DrawSetTextFont( m_hDescFont );
|
|
vgui::surface()->DrawSetTextPos( flX, flY );
|
|
|
|
int nMaxWidth = nParentW - flX - (m_flFooterButtonsOffsetX + m_nFooterButtonWidth + m_flFooterButtonsSpacing);
|
|
|
|
DrawPrintWrappedText( m_hDescFont, flX, flY, m_strOptionDescription->String(), m_strOptionDescription->Length(), nMaxWidth, true );
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::UpdateGradients()
|
|
{
|
|
const float flTime = GamepadUI::GetInstance().GetTime();
|
|
GamepadUI::GetInstance().GetGradientHelper()->ResetTargets( flTime );
|
|
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Up, { 1.0f, 1.0f }, flTime );
|
|
GamepadUI::GetInstance().GetGradientHelper()->SetTargetGradient( GradientSide::Down, { 1.0f, 0.5f }, flTime );
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::LayoutCurrentTab()
|
|
{
|
|
int nParentW, nParentH;
|
|
GetParent()->GetSize( nParentW, nParentH );
|
|
|
|
int x = m_flTabsOffsetX;
|
|
int y = 0;
|
|
for ( int i = 0; i < m_nTabCount; i++ )
|
|
{
|
|
GamepadUITab& tab = m_Tabs[ i ];
|
|
tab.pTabButton->SetPos( x, m_flTabsOffsetY );
|
|
tab.pTabButton->SetVisible( true );
|
|
x += tab.pTabButton->GetWide();
|
|
y = m_flTabsOffsetY + tab.pTabButton->GetTall();
|
|
|
|
for ( GamepadUIButton *pButton : tab.pButtons )
|
|
pButton->SetVisible( false );
|
|
}
|
|
|
|
int nActiveTab = GetActiveTab();
|
|
|
|
int i = 0;
|
|
int previousxSizes = 0;
|
|
int previousySizes = 0;
|
|
int previousxHeight = 0;
|
|
int buttonWide = 0;
|
|
for ( GamepadUIOptionButton *pButton : m_Tabs[ nActiveTab ].pButtons )
|
|
{
|
|
int fade = 255;
|
|
|
|
int buttonY = y;
|
|
int buttonX = m_flTabsOffsetX;
|
|
if ( pButton->IsHorizontal() )
|
|
{
|
|
buttonX += previousxSizes;
|
|
}
|
|
else if (previousxHeight > 0)
|
|
{
|
|
// We just ended a row, append its height
|
|
previousySizes += previousxHeight;
|
|
previousxHeight = 0;
|
|
previousxSizes = 0;
|
|
}
|
|
|
|
{
|
|
buttonY = y + previousySizes - m_Tabs[nActiveTab].ScrollState.GetScrollProgress();
|
|
if ( buttonY < y )
|
|
fade = RemapValClamped( y - buttonY, abs(m_flOptionsFade - pButton->GetTall()), 0, 0, 255 );
|
|
else if ( buttonY > ( nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight - m_flOptionsFade ) )
|
|
fade = RemapValClamped( ( nParentH - m_flFooterButtonsOffsetY - m_nFooterButtonHeight ) - ( buttonY + pButton->GetTall() ), 0, m_flOptionsFade, 0, 255 );
|
|
if ( ( pButton->HasFocus() && pButton->IsEnabled() ) && fade != 0 )
|
|
fade = 255;
|
|
}
|
|
|
|
GamepadUIConvarButton* pCvarButton = dynamic_cast<GamepadUIConvarButton*>(pButton);
|
|
bool bHasDependencies = true;
|
|
if ( pCvarButton )
|
|
{
|
|
const char *pszDependentCVar = pCvarButton->GetDependentCVar();
|
|
if ( pszDependentCVar && *pszDependentCVar )
|
|
{
|
|
bHasDependencies = false;
|
|
|
|
bool bFound = false;
|
|
|
|
for ( GamepadUIButton *pOtherButton : m_Tabs[ nActiveTab ].pButtons )
|
|
{
|
|
GamepadUIConvarButton* pOtherCvarButton = dynamic_cast<GamepadUIConvarButton*>(pOtherButton);
|
|
if ( pOtherCvarButton )
|
|
{
|
|
const char* pszConVarName = pOtherCvarButton->GetConVarName();
|
|
if ( pszConVarName && *pszConVarName && !V_strcmp( pszDependentCVar, pszConVarName ) )
|
|
{
|
|
bHasDependencies = pOtherCvarButton->IsConVarEnabled();
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !bFound )
|
|
{
|
|
ConVarRef cvar(pszDependentCVar);
|
|
bHasDependencies = cvar.GetBool();
|
|
}
|
|
}
|
|
}
|
|
|
|
pButton->SetAlpha(fade);
|
|
pButton->SetVisible(bHasDependencies);
|
|
pButton->SetPos( buttonX, buttonY );
|
|
|
|
if ( pButton->IsEnabled() && pButton->IsVisible() && fade && m_Tabs[nActiveTab].bAlternating)
|
|
{
|
|
buttonWide = pButton->GetWide();
|
|
if ( i % 2 )
|
|
vgui::surface()->DrawSetColor( Color( 0, 0, 0, ( 20 * Min( 255, fade + 127 ) ) / 255 ) );
|
|
else
|
|
vgui::surface()->DrawSetColor( Color( fade, fade, fade, fade > 64 ? 1 : 0 ) );
|
|
|
|
vgui::surface()->DrawFilledRect( buttonX, buttonY, buttonX + buttonWide, buttonY + pButton->GetTall() );
|
|
}
|
|
|
|
if ( pButton->IsHorizontal() )
|
|
{
|
|
// Set previousxHeight to the tallest button
|
|
if (pButton->GetTall() > previousxHeight)
|
|
previousxHeight = pButton->GetTall();
|
|
previousxSizes += pButton->GetWide();
|
|
}
|
|
else
|
|
{
|
|
previousySizes += pButton->GetTall();
|
|
}
|
|
i++;
|
|
}
|
|
|
|
int yMax = 0;
|
|
{
|
|
if (previousySizes > m_flScrollBarHeight)
|
|
yMax = previousySizes - m_flScrollBarHeight;
|
|
m_Tabs[ nActiveTab ].ScrollState.UpdateScrollBounds( 0.0f, yMax );
|
|
|
|
m_pScrollBar->InitScrollBar( &m_Tabs[nActiveTab].ScrollState,
|
|
m_flScrollBarOffsetX, m_flScrollBarOffsetY );
|
|
|
|
m_pScrollBar->UpdateScrollBounds( 0.0f, yMax,
|
|
m_flScrollBarHeight, m_flScrollBarHeight );
|
|
|
|
m_Tabs[ nActiveTab ].ScrollState.UpdateScrollBounds( 0.0f, yMax );
|
|
}
|
|
|
|
m_Tabs[nActiveTab].ScrollState.UpdateScrolling( 2.0f, GamepadUI::GetInstance().GetTime() );
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnMouseWheeled( int delta )
|
|
{
|
|
m_Tabs[ GetActiveTab() ].ScrollState.OnMouseWheeled( delta * 100.0f, GamepadUI::GetInstance().GetTime() );
|
|
}
|
|
|
|
CON_COMMAND( _gamepadui_resetkeys, "" )
|
|
{
|
|
GamepadUIOptionsPanel::GetInstance()->ClearBindings();
|
|
GamepadUIOptionsPanel::GetInstance()->FillInBindings();
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnCommand( char const* pCommand )
|
|
{
|
|
if ( !V_strcmp( pCommand, "action_back" ) )
|
|
{
|
|
Close();
|
|
}
|
|
else if ( !V_strcmp( pCommand, "action_apply" ) )
|
|
{
|
|
for ( int i = 0; i < m_Tabs[ GetActiveTab() ].pButtons.Count(); i++ )
|
|
{
|
|
GamepadUIConvarButton *pConVarButton = dynamic_cast< GamepadUIConvarButton* >( m_Tabs[ GetActiveTab() ].pButtons[ i ] );
|
|
if ( pConVarButton )
|
|
pConVarButton->UpdateConVar();
|
|
}
|
|
|
|
FlushHelperConVars();
|
|
ApplyKeyBindings();
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( "exec userconfig.cfg\nhost_writeconfig\nmat_savechanges\n" );
|
|
}
|
|
else if ( !V_strcmp( pCommand, "action_usedefaults" ) )
|
|
{
|
|
new GamepadUIGenericConfirmationPanel( GamepadUIOptionsPanel::GetInstance(), "UseDefaultsConfirm", GamepadUIString( "#GameUI_KeyboardSettings" ).String(), GamepadUIString("#GameUI_KeyboardSettingsText").String(),
|
|
[](){
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( "exec config_default.cfg\n_gamepadui_resetkeys\n" );
|
|
}, false, true);
|
|
}
|
|
else if ( StringHasPrefixCaseSensitive( pCommand, "tab " ) )
|
|
{
|
|
const char *pszTab = &pCommand[4];
|
|
if ( *pszTab )
|
|
SetActiveTab( atoi( pszTab ) );
|
|
}
|
|
else if ( !V_strcmp( pCommand, "open_steaminput" ) )
|
|
{
|
|
#ifdef STEAM_INPUT
|
|
if (GamepadUI::GetInstance().GetSteamInput()->IsEnabled())
|
|
{
|
|
GamepadUI::GetInstance().GetSteamInput()->ShowBindingPanel( GamepadUI::GetInstance().GetSteamInput()->GetActiveController() );
|
|
}
|
|
#elif defined(HL2_RETAIL) // Steam input and Steam Controller are not supported in SDK2013 (Madi)
|
|
uint64_t nController = g_pInputSystem->GetActiveSteamInputHandle();
|
|
if ( !nController )
|
|
{
|
|
InputHandle_t nControllers[ STEAM_INPUT_MAX_COUNT ];
|
|
GamepadUI::GetInstance().GetSteamAPIContext()->SteamInput()->GetConnectedControllers( nControllers );
|
|
nController = nControllers[0];
|
|
}
|
|
if ( nController )
|
|
GamepadUI::GetInstance().GetSteamAPIContext()->SteamInput()->ShowBindingPanel( nController );
|
|
#endif // HL2_RETAIL
|
|
}
|
|
else if ( !V_strcmp( pCommand, "open_techcredits" ) )
|
|
{
|
|
GamepadUIString title = "#GameUI_ThirdPartyTechCredits";
|
|
GamepadUIString bink = "#GameUI_Bink";
|
|
GamepadUIString miles = "#GameUI_Miles_Audio";
|
|
GamepadUIString voice = "#GameUI_Miles_Voice";
|
|
wchar_t wszBuf[4096];
|
|
#ifdef WIN32
|
|
V_snwprintf( wszBuf, 4096, L"%s\n\n%s\n\n%s", bink.String(), miles.String(), voice.String() );
|
|
#else
|
|
V_snwprintf( wszBuf, 4096, L"%S\n\n%S\n\n%S", bink.String(), miles.String(), voice.String() );
|
|
#endif
|
|
new GamepadUIGenericConfirmationPanel( GamepadUIOptionsPanel::GetInstance(), "TechCredits", title.String(), wszBuf,
|
|
[](){}, true, false);
|
|
}
|
|
else if ( StringHasPrefixCaseSensitive( pCommand, "cmd " ) )
|
|
{
|
|
const char* pszClientCmd = &pCommand[ 4 ];
|
|
if ( *pszClientCmd )
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( pszClientCmd );
|
|
}
|
|
else
|
|
{
|
|
BaseClass::OnCommand( pCommand );
|
|
}
|
|
}
|
|
|
|
int GamepadUIOptionsPanel::GetActiveTab()
|
|
{
|
|
int nUserTab = gamepadui_last_options_tab.GetInt();
|
|
|
|
int nActiveTab = Clamp( nUserTab, 0, Max( 0, m_nTabCount - 1 ) );
|
|
if ( nUserTab != nActiveTab )
|
|
gamepadui_last_options_tab.SetValue( nActiveTab );
|
|
return nActiveTab;
|
|
}
|
|
|
|
const char *UTIL_Parse( const char *data, char *token, int sizeofToken )
|
|
{
|
|
data = GamepadUI::GetInstance().GetEngineClient()->ParseFile( data, token, sizeofToken );
|
|
return data;
|
|
}
|
|
|
|
static void GetResolutionName( vmode_t *mode, char *sz, int sizeofsz, int desktopWidth, int desktopHeight )
|
|
{
|
|
Q_snprintf( sz, sizeofsz, "%i x %i%s", mode->width, mode->height,
|
|
( mode->width == desktopWidth ) && ( mode->height == desktopHeight ) ? " (native)": "" );
|
|
}
|
|
|
|
static void GetCurrentAndDesktopSize( int ¤tWidth, int ¤tHeight, int &desktopWidth, int &desktopHeight )
|
|
{
|
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
|
|
|
currentWidth = config.m_VideoMode.m_Width;
|
|
currentHeight = config.m_VideoMode.m_Height;
|
|
|
|
// Windowed is the last item in the combobox.
|
|
GamepadUI::GetInstance().GetGameUIFuncs()->GetDesktopResolution( desktopWidth, desktopHeight );
|
|
|
|
#if defined( USE_SDL )
|
|
bool bWindowed = _gamepadui_displaymode.GetInt() < 2;
|
|
|
|
int nNewDisplayIndex = _gamepadui_displaymode.GetInt() - 2;
|
|
if ( !bWindowed )
|
|
{
|
|
|
|
SDL_Rect rect;
|
|
if ( !SDL_GetDisplayBounds( nNewDisplayIndex, &rect ) )
|
|
{
|
|
desktopWidth = rect.w;
|
|
desktopHeight = rect.h;
|
|
}
|
|
}
|
|
|
|
bool bNewFullscreenDisplay = ( !bWindowed && ( GetSDLDisplayIndexFullscreen() != nNewDisplayIndex ) );
|
|
if ( bNewFullscreenDisplay )
|
|
{
|
|
currentWidth = desktopWidth;
|
|
currentHeight = desktopHeight;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::UpdateResolutions()
|
|
{
|
|
if ( !m_pResolutionButton )
|
|
return;
|
|
|
|
m_pResolutionButton->ClearOptions();
|
|
|
|
const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
|
|
|
|
int currentWidth, currentHeight, desktopWidth, desktopHeight;
|
|
GetCurrentAndDesktopSize( currentWidth, currentHeight, desktopWidth, desktopHeight );
|
|
|
|
// get full video mode list
|
|
vmode_t *plist = NULL;
|
|
int count = 0;
|
|
GamepadUI::GetInstance().GetGameUIFuncs()->GetVideoModes(&plist, &count);
|
|
|
|
int nFilteredModeCount = 0;
|
|
int nSelectedDefaultMode = -1;
|
|
for ( int i = 0; i < count; i++, plist++ )
|
|
{
|
|
char sz[ 256 ];
|
|
GetResolutionName( plist, sz, sizeof( sz ), desktopWidth, desktopHeight );
|
|
|
|
int iAspectMode = GetScreenAspectMode( plist->width, plist->height );
|
|
|
|
if ( iAspectMode == _gamepadui_aspectratio.GetInt() )
|
|
{
|
|
if ( ( plist->width == currentWidth && plist->height == currentHeight ) ||
|
|
( nSelectedDefaultMode == -1 && plist->width == config.m_VideoMode.m_Width && plist->height == config.m_VideoMode.m_Height ) )
|
|
{
|
|
nSelectedDefaultMode = nFilteredModeCount;
|
|
}
|
|
|
|
GamepadUIOption option;
|
|
option.nValue = nFilteredModeCount++;
|
|
option.strOptionText.SetRawUTF8( sz );
|
|
option.userdata.nWidth = plist->width;
|
|
option.userdata.nHeight = plist->height;
|
|
m_pResolutionButton->AddOptionItem( option );
|
|
}
|
|
}
|
|
|
|
if ( nSelectedDefaultMode == -1 )
|
|
nSelectedDefaultMode = Max( m_pResolutionButton->GetOptionCount() - 1, 0 );
|
|
|
|
_gamepadui_resolution.SetValue( nSelectedDefaultMode );
|
|
m_pResolutionButton->SetToDefault();
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::ClearBindings()
|
|
{
|
|
for ( int i = 0; i < m_nTabCount; i++ )
|
|
{
|
|
for ( GamepadUIButton* pButton : m_Tabs[i].pButtons )
|
|
{
|
|
GamepadUIKeyButton* pKeyButton = dynamic_cast<GamepadUIKeyButton*>(pButton);
|
|
if ( pKeyButton )
|
|
pKeyButton->ClearKey();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Mainly from GameUI
|
|
void GamepadUIOptionsPanel::FillInBindings()
|
|
{
|
|
for ( int i = 0; i < m_nTabCount; i++ )
|
|
m_Tabs[ i ].KeysToUnbind.RemoveAll();
|
|
|
|
bool bJoystick = false;
|
|
ConVarRef var( "joystick" );
|
|
if ( var.IsValid() )
|
|
{
|
|
bJoystick = var.GetBool();
|
|
}
|
|
|
|
// NVNT see if we have a falcon connected.
|
|
bool bFalcon = false;
|
|
ConVarRef falconVar("hap_HasDevice");
|
|
if ( var.IsValid() )
|
|
{
|
|
bFalcon = var.GetBool();
|
|
}
|
|
|
|
// Fill in bindings
|
|
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
|
|
{
|
|
// Look up binding
|
|
const char *binding = GamepadUI::GetInstance().GetGameUIFuncs()->GetBindingForButtonCode((ButtonCode_t)i);
|
|
if ( !binding )
|
|
continue;
|
|
|
|
// See if there is an item for this one?
|
|
GamepadUIKeyButton *pButton = NULL;
|
|
int nTab = 0;
|
|
for ( int j = 0; j < m_nTabCount; j++ )
|
|
{
|
|
for ( GamepadUIButton *pFindButton : m_Tabs[ j ].pButtons )
|
|
{
|
|
GamepadUIKeyButton *pFindKeyButton = dynamic_cast< GamepadUIKeyButton* >( pFindButton );
|
|
if ( pFindKeyButton && !V_strcmp( pFindKeyButton->GetKeyBinding(), binding ) )
|
|
{
|
|
pButton = pFindKeyButton;
|
|
nTab = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pButton )
|
|
{
|
|
const char *pKeyName = g_pInputSystem->ButtonCodeToString( (ButtonCode_t)i );
|
|
const char *pCurrentKey = pButton->GetKey();
|
|
if ( *pCurrentKey )
|
|
{
|
|
ButtonCode_t currentBC = (ButtonCode_t)GamepadUI::GetInstance().GetGameUIFuncs()->GetButtonCodeForBind( pCurrentKey );
|
|
|
|
bool bShouldOverride = bJoystick && IsJoystickCode((ButtonCode_t)i) && !IsJoystickCode(currentBC);
|
|
if( !bShouldOverride && bFalcon && IsNovintCode((ButtonCode_t)i) && !IsNovintCode(currentBC) )
|
|
bShouldOverride = true;
|
|
|
|
if ( !bShouldOverride )
|
|
continue;
|
|
|
|
m_Tabs[ nTab ].KeysToUnbind.FindAndRemove( pCurrentKey );
|
|
}
|
|
pButton->SetKey( pKeyName );
|
|
m_Tabs[ nTab ].KeysToUnbind.AddToTail( pKeyName );
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::ApplyKeyBindings()
|
|
{
|
|
const int nTab = GetActiveTab();
|
|
for ( int i = 0; i < m_Tabs[ nTab ].KeysToUnbind.Count(); i++ )
|
|
{
|
|
char buff[256];
|
|
Q_snprintf( buff, sizeof(buff), "unbind \"%s\"\n", m_Tabs[ nTab].KeysToUnbind[ i ].String() );
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( buff );
|
|
}
|
|
m_Tabs[ nTab ].KeysToUnbind.RemoveAll();
|
|
|
|
for ( GamepadUIButton *pButton : m_Tabs[ nTab ].pButtons )
|
|
{
|
|
GamepadUIKeyButton *pKeyButton = dynamic_cast< GamepadUIKeyButton* >( pButton );
|
|
if ( !pKeyButton )
|
|
continue;
|
|
|
|
const char *pKey = pKeyButton->GetKey();
|
|
if ( !pKey )
|
|
continue;
|
|
|
|
char buff[256];
|
|
Q_snprintf( buff, sizeof(buff), "bind \"%s\" \"%s\"\n", pKey, pKeyButton->GetKeyBinding() );
|
|
GamepadUI::GetInstance().GetEngineClient()->ClientCmd_Unrestricted( buff );
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnKeyBound( const char *pKey )
|
|
{
|
|
for ( int i = 0; i < m_nTabCount; i++ )
|
|
{
|
|
for ( GamepadUIButton* pFindButton : m_Tabs[i].pButtons )
|
|
{
|
|
GamepadUIKeyButton* pFindKeyButton = dynamic_cast<GamepadUIKeyButton*>(pFindButton);
|
|
if ( pFindKeyButton && !V_strcmp( pFindKeyButton->GetKey(), pKey ) )
|
|
pFindKeyButton->ClearKey();
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnKeyCodePressed( vgui::KeyCode code )
|
|
{
|
|
ButtonCode_t buttonCode = GetBaseButtonCode( code );
|
|
|
|
|
|
switch ( buttonCode )
|
|
{
|
|
#ifdef HL2_RETAIL // Steam input and Steam Controller are not supported in SDK2013 (Madi)
|
|
case STEAMCONTROLLER_LEFT_BUMPER:
|
|
#else
|
|
case KEY_XBUTTON_LEFT_SHOULDER:
|
|
#endif
|
|
SetActiveTab( GetActiveTab() - 1 );
|
|
break;
|
|
|
|
#ifdef HL2_RETAIL
|
|
case STEAMCONTROLLER_RIGHT_BUMPER:
|
|
#else
|
|
case KEY_XBUTTON_RIGHT_SHOULDER:
|
|
#endif
|
|
SetActiveTab( GetActiveTab() + 1 );
|
|
break;
|
|
default:
|
|
return BaseClass::OnKeyCodePressed( code );
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::OnGamepadUIButtonNavigatedTo( vgui::VPANEL button )
|
|
{
|
|
GamepadUIButton *pButton = dynamic_cast< GamepadUIButton * >( vgui::ipanel()->GetPanel( button, GetModuleName() ) );
|
|
if ( pButton )
|
|
{
|
|
int nParentW, nParentH;
|
|
GetParent()->GetSize( nParentW, nParentH );
|
|
|
|
const float flTabButtonHeight = m_Tabs[ GetActiveTab() ].pTabButton->m_flHeight;
|
|
|
|
float flScrollRegion = nParentH - (m_flTabsOffsetY + m_flFooterButtonsOffsetY + m_nFooterButtonHeight + flTabButtonHeight);
|
|
int nX, nY;
|
|
pButton->GetPos( nX, nY );
|
|
if ( nY + m_flFooterButtonsOffsetY + m_nFooterButtonHeight + pButton->GetTall() > nParentH || nY < m_flTabsOffsetY + flTabButtonHeight )
|
|
{
|
|
int nTargetY = 0;
|
|
int nThisButton = -1;
|
|
int nHeader = -1;
|
|
int nHorzHeight = 0;
|
|
for ( int i = 0; i < m_Tabs[ GetActiveTab() ].pButtons.Count(); i++ )
|
|
{
|
|
if ( m_Tabs[ GetActiveTab() ].pButtons[i] == pButton)
|
|
{
|
|
nThisButton = i;
|
|
break;
|
|
}
|
|
|
|
if (m_Tabs[GetActiveTab()].pButtons[i]->IsHorizontal())
|
|
{
|
|
nHorzHeight += m_Tabs[GetActiveTab()].pButtons[i]->m_flHeight;
|
|
continue;
|
|
}
|
|
else if (nHorzHeight != 0)
|
|
{
|
|
nTargetY += nHorzHeight;
|
|
nHorzHeight = 0;
|
|
}
|
|
|
|
if (!m_Tabs[GetActiveTab()].pButtons[i]->IsEnabled())
|
|
nHeader = i;
|
|
else
|
|
nHeader = -1;
|
|
|
|
nTargetY += m_Tabs[ GetActiveTab() ].pButtons[i]->m_flHeight;
|
|
}
|
|
|
|
// This button isn't part of the current tab, so don't scroll
|
|
if (nThisButton == -1)
|
|
return;
|
|
|
|
// If this button has a section header above it and we're going up, scroll to it
|
|
if ( nHeader != -1 && nY < nParentH / 2 )
|
|
nTargetY -= m_Tabs[ GetActiveTab() ].pButtons[ nHeader ]->m_flHeight;
|
|
|
|
if ( nY < nParentH / 2 )
|
|
{
|
|
nTargetY -= (pButton->m_flHeightAnimationValue[ButtonStates::Over] / 2);
|
|
}
|
|
else
|
|
{
|
|
nTargetY -= flScrollRegion;
|
|
nTargetY += pButton->m_flHeight;
|
|
nTargetY += (pButton->m_flHeightAnimationValue[ButtonStates::Over] / 2);
|
|
}
|
|
|
|
m_Tabs[ GetActiveTab() ].ScrollState.SetScrollTarget( nTargetY, GamepadUI::GetInstance().GetTime());
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::SetActiveTab( int nTab )
|
|
{
|
|
nTab = Clamp( nTab, 0, Max( m_nTabCount - 1, 0 ) );
|
|
|
|
gamepadui_last_options_tab.SetValue( nTab );
|
|
int nActiveTab = GetActiveTab();
|
|
for ( int i = 0; i < m_nTabCount; i++ )
|
|
m_Tabs[ i ].pTabButton->ForceDepressed( i == nActiveTab );
|
|
|
|
FooterButtonMask buttons = FooterButtons::Apply | FooterButtons::Back;
|
|
if ( V_strncmp( m_Tabs[nActiveTab].pTabButton->GetName(), "Keyboard", 8 ) == 0 )
|
|
buttons |= FooterButtons::UseDefaults;
|
|
SetFooterButtons( buttons );
|
|
|
|
for ( GamepadUIButton *pButton : m_Tabs[ nActiveTab ].pButtons )
|
|
{
|
|
if ( pButton->GetCurrentButtonState() == ButtonState::Pressed )
|
|
{
|
|
pButton->NavigateTo();
|
|
return;
|
|
}
|
|
}
|
|
|
|
for ( GamepadUIButton *pButton : m_Tabs[ nActiveTab ].pButtons )
|
|
{
|
|
if ( pButton->IsEnabled() )
|
|
{
|
|
pButton->NavigateTo();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::LoadOptionTabs( const char *pszOptionsFile )
|
|
{
|
|
KeyValues* pDataFile = new KeyValues( "Options" );
|
|
if ( pDataFile->LoadFromFile( g_pFullFileSystem, pszOptionsFile ) )
|
|
{
|
|
for ( KeyValues* pTabData = pDataFile->GetFirstSubKey(); pTabData != NULL; pTabData = pTabData->GetNextKey() )
|
|
{
|
|
{
|
|
char buttonCmd[64];
|
|
V_snprintf( buttonCmd, sizeof( buttonCmd ), "tab %d", m_nTabCount );
|
|
|
|
auto button = new GamepadUIButton(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemetab.res",
|
|
buttonCmd,
|
|
pTabData->GetString( "title" ), "" );
|
|
button->SetZPos( 50 );
|
|
//button->SetFooterButton( true );
|
|
if ( m_nTabCount == gamepadui_last_options_tab.GetInt() )
|
|
button->ForceDepressed( true );
|
|
m_Tabs[ m_nTabCount ].pTabButton = button;
|
|
}
|
|
|
|
m_Tabs[ m_nTabCount ].pTabButton->SetName( pTabData->GetName() );
|
|
m_Tabs[ m_nTabCount ].bAlternating = pTabData->GetBool( "alternating" );
|
|
m_Tabs[ m_nTabCount ].bHorizontal = pTabData->GetBool( "horizontal" );
|
|
|
|
if ( !V_strcmp( pTabData->GetString( "items_from" ), "keyboard" ) )
|
|
{
|
|
char szBinding[256];
|
|
char szDescription[256];
|
|
|
|
// Load the default keys list
|
|
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
|
if ( !g_pFullFileSystem->ReadFile( "scripts/kb_act.lst", NULL, buf ) )
|
|
return;
|
|
|
|
const char *data = ( const char* )buf.Base();
|
|
|
|
char token[512];
|
|
while ( 1 )
|
|
{
|
|
data = UTIL_Parse( data, token, sizeof( token ) );
|
|
// Done.
|
|
if ( strlen( token ) <= 0 )
|
|
break;
|
|
|
|
Q_strncpy( szBinding, token, sizeof( szBinding ) );
|
|
|
|
data = UTIL_Parse( data, token, sizeof( token ) );
|
|
if ( strlen( token ) <= 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
Q_strncpy( szDescription, token, sizeof( szDescription ) );
|
|
|
|
// Skip '======' rows
|
|
if ( szDescription[ 0 ] != '=' )
|
|
{
|
|
// Flag as special header row if binding is "blank"
|
|
if ( !stricmp( szBinding, "blank" ) )
|
|
{
|
|
// add header item
|
|
auto button = new GamepadUIHeaderButton(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_sectiontitle.res",
|
|
"button_pressed",
|
|
szDescription, "" );
|
|
//button->SetFooterButton( true );
|
|
button->SetEnabled( false );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else
|
|
{
|
|
// Add to list
|
|
auto button = new GamepadUIKeyButton(
|
|
szBinding, this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_wheelywheel.res",
|
|
"button_pressed",
|
|
szDescription, "" );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
}
|
|
}
|
|
|
|
FillInBindings();
|
|
}
|
|
|
|
KeyValues* pTabItems = pTabData->FindKey( "items" );
|
|
if ( pTabItems )
|
|
{
|
|
for ( KeyValues* pItemData = pTabItems->GetFirstSubKey(); pItemData != NULL; pItemData = pItemData->GetNextKey() )
|
|
{
|
|
const char *pItemType = pItemData->GetString( "type", "droppydown" );
|
|
if ( !V_strcmp( pItemType, "checkybox" ) )
|
|
{
|
|
auto button = new GamepadUICheckButton(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_checkybox.res",
|
|
"button_pressed",
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ) );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else if ( !V_strcmp( pItemType, "skillyskill" ) )
|
|
{
|
|
auto button = new GamepadUISkillySkill(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_skillyskill.res",
|
|
"button_pressed",
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ),
|
|
pItemData->GetString( "image", "" ), V_atoi( pItemData->GetString( "skill", "" ) ) );
|
|
button->SetMouseNavigate( false );
|
|
button->SetHorizontal( pItemData->GetBool( "horizontal", m_Tabs[ m_nTabCount ].bHorizontal ) );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else if ( !V_strcmp( pItemType, "slideyslide" ) )
|
|
{
|
|
const char *pszCvar = pItemData->GetString( "convar" );
|
|
const char *pszCvarDepends = pItemData->GetString( "depends_on" );
|
|
bool bInstantApply = pItemData->GetBool( "instantapply" );
|
|
float flMin = pItemData->GetFloat( "min", 0.0f );
|
|
float flMax = pItemData->GetFloat( "max", 1.0f );
|
|
float flStep = pItemData->GetFloat( "step", 0.1f );
|
|
int nTextPrecision = pItemData->GetInt( "textprecision", -1 );
|
|
auto button = new GamepadUISlideySlide(
|
|
pszCvar, pszCvarDepends, bInstantApply, flMin, flMax, flStep, nTextPrecision,
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_slideyslide.res",
|
|
"button_pressed",
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ) );
|
|
button->SetToDefault();
|
|
button->SetMouseStep( pItemData->GetFloat( "mouse_step", flStep ) );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else if ( !V_strcmp( pItemType, "headeryheader" ) )
|
|
{
|
|
// add header item
|
|
auto button = new GamepadUIHeaderButton(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_sectiontitle.res",
|
|
"button_pressed",
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ) );
|
|
//button->SetFooterButton( true );
|
|
button->SetEnabled( false );
|
|
button->SetCentered( pItemData->GetBool( "center" ) );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else if ( !V_strcmp( pItemType, "wheelywheel" ) )
|
|
{
|
|
const char *pszCvar = pItemData->GetString( "convar" );
|
|
const char *pszCvarDepends = pItemData->GetString( "depends_on" );
|
|
bool bInstantApply = pItemData->GetBool( "instantapply" );
|
|
bool bSignOnly = pItemData->GetBool( "signonly" );
|
|
auto button = new GamepadUIWheelyWheel(
|
|
pszCvar, pszCvarDepends, bInstantApply, bSignOnly,
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_wheelywheel.res",
|
|
"button_pressed",
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ) );
|
|
|
|
const char *pszOptionsFrom = pItemData->GetString( "options_from" );
|
|
KeyValues *pOptions = pItemData->FindKey( "options" );
|
|
if ( pOptions )
|
|
{
|
|
for ( KeyValues* pOptionData = pOptions->GetFirstSubKey(); pOptionData != NULL; pOptionData = pOptionData->GetNextKey() )
|
|
{
|
|
GamepadUIOption option;
|
|
option.nValue = V_atoi( pOptionData->GetName() );
|
|
option.strOptionText = GamepadUIString( pOptionData->GetString() );
|
|
button->AddOptionItem( option );
|
|
}
|
|
}
|
|
else if ( pszOptionsFrom && *pszOptionsFrom )
|
|
{
|
|
if ( !V_strcmp( pszOptionsFrom, "antialiasing" ) )
|
|
{
|
|
for ( int i = 0; i < g_nNumAAModes; i++ )
|
|
{
|
|
GamepadUIOption option;
|
|
option.nValue = i;
|
|
option.strOptionText = g_AAModes[ i ].strName;
|
|
button->AddOptionItem( option );
|
|
}
|
|
}
|
|
else if ( !V_strcmp( pszOptionsFrom, "displaymode" ) )
|
|
{
|
|
int i = 0;
|
|
|
|
GamepadUIOption option;
|
|
option.nValue = i++;
|
|
option.strOptionText = "#GameUI_Windowed";
|
|
button->AddOptionItem( option );
|
|
|
|
#ifdef HL2_RETAIL // SDK2013 does not support borderless windowed (Madi)
|
|
wchar_t wszNoBorderText[ 256 ];
|
|
V_swprintf_safe( wszNoBorderText, L"%ls (No Border)", option.strOptionText.String() );
|
|
option.nValue = i++;
|
|
option.strOptionText = wszNoBorderText;
|
|
button->AddOptionItem( option );
|
|
#endif // HL2_RETAIL
|
|
|
|
#if defined( USE_SDL ) && defined( DX_TO_GL_ABSTRACTION )
|
|
GamepadUIString strFullscreen = "#GameUI_Fullscreen";
|
|
int numVideoDisplays = SDL_GetNumVideoDisplays();
|
|
|
|
if ( numVideoDisplays <= 1 )
|
|
{
|
|
option.nValue = i++;
|
|
option.strOptionText = strFullscreen;
|
|
button->AddOptionItem( option );
|
|
}
|
|
else
|
|
{
|
|
for ( int display = 0; display < numVideoDisplays; display++ )
|
|
{
|
|
wchar_t wszItemText[ 256 ];
|
|
V_swprintf_safe( wszItemText, L"%ls (%d)", strFullscreen.String(), display);
|
|
|
|
option.nValue = i++;
|
|
option.strOptionText = wszItemText;
|
|
button->AddOptionItem( option );
|
|
}
|
|
|
|
}
|
|
#else
|
|
option.nValue = i++;
|
|
option.strOptionText = "#GameUI_Fullscreen";
|
|
button->AddOptionItem( option );
|
|
#endif
|
|
}
|
|
else if ( !V_strcmp( pszOptionsFrom, "resolutions" ) )
|
|
{
|
|
m_pResolutionButton = button;
|
|
|
|
UpdateResolutions();
|
|
}
|
|
}
|
|
button->SetToDefault();
|
|
|
|
// Values which require confirmation before changing
|
|
KeyValues *pConfirm = pItemData->FindKey( "confirm" );
|
|
if (pConfirm)
|
|
{
|
|
for ( KeyValues* pConfirmData = pConfirm->GetFirstSubKey(); pConfirmData != NULL; pConfirmData = pConfirmData->GetNextKey() )
|
|
{
|
|
button->AddDangerousOption( V_atoi( pConfirmData->GetName() ), pConfirmData->GetString() );
|
|
}
|
|
}
|
|
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
else if ( !V_strcmp( pItemType, "button" ) )
|
|
{
|
|
auto button = new GamepadUIOptionButton(
|
|
this, this,
|
|
GAMEPADUI_RESOURCE_FOLDER "schemeoptions_wheelywheel.res",
|
|
pItemData->GetString( "command", "button_pressed" ),
|
|
pItemData->GetString( "text", "" ), pItemData->GetString( "description", "" ) );
|
|
m_Tabs[ m_nTabCount ].pButtons.AddToTail( button );
|
|
}
|
|
}
|
|
}
|
|
|
|
CUtlVector< GamepadUIOptionButton* >& pButtons = m_Tabs[ m_nTabCount ].pButtons;
|
|
for ( int i = 1; i < pButtons.Count(); i++ )
|
|
{
|
|
int iPrev = i - 1;
|
|
|
|
if ( pButtons[i]->IsHorizontal() )
|
|
{
|
|
pButtons[ i ]->SetNavLeft( pButtons[ iPrev ] );
|
|
pButtons[ iPrev ]->SetNavRight( pButtons[ i ] );
|
|
}
|
|
else if ( pButtons[ iPrev ]->IsHorizontal() )
|
|
{
|
|
pButtons[ i ]->SetNavUp( pButtons[ iPrev ] );
|
|
|
|
// Make sure all previous horizontal buttons go down to this
|
|
int i2 = i-1;
|
|
for (; i2 >= 1 && pButtons[i2]->IsHorizontal(); i2-- )
|
|
{
|
|
pButtons[ i2 ]->SetNavDown( pButtons[ i ] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pButtons[ i ]->SetNavUp( pButtons[ iPrev ] );
|
|
pButtons[ iPrev ]->SetNavDown( pButtons[ i ] );
|
|
}
|
|
}
|
|
|
|
m_nTabCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamepadUIOptionsPanel::ApplySchemeSettings( vgui::IScheme* pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
m_hDescFont = pScheme->GetFont( "Button.Description.Font", true );
|
|
|
|
float flX, flY;
|
|
if (GamepadUI::GetInstance().GetScreenRatio( flX, flY ))
|
|
{
|
|
m_flTabsOffsetX *= (flX * flX);
|
|
m_flScrollBarOffsetX *= (flX);
|
|
}
|
|
|
|
int nX, nY;
|
|
GamepadUI::GetInstance().GetSizingPanelOffset( nX, nY );
|
|
if (nX > 0)
|
|
{
|
|
GamepadUI::GetInstance().GetSizingPanelScale( flX, flY );
|
|
m_flTabsOffsetX += ((float)nX) * flX * 0.5f;
|
|
m_flScrollBarOffsetX += ((float)nX) * flX * 0.1f;
|
|
}
|
|
}
|
|
|
|
CON_COMMAND( gamepadui_openoptionsdialog, "" )
|
|
{
|
|
new GamepadUIOptionsPanel( GamepadUI::GetInstance().GetBasePanel(), "" );
|
|
}
|