diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /common/GameUI | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'common/GameUI')
| -rw-r--r-- | common/GameUI/IGameConsole.h | 41 | ||||
| -rw-r--r-- | common/GameUI/IGameUI.h | 121 | ||||
| -rw-r--r-- | common/GameUI/ObjectList.cpp | 243 | ||||
| -rw-r--r-- | common/GameUI/ObjectList.h | 58 | ||||
| -rw-r--r-- | common/GameUI/Random.cpp | 131 | ||||
| -rw-r--r-- | common/GameUI/Random.h | 30 | ||||
| -rw-r--r-- | common/GameUI/cvarslider.cpp | 334 | ||||
| -rw-r--r-- | common/GameUI/cvarslider.h | 63 | ||||
| -rw-r--r-- | common/GameUI/scriptobject.cpp | 1153 | ||||
| -rw-r--r-- | common/GameUI/scriptobject.h | 155 |
10 files changed, 2329 insertions, 0 deletions
diff --git a/common/GameUI/IGameConsole.h b/common/GameUI/IGameConsole.h new file mode 100644 index 0000000..a18f331 --- /dev/null +++ b/common/GameUI/IGameConsole.h @@ -0,0 +1,41 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef IGAMECONSOLE_H +#define IGAMECONSOLE_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/interface.h" + + +//----------------------------------------------------------------------------- +// Purpose: interface to game/dev console +//----------------------------------------------------------------------------- +abstract_class IGameConsole : public IBaseInterface +{ +public: + // activates the console, makes it visible and brings it to the foreground + virtual void Activate() = 0; + + virtual void Initialize() = 0; + + // hides the console + virtual void Hide() = 0; + + // clears the console + virtual void Clear() = 0; + + // return true if the console has focus + virtual bool IsConsoleVisible() = 0; + + virtual void SetParent( int parent ) = 0; +}; + +#define GAMECONSOLE_INTERFACE_VERSION "GameConsole004" + +#endif // IGAMECONSOLE_H diff --git a/common/GameUI/IGameUI.h b/common/GameUI/IGameUI.h new file mode 100644 index 0000000..99967f4 --- /dev/null +++ b/common/GameUI/IGameUI.h @@ -0,0 +1,121 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IGAMEUI_H +#define IGAMEUI_H +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" +#include "vgui/IPanel.h" + +#if !defined( _X360 ) +#include "xbox/xboxstubs.h" +#endif + +// reasons why the user can't connect to a game server +enum ESteamLoginFailure +{ + STEAMLOGINFAILURE_NONE, + STEAMLOGINFAILURE_BADTICKET, + STEAMLOGINFAILURE_NOSTEAMLOGIN, + STEAMLOGINFAILURE_VACBANNED, + STEAMLOGINFAILURE_LOGGED_IN_ELSEWHERE +}; + +enum ESystemNotify +{ + SYSTEMNOTIFY_STORAGEDEVICES_CHANGED, + SYSTEMNOTIFY_USER_SIGNEDIN, + SYSTEMNOTIFY_USER_SIGNEDOUT, + SYSTEMNOTIFY_XUIOPENING, + SYSTEMNOTIFY_XUICLOSED, + SYSTEMNOTIFY_INVITE_SHUTDOWN, // Cross-game invite is causing us to shutdown +}; + +//----------------------------------------------------------------------------- +// Purpose: contains all the functions that the GameUI dll exports +//----------------------------------------------------------------------------- +abstract_class IGameUI +{ +public: + // initialization/shutdown + virtual void Initialize( CreateInterfaceFn appFactory ) = 0; + virtual void PostInit() = 0; + + // connect to other interfaces at the same level (gameui.dll/server.dll/client.dll) + virtual void Connect( CreateInterfaceFn gameFactory ) = 0; + + virtual void Start() = 0; + virtual void Shutdown() = 0; + virtual void RunFrame() = 0; + + // notifications + virtual void OnGameUIActivated() = 0; + virtual void OnGameUIHidden() = 0; + + // OLD: Use OnConnectToServer2 + virtual void OLD_OnConnectToServer(const char *game, int IP, int port) = 0; + + virtual void OnDisconnectFromServer_OLD( uint8 eSteamLoginFailure, const char *username ) = 0; + virtual void OnLevelLoadingStarted(bool bShowProgressDialog) = 0; + virtual void OnLevelLoadingFinished(bool bError, const char *failureReason, const char *extendedReason) = 0; + + // level loading progress, returns true if the screen needs updating + virtual bool UpdateProgressBar(float progress, const char *statusText) = 0; + // Shows progress desc, returns previous setting... (used with custom progress bars ) + virtual bool SetShowProgressText( bool show ) = 0; + + // !!!!!!!!!members added after "GameUI011" initial release!!!!!!!!!!!!!!!!!!! + virtual void ShowNewGameDialog( int chapter ) = 0; + + // Xbox 360 + virtual void SessionNotification( const int notification, const int param = 0 ) = 0; + virtual void SystemNotification( const int notification ) = 0; + virtual void ShowMessageDialog( const uint nType, vgui::Panel *pOwner ) = 0; + virtual void UpdatePlayerInfo( uint64 nPlayerId, const char *pName, int nTeam, byte cVoiceState, int nPlayersNeeded, bool bHost ) = 0; + virtual void SessionSearchResult( int searchIdx, void *pHostData, XSESSION_SEARCHRESULT *pResult, int ping ) = 0; + virtual void OnCreditsFinished( void ) = 0; + + // inserts specified panel as background for level load dialog + virtual void SetLoadingBackgroundDialog( vgui::VPANEL panel ) = 0; + + // Bonus maps interfaces + virtual void BonusMapUnlock( const char *pchFileName = NULL, const char *pchMapName = NULL ) = 0; + virtual void BonusMapComplete( const char *pchFileName = NULL, const char *pchMapName = NULL ) = 0; + virtual void BonusMapChallengeUpdate( const char *pchFileName, const char *pchMapName, const char *pchChallengeName, int iBest ) = 0; + virtual void BonusMapChallengeNames( char *pchFileName, char *pchMapName, char *pchChallengeName ) = 0; + virtual void BonusMapChallengeObjectives( int &iBronze, int &iSilver, int &iGold ) = 0; + virtual void BonusMapDatabaseSave( void ) = 0; + virtual int BonusMapNumAdvancedCompleted( void ) = 0; + virtual void BonusMapNumMedals( int piNumMedals[ 3 ] ) = 0; + + virtual void OnConnectToServer2(const char *game, int IP, int connectionPort, int queryPort) = 0; + + // X360 Storage device validation: + // returns true right away if storage device has been previously selected. + // otherwise returns false and will set the variable pointed by pStorageDeviceValidated to 1 + // once the storage device is selected by user. + virtual bool ValidateStorageDevice( int *pStorageDeviceValidated ) = 0; + + virtual void SetProgressOnStart() = 0; + virtual void OnDisconnectFromServer( uint8 eSteamLoginFailure ) = 0; + + virtual void OnConfirmQuit( void ) = 0; + + virtual bool IsMainMenuVisible( void ) = 0; + + // Client DLL is providing us with a panel that it wants to replace the main menu with + virtual void SetMainMenuOverride( vgui::VPANEL panel ) = 0; + // Client DLL is telling us that a main menu command was issued, probably from its custom main menu panel + virtual void SendMainMenuCommand( const char *pszCommand ) = 0; +}; + +#define GAMEUI_INTERFACE_VERSION "GameUI011" + +#endif // IGAMEUI_H diff --git a/common/GameUI/ObjectList.cpp b/common/GameUI/ObjectList.cpp new file mode 100644 index 0000000..7da1100 --- /dev/null +++ b/common/GameUI/ObjectList.cpp @@ -0,0 +1,243 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include <stdio.h> +#include <malloc.h> +#include "ObjectList.h" +#include "tier1/strtools.h" + +//#include "port.h" +//#include "mem.h" +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +ObjectList::ObjectList() +{ + head = tail = current = NULL; + number = 0; +} + +ObjectList::~ObjectList() +{ + Clear( false ); +} + +bool ObjectList::AddHead(void * newObject) +{ + // create new element + element_t * newElement = (element_t *) calloc(1, sizeof(element_t)); + + if (newElement == NULL ) + return false; // out of memory + + // insert element + newElement->object = newObject; + + if (head) + { + newElement->next = head; + head->prev = newElement; + }; + + head = newElement; + + // if list was empty set new tail + if (tail==NULL) tail = head; + + number++; + + return true; + +} + +void * ObjectList::RemoveHead() +{ + void * retObj; + + // check head is present + if (head) + { + retObj = head->object; + element_t * newHead = head->next; + if (newHead) newHead->prev = NULL; + + // if only one element is in list also update tail + // if we remove this prev element + if (tail==head) tail = NULL; + + free(head); + head = newHead; + + number--; + + } else + retObj = NULL; + + return retObj; +} + +bool ObjectList::AddTail(void * newObject) +{ + element_t * newElement = (element_t *) calloc(1, sizeof(element_t)); + + if (newElement == NULL) + return false; // out of memory; + + newElement->object = newObject; + + if (tail) + { + newElement->prev = tail; + tail->next = newElement; + } + + tail = newElement; + + // if list was empty set new head + if (head==NULL) head = tail; + + number++; + + return true; + +} + +void * ObjectList::RemoveTail() +{ + void * retObj; + + // check tail is present + if (tail) + { + retObj = tail->object; + element_t * newTail = tail->prev; + if (newTail) newTail->next = NULL; + + // if only one element is in list also update tail + // if we remove this prev element + if (head==tail) head = NULL; + + free(tail); + tail = newTail; + + number--; + + } else + retObj = NULL; + + return retObj; +} + +bool ObjectList::IsEmpty() +{ + return ( head == NULL ); +} + +int ObjectList::CountElements() +{ + return number; +} + +bool ObjectList::Contains(void * object) +{ + element_t * e = head; + + while(e && e->object!=object) { e = e->next;} + + if ( e ) + { + current = e; + return true; + } + else + { + return false; + } +} + +void ObjectList::Clear( bool freeElementsMemory ) +{ + element_t * ne; + + element_t * e = head; + while(e) + { + ne = e->next; + + if ( freeElementsMemory && e->object ) + free( e->object ); + + free(e); + e = ne; + } + + head = tail = current = NULL; + number = 0; + +} + +bool ObjectList::Remove( void * object ) +{ + element_t * e = head; + + while(e && e->object!=object) { e = e->next;} + + if (e!=NULL) + { + if (e->prev) e->prev->next = e->next; + if (e->next) e->next->prev = e->prev; + if (head==e) head = e->next; + if (tail==e) tail = e->prev; + if (current == e) current= e->next; + free(e); + number--; + } + + return (e!=NULL); +} + +void ObjectList::Init() +{ + head = tail = current = NULL; + number = 0; +} + +void * ObjectList::GetFirst() +{ + if (head) + { + current = head->next; + return head->object; + } + else + { + current = NULL; + return NULL; + }; + +} + +void * ObjectList::GetNext() +{ + void * retObj = NULL; + if (current) + { + retObj = current->object; + current = current->next; + } + return retObj; +} + +bool ObjectList::Add(void *newObject) +{ + return AddTail( newObject ); +} + diff --git a/common/GameUI/ObjectList.h b/common/GameUI/ObjectList.h new file mode 100644 index 0000000..b52a0ce --- /dev/null +++ b/common/GameUI/ObjectList.h @@ -0,0 +1,58 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// ObjectList.h: interface for the ObjectList class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef OBJECTLIST_H +#define OBJECTLIST_H + +#pragma once + +#include "IObjectContainer.h" // Added by ClassView + +class ObjectList : public IObjectContainer +{ +public: + void Init(); + bool Add( void * newObject ); + void * GetFirst(); + void * GetNext(); + + + + ObjectList(); + virtual ~ObjectList(); + + void Clear( bool freeElementsMemory ); + int CountElements(); + void * RemoveTail(); + void * RemoveHead(); + + bool AddTail(void * newObject); + bool AddHead(void * newObject); + bool Remove(void * object); + bool Contains(void * object); + bool IsEmpty(); + + typedef struct element_s { + element_s * prev; // pointer to the last element or NULL + element_s * next; // pointer to the next elemnet or NULL + void * object; // the element's object + } element_t; + +protected: + + element_t * head; // first element in list + element_t * tail; // last element in list + element_t * current; // current element in list + int number; + +}; + +#endif // !defined diff --git a/common/GameUI/Random.cpp b/common/GameUI/Random.cpp new file mode 100644 index 0000000..ec17986 --- /dev/null +++ b/common/GameUI/Random.cpp @@ -0,0 +1,131 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Basic random number generator +// +// $NoKeywords: $ +//===========================================================================// + + +#include <time.h> +#include "Random.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define IA 16807 +#define IM 2147483647 +#define IQ 127773 +#define IR 2836 +#define NTAB 32 +#define NDIV (1+(IM-1)/NTAB) + +static long idum = 0; + +void SeedRandomNumberGenerator(long lSeed) +{ + if (lSeed) + { + idum = lSeed; + } + else + { + idum = -time(NULL); + } + if (1000 < idum) + { + idum = -idum; + } + else if (-1000 < idum) + { + idum -= 22261048; + } +} + +long ran1(void) +{ + int j; + long k; + static long iy=0; + static long iv[NTAB]; + + if (idum <= 0 || !iy) + { + if (-(idum) < 1) idum=1; + else idum = -(idum); + for (j=NTAB+7;j>=0;j--) + { + k=(idum)/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + if (j < NTAB) iv[j] = idum; + } + iy=iv[0]; + } + k=(idum)/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + j=iy/NDIV; + iy=iv[j]; + iv[j] = idum; + + return iy; +} + +// fran1 -- return a random floating-point number on the interval [0,1) +// +#define AM (1.0/IM) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) +float fran1(void) +{ + float temp = (float)AM*ran1(); + if (temp > RNMX) return (float)RNMX; + else return temp; +} + +#ifndef _XBOX +float RandomFloat( float flLow, float flHigh ) +{ + if (idum == 0) + { + SeedRandomNumberGenerator(0); + } + + float fl = fran1(); // float in [0,1) + return (fl * (flHigh-flLow)) + flLow; // float in [low,high) +} +#endif + +long RandomLong( long lLow, long lHigh ) +{ + if (idum == 0) + { + SeedRandomNumberGenerator(0); + } + + unsigned long maxAcceptable; + unsigned long x = lHigh-lLow+1; + unsigned long n; + if (x <= 0 || MAX_RANDOM_RANGE < x-1) + { + return lLow; + } + + // The following maps a uniform distribution on the interval [0,MAX_RANDOM_RANGE] + // to a smaller, client-specified range of [0,x-1] in a way that doesn't bias + // the uniform distribution unfavorably. Even for a worst case x, the loop is + // guaranteed to be taken no more than half the time, so for that worst case x, + // the average number of times through the loop is 2. For cases where x is + // much smaller than MAX_RANDOM_RANGE, the average number of times through the + // loop is very close to 1. + // + maxAcceptable = MAX_RANDOM_RANGE - ((MAX_RANDOM_RANGE+1) % x ); + do + { + n = ran1(); + } while (n > maxAcceptable); + + return lLow + (n % x); +} + + diff --git a/common/GameUI/Random.h b/common/GameUI/Random.h new file mode 100644 index 0000000..90beb78 --- /dev/null +++ b/common/GameUI/Random.h @@ -0,0 +1,30 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Generalized 32-bit random number generator +// Range is 0x00000000 - 0x7FFFFFFF +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef RANDOM_H +#define RANDOM_H +#ifdef _WIN32 +#pragma once +#endif + +// the random number seeding is automatic + +#define MAX_RANDOM_RANGE 0x7FFFFFFFUL + +// restarts random generator +// setting lSeed to 0 causes the current time to be used as the seed +// random number generator will automatically seed itself on first use with current time if this is not called +extern void SeedRandomNumberGenerator(long lSeed = 0); + +// returns a random integer of range [low, high] +extern long RandomLong( long lLow, long lHigh ); + +// returns a random float of range [low, high) +extern float RandomFloat( float flLow, float flHigh ); + +#endif // RANDOM_H diff --git a/common/GameUI/cvarslider.cpp b/common/GameUI/cvarslider.cpp new file mode 100644 index 0000000..7220538 --- /dev/null +++ b/common/GameUI/cvarslider.cpp @@ -0,0 +1,334 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "cvarslider.h" +#include <stdio.h> +#include "tier1/KeyValues.h" +#include "tier1/convar.h" +#include <vgui/IVGui.h> +#include <vgui_controls/PropertyPage.h> + +#define CVARSLIDER_SCALE_FACTOR 100.0f + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +DECLARE_BUILD_FACTORY( CCvarSlider ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCvarSlider::CCvarSlider( Panel *parent, const char *name ) : Slider( parent, name ) +{ + SetupSlider( 0, 1, "", false ); + m_bCreatedInCode = false; + + AddActionSignalTarget( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCvarSlider::CCvarSlider( Panel *parent, const char *panelName, char const *caption, + float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange ) + : Slider( parent, panelName ) +{ + AddActionSignalTarget( this ); + + SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange ); + + // For backwards compatability. Ignore .res file settings for forced setup sliders. + m_bCreatedInCode = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange ) +{ + // make sure min/max don't go outside cvar range if there's one + ConVarRef var( cvarname, true ); + if ( var.IsValid() ) + { + float flCVarMin; + if ( var.GetMin( flCVarMin ) ) + { + minValue = m_bUseConVarMinMax ? flCVarMin : MAX( minValue, flCVarMin ); + } + float flCVarMax; + if ( var.GetMax( flCVarMax ) ) + { + maxValue = m_bUseConVarMinMax ? flCVarMax : MIN( maxValue, flCVarMax ); + } + } + + m_flMinValue = minValue; + m_flMaxValue = maxValue; + + // scale by CVARSLIDER_SCALE_FACTOR + SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) ); + + char szMin[ 32 ]; + char szMax[ 32 ]; + + Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue ); + Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue ); + + SetTickCaptions( szMin, szMax ); + + Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) ); + + m_bModifiedOnce = false; + m_bAllowOutOfRange = bAllowOutOfRange; + + // Set slider to current value + Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CCvarSlider::~CCvarSlider() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::ApplySettings( KeyValues *inResourceData ) +{ + BaseClass::ApplySettings( inResourceData ); + + if ( !m_bCreatedInCode ) + { + float minValue = inResourceData->GetFloat( "minvalue", 0 ); + float maxValue = inResourceData->GetFloat( "maxvalue", 1 ); + const char *cvarname = inResourceData->GetString( "cvar_name", "" ); + bool bAllowOutOfRange = inResourceData->GetInt( "allowoutofrange", 0 ) != 0; + SetupSlider( minValue, maxValue, cvarname, bAllowOutOfRange ); + + if ( GetParent() ) + { + // HACK: If our parent is a property page, we want the dialog containing it + if ( dynamic_cast<vgui::PropertyPage*>(GetParent()) && GetParent()->GetParent() ) + { + GetParent()->GetParent()->AddActionSignalTarget( this ); + } + else + { + GetParent()->AddActionSignalTarget( this ); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Get control settings for editing +//----------------------------------------------------------------------------- +void CCvarSlider::GetSettings( KeyValues *outResourceData ) +{ + BaseClass::GetSettings(outResourceData); + + if ( !m_bCreatedInCode ) + { + outResourceData->SetFloat( "minvalue", m_flMinValue ); + outResourceData->SetFloat( "maxvalue", m_flMaxValue ); + outResourceData->SetString( "cvar_name", m_szCvarName ); + outResourceData->SetInt( "allowoutofrange", m_bAllowOutOfRange ); + } +} + +void CCvarSlider::SetCVarName( char const *cvarname ) +{ + Q_strncpy( m_szCvarName, cvarname, sizeof( m_szCvarName ) ); + + m_bModifiedOnce = false; + + // Set slider to current value + Reset(); +} + +void CCvarSlider::SetMinMaxValues( float minValue, float maxValue, bool bSetTickDisplay ) +{ + SetRange( (int)( CVARSLIDER_SCALE_FACTOR * minValue ), (int)( CVARSLIDER_SCALE_FACTOR * maxValue ) ); + + if ( bSetTickDisplay ) + { + char szMin[ 32 ]; + char szMax[ 32 ]; + + Q_snprintf( szMin, sizeof( szMin ), "%.2f", minValue ); + Q_snprintf( szMax, sizeof( szMax ), "%.2f", maxValue ); + + + SetTickCaptions( szMin, szMax ); + } + + // Set slider to current value + Reset(); +} + +void CCvarSlider::SetTickColor( Color color ) +{ + m_TickColor = color; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::Paint() +{ + // Get engine's current value +// float curvalue = engine->pfnGetCvarFloat( m_szCvarName ); + ConVarRef var( m_szCvarName, true ); + if ( !var.IsValid() ) + return; + float curvalue = var.GetFloat(); + + // did it get changed from under us? + if (curvalue != m_fStartValue) + { + int val = (int)( CVARSLIDER_SCALE_FACTOR * curvalue ); + m_fStartValue = curvalue; + m_fCurrentValue = curvalue; + + SetValue( val ); + m_iStartValue = GetValue(); + } + + BaseClass::Paint(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::ApplyChanges() +{ + if (m_bModifiedOnce) + { + m_iStartValue = GetValue(); + if (m_bAllowOutOfRange) + { + m_fStartValue = m_fCurrentValue; + } + else + { + m_fStartValue = (float) m_iStartValue / CVARSLIDER_SCALE_FACTOR; + } + + //engine->Cvar_SetValue( m_szCvarName, m_fStartValue ); + ConVarRef var( m_szCvarName, true ); + if ( !var.IsValid() ) + return; + var.SetValue( (float)m_fStartValue ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CCvarSlider::GetSliderValue() +{ + if (m_bAllowOutOfRange) + { + return m_fCurrentValue; + } + else + { + return ((float)GetValue())/ CVARSLIDER_SCALE_FACTOR; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::SetSliderValue(float fValue) +{ + int nVal = (int)( CVARSLIDER_SCALE_FACTOR * fValue ); + SetValue( nVal, false); + + // remember this slider value + m_iLastSliderValue = GetValue(); + + if (m_fCurrentValue != fValue) + { + m_fCurrentValue = fValue; + m_bModifiedOnce = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::Reset() +{ + // Set slider to current value +// m_fStartValue = engine->pfnGetCvarFloat( m_szCvarName ); + ConVarRef var( m_szCvarName, true ); + if ( !var.IsValid() ) + { + m_fCurrentValue = m_fStartValue = 0.0f; + SetValue( 0, false ); + m_iStartValue = GetValue(); + m_iLastSliderValue = m_iStartValue; + return; + } + m_fStartValue = var.GetFloat(); + m_fCurrentValue = m_fStartValue; + + int value = (int)( CVARSLIDER_SCALE_FACTOR * m_fStartValue ); + SetValue( value, false ); + + m_iStartValue = GetValue(); + m_iLastSliderValue = m_iStartValue; + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CCvarSlider::HasBeenModified() +{ + if (GetValue() != m_iStartValue) + { + m_bModifiedOnce = true; + } + + return m_bModifiedOnce; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : position - +//----------------------------------------------------------------------------- +void CCvarSlider::OnSliderMoved() +{ + if (HasBeenModified()) + { + if (m_iLastSliderValue != GetValue()) + { + m_iLastSliderValue = GetValue(); + m_fCurrentValue = ((float) m_iLastSliderValue)/CVARSLIDER_SCALE_FACTOR; + } + + // tell parent that we've been modified + PostActionSignal(new KeyValues("ControlModified")); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCvarSlider::OnSliderDragEnd( void ) +{ + if ( !m_bCreatedInCode ) + { + ApplyChanges(); + } +}
\ No newline at end of file diff --git a/common/GameUI/cvarslider.h b/common/GameUI/cvarslider.h new file mode 100644 index 0000000..b03417a --- /dev/null +++ b/common/GameUI/cvarslider.h @@ -0,0 +1,63 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CVARSLIDER_H +#define CVARSLIDER_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Slider.h> + +class CCvarSlider : public vgui::Slider +{ + DECLARE_CLASS_SIMPLE( CCvarSlider, vgui::Slider ); + +public: + + CCvarSlider( vgui::Panel *parent, const char *panelName ); + CCvarSlider( vgui::Panel *parent, const char *panelName, char const *caption, + float minValue, float maxValue, char const *cvarname, bool bAllowOutOfRange=false ); + ~CCvarSlider(); + + void SetupSlider( float minValue, float maxValue, const char *cvarname, bool bAllowOutOfRange ); + + void SetCVarName( char const *cvarname ); + void SetMinMaxValues( float minValue, float maxValue, bool bSetTickdisplay = true ); + void SetTickColor( Color color ); + + virtual void Paint(); + + virtual void ApplySettings( KeyValues *inResourceData ); + virtual void GetSettings( KeyValues *outResourceData ); + + void ApplyChanges(); + float GetSliderValue(); + void SetSliderValue(float fValue); + void Reset(); + bool HasBeenModified(); + +private: + MESSAGE_FUNC( OnSliderMoved, "SliderMoved" ); + MESSAGE_FUNC( OnSliderDragEnd, "SliderDragEnd" ); + + CPanelAnimationVar( bool, m_bUseConVarMinMax, "use_convar_minmax", "0" ); + + bool m_bAllowOutOfRange; + bool m_bModifiedOnce; + float m_fStartValue; + int m_iStartValue; + int m_iLastSliderValue; + float m_fCurrentValue; + char m_szCvarName[ 64 ]; + + bool m_bCreatedInCode; + float m_flMinValue; + float m_flMaxValue; +}; + +#endif // CVARSLIDER_H diff --git a/common/GameUI/scriptobject.cpp b/common/GameUI/scriptobject.cpp new file mode 100644 index 0000000..e83f5fd --- /dev/null +++ b/common/GameUI/scriptobject.cpp @@ -0,0 +1,1153 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// +// CScriptObject and CDescription class definitions +// +#include "scriptobject.h" +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <vgui_controls/Label.h> +#include "filesystem.h" +#include "tier1/convar.h" +#include "cdll_int.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; +static char token[ 1024 ]; + +extern IVEngineClient *engine; + +void StripFloatTrailingZeros(char *str) +{ + // scan for a '.' + char *period = strchr(str, '.'); + if (!period) + return; + + // start at the end and scan back to the period + char *end = 0; + for ( end = str + strlen(str) - 1; end > period; --end ) + { + if (*end == '0') + { + *end = '\0'; + } + else + { + // we've hit a real value, stop truncating + break; + } + } + + // if we've made it up to the period, kill that to + if ( *end == '.' ) + { + *end = '\0'; + } +} + +///////////////////// +objtypedesc_t objtypes[] = +{ + { O_BOOL , "BOOL" }, + { O_NUMBER, "NUMBER" }, + { O_LIST , "LIST" }, + { O_STRING, "STRING" }, + { O_OBSOLETE , "OBSOLETE" }, + { O_SLIDER , "SLIDER" }, + { O_CATEGORY, "CATEGORY" }, +}; + +mpcontrol_t::mpcontrol_t( Panel *parent, char const *panelName ) +: Panel( parent, panelName ) +{ + type = O_BADTYPE; + pControl = NULL; + pPrompt = NULL; + pScrObj = NULL; + + next = NULL; + + SetPaintBackgroundEnabled( false ); +} + +void mpcontrol_t::OnSizeChanged( int wide, int tall ) +{ + int inset = 4; + + if ( pPrompt ) + { + int w = wide / 2; + + if ( pControl ) + { + pControl->SetBounds( w + 20, inset, w - 20, tall - 2 * inset ); + } + pPrompt->SetBounds( 0, inset, w + 20, tall - 2 * inset ); + } + else + { + if ( pControl ) + { + pControl->SetBounds( 0, inset, wide, tall - 2 * inset ); + } + } +} + +CScriptListItem::CScriptListItem() +{ + pNext = NULL; + memset( szItemText, 0, 128 ); + memset( szValue, 0, 256 ); +} + +CScriptListItem::CScriptListItem( char const *strItem, char const *strValue ) +{ + pNext = NULL; + Q_strncpy( szItemText, strItem, sizeof( szItemText ) ); + Q_strncpy( szValue , strValue, sizeof( szValue ) ); +} + +CScriptObject::CScriptObject( void ) +{ + type = O_BOOL; + bSetInfo = false; // Prepend "Setinfo" to keyvalue pair in config? + pNext = NULL; + pListItems = NULL; + tooltip[0] = '\0'; +} + +CScriptObject::~CScriptObject() +{ + RemoveAndDeleteAllItems(); +} + +void CScriptObject::RemoveAndDeleteAllItems( void ) +{ + CScriptListItem *p, *n; + + p = pListItems; + while ( p ) + { + n = p->pNext; + delete p; + p = n; + } + pListItems = NULL; +} + +void CScriptObject::SetCurValue( char const *strValue ) +{ + Q_strncpy( curValue, strValue, sizeof( curValue ) ); + + fcurValue = (float)atof( curValue ); + + if ( type == O_NUMBER || type == O_BOOL || type == O_SLIDER ) + { + StripFloatTrailingZeros( curValue ); + } +} + +void CScriptObject::AddItem( CScriptListItem *pItem ) +{ + // Link it into the end of the list; + CScriptListItem *p; + p = pListItems; + if ( !p ) + { + pListItems = pItem; + pItem->pNext = NULL; + return; + } + + while ( p ) + { + if ( !p->pNext ) + { + p->pNext = pItem; + pItem->pNext = NULL; + return; + } + p = p->pNext; + } +} + +/* +=================== +UTIL_StripInvalidCharacters + +Removes any possible formatting codes and double quote characters from the input string +=================== +*/ +void UTIL_StripInvalidCharacters( char *pszInput, int maxlen ) +{ + char szOutput[4096]; + char *pIn, *pOut; + + pIn = pszInput; + pOut = szOutput; + + *pOut = '\0'; + + while ( *pIn ) + { + if ( ( *pIn != '"' ) && + ( *pIn != '%' ) ) + { + *pOut++ = *pIn; + } + pIn++; + } + + *pOut = '\0'; + + // Copy back over, in place + Q_strncpy( pszInput, szOutput, maxlen ); +} + +void FixupString( char *inString, int maxlen ) +{ + char szBuffer[ 4096 ]; + Q_strncpy( szBuffer, inString, sizeof( szBuffer ) ); + UTIL_StripInvalidCharacters( szBuffer, sizeof( szBuffer ) ); + Q_strncpy( inString, szBuffer, maxlen ); +} + +/* +=================== +CleanFloat + +Removes any ".000" from the end of floats +=================== +*/ +char * CleanFloat( float val ) +{ + static int curstring = 0; + static char string[2][32]; + curstring = ( curstring + 1 ) % 2; + + Q_snprintf( string[curstring], sizeof( string[curstring] ), "%f", val ); + + char * str = string[curstring]; + + char * tmp = str; + if ( !str || !*str || !strchr( str, '.' ) ) + return str; + + while ( *tmp ) + ++tmp; + --tmp; + + while ( *tmp == '0' && tmp > str ) + { + *tmp = 0; + --tmp; + } + + if ( *tmp == '.' ) + { + *tmp = 0; + } + + return str; +} + +void CScriptObject::WriteToScriptFile( FileHandle_t fp ) +{ + if ( type == O_OBSOLETE ) + return; + + FixupString( cvarname, sizeof( cvarname ) ); + g_pFullFileSystem->FPrintf( fp, "\t\"%s\"\r\n", cvarname ); + + g_pFullFileSystem->FPrintf( fp, "\t{\r\n" ); + + CScriptListItem *pItem; + + FixupString( prompt, sizeof( prompt ) ); + FixupString( tooltip, sizeof( tooltip ) ); + + switch ( type ) + { + case O_BOOL: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{ BOOL }\r\n" ); + g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%i\" }\r\n", (int)fcurValue ? 1 : 0 ); + break; + case O_NUMBER: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{ NUMBER %s %s }\r\n", CleanFloat(fMin), CleanFloat(fMax) ); + g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) ); + break; + case O_STRING: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{ STRING }\r\n" ); + FixupString( curValue, sizeof( curValue ) ); + g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", curValue ); + break; + case O_LIST: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{\r\n\t\t\tLIST\r\n" ); + + pItem = pListItems; + while ( pItem ) + { + UTIL_StripInvalidCharacters( pItem->szItemText, sizeof( pItem->szItemText ) ); + UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) ); + g_pFullFileSystem->FPrintf( fp, "\t\t\t\"%s\" \"%s\"\r\n", + pItem->szItemText, pItem->szValue ); + + pItem = pItem->pNext; + } + + g_pFullFileSystem->FPrintf( fp, "\t\t}\r\n"); + g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) ); + break; + case O_SLIDER: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{ SLIDER %s %s }\r\n", CleanFloat(fMin), CleanFloat(fMax) ); + g_pFullFileSystem->FPrintf( fp, "\t\t{ \"%s\" }\r\n", CleanFloat(fcurValue) ); + break; + case O_CATEGORY: + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", prompt ); + if ( tooltip && tooltip[0] ) + { + g_pFullFileSystem->FPrintf( fp, "\t\t\"%s\"\r\n", tooltip ); + } + g_pFullFileSystem->FPrintf( fp, "\t\t{ CATEGORY }\r\n" ); + break; + } + + if ( bSetInfo ) + g_pFullFileSystem->FPrintf( fp, "\t\tSetInfo\r\n" ); + + g_pFullFileSystem->FPrintf( fp, "\t}\r\n\r\n" ); +} + +void CScriptObject::WriteToFile( FileHandle_t fp ) +{ + if ( type == O_OBSOLETE || type == O_CATEGORY ) + return; + + FixupString( cvarname, sizeof( cvarname ) ); + g_pFullFileSystem->FPrintf( fp, "\"%s\"\t\t", cvarname ); + + CScriptListItem *pItem; + float fVal; + + switch ( type ) + { + case O_BOOL: + g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", fcurValue != 0.0 ? "1" : "0" ); + break; + case O_NUMBER: + case O_SLIDER: + fVal = fcurValue; + if ( fMin != -1.0 ) + fVal = max( fVal, fMin ); + if ( fMax != -1.0 ) + fVal = min( fVal, fMax ); + g_pFullFileSystem->FPrintf( fp, "\"%f\"\r\n", fVal ); + break; + case O_STRING: + FixupString( curValue, sizeof( curValue ) ); + g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", curValue ); + break; + case O_LIST: + pItem = pListItems; + while ( pItem ) + { + if ( !Q_stricmp( pItem->szValue, curValue ) ) + break; + + pItem = pItem->pNext; + } + + if ( pItem ) + { + UTIL_StripInvalidCharacters( pItem->szValue, sizeof( pItem->szValue ) ); + g_pFullFileSystem->FPrintf( fp, "\"%s\"\r\n", pItem->szValue ); + } + else //Couln't find index + { + g_pFullFileSystem->FPrintf( fp, "\"0\"\r\n" ); + } + break; + } +} + +void CScriptObject::WriteToConfig( void ) +{ + if ( type == O_OBSOLETE || type == O_CATEGORY ) + return; + + char *pszKey; + char szValue[2048]; + + pszKey = ( char * )cvarname; + + CScriptListItem *pItem; + float fVal; + + switch ( type ) + { + case O_BOOL: + Q_snprintf( szValue, sizeof( szValue ), "%s", fcurValue != 0.0 ? "1" : "0" ); + break; + case O_NUMBER: + case O_SLIDER: + fVal = fcurValue; + if ( fMin != -1.0 ) + fVal = max( fVal, fMin ); + if ( fMax != -1.0 ) + fVal = min( fVal, fMax ); + Q_snprintf( szValue, sizeof( szValue ), "%f", fVal ); + break; + case O_STRING: + Q_snprintf( szValue, sizeof( szValue ), "\"%s\"", (char *)curValue ); + UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) ); + break; + case O_LIST: + pItem = pListItems; + while ( pItem ) + { + if ( !Q_stricmp( pItem->szValue, curValue ) ) + break; + + pItem = pItem->pNext; + } + + if ( pItem ) + { + Q_snprintf( szValue, sizeof( szValue ), "%s", pItem->szValue ); + UTIL_StripInvalidCharacters( szValue, sizeof( szValue ) ); + } + else //Couldn't find index + { + Q_strncpy( szValue, "0", sizeof( szValue ) ); + } + break; + } + + char command[ 256 ]; + if ( bSetInfo ) + { + Q_snprintf( command, sizeof(command), "setinfo %s \"%s\"\n", pszKey, szValue ); + } + else + { + Q_snprintf( command, sizeof(command), "%s \"%s\"\n", pszKey, szValue ); + } + + engine->ClientCmd_Unrestricted( command ); + + // CFG_SetKey( g_szCurrentConfigFile, pszKey, szValue, bSetInfo ); +} + + +objtype_t CScriptObject::GetType( char *pszType ) +{ + int i; + int nTypes; + + nTypes = sizeof( objtypes ) / sizeof( objtypedesc_t); + + for ( i = 0; i < nTypes; i++ ) + { + if ( !stricmp( objtypes[i].szDescription, pszType ) ) + return objtypes[i].type; + } + + return O_BADTYPE; +} + +bool CScriptObject::ReadFromBuffer( const char **pBuffer, bool isNewObject ) +{ + // Get the first token. + // The cvar we are setting + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( isNewObject ) + { + Q_strncpy( cvarname, token, sizeof( cvarname ) ); + } + + // Parse the { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "{" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + // Parse the Prompt + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( isNewObject ) + { + Q_strncpy( prompt, token, sizeof( prompt ) ); + } + + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + // If it's not a {, consider it the optional tooltip + if ( strcmp( token, "{" ) ) + { + Q_strncpy( tooltip, token, sizeof( tooltip ) ); + + // Parse the next { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + } + + if ( strcmp( token, "{" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + // Now parse the type: + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + objtype_t newType = GetType( token ); + if ( isNewObject ) + { + type = newType; + } + if ( newType == O_BADTYPE ) + { + Msg( "Type '%s' unknown", token ); + return false; + } + + // If it's a category, we're done. + if ( newType == O_CATEGORY ) + { + // Parse the } + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + // Parse the final } + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + return true; + } + + switch ( newType ) + { + case O_OBSOLETE: + case O_BOOL: + // Parse the next { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + break; + case O_NUMBER: + case O_SLIDER: + // Parse the Min + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( isNewObject ) + { + fMin = (float)atof( token ); + } + + // Parse the Min + *pBuffer = engine->ParseFile( *pBuffer, token , sizeof( token )); + if ( strlen( token ) <= 0 ) + return false; + + if ( isNewObject ) + { + fMax = (float)atof( token ); + } + + // Parse the next { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + break; + case O_STRING: + // Parse the next { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + break; + case O_LIST: + // Parse items until we get the } + while ( 1 ) + { + // Parse the next { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + // Done? + if ( !strcmp( token, "}" ) ) + break; + + // + // Add the item to a list somewhere + // AddItem( token ) + char strItem[ 128 ]; + char strValue[128]; + + Q_strncpy( strItem, token, sizeof( strItem ) ); + + // Parse the value + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + Q_strncpy( strValue, token, sizeof( strValue ) ); + + if ( isNewObject ) + { + CScriptListItem *pItem; + pItem = new CScriptListItem( strItem, strValue ); + + AddItem( pItem ); + } + } + break; + } + + // + // Now read in the default value + + // Parse the { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "{" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + // Parse the default + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + //if ( strlen( token ) <= 0 ) + // return false; + + // Set the values + Q_strncpy( defValue, token, sizeof( defValue ) ); + fdefValue = (float)atof( token ); + + if (type == O_NUMBER || type == O_SLIDER) + { + StripFloatTrailingZeros( defValue ); + } + + SetCurValue( defValue ); + + // Parse the } + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + // Parse the final } + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( !stricmp( token, "SetInfo" ) ) + { + bSetInfo = true; + // Parse the final } + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + } + + if ( strcmp( token, "}" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + return true; +} + +///////////////////////// +CDescription::CDescription( void ) +{ + pObjList = NULL; +} + +CDescription::~CDescription() +{ + CScriptObject *p, *n; + + p = pObjList; + while ( p ) + { + n = p->pNext; + p->pNext = NULL; + p->MarkForDeletion(); + //delete p; + p = n; + } + + pObjList = NULL; + + if ( m_pszHintText ) + free( m_pszHintText ); + if ( m_pszDescriptionType ) + free( m_pszDescriptionType ); +} + +CScriptObject * CDescription::FindObject( const char *pszObjectName ) +{ + if ( !pszObjectName ) + return NULL; + + CScriptObject *p; + p = pObjList; + while ( p ) + { + if ( !stricmp( pszObjectName, p->cvarname ) ) + return p; + p = p->pNext; + } + return NULL; +} + +void CDescription::AddObject( CScriptObject *pObj ) +{ + CScriptObject *p; + p = pObjList; + if ( !p ) + { + pObjList = pObj; + pObj->pNext = NULL; + return; + } + + while ( p ) + { + if ( !p->pNext ) + { + p->pNext = pObj; + pObj->pNext = NULL; + return; + } + p = p->pNext; + } +} + +bool CDescription::ReadFromBuffer( const char **pBuffer, bool bAllowNewObject ) +{ + // Get the first token. + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + // Read VERSION # + if ( stricmp ( token, "VERSION" ) ) + { + Msg( "Expecting 'VERSION', got '%s'", token ); + return false; + } + + // Parse in the version # + // Get the first token. + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + { + Msg( "Expecting version #" ); + return false; + } + + float fVer; + fVer = (float)atof( token ); + + if ( fVer != SCRIPT_VERSION ) + { + Msg( "Version mismatch, expecting %f, got %f", SCRIPT_VERSION, fVer ); + return false; + } + + // Get the "DESCRIPTION" + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + // Read DESCRIPTION + if ( stricmp ( token, "DESCRIPTION" ) ) + { + Msg( "Expecting 'DESCRIPTION', got '%s'", token ); + return false; + } + + // Parse in the description type + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + { + Msg( "Expecting '%s'", m_pszDescriptionType ); + return false; + } + + if ( stricmp ( token, m_pszDescriptionType ) ) + { + Msg( "Expecting %s, got %s", m_pszDescriptionType, token ); + return false; + } + + // Parse the { + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + if ( strcmp( token, "{" ) ) + { + Msg( "Expecting '{', got '%s'", token ); + return false; + } + + const char *pStart; + CScriptObject *pObj; + // Now read in the objects and link them in + while ( 1 ) + { + pStart = *pBuffer; + + // Get the first token. + *pBuffer = engine->ParseFile( *pBuffer, token, sizeof( token ) ); + if ( strlen( token ) <= 0 ) + return false; + + // Read "cvar name" or } when done + if ( !stricmp ( token, "}" ) ) + break; + + // Unget the token + *pBuffer = pStart; + + // Create a new object + bool mustAdd = bAllowNewObject; + pObj = FindObject( token ); + if ( pObj ) + { + pObj->ReadFromBuffer( &pStart, false ); + mustAdd = false; // already in list + } + else + { + pObj = new CScriptObject(); + if ( !pObj ) + { + Msg( "Couldn't create script object" ); + return false; + } + + if ( !pObj->ReadFromBuffer( &pStart, true ) ) + { + delete pObj; + return false; + } + + // throw away the object if we're not adding it. + if ( !mustAdd ) + { + delete pObj; + } + } + + *pBuffer = pStart; + + // Add to list + // Fixme, move to end of list first + if ( mustAdd ) + { + AddObject( pObj ); + } + } + + return true; +} + +bool CDescription::InitFromFile( const char *pszFileName, bool bAllowNewObject /*= true*/ ) +{ + + // Load file into memory + FileHandle_t file = g_pFullFileSystem->Open( pszFileName, "rb" ); + if ( !file ) + return false; + + int len =g_pFullFileSystem->Size( file ); + + // read the file + byte *buffer = new unsigned char[ len ]; + Assert( buffer ); + g_pFullFileSystem->Read( buffer, len, file ); + g_pFullFileSystem->Close( file ); + + const char *pBuffer = (const char*)buffer; + + ReadFromBuffer( &pBuffer, bAllowNewObject ); + + delete[] buffer; + + return true; +} + +void CDescription::WriteToFile( FileHandle_t fp ) +{ + CScriptObject *pObj; + + WriteFileHeader( fp ); + + pObj = pObjList; + while ( pObj ) + { + pObj->WriteToFile( fp ); + pObj = pObj->pNext; + } +} + +void CDescription::WriteToConfig( void ) +{ + CScriptObject *pObj; + + pObj = pObjList; + while ( pObj ) + { + pObj->WriteToConfig(); + pObj = pObj->pNext; + } +} + +void CDescription::WriteToScriptFile( FileHandle_t fp ) +{ + CScriptObject *pObj; + + WriteScriptHeader( fp ); + + pObj = pObjList; + while ( pObj ) + { + pObj->WriteToScriptFile( fp ); + pObj = pObj->pNext; + } + + g_pFullFileSystem->FPrintf( fp, "}\r\n" ); +} + +void CDescription::TransferCurrentValues( const char *pszConfigFile ) +{ + char szValue[ 1024 ]; + + CScriptObject *pObj; + + pObj = pObjList; + while ( pObj ) + { + + /* + TODO: if/when prefixed keys are implemented + const char *value; + if ( pObj->bSetInfo ) + { + value = engine->LocalPlayerInfo_ValueForKey( pObj->cvarname ); // use LocalPlayerInfo because PlayerInfo strips keys prefixed with "_" + } + else + { + value = engine->pfnGetCvarString( pObj->cvarname ); + } + */ + + ConVarRef var( pObj->cvarname, true ); + if ( !var.IsValid() ) + { + if ( pObj->type != O_CATEGORY ) + { + DevMsg( "Could not find '%s'\n", pObj->cvarname ); + } + pObj = pObj->pNext; + continue; + } + const char *value = var.GetString(); + + if ( value && value[ 0 ] ) + //if ( CFG_GetValue( pszConfigFile, pObj->cvarname, szValue ) ) + { + Q_strncpy( szValue, value, sizeof( szValue ) ); + + // Fill in better default value + // + Q_strncpy( pObj->curValue, szValue, sizeof( pObj->curValue ) ); + pObj->fcurValue = (float)atof( szValue ); + + Q_strncpy( pObj->defValue, szValue, sizeof( pObj->defValue ) ); + pObj->fdefValue = (float)atof( szValue ); + } + + pObj = pObj->pNext; + } +} + +void CDescription::setDescription( const char *pszDesc ) +{ + m_pszDescriptionType = strdup( pszDesc ); +} + +void CDescription::setHint( const char *pszHint ) +{ + m_pszHintText = strdup( pszHint ); +} + +//----------------------------------------------------------------------------- +// Purpose: Constructor, load/save client settings object +//----------------------------------------------------------------------------- +CInfoDescription::CInfoDescription( void ) + : CDescription( ) +{ + setHint( "// NOTE: THIS FILE IS AUTOMATICALLY REGENERATED, \r\n\ +//DO NOT EDIT THIS HEADER, YOUR COMMENTS WILL BE LOST IF YOU DO\r\n\ +// User options script\r\n\ +//\r\n\ +// Format:\r\n\ +// Version [float]\r\n\ +// Options description followed by \r\n\ +// Options defaults\r\n\ +//\r\n\ +// Option description syntax:\r\n\ +//\r\n\ +// \"cvar\" { \"Prompt\" { type [ type info ] } { default } }\r\n\ +//\r\n\ +// type = \r\n\ +// BOOL (a yes/no toggle)\r\n\ +// STRING\r\n\ +// NUMBER\r\n\ +// LIST\r\n\ +//\r\n\ +// type info:\r\n\ +// BOOL no type info\r\n\ +// NUMBER min max range, use -1 -1 for no limits\r\n\ +// STRING no type info\r\n\ +// LIST "" delimited list of options value pairs\r\n\ +//\r\n\ +//\r\n\ +// default depends on type\r\n\ +// BOOL is \"0\" or \"1\"\r\n\ +// NUMBER is \"value\"\r\n\ +// STRING is \"value\"\r\n\ +// LIST is \"index\", where index \"0\" is the first element of the list\r\n\r\n\r\n" ); + + setDescription( "INFO_OPTIONS" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInfoDescription::WriteScriptHeader( FileHandle_t fp ) +{ + char am_pm[] = "AM"; + tm newtime; + VCRHook_LocalTime( &newtime ); + + g_pFullFileSystem->FPrintf( fp, (char *)getHint() ); + +// Write out the comment and Cvar Info: + g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Layout Script (stores last settings chosen, too)\r\n" ); + g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm ); + g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" ); + g_pFullFileSystem->FPrintf( fp, "VERSION %.1f\r\n\r\n", SCRIPT_VERSION ); + g_pFullFileSystem->FPrintf( fp, "DESCRIPTION INFO_OPTIONS\r\n{\r\n" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInfoDescription::WriteFileHeader( FileHandle_t fp ) +{ + char am_pm[] = "AM"; + tm newtime; + VCRHook_LocalTime( &newtime ); + + g_pFullFileSystem->FPrintf( fp, "// Half-Life User Info Configuration Settings\r\n" ); + g_pFullFileSystem->FPrintf( fp, "// DO NOT EDIT, GENERATED BY HALF-LIFE\r\n" ); + g_pFullFileSystem->FPrintf( fp, "// File generated: %.19s %s\r\n", asctime( &newtime ), am_pm ); + g_pFullFileSystem->FPrintf( fp, "//\r\n//\r\n// Cvar\t-\tSetting\r\n\r\n" ); +} + +//-----------------------------------------------------------------------------
\ No newline at end of file diff --git a/common/GameUI/scriptobject.h b/common/GameUI/scriptobject.h new file mode 100644 index 0000000..78bf3e3 --- /dev/null +++ b/common/GameUI/scriptobject.h @@ -0,0 +1,155 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SCRIPTOBJECT_H +#define SCRIPTOBJECT_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Panel.h> + +class CPanelListPanel; + +#define SCRIPT_VERSION 1.0f + +typedef void * FileHandle_t; + +enum objtype_t +{ + O_BADTYPE, + O_BOOL, + O_NUMBER, + O_LIST, + O_STRING, + O_OBSOLETE, + O_SLIDER, + O_CATEGORY, +}; + +typedef struct +{ + objtype_t type; + char szDescription[32]; +} objtypedesc_t; + +class CScriptListItem +{ +public: + CScriptListItem(); + CScriptListItem( char const *strItem, char const *strValue ); + + char szItemText[128]; + char szValue[256]; + + CScriptListItem *pNext; +}; + +class CScriptObject : public vgui::Panel +{ +public: + void AddItem( CScriptListItem *pItem ); + void RemoveAndDeleteAllItems( void ); + CScriptObject( void ); + ~CScriptObject(); + + bool ReadFromBuffer( const char **pBuffer, bool isNewObject ); + void WriteToConfig(); + void WriteToFile( FileHandle_t fp ); + void WriteToScriptFile( FileHandle_t fp ); + void SetCurValue( char const *strValue ); + + objtype_t GetType( char *pszType ); + + objtype_t type; + + char cvarname[64 ]; + char prompt[ 256 ]; + char tooltip[ 256 ]; + + CScriptListItem *pListItems; + + float fMin, fMax; + + char defValue[ 128 ]; // Default value string + float fdefValue; // Float version of default value. + + char curValue[ 128 ]; + float fcurValue; + + bool bSetInfo; // Prepend "Setinfo" to keyvalue pair in config? + // Linked list of default list box items. + + CScriptObject *pNext; +}; + +abstract_class CDescription +{ +public: + CDescription( void ); + virtual ~CDescription(); + + bool ReadFromBuffer( const char **pBuffer, bool bAllowNewObject ); + bool InitFromFile( const char *pszFileName, bool bAllowNewObject = true ); + void TransferCurrentValues( const char *pszConfigFile ); + + void AddObject( CScriptObject *pItem ); + void WriteToConfig(); + void WriteToFile( FileHandle_t fp ); + void WriteToScriptFile( FileHandle_t fp ); + + virtual void WriteScriptHeader( FileHandle_t fp ) = 0; // Clients must implement this. + virtual void WriteFileHeader( FileHandle_t fp ) = 0; // Clients must implement this. + + void setDescription( const char *pszDesc ); + void setHint( const char *pszHint ); + + const char *GetDescription( void ) { return m_pszDescriptionType; }; + const char *getHint( void ) { return m_pszHintText; } ; +public: + CScriptObject *pObjList; + CScriptObject *FindObject( const char *pszObjectName ); + +private: + + char *m_pszHintText; + char *m_pszDescriptionType; +}; + +namespace vgui +{ + class Label; + class Panel; +} + +class mpcontrol_t : public vgui::Panel +{ +public: + mpcontrol_t( vgui::Panel *parent, char const *panelName ); + + virtual void OnSizeChanged( int wide, int tall ) OVERRIDE; + + objtype_t type; + vgui::Panel *pControl; + vgui::Label *pPrompt; + CScriptObject *pScrObj; + + mpcontrol_t *next; +}; + +class CInfoDescription : public CDescription +{ +public: + CInfoDescription( void ); + + virtual void WriteScriptHeader( FileHandle_t fp ) OVERRIDE; + virtual void WriteFileHeader( FileHandle_t fp ) OVERRIDE; +}; + +void UTIL_StripInvalidCharacters( char *pszInput, int maxlen ); + +#endif // SCRIPTOBJECT_H |