mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-07-30 17:11:52 +03:00
Merge branch 'master' of https://github.com/ValveSoftware/source-sdk-2013 into mapbase-mp-2025
# Conflicts: # src/game/client/c_point_commentary_node.cpp # src/game/client/particlemgr.cpp # src/game/server/player.cpp
This commit is contained in:
commit
ec163919a6
2
LICENSE
2
LICENSE
@ -18,6 +18,6 @@ WARRANTY OF ANY KIND. VALVE EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS O
|
||||
INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, TITLE AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
LIMITATION OF LIABILITY. VALVE AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
||||
OR CONSEQUENTIAL DAMAGES WHATSOEVER ) THAT MAY BE INCURRED BY YOU EVEN IF VALVE HAS BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
OR CONSEQUENTIAL DAMAGES WHATSOEVER THAT MAY BE INCURRED BY YOU EVEN IF VALVE HAS BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
|
@ -270,7 +270,11 @@ Clone the repository using the following command:
|
||||
|
||||
Requirements:
|
||||
- Source SDK 2013 Multiplayer installed via Steam
|
||||
- Visual Studio 2022
|
||||
- Visual Studio 2022 with the following workload and components:
|
||||
- Desktop development with C++:
|
||||
- MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
|
||||
- Windows 11 SDK (10.0.22621.0) or Windows 10 SDK (10.0.19041.1)
|
||||
- Python 3.13 or later
|
||||
|
||||
Inside the cloned directory, navigate to `src`, run:
|
||||
```bat
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1388,10 +1388,10 @@ void CHudCommentary::StartCommentary( C_PointCommentaryNode *pNode, char *pszSpe
|
||||
|
||||
// Get our scheme and font information
|
||||
vgui::HScheme scheme = GetScheme();
|
||||
m_hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "CommentaryDefault" );
|
||||
m_hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "CommentaryDefault", true );
|
||||
if ( !m_hFont )
|
||||
{
|
||||
m_hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "Default" );
|
||||
m_hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "Default", true );
|
||||
}
|
||||
|
||||
m_hSmallFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "CommentarySmall" );
|
||||
|
@ -267,7 +267,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void )
|
||||
char szFullFileName[_MAX_PATH];
|
||||
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
|
||||
|
||||
KeyValues *pMaterialKeys = new KeyValues( "material" );
|
||||
KeyValuesAD pMaterialKeys( "material" );
|
||||
bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
|
||||
|
||||
if ( bLoaded )
|
||||
|
@ -121,7 +121,7 @@ inline ClientThinkHandle_t CClientThinkList::GetInvalidThinkHandle()
|
||||
|
||||
inline CClientThinkList::ThinkEntry_t* CClientThinkList::GetThinkEntry( ClientThinkHandle_t hThink )
|
||||
{
|
||||
return &m_ThinkEntries[ (unsigned long)hThink ];
|
||||
return &m_ThinkEntries[ (uintp)hThink ];
|
||||
}
|
||||
|
||||
|
||||
|
@ -901,23 +901,26 @@ void ClientModeShared::StartMessageMode( int iMessageModeType )
|
||||
}
|
||||
|
||||
#if defined( TF_CLIENT_DLL )
|
||||
bool bSuspensionInMatch = GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch();
|
||||
if ( !cl_enable_text_chat.GetBool() || bSuspensionInMatch )
|
||||
if ( iMessageModeType == MM_SAY || iMessageModeType == MM_SAY_TEAM )
|
||||
{
|
||||
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
|
||||
if ( pHUDChat )
|
||||
bool bSuspensionInMatch = GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch();
|
||||
if ( !cl_enable_text_chat.GetBool() || bSuspensionInMatch )
|
||||
{
|
||||
const char *pszReason = "#TF_Chat_Disabled";
|
||||
if ( bSuspensionInMatch )
|
||||
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
|
||||
if ( pHUDChat )
|
||||
{
|
||||
pszReason = "#TF_Chat_Unavailable";
|
||||
}
|
||||
const char *pszReason = "#TF_Chat_Disabled";
|
||||
if ( bSuspensionInMatch )
|
||||
{
|
||||
pszReason = "#TF_Chat_Unavailable";
|
||||
}
|
||||
|
||||
char szLocalized[100];
|
||||
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pszReason ), szLocalized, sizeof( szLocalized ) );
|
||||
pHUDChat->ChatPrintf( 0, CHAT_FILTER_NONE, "%s ", szLocalized );
|
||||
char szLocalized[100];
|
||||
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pszReason ), szLocalized, sizeof( szLocalized ) );
|
||||
pHUDChat->ChatPrintf( 0, CHAT_FILTER_NONE, "%s ", szLocalized );
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif // TF_CLIENT_DLL
|
||||
|
||||
|
@ -1672,7 +1672,7 @@ void CHudCloseCaption::CreateFonts( void )
|
||||
{
|
||||
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
|
||||
|
||||
m_hFonts[CCFONT_NORMAL] = pScheme->GetFont( "CloseCaption_Normal", true );
|
||||
m_hFonts[CCFONT_NORMAL] = pScheme->GetFont( "CloseCaption", true );
|
||||
|
||||
if ( IsPC() )
|
||||
{
|
||||
|
@ -191,12 +191,12 @@ void CMoveHelperClient::ProcessImpacts( void )
|
||||
}
|
||||
|
||||
// misyl: Debug
|
||||
if ( vOldLocalVel != vOldAbsVel )
|
||||
{
|
||||
Msg( "%d\n", gpGlobals->tickcount );
|
||||
Msg( "vOldLocalVel: %f %f %f\n", vOldLocalVel.x, vOldLocalVel.y, vOldLocalVel.z );
|
||||
Msg( "vOldAbsVel: %f %f %f\n", vOldAbsVel.x, vOldAbsVel.y, vOldAbsVel.z );
|
||||
}
|
||||
// if ( vOldLocalVel != vOldAbsVel )
|
||||
// {
|
||||
// Msg( "%d\n", gpGlobals->tickcount );
|
||||
// Msg( "vOldLocalVel: %f %f %f\n", vOldLocalVel.x, vOldLocalVel.y, vOldLocalVel.z );
|
||||
// Msg( "vOldAbsVel: %f %f %f\n", vOldAbsVel.x, vOldAbsVel.y, vOldAbsVel.z );
|
||||
// }
|
||||
// Restore the velocity
|
||||
m_pHost->SetAbsVelocity( vOldAbsVel );
|
||||
//m_pHost->SetLocalVelocity( vOldLocalVel );
|
||||
|
@ -146,7 +146,7 @@ CParticleEffectBinding::CParticleEffectBinding()
|
||||
m_LastMin = m_Min;
|
||||
m_LastMax = m_Max;
|
||||
|
||||
m_flParticleCullRadius = 0.0f;
|
||||
m_flParticleCullRadius = -1.f; // dummy value, is overwritten below
|
||||
|
||||
SetParticleCullRadius( 0.0f );
|
||||
m_nActiveParticles = 0;
|
||||
|
@ -60,7 +60,7 @@ C_ObjectSentrygun::C_ObjectSentrygun()
|
||||
m_nShieldLevel = SHIELD_NONE;
|
||||
m_nOldShieldLevel = SHIELD_NONE;
|
||||
m_hLaserBeamEffect = NULL;
|
||||
m_pTempShield = NULL;
|
||||
m_hShieldModel = NULL;
|
||||
m_bNearMiss = false;
|
||||
m_flNextNearMissCheck = 0.f;
|
||||
|
||||
@ -312,7 +312,7 @@ void C_ObjectSentrygun::SetDormant( bool bDormant )
|
||||
if ( IsDormant() && !bDormant )
|
||||
{
|
||||
// Make sure our shield is where we are. We may have moved since last seen.
|
||||
if ( m_pTempShield )
|
||||
if ( m_hShieldModel )
|
||||
{
|
||||
m_bRecreateShield = true;
|
||||
m_bRecreateLaserBeam = true;
|
||||
@ -329,13 +329,12 @@ void C_ObjectSentrygun::CreateShield( void )
|
||||
{
|
||||
DestroyShield();
|
||||
|
||||
model_t *pModel = (model_t *) engine->LoadModel( "models/buildables/sentry_shield.mdl" );
|
||||
m_pTempShield = tempents->SpawnTempModel( pModel, GetAbsOrigin(), GetAbsAngles(), Vector(0, 0, 0), 1, FTENT_NEVERDIE );
|
||||
if ( m_pTempShield )
|
||||
m_hShieldModel = C_SentrygunShield::Create( "models/buildables/sentry_shield.mdl" );
|
||||
if ( m_hShieldModel )
|
||||
{
|
||||
m_pTempShield->ChangeTeam( GetTeamNumber() );
|
||||
m_pTempShield->m_nSkin = ( GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
|
||||
//m_pTempShield->m_nRenderFX = kRenderFxDistort;
|
||||
m_hShieldModel->FollowEntity( this, false );
|
||||
m_hShieldModel->ChangeTeam( GetTeamNumber() );
|
||||
m_hShieldModel->m_nSkin = ( GetTeamNumber() == TF_TEAM_RED ) ? 0 : 1;
|
||||
}
|
||||
|
||||
m_hShieldEffect = ParticleProp()->Create( "turret_shield", PATTACH_ABSORIGIN_FOLLOW, 0, Vector( 0,0,30) );
|
||||
@ -356,12 +355,10 @@ void C_ObjectSentrygun::CreateShield( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ObjectSentrygun::DestroyShield( void )
|
||||
{
|
||||
if ( m_pTempShield )
|
||||
if ( m_hShieldModel )
|
||||
{
|
||||
m_pTempShield->flags = FTENT_FADEOUT;
|
||||
m_pTempShield->die = gpGlobals->curtime;
|
||||
m_pTempShield->fadeSpeed = 1.0f;
|
||||
m_pTempShield = NULL;
|
||||
m_hShieldModel->StartFadeOut( 1.0f );
|
||||
m_hShieldModel = NULL;
|
||||
}
|
||||
|
||||
if ( m_hShieldEffect )
|
||||
@ -758,4 +755,49 @@ const char* C_ObjectSentrygun::GetStatusName() const
|
||||
return "#TF_Object_Sentry";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_SentrygunShield* C_SentrygunShield::Create( const char* pszModelName )
|
||||
{
|
||||
C_SentrygunShield* pShield = new C_SentrygunShield();
|
||||
if ( !pShield )
|
||||
return NULL;
|
||||
|
||||
if ( !pShield->InitializeAsClientEntity( pszModelName, RENDER_GROUP_TRANSLUCENT_ENTITY ) )
|
||||
{
|
||||
pShield->Release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pShield->AddEffects( EF_NORECEIVESHADOW | EF_NOSHADOW );
|
||||
return pShield;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_SentrygunShield::ClientThink()
|
||||
{
|
||||
if ( m_flFadeOutEndTime <= gpGlobals->curtime )
|
||||
{
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
|
||||
float flAlpha = RemapVal( gpGlobals->curtime, m_flFadeOutStartTime, m_flFadeOutEndTime, 255.0f, 0.0f );
|
||||
SetRenderColorA( (byte)flAlpha );
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_SentrygunShield::StartFadeOut( float flDuration )
|
||||
{
|
||||
SetRenderMode( kRenderTransTexture );
|
||||
|
||||
m_flFadeOutStartTime = gpGlobals->curtime;
|
||||
m_flFadeOutEndTime = gpGlobals->curtime + flDuration;
|
||||
SetNextClientThink( gpGlobals->curtime );
|
||||
}
|
@ -27,6 +27,25 @@ enum
|
||||
SHIELD_MAX, // 10% damage taken, no inactive period
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Wrangler shield
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_SentrygunShield : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_SentrygunShield, C_BaseAnimating );
|
||||
|
||||
public:
|
||||
static C_SentrygunShield* Create( const char* pszModelName );
|
||||
|
||||
virtual void ClientThink();
|
||||
|
||||
void StartFadeOut( float flDuration );
|
||||
|
||||
private:
|
||||
float m_flFadeOutStartTime;
|
||||
float m_flFadeOutEndTime;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sentry object
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -124,7 +143,7 @@ private:
|
||||
bool m_bRecreateLaserBeam;
|
||||
float m_flNextNearMissCheck;
|
||||
|
||||
C_LocalTempEntity *m_pTempShield;
|
||||
CHandle<C_SentrygunShield> m_hShieldModel;
|
||||
|
||||
HPARTICLEFFECT m_hSirenEffect;
|
||||
HPARTICLEFFECT m_hShieldEffect;
|
||||
|
@ -531,6 +531,7 @@ void ClientModeTFNormal::Shutdown()
|
||||
{
|
||||
RemoveFilesInPath( "materials/temp" );
|
||||
RemoveFilesInPath( "download/user_custom" );
|
||||
RemoveFilesInPath( "sound/temp" );
|
||||
}
|
||||
|
||||
DestroyStatsSummaryPanel();
|
||||
|
@ -35,7 +35,7 @@ void CTFAutoRP::ParseDataFile( void )
|
||||
Assert( !m_pDataFileKV );
|
||||
|
||||
// Load & parse the word files
|
||||
KeyValues *pFileKV = new KeyValues( "AutoRPFile" );
|
||||
KeyValuesAD pFileKV( "AutoRPFile" );
|
||||
if ( pFileKV->LoadFromFile( filesystem, "scripts/autorp.txt", "MOD" ) == false )
|
||||
return;
|
||||
|
||||
@ -547,7 +547,7 @@ void CTFAutoRP::ModifySpeech( const char *pszInText, char *pszOutText, int iOutL
|
||||
{
|
||||
szStoredWord[0] = toupper( szStoredWord[0] );
|
||||
}
|
||||
else if ( pszCurWord[0] >= 'a' && pszCurWord[0] <= 'a' )
|
||||
else if ( pszCurWord[0] >= 'a' && pszCurWord[0] <= 'z' )
|
||||
{
|
||||
szStoredWord[0] = tolower( szStoredWord[0] );
|
||||
}
|
||||
|
@ -777,7 +777,7 @@ void CHudMainMenuOverride::LoadCharacterImageFile( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMainMenuOverride::LoadMenuEntries( void )
|
||||
{
|
||||
KeyValues *datafile = new KeyValues("GameMenu");
|
||||
KeyValuesAD datafile("GameMenu");
|
||||
datafile->UsesEscapeSequences( true ); // VGUI uses escape sequences
|
||||
bool bLoaded = datafile->LoadFromFile( g_pFullFileSystem, "Resource/GameMenu.res", "custom_mod" );
|
||||
if ( !bLoaded )
|
||||
@ -2274,7 +2274,7 @@ public:
|
||||
|
||||
//V_strcpy_safe( uilanguage, "german" );
|
||||
|
||||
KeyValues *pEntriesKV = new KeyValues( "motd_entries");
|
||||
KeyValuesAD pEntriesKV( "motd_entries");
|
||||
|
||||
// Try and load the cache file. If we fail, we'll just create a new one.
|
||||
if ( !pMMPanel->ReloadedAllMOTDs() )
|
||||
|
@ -851,7 +851,14 @@ void CWaveStatusPanel::UpdateEnemyCounts( void )
|
||||
|
||||
if ( pPanel->m_pEnemyCountImageBG )
|
||||
{
|
||||
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
|
||||
if ( support[i].iFlags & MVM_CLASS_FLAG_MINIBOSS )
|
||||
{
|
||||
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrMiniBoss );
|
||||
}
|
||||
else
|
||||
{
|
||||
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
|
||||
}
|
||||
}
|
||||
|
||||
if ( pPanel->m_pEnemyCountCritBG )
|
||||
|
@ -574,6 +574,23 @@ void CTFHudMatchStatus::FireGameEvent( IGameEvent * event )
|
||||
}
|
||||
|
||||
const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
|
||||
|
||||
// FIX: Refresh versus doors so late-joiners do not see the wrong skin
|
||||
int nSkin = 0;
|
||||
int nSubModel = 0;
|
||||
if (pMatchDesc->BGetRoundDoorParameters(nSkin, nSubModel))
|
||||
{
|
||||
// Is VS doors model not initialized yet?
|
||||
if (m_pMatchStartModelPanel->m_hModel == NULL)
|
||||
{
|
||||
m_pMatchStartModelPanel->UpdateModel();
|
||||
}
|
||||
|
||||
m_pMatchStartModelPanel->SetBodyGroup( "logos", nSubModel );
|
||||
m_pMatchStartModelPanel->UpdateModel();
|
||||
m_pMatchStartModelPanel->SetSkin( nSkin );
|
||||
}
|
||||
|
||||
bool bForceDoors = false;
|
||||
if ( bForceDoors || ( pMatchDesc && pMatchDesc->BUsesPostRoundDoors() ) )
|
||||
{
|
||||
|
@ -242,6 +242,7 @@ protected:
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *scheme);
|
||||
virtual void Paint( void );
|
||||
virtual bool ShouldDraw( void );
|
||||
virtual bool CanAnimate() const OVERRIDE { return false; }
|
||||
|
||||
private:
|
||||
int m_iScopeTexture[4];
|
||||
|
@ -385,14 +385,6 @@ void CTFMapInfoMenu::LoadMapPage()
|
||||
{
|
||||
m_pMapInfo->SetText( wszMapDescription );
|
||||
}
|
||||
else if ( StringHasPrefix( m_szMapName, "vsh_" ) )
|
||||
{
|
||||
m_pMapInfo->SetText( "#default_vsh_description" );
|
||||
}
|
||||
else if ( StringHasPrefix( m_szMapName, "zi_" ) )
|
||||
{
|
||||
m_pMapInfo->SetText( "#default_zi_description" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// try loading map descriptions from .txt files first
|
||||
@ -497,7 +489,15 @@ void CTFMapInfoMenu::LoadMapPage()
|
||||
|
||||
if( !g_pVGuiLocalize->Find( mapInfoKey ) )
|
||||
{
|
||||
if ( TFGameRules() )
|
||||
if ( StringHasPrefix( m_szMapName, "vsh_" ) )
|
||||
{
|
||||
pszDescription = "#default_vsh_description";
|
||||
}
|
||||
else if ( StringHasPrefix( m_szMapName, "zi_" ) )
|
||||
{
|
||||
pszDescription = "#default_zi_description";
|
||||
}
|
||||
else if ( TFGameRules() )
|
||||
{
|
||||
if ( TFGameRules()->IsMannVsMachineMode() )
|
||||
{
|
||||
|
@ -17,6 +17,10 @@
|
||||
|
||||
static int g_ActiveVoiceMenu = 0;
|
||||
|
||||
#if defined( TF_CLIENT_DLL )
|
||||
extern ConVar tf_voice_command_suspension_mode;
|
||||
#endif
|
||||
|
||||
void OpenVoiceMenu( int index )
|
||||
{
|
||||
// do not show the menu if the player is dead or is an observer
|
||||
@ -28,7 +32,7 @@ void OpenVoiceMenu( int index )
|
||||
return;
|
||||
|
||||
#if defined ( TF_CLIENT_DLL )
|
||||
if ( GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch() )
|
||||
if ( GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch() && tf_voice_command_suspension_mode.GetInt() == 1 )
|
||||
{
|
||||
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
|
||||
if ( pHUDChat )
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
virtual Vector EyePosition( void );
|
||||
|
||||
virtual INextBot *MyNextBotPointer( void ) { return this; }
|
||||
virtual bool IsNextBot(void) const { return true; }
|
||||
|
||||
// Event hooks into NextBot system ---------------------------------------
|
||||
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
||||
|
@ -1165,6 +1165,9 @@ public:
|
||||
void TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType );
|
||||
virtual bool IsTriggered( CBaseEntity *pActivator ) {return true;}
|
||||
virtual bool IsNPC( void ) const { return false; }
|
||||
#ifdef NEXT_BOT
|
||||
virtual bool IsNextBot(void) const { return false; }
|
||||
#endif
|
||||
CAI_BaseNPC *MyNPCPointer( void );
|
||||
virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; }
|
||||
virtual INextBot *MyNextBotPointer( void ) { return NULL; }
|
||||
|
@ -110,9 +110,9 @@ ConVar spec_freeze_traveltime( "spec_freeze_traveltime", "0.4", FCVAR_CHEAT | FC
|
||||
|
||||
ConVar sv_bonus_challenge( "sv_bonus_challenge", "0", FCVAR_REPLICATED, "Set to values other than 0 to select a bonus map challenge type." );
|
||||
|
||||
ConVar sv_chat_bucket_size_tier1( "sv_chat_bucket_size_tier1", "4", FCVAR_NONE, "The maxmimum size of the short term chat msg bucket." );
|
||||
ConVar sv_chat_bucket_size_tier1( "sv_chat_bucket_size_tier1", "4", FCVAR_NONE, "The maximum size of the short term chat msg bucket." );
|
||||
ConVar sv_chat_seconds_per_msg_tier1( "sv_chat_seconds_per_msg_tier1", "3", FCVAR_NONE, "The number of seconds to accrue an additional short term chat msg." );
|
||||
ConVar sv_chat_bucket_size_tier2( "sv_chat_bucket_size_tier2", "30", FCVAR_NONE, "The maxmimum size of the long term chat msg bucket." );
|
||||
ConVar sv_chat_bucket_size_tier2( "sv_chat_bucket_size_tier2", "30", FCVAR_NONE, "The maximum size of the long term chat msg bucket." );
|
||||
ConVar sv_chat_seconds_per_msg_tier2( "sv_chat_seconds_per_msg_tier2", "10", FCVAR_NONE, "The number of seconds to accrue an additional long term chat msg." );
|
||||
|
||||
static ConVar sv_maxusrcmdprocessticks( "sv_maxusrcmdprocessticks", "24", FCVAR_NOTIFY, "Maximum number of client-issued usrcmd ticks that can be replayed in packet loss conditions, 0 to allow no restrictions" );
|
||||
@ -8982,13 +8982,6 @@ void CLogicPlayerInfo::GetPlayerInfo( CBasePlayer *pPlayer )
|
||||
}
|
||||
#endif
|
||||
|
||||
void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp* pProp, const void* pStruct, const void* pVarData, DVariant* pOut, int iElement, int objectID )
|
||||
{
|
||||
int mask = ( 1 << PLAYER_FLAG_BITS ) - 1;
|
||||
int data = *( int* )pVarData;
|
||||
|
||||
pOut->m_Int = ( data & mask );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Needs to shift bits since network table only sends the player ones
|
||||
@ -9088,7 +9081,7 @@ void SendProxy_ShiftPlayerSpawnflags( const SendProp *pProp, const void *pStruct
|
||||
SendPropInt (SENDINFO(m_iBonusProgress), 15 ),
|
||||
SendPropInt (SENDINFO(m_iBonusChallenge), 4 ),
|
||||
SendPropFloat (SENDINFO(m_flMaxspeed), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), // CL
|
||||
SendPropInt (SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN, SendProxy_CropFlagsToPlayerFlagBitsLength ),
|
||||
SendPropInt (SENDINFO(m_fFlags), 0, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN ),
|
||||
SendPropInt (SENDINFO(m_iObserverMode), 3, SPROP_UNSIGNED ),
|
||||
SendPropEHandle (SENDINFO(m_hObserverTarget) ),
|
||||
SendPropInt (SENDINFO(m_iFOV), 8, SPROP_UNSIGNED ),
|
||||
|
@ -523,7 +523,7 @@ void CSlideshowDisplay::BuildSlideShowImagesList( void )
|
||||
char szFullFileName[_MAX_PATH];
|
||||
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName );
|
||||
|
||||
KeyValues *pMaterialKeys = new KeyValues( "material" );
|
||||
KeyValuesAD pMaterialKeys( "material" );
|
||||
bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
|
||||
|
||||
if ( bLoaded )
|
||||
|
@ -1156,6 +1156,9 @@ int CTeamControlPointMaster::GetNumPointsOwnedByTeam( int iTeam )
|
||||
//-----------------------------------------------------------------------------
|
||||
int CTeamControlPointMaster::CalcNumRoundsRemaining( int iTeam )
|
||||
{
|
||||
if ( m_ControlPointRounds.IsEmpty() )
|
||||
return 0;
|
||||
|
||||
// To determine how many rounds remain for a given team if it consistently wins mini-rounds, we have to
|
||||
// simulate forward each mini-round and track the control point ownership that would result
|
||||
|
||||
|
@ -29,7 +29,8 @@ ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::OnStart( CTFBot *me,
|
||||
ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::Update( CTFBot *me, float interval )
|
||||
{
|
||||
CTeamControlPoint *point = me->GetMyControlPoint();
|
||||
if ( !point )
|
||||
CCaptureZone *zone = me->GetFlagCaptureZone();
|
||||
if ( !point && !zone )
|
||||
{
|
||||
// wait until a control point becomes available
|
||||
return Continue();
|
||||
@ -64,7 +65,14 @@ ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::Update( CTFBot *me,
|
||||
if ( !m_path.IsValid() )
|
||||
{
|
||||
CTFBotPathCost cost( me, FASTEST_ROUTE );
|
||||
m_path.Compute( me, point->GetAbsOrigin(), cost );
|
||||
if ( point )
|
||||
{
|
||||
m_path.Compute( me, point->GetAbsOrigin(), cost );
|
||||
}
|
||||
else if ( zone )
|
||||
{
|
||||
m_path.Compute( me, zone->WorldSpaceCenter(), cost );
|
||||
}
|
||||
}
|
||||
|
||||
m_path.Update( me );
|
||||
|
@ -243,7 +243,7 @@ ActionResult< CTFBot > CTFBotDeliverFlag::Update( CTFBot *me, float interval )
|
||||
|
||||
m_flTotalTravelDistance = NavAreaTravelDistance( me->GetLastKnownArea(), TheNavMesh->GetNavArea( zone->WorldSpaceCenter() ), cost );
|
||||
|
||||
if ( flOldTravelDistance != -1.0f && m_flTotalTravelDistance - flOldTravelDistance > 2000.0f )
|
||||
if ( TFGameRules()->IsMannVsMachineMode() && flOldTravelDistance != -1.0f && m_flTotalTravelDistance - flOldTravelDistance > 2000.0f )
|
||||
{
|
||||
TFGameRules()->BroadcastSound( 255, "Announcer.MVM_Bomb_Reset" );
|
||||
|
||||
|
@ -70,7 +70,14 @@ ActionResult< CTFBot > CTFBotSpyHide::Update( CTFBot *me, float interval )
|
||||
if ( m_talkTimer.IsElapsed() )
|
||||
{
|
||||
m_talkTimer.Start( RandomFloat( 5.0f, 10.0f ) );
|
||||
me->EmitSound( "Spy.TeaseVictim" );
|
||||
if ( TFGameRules()->IsMannVsMachineMode() && me->GetTeamNumber() == TF_TEAM_PVE_INVADERS )
|
||||
{
|
||||
me->EmitSound( "Spy.MVM_TeaseVictim" );
|
||||
}
|
||||
else
|
||||
{
|
||||
me->EmitSound( "Spy.TeaseVictim" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_isAtGoal )
|
||||
|
@ -704,9 +704,9 @@ DEFINE_SCRIPTFUNC( IsOnAnyMission, "Return true if this bot has a current missio
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( SetMissionTarget, "Set this bot's mission target to the given entity" )
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( GetMissionTarget, "Get this bot's current mission target" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( SetBehaviorFlag, "Set the given behavior flag(s) for this bot" )
|
||||
DEFINE_SCRIPTFUNC( ClearBehaviorFlag, "Clear the given behavior flag(s) for this bot" )
|
||||
DEFINE_SCRIPTFUNC( IsBehaviorFlagSet, "Return true if the given behavior flag(s) are set for this bot" )
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( SetBehaviorFlag, "Set the given behavior flag(s) for this bot" )
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( ClearBehaviorFlag, "Clear the given behavior flag(s) for this bot" )
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( IsBehaviorFlagSet, "Return true if the given behavior flag(s) are set for this bot" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( SetActionPoint, "Set the given action point for this bot" )
|
||||
DEFINE_SCRIPTFUNC_WRAPPED( GetActionPoint, "Get the given action point for this bot" )
|
||||
|
@ -331,6 +331,9 @@ public:
|
||||
void SetBehaviorFlag( unsigned int flags );
|
||||
void ClearBehaviorFlag( unsigned int flags );
|
||||
bool IsBehaviorFlagSet( unsigned int flags ) const;
|
||||
void ScriptSetBehaviorFlag( int flags ) { this->SetBehaviorFlag( (unsigned int)flags ); }
|
||||
void ScriptClearBehaviorFlag( int flags ) { this->ClearBehaviorFlag( (unsigned int)flags ); }
|
||||
bool ScriptIsBehaviorFlagSet( int flags ) const { return this->IsBehaviorFlagSet( (unsigned int)flags ); }
|
||||
|
||||
bool FindSplashTarget( CBaseEntity *target, float maxSplashRadius, Vector *splashTarget ) const;
|
||||
|
||||
@ -358,11 +361,11 @@ public:
|
||||
CBaseEntity *GetMissionTarget( void ) const;
|
||||
void SetMissionString( CUtlString string );
|
||||
CUtlString *GetMissionString( void );
|
||||
void ScriptSetMission( unsigned int mission, bool resetBehaviorSystem = true ) { this->SetMission( (MissionType)mission, resetBehaviorSystem ); }
|
||||
void ScriptSetPrevMission( unsigned int mission ) { this->SetPrevMission( (MissionType)mission ); }
|
||||
unsigned int ScriptGetMission( void ) const { return (unsigned int)this->GetMission(); }
|
||||
unsigned int ScriptGetPrevMission( void ) const { return (unsigned int)this->GetPrevMission(); }
|
||||
bool ScriptHasMission( unsigned int mission ) const { return this->HasMission( (MissionType)mission ); }
|
||||
void ScriptSetMission( int mission, bool resetBehaviorSystem = true ) { this->SetMission( (MissionType)mission, resetBehaviorSystem ); }
|
||||
void ScriptSetPrevMission( int mission ) { this->SetPrevMission( (MissionType)mission ); }
|
||||
int ScriptGetMission( void ) const { return (int)this->GetMission(); }
|
||||
int ScriptGetPrevMission( void ) const { return (int)this->GetPrevMission(); }
|
||||
bool ScriptHasMission( int mission ) const { return this->HasMission( (MissionType)mission ); }
|
||||
void ScriptSetMissionTarget( HSCRIPT hTarget ) { this->SetMissionTarget( ToEnt( hTarget ) ); }
|
||||
HSCRIPT ScriptGetMissionTarget( void ) const { return ToHScript( this->GetMissionTarget() ); }
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "particle_parse.h"
|
||||
#include "player_vs_environment/tf_population_manager.h"
|
||||
#include "collisionutils.h"
|
||||
#include "func_respawnroom.h"
|
||||
#include "tf_objective_resource.h"
|
||||
|
||||
//=============================================================================
|
||||
@ -209,6 +210,21 @@ void CCurrencyPack::ComeToRest( void )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Or a func_respawnroom (robots can drop money in their own spawn)
|
||||
for ( int i = 0; i < IFuncRespawnRoomAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
CFuncRespawnRoom *pRespawnRoom = static_cast<CFuncRespawnRoom *>( IFuncRespawnRoomAutoList::AutoList()[ i ] );
|
||||
Vector vecMins, vecMaxs;
|
||||
pRespawnRoom->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs );
|
||||
if ( IsPointInBox( GetCollideable()->GetCollisionOrigin(), vecMins, vecMaxs ) )
|
||||
{
|
||||
TFGameRules()->DistributeCurrencyAmount( m_nAmount );
|
||||
|
||||
m_bTouched = true;
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -126,7 +126,6 @@
|
||||
#include "tf_revive.h"
|
||||
#include "tf_logic_halloween_2014.h"
|
||||
#include "tf_logic_player_destruction.h"
|
||||
#include "tf_weapon_rocketpack.h"
|
||||
#include "tf_weapon_slap.h"
|
||||
#include "func_croc.h"
|
||||
#include "tf_weapon_bonesaw.h"
|
||||
@ -278,6 +277,7 @@ extern ConVar sv_vote_allow_spectators;
|
||||
ConVar sv_vote_late_join_time( "sv_vote_late_join_time", "90", FCVAR_NONE, "Grace period after the match starts before players who join the match receive a vote-creation cooldown" );
|
||||
ConVar sv_vote_late_join_cooldown( "sv_vote_late_join_cooldown", "300", FCVAR_NONE, "Length of the vote-creation cooldown when joining the server after the grace period has expired" );
|
||||
|
||||
extern ConVar tf_voice_command_suspension_mode;
|
||||
extern ConVar tf_feign_death_duration;
|
||||
extern ConVar spec_freeze_time;
|
||||
extern ConVar spec_freeze_traveltime;
|
||||
@ -997,7 +997,6 @@ CTFPlayer::CTFPlayer()
|
||||
m_flNextChangeClassTime = 0.0f;
|
||||
m_flNextChangeTeamTime = 0.0f;
|
||||
|
||||
m_bScattergunJump = false;
|
||||
m_iOldStunFlags = 0;
|
||||
m_iLastWeaponSlot = 1;
|
||||
m_iNumberofDominations = 0;
|
||||
@ -1453,35 +1452,6 @@ void CTFPlayer::TFPlayerThink()
|
||||
else
|
||||
{
|
||||
m_iLeftGroundHealth = -1;
|
||||
if ( GetFlags() & FL_ONGROUND )
|
||||
{
|
||||
// Airborne conditions end on ground contact
|
||||
m_Shared.RemoveCond( TF_COND_KNOCKED_INTO_AIR );
|
||||
m_Shared.RemoveCond( TF_COND_AIR_CURRENT );
|
||||
|
||||
if ( m_Shared.InCond( TF_COND_ROCKETPACK ) )
|
||||
{
|
||||
// Make sure we're still not dealing with launch, where it's possible
|
||||
// to hit your head and fall to the ground before the second stage.
|
||||
CTFWeaponBase *pRocketPack = Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK );
|
||||
if ( pRocketPack )
|
||||
{
|
||||
if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) )
|
||||
{
|
||||
EmitSound( "Weapon_RocketPack.BoostersShutdown" );
|
||||
EmitSound( "Weapon_RocketPack.Land" );
|
||||
m_Shared.RemoveCond( TF_COND_ROCKETPACK );
|
||||
|
||||
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" );
|
||||
if ( pEvent )
|
||||
{
|
||||
pEvent->SetInt( "userid", GetUserID() );
|
||||
gameeventmanager->FireEvent( pEvent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_iBlastJumpState )
|
||||
{
|
||||
@ -2833,6 +2803,7 @@ void CTFPlayer::PrecacheMvM()
|
||||
PrecacheScriptSound( "MVM.DeployBombGiant" );
|
||||
PrecacheScriptSound( "Weapon_Upgrade.ExplosiveHeadshot" );
|
||||
PrecacheScriptSound( "Spy.MVM_Chuckle" );
|
||||
PrecacheScriptSound( "Spy.MVM_TeaseVictim" );
|
||||
PrecacheScriptSound( "MVM.Robot_Engineer_Spawn" );
|
||||
PrecacheScriptSound( "MVM.Robot_Teleporter_Deliver" );
|
||||
PrecacheScriptSound( "MVM.MoneyPickup" );
|
||||
@ -3781,7 +3752,6 @@ void CTFPlayer::Spawn()
|
||||
|
||||
m_Shared.SetFeignDeathReady( false );
|
||||
|
||||
m_bScattergunJump = false;
|
||||
m_iOldStunFlags = 0;
|
||||
|
||||
m_flAccumulatedHealthRegen = 0;
|
||||
@ -9127,44 +9097,40 @@ int CTFPlayer::OnTakeDamage( const CTakeDamageInfo &inputInfo )
|
||||
}
|
||||
}
|
||||
|
||||
if ( pTFAttacker && pTFAttacker->IsPlayerClass( TF_CLASS_MEDIC ) )
|
||||
if ( pTFAttacker && pTFAttacker->IsPlayerClass( TF_CLASS_MEDIC ) && pWeapon && pWeapon->GetWeaponID() == TF_WEAPON_BONESAW )
|
||||
{
|
||||
CTFWeaponBase *pAttackerWeapon = pTFAttacker->GetActiveTFWeapon();
|
||||
if ( pAttackerWeapon && pAttackerWeapon->GetWeaponID() == TF_WEAPON_BONESAW )
|
||||
CTFBonesaw *pBoneSaw = static_cast< CTFBonesaw* >( pWeapon );
|
||||
if ( pBoneSaw->GetBonesawType() == BONESAW_UBER_SAVEDONDEATH )
|
||||
{
|
||||
CTFBonesaw *pBoneSaw = static_cast< CTFBonesaw* >( pAttackerWeapon );
|
||||
if ( pBoneSaw->GetBonesawType() == BONESAW_UBER_SAVEDONDEATH )
|
||||
// Spawn their spleen
|
||||
CPhysicsProp *pRandomInternalOrgan = dynamic_cast< CPhysicsProp* >( CreateEntityByName( "prop_physics_override" ) );
|
||||
if ( pRandomInternalOrgan )
|
||||
{
|
||||
// Spawn their spleen
|
||||
CPhysicsProp *pRandomInternalOrgan = dynamic_cast< CPhysicsProp* >( CreateEntityByName( "prop_physics_override" ) );
|
||||
if ( pRandomInternalOrgan )
|
||||
{
|
||||
pRandomInternalOrgan->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
|
||||
pRandomInternalOrgan->AddFlag( FL_GRENADE );
|
||||
char buf[512];
|
||||
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
|
||||
pRandomInternalOrgan->KeyValue( "origin", buf );
|
||||
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z );
|
||||
pRandomInternalOrgan->KeyValue( "angles", buf );
|
||||
pRandomInternalOrgan->KeyValue( "model", "models/player/gibs/random_organ.mdl" );
|
||||
pRandomInternalOrgan->KeyValue( "fademindist", "-1" );
|
||||
pRandomInternalOrgan->KeyValue( "fademaxdist", "0" );
|
||||
pRandomInternalOrgan->KeyValue( "fadescale", "1" );
|
||||
pRandomInternalOrgan->KeyValue( "inertiaScale", "1.0" );
|
||||
pRandomInternalOrgan->KeyValue( "physdamagescale", "0.1" );
|
||||
DispatchSpawn( pRandomInternalOrgan );
|
||||
pRandomInternalOrgan->m_takedamage = DAMAGE_YES; // Take damage, otherwise this can block trains
|
||||
pRandomInternalOrgan->SetHealth( 100 );
|
||||
pRandomInternalOrgan->Activate();
|
||||
pRandomInternalOrgan->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
|
||||
pRandomInternalOrgan->AddFlag( FL_GRENADE );
|
||||
char buf[512];
|
||||
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
|
||||
pRandomInternalOrgan->KeyValue( "origin", buf );
|
||||
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z );
|
||||
pRandomInternalOrgan->KeyValue( "angles", buf );
|
||||
pRandomInternalOrgan->KeyValue( "model", "models/player/gibs/random_organ.mdl" );
|
||||
pRandomInternalOrgan->KeyValue( "fademindist", "-1" );
|
||||
pRandomInternalOrgan->KeyValue( "fademaxdist", "0" );
|
||||
pRandomInternalOrgan->KeyValue( "fadescale", "1" );
|
||||
pRandomInternalOrgan->KeyValue( "inertiaScale", "1.0" );
|
||||
pRandomInternalOrgan->KeyValue( "physdamagescale", "0.1" );
|
||||
DispatchSpawn( pRandomInternalOrgan );
|
||||
pRandomInternalOrgan->m_takedamage = DAMAGE_YES; // Take damage, otherwise this can block trains
|
||||
pRandomInternalOrgan->SetHealth( 100 );
|
||||
pRandomInternalOrgan->Activate();
|
||||
|
||||
Vector vecImpulse = RandomVector( -1.f, 1.f );
|
||||
vecImpulse.z = 1.f;
|
||||
VectorNormalize( vecImpulse );
|
||||
Vector vecVelocity = vecImpulse * 250.0;
|
||||
pRandomInternalOrgan->ApplyAbsVelocityImpulse( vecVelocity );
|
||||
Vector vecImpulse = RandomVector( -1.f, 1.f );
|
||||
vecImpulse.z = 1.f;
|
||||
VectorNormalize( vecImpulse );
|
||||
Vector vecVelocity = vecImpulse * 250.0;
|
||||
pRandomInternalOrgan->ApplyAbsVelocityImpulse( vecVelocity );
|
||||
|
||||
pRandomInternalOrgan->ThinkSet( &CBaseEntity::SUB_Remove, gpGlobals->curtime + 5.f, "DieContext" );
|
||||
}
|
||||
pRandomInternalOrgan->ThinkSet( &CBaseEntity::SUB_Remove, gpGlobals->curtime + 5.f, "DieContext" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20032,7 +19998,20 @@ bool CTFPlayer::ShouldShowVoiceSubtitleToEnemy( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFPlayer::CanSpeakVoiceCommand( void )
|
||||
{
|
||||
return ( gpGlobals->curtime > m_flNextVoiceCommandTime );
|
||||
if ( tf_voice_command_suspension_mode.GetInt() == 1 )
|
||||
return false;
|
||||
|
||||
if ( gpGlobals->curtime <= m_flNextVoiceCommandTime )
|
||||
return false;
|
||||
|
||||
// misyl: New F2P voice command rate-limiting path.
|
||||
if ( BHaveChatSuspensionInCurrentMatch() && tf_voice_command_suspension_mode.GetInt() == 2 )
|
||||
{
|
||||
if ( !m_RateLimitedVoiceCommandTokenBucket.BTakeToken( gpGlobals->curtime ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -66,6 +66,46 @@ enum EAmmoSource
|
||||
kAmmoSource_ResourceMeter, // it regenerated after a cooldown
|
||||
};
|
||||
|
||||
extern ConVar tf_voice_command_suspension_rate_limit_bucket_count;
|
||||
extern ConVar tf_voice_command_suspension_rate_limit_bucket_refill_rate;
|
||||
|
||||
class CVoiceCommandBucketSizer
|
||||
{
|
||||
public:
|
||||
int GetBucketSize() const { return tf_voice_command_suspension_rate_limit_bucket_count.GetInt(); }
|
||||
float GetBucketRefillRate() const { return tf_voice_command_suspension_rate_limit_bucket_refill_rate.GetFloat(); }
|
||||
};
|
||||
|
||||
template <typename TBucketSizer>
|
||||
class CRateLimitingTokenBucket : public TBucketSizer
|
||||
{
|
||||
public:
|
||||
CRateLimitingTokenBucket()
|
||||
: m_nBucket( this->GetBucketSize() )
|
||||
{
|
||||
}
|
||||
|
||||
bool BTakeToken( float flNow )
|
||||
{
|
||||
// misyl: This token bucket doesn't go negative, so you don't ever dig yourself into a hole by spamming.
|
||||
// You might want that if you use this class, feel free to add something to the BucketSizer.
|
||||
|
||||
int nNewBucket = MIN( m_nBucket + ( flNow - m_flLastTokenTaken ) / this->GetBucketRefillRate(), this->GetBucketSize() ) - 1;
|
||||
if ( nNewBucket <= 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nBucket = nNewBucket;
|
||||
m_flLastTokenTaken = flNow;
|
||||
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
float m_flLastTokenTaken = 0.0f;
|
||||
int m_nBucket = 0;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// TF Player
|
||||
@ -483,6 +523,8 @@ public:
|
||||
float m_flNextVoiceCommandTime;
|
||||
int m_iVoiceSpamCounter;
|
||||
|
||||
CRateLimitingTokenBucket<CVoiceCommandBucketSizer> m_RateLimitedVoiceCommandTokenBucket;
|
||||
|
||||
float m_flNextSpeakWeaponFire;
|
||||
|
||||
virtual int CalculateTeamBalanceScore( void );
|
||||
@ -938,7 +980,6 @@ public:
|
||||
|
||||
bool m_bSuicideExplode;
|
||||
|
||||
bool m_bScattergunJump;
|
||||
int m_iOldStunFlags;
|
||||
|
||||
bool m_bFlipViewModels;
|
||||
|
@ -801,7 +801,7 @@ void CAchievementMgr::LoadGlobalState()
|
||||
// HPE_END
|
||||
//=============================================================================
|
||||
|
||||
KeyValues *pKV = new KeyValues("GameState" );
|
||||
KeyValuesAD pKV("GameState" );
|
||||
if ( pKV->LoadFromFile( filesystem, szFilename, "MOD" ) )
|
||||
{
|
||||
KeyValues *pNode = pKV->GetFirstSubKey();
|
||||
|
@ -3143,7 +3143,7 @@ void UTIL_LoadActivityRemapFile( const char *filename, const char *section, CUtl
|
||||
return;
|
||||
}
|
||||
|
||||
KeyValues *pkvFile = new KeyValues( section );
|
||||
KeyValuesAD pkvFile( section );
|
||||
|
||||
if ( pkvFile->LoadFromFile( filesystem, filename, NULL ) )
|
||||
{
|
||||
|
@ -70,8 +70,6 @@ BEGIN_DATADESC( CBaseGrenade )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
@ -108,7 +106,7 @@ BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade )
|
||||
|
||||
SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ),
|
||||
// HACK: Use same flag bits as player for now
|
||||
SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ),
|
||||
SendPropInt ( SENDINFO(m_fFlags), 0, SPROP_UNSIGNED ),
|
||||
#else
|
||||
RecvPropFloat( RECVINFO( m_flDamage ) ),
|
||||
RecvPropFloat( RECVINFO( m_DmgRadius ) ),
|
||||
|
@ -177,10 +177,14 @@ void CEconItemSystem::ReloadWhitelist( void )
|
||||
|
||||
// If we didn't find a file, we're done.
|
||||
if ( !bFoundWhitelist )
|
||||
{
|
||||
pWhitelistKV->deleteThis();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, go through the KVs and turn on the matching items.
|
||||
Msg("Parsing item whitelist (default: %s)\n", bDefault ? "allowed" : "disallowed" );
|
||||
KeyValues* ownerWhitelistKV = pWhitelistKV;
|
||||
pWhitelistKV = pWhitelistKV->GetFirstSubKey();
|
||||
while ( pWhitelistKV )
|
||||
{
|
||||
@ -204,6 +208,8 @@ void CEconItemSystem::ReloadWhitelist( void )
|
||||
pWhitelistKV = pWhitelistKV->GetNextKey();
|
||||
}
|
||||
Msg("Finished.\n");
|
||||
|
||||
ownerWhitelistKV->deleteThis();
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_hl2mp_player.h"
|
||||
#include <prediction.h>
|
||||
#else
|
||||
#include "hl2mp_player.h"
|
||||
#endif
|
||||
@ -146,16 +147,18 @@ void CWeapon357::PrimaryAttack( void )
|
||||
// Fire the bullets, and force the first shot to be perfectly accuracy
|
||||
pPlayer->FireBullets( info );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
//Disorient the player
|
||||
QAngle angles = pPlayer->GetLocalAngles();
|
||||
|
||||
angles.x += random->RandomInt( -1, 1 );
|
||||
angles.y += random->RandomInt( -1, 1 );
|
||||
angles.z = 0;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
pPlayer->SnapEyeAngles( angles );
|
||||
#endif
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
QAngle angles;
|
||||
engine->GetViewAngles( angles );
|
||||
angles.x += random->RandomInt( -1, 1 );
|
||||
angles.y += random->RandomInt( -1, 1 );
|
||||
angles.z += 0.0f;
|
||||
engine->SetViewAngles( angles );
|
||||
}
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
pPlayer->ViewPunch( QAngle( -8, random->RandomFloat( -2, 2 ), 0 ) );
|
||||
|
||||
|
@ -186,7 +186,7 @@ void ParseParticleEffectsMap( const char *pMapName, bool bLoadSheets )
|
||||
V_snprintf( szMapManifestFilename, sizeof( szMapManifestFilename ), "maps/%s_particles.txt", pMapName );
|
||||
}
|
||||
|
||||
KeyValues *manifest = new KeyValues( szMapManifestFilename );
|
||||
KeyValuesAD manifest( szMapManifestFilename );
|
||||
|
||||
// In order:
|
||||
// - particles.txt within the map BSP
|
||||
|
@ -325,6 +325,7 @@ void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int coun
|
||||
char chValue = pValue[iCount];
|
||||
Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%c", chValue );
|
||||
Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
|
||||
break;
|
||||
}
|
||||
case FIELD_COLOR32:
|
||||
{
|
||||
@ -332,6 +333,7 @@ void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int coun
|
||||
byte *pColor = &pValue[iCount*4];
|
||||
Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%d %d %d %d)", ( int )pColor[0], ( int )pColor[1], ( int )pColor[2], ( int )pColor[3] );
|
||||
Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
|
||||
break;
|
||||
}
|
||||
case FIELD_EMBEDDED:
|
||||
case FIELD_CUSTOM:
|
||||
|
@ -53,7 +53,7 @@ ConVar tf_max_charge_speed( "tf_max_charge_speed", "750", FCVAR_NOTIFY | FCVAR_R
|
||||
ConVar tf_parachute_gravity( "tf_parachute_gravity", "0.2f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Gravity while parachute is deployed" );
|
||||
ConVar tf_parachute_maxspeed_xy( "tf_parachute_maxspeed_xy", "300.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max XY Speed while Parachute is deployed" );
|
||||
ConVar tf_parachute_maxspeed_z( "tf_parachute_maxspeed_z", "-100.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed while Parachute is deployed" );
|
||||
ConVar tf_parachute_maxspeed_onfire_z( "tf_parachute_maxspeed_onfire_z", "10.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed when on Fire and Parachute is deployed" );
|
||||
ConVar tf_parachute_maxspeed_onfire_z( "tf_parachute_maxspeed_onfire_z", "-100.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed when on Fire and Parachute is deployed" );
|
||||
ConVar tf_parachute_aircontrol( "tf_parachute_aircontrol", "2.5f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Multiplier for how much air control players have when Parachute is deployed" );
|
||||
ConVar tf_parachute_deploy_toggle_allowed( "tf_parachute_deploy_toggle_allowed", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
@ -1116,12 +1116,6 @@ void CTFGameMovement::PreventBunnyJumping()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFGameMovement::ToggleParachute()
|
||||
{
|
||||
if ( ( m_pTFPlayer->GetFlags() & FL_ONGROUND ) )
|
||||
{
|
||||
m_pTFPlayer->m_Shared.RemoveCond( TF_COND_PARACHUTE_DEPLOYED );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mv->m_nOldButtons & IN_JUMP )
|
||||
return;
|
||||
|
||||
@ -1148,9 +1142,10 @@ void CTFGameMovement::ToggleParachute()
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bOnGround = ( m_pTFPlayer->GetFlags() & FL_ONGROUND );
|
||||
int iParachuteDisabled = 0;
|
||||
CALL_ATTRIB_HOOK_INT_ON_OTHER( m_pTFPlayer, iParachuteDisabled, parachute_disabled );
|
||||
if ( !iParachuteDisabled && ( tf_parachute_deploy_toggle_allowed.GetBool() || !m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
|
||||
if ( !bOnGround && !iParachuteDisabled && ( tf_parachute_deploy_toggle_allowed.GetBool() || !m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
|
||||
{
|
||||
m_pTFPlayer->m_Shared.AddCond( TF_COND_PARACHUTE_ACTIVE );
|
||||
m_pTFPlayer->m_Shared.AddCond( TF_COND_PARACHUTE_DEPLOYED );
|
||||
@ -1382,7 +1377,7 @@ int CTFGameMovement::CheckStuck( void )
|
||||
m_pTFPlayer->GetTeam()->GetName(),
|
||||
m_pTFPlayer->GetAbsOrigin().x, m_pTFPlayer->GetAbsOrigin().y, m_pTFPlayer->GetAbsOrigin().z );
|
||||
|
||||
m_pTFPlayer->TakeDamage( CTakeDamageInfo( m_pTFPlayer, m_pTFPlayer, vec3_origin, m_pTFPlayer->WorldSpaceCenter(), 999999.9f, DMG_CRUSH ) );
|
||||
m_pTFPlayer->CommitSuicide( false, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2630,8 +2625,8 @@ void CTFGameMovement::FullWalkMove()
|
||||
{
|
||||
if ( m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_ACTIVE ) && mv->m_vecVelocity[2] < 0 )
|
||||
{
|
||||
mv->m_vecVelocity[2] = Max( mv->m_vecVelocity[2], tf_parachute_maxspeed_z.GetFloat() );
|
||||
|
||||
mv->m_vecVelocity[2] = Max( mv->m_vecVelocity[2], m_pTFPlayer->m_Shared.InCond( TF_COND_BURNING ) ? tf_parachute_maxspeed_onfire_z.GetFloat() : tf_parachute_maxspeed_z.GetFloat() );
|
||||
|
||||
float flDrag = tf_parachute_maxspeed_xy.GetFloat();
|
||||
// Instead of clamping, we'll dampen
|
||||
float flSpeedX = abs( mv->m_vecVelocity[0] );
|
||||
@ -2957,9 +2952,9 @@ void CTFGameMovement::SetGroundEntity( trace_t *pm )
|
||||
{
|
||||
m_pTFPlayer->SpeakConceptIfAllowed( MP_CONCEPT_DOUBLE_JUMP, "started_jumping:0" );
|
||||
}
|
||||
m_pTFPlayer->m_Shared.SetWeaponKnockbackID( -1 );
|
||||
m_pTFPlayer->m_bScattergunJump = false;
|
||||
#endif // GAME_DLL
|
||||
m_pTFPlayer->m_Shared.SetWeaponKnockbackID( -1 );
|
||||
m_pTFPlayer->m_Shared.m_bScattergunJump = false;
|
||||
m_pTFPlayer->m_Shared.SetAirDash( 0 );
|
||||
m_pTFPlayer->m_Shared.SetAirDucked( 0 );
|
||||
|
||||
|
@ -1107,7 +1107,13 @@ ConVar tf_competitive_required_late_join_confirm_timeout( "tf_competitive_requir
|
||||
|
||||
ConVar tf_gamemode_community ( "tf_gamemode_community", "0", FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
ConVar tf_voice_command_suspension_mode( "tf_voice_command_suspension_mode", "2", FCVAR_REPLICATED, "0 = None | 1 = No Voice Commands | 2 = Rate Limited" );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
ConVar tf_voice_command_suspension_rate_limit_bucket_count( "tf_voice_command_suspension_rate_limit_bucket_count", "5" ); // Bucket size of 5.
|
||||
ConVar tf_voice_command_suspension_rate_limit_bucket_refill_rate( "tf_voice_command_suspension_rate_limit_bucket_refill_rate", "6" ); // 6s
|
||||
|
||||
void cc_powerup_mode( IConVar *pConVar, const char *pOldString, float flOldValue )
|
||||
{
|
||||
ConVarRef var( pConVar );
|
||||
@ -10129,7 +10135,12 @@ VoiceCommandMenuItem_t *CTFGameRules::VoiceCommand( CBaseMultiplayerPlayer *pPla
|
||||
if ( pTFPlayer )
|
||||
{
|
||||
if ( pTFPlayer->BHaveChatSuspensionInCurrentMatch() )
|
||||
return NULL;
|
||||
{
|
||||
if ( tf_voice_command_suspension_mode.GetInt() == 1 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pTFPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) )
|
||||
{
|
||||
@ -16969,7 +16980,7 @@ int CTFGameRules::CalcPlayerScore( RoundStats_t *pRoundStats, CTFPlayer *pPlayer
|
||||
( pRoundStats->m_iStat[TFSTAT_TELEPORTS] / TF_SCORE_TELEPORTS_PER_POINT ) +
|
||||
( pRoundStats->m_iStat[TFSTAT_INVULNS] / TF_SCORE_INVULN ) +
|
||||
( pRoundStats->m_iStat[TFSTAT_REVENGE] / TF_SCORE_REVENGE ) +
|
||||
( pRoundStats->m_iStat[TFSTAT_BONUS_POINTS] / TF_SCORE_BONUS_POINT_DIVISOR );
|
||||
( pRoundStats->m_iStat[TFSTAT_BONUS_POINTS] / TF_SCORE_BONUS_POINT_DIVISOR ) +
|
||||
( pRoundStats->m_iStat[TFSTAT_CURRENCY_COLLECTED] / TF_SCORE_CURRENCY_COLLECTED );
|
||||
|
||||
if ( pPlayer )
|
||||
|
@ -279,7 +279,7 @@ void CTFPowerupBottle::ReapplyProvision( void )
|
||||
// Refill weapon clips
|
||||
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
||||
{
|
||||
CBaseCombatWeapon *pWeapon = pTFPlayer->GetWeapon(i);
|
||||
CTFWeaponBase *pWeapon = dynamic_cast<CTFWeaponBase *>( pTFPlayer->GetWeapon( i ) );
|
||||
if ( !pWeapon )
|
||||
continue;
|
||||
|
||||
@ -287,7 +287,8 @@ void CTFPowerupBottle::ReapplyProvision( void )
|
||||
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||||
{
|
||||
if ( ( pWeapon->UsesPrimaryAmmo() && !pWeapon->HasPrimaryAmmo() ) ||
|
||||
( pWeapon->UsesSecondaryAmmo() && !pWeapon->HasSecondaryAmmo() ) )
|
||||
( pWeapon->UsesSecondaryAmmo() && !pWeapon->HasSecondaryAmmo() ) ||
|
||||
( pWeapon->IsEnergyWeapon() && !pWeapon->Energy_HasEnergy() ) )
|
||||
{
|
||||
pTFPlayer->AwardAchievement( ACHIEVEMENT_TF_MVM_USE_AMMO_BOTTLE );
|
||||
}
|
||||
@ -297,7 +298,7 @@ void CTFPowerupBottle::ReapplyProvision( void )
|
||||
|
||||
if ( iShareBottle && pHealTarget )
|
||||
{
|
||||
CBaseCombatWeapon *pPatientWeapon = pHealTarget->GetWeapon(i);
|
||||
CTFWeaponBase *pPatientWeapon = dynamic_cast<CTFWeaponBase *>( pHealTarget->GetWeapon( i ) );
|
||||
if ( !pPatientWeapon )
|
||||
continue;
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "tf_mapinfo.h"
|
||||
#include "tf_dropped_weapon.h"
|
||||
#include "tf_weapon_passtime_gun.h"
|
||||
#include "tf_weapon_rocketpack.h"
|
||||
#include <functional>
|
||||
|
||||
// Client specific.
|
||||
@ -471,7 +472,10 @@ BEGIN_PREDICTION_DATA_NO_BASE( CTFPlayerShared )
|
||||
DEFINE_PRED_FIELD( m_bHasPasstimeBall, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bIsTargetedForPasstimePass, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), // does this belong here?
|
||||
DEFINE_PRED_FIELD( m_askForBallTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flHolsterAnimTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_flItemChargeMeter, FIELD_FLOAT, LAST_LOADOUT_SLOT_WITH_CHARGE_METER, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_iStunIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bScattergunJump, FIELD_BOOLEAN, 0 ),
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
// Server specific.
|
||||
@ -784,6 +788,8 @@ CTFPlayerShared::CTFPlayerShared()
|
||||
m_flPrevInvisibility = 0.f;
|
||||
m_flTmpDamageBonusAmount = 1.0f;
|
||||
|
||||
m_bScattergunJump = false;
|
||||
|
||||
m_bFeignDeathReady = false;
|
||||
|
||||
m_fCloakConsumeRate = tf_spy_cloak_consume_rate.GetFloat();
|
||||
@ -1005,7 +1011,6 @@ void CTFPlayerShared::Spawn( void )
|
||||
SetRevengeCrits( 0 );
|
||||
|
||||
m_PlayerStuns.RemoveAll();
|
||||
m_iStunIndex = -1;
|
||||
|
||||
m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_NONE;
|
||||
m_bHasPasstimeBall = false;
|
||||
@ -1014,6 +1019,7 @@ void CTFPlayerShared::Spawn( void )
|
||||
#else
|
||||
m_bSyncingConditions = false;
|
||||
#endif
|
||||
m_iStunIndex = -1;
|
||||
m_bKingRuneBuffActive = false;
|
||||
|
||||
// Reset our assist here incase something happens before we get killed
|
||||
@ -3090,9 +3096,46 @@ void CTFPlayerShared::ConditionThink( void )
|
||||
|
||||
VehicleThink();
|
||||
|
||||
if ( m_pOuter->GetFlags() & FL_ONGROUND && InCond( TF_COND_PARACHUTE_ACTIVE ) )
|
||||
if ( m_pOuter->GetFlags() & FL_ONGROUND )
|
||||
{
|
||||
// Airborne conditions end on ground contact
|
||||
RemoveCond( TF_COND_KNOCKED_INTO_AIR );
|
||||
RemoveCond( TF_COND_AIR_CURRENT );
|
||||
|
||||
RemoveCond( TF_COND_PARACHUTE_ACTIVE );
|
||||
RemoveCond( TF_COND_PARACHUTE_DEPLOYED );
|
||||
|
||||
if ( InCond( TF_COND_ROCKETPACK ) )
|
||||
{
|
||||
// Make sure we're still not dealing with launch, where it's possible
|
||||
// to hit your head and fall to the ground before the second stage.
|
||||
CTFWeaponBase *pRocketPack = m_pOuter->Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK );
|
||||
if ( pRocketPack )
|
||||
{
|
||||
if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
#endif
|
||||
{
|
||||
CPASAttenuationFilter filter( m_pOuter );
|
||||
filter.UsePredictionRules();
|
||||
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.BoostersShutdown" );
|
||||
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.Land" );
|
||||
}
|
||||
RemoveCond( TF_COND_ROCKETPACK );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" );
|
||||
if ( pEvent )
|
||||
{
|
||||
pEvent->SetInt( "userid", m_pOuter->GetUserID() );
|
||||
gameeventmanager->FireEvent( pEvent );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if we should be pulsing our radius heal
|
||||
@ -7301,6 +7344,8 @@ void CTFPlayerShared::OnRemoveStunned( void )
|
||||
m_iStunFlags = 0;
|
||||
m_hStunner = NULL;
|
||||
|
||||
m_iStunIndex = -1;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
if ( m_pOuter->m_pStunnedEffect )
|
||||
{
|
||||
@ -7310,7 +7355,6 @@ void CTFPlayerShared::OnRemoveStunned( void )
|
||||
m_pOuter->m_pStunnedEffect = NULL;
|
||||
}
|
||||
#else
|
||||
m_iStunIndex = -1;
|
||||
m_PlayerStuns.RemoveAll();
|
||||
#endif
|
||||
|
||||
@ -9624,15 +9668,16 @@ bool CTFPlayerShared::AddToSpyCloakMeter( float val, bool bForce )
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GAME_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stun & Snare Application
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iStunFlags, CTFPlayer* pAttacker )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
// Insanity prevention
|
||||
if ( ( m_PlayerStuns.Count() + 1 ) >= 250 )
|
||||
return;
|
||||
#endif
|
||||
|
||||
if ( InCond( TF_COND_PHASE ) || InCond( TF_COND_PASSTIME_INTERCEPTION ) )
|
||||
return;
|
||||
@ -9643,15 +9688,19 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
|
||||
if ( InCond( TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED ) && !InCond( TF_COND_MVM_BOT_STUN_RADIOWAVE ) )
|
||||
return;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
if ( pAttacker && TFGameRules() && TFGameRules()->IsTruceActive() && pAttacker->IsTruceValidForEnt() )
|
||||
{
|
||||
if ( ( pAttacker->GetTeamNumber() == TF_TEAM_RED ) || ( pAttacker->GetTeamNumber() == TF_TEAM_BLUE ) )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
float flRemapAmount = RemapValClamped( flReductionAmount, 0.0, 1.0, 0, 255 );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
int iOldStunFlags = GetStunFlags();
|
||||
#endif
|
||||
|
||||
// Already stunned
|
||||
bool bStomp = false;
|
||||
@ -9674,10 +9723,13 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
|
||||
}
|
||||
else if ( GetActiveStunInfo() )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
// Something yanked our TF_COND_STUNNED in an unexpected way
|
||||
if ( !HushAsserts() )
|
||||
Assert( !"Something yanked out TF_COND_STUNNED." );
|
||||
m_PlayerStuns.RemoveAll();
|
||||
#endif
|
||||
m_iStunIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -9699,7 +9751,16 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
|
||||
// This can happen when stuns use TF_STUN_CONTROLS or TF_STUN_LOSER_STATE.
|
||||
float flOldStun = GetActiveStunInfo() ? GetActiveStunInfo()->flStunAmount : 0.f;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
m_iStunIndex = m_PlayerStuns.AddToTail( stunEvent );
|
||||
#else
|
||||
m_iStunIndex = 0;
|
||||
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
m_ActiveStunInfo = stunEvent;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( flOldStun > flRemapAmount )
|
||||
{
|
||||
@ -9709,10 +9770,18 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
|
||||
else
|
||||
{
|
||||
// Done for now
|
||||
#ifdef GAME_DLL
|
||||
m_PlayerStuns.AddToTail( stunEvent );
|
||||
#else
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
m_ActiveStunInfo = stunEvent;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
// Add in extra time when TF_STUN_CONTROLS
|
||||
if ( GetActiveStunInfo()->iStunFlags & TF_STUN_CONTROLS )
|
||||
{
|
||||
@ -9766,10 +9835,10 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
|
||||
m_pOuter->ClearExpression();
|
||||
m_pOuter->ClearWeaponFireScene();
|
||||
}
|
||||
#endif
|
||||
|
||||
AddCond( TF_COND_STUNNED, -1.f, pAttacker );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the intensity of the current stun effect, if we have the type of stun indicated.
|
||||
|
@ -560,9 +560,7 @@ public:
|
||||
|
||||
// Stuns
|
||||
stun_struct_t *GetActiveStunInfo( void ) const;
|
||||
#ifdef GAME_DLL
|
||||
void StunPlayer( float flTime, float flReductionAmount, int iStunFlags = TF_STUN_MOVEMENT, CTFPlayer* pAttacker = NULL );
|
||||
#endif // GAME_DLL
|
||||
float GetAmountStunned( int iStunFlags );
|
||||
bool IsLoserStateStunned( void ) const;
|
||||
bool IsControlStunned( void );
|
||||
@ -1218,6 +1216,8 @@ private:
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool m_bScattergunJump;
|
||||
|
||||
float m_flStunFade;
|
||||
float m_flStunEnd;
|
||||
float m_flStunMid;
|
||||
|
@ -1144,7 +1144,7 @@ protected:
|
||||
|
||||
int nNumJumps = pNonConstPlayer->GetGroundEntity() == NULL ? 1 : 0;
|
||||
nNumJumps += pPlayer->m_Shared.GetAirDash();
|
||||
nNumJumps += pPlayer->m_bScattergunJump;
|
||||
nNumJumps += pPlayer->m_Shared.m_bScattergunJump;
|
||||
|
||||
if ( m_eJumpingState == JUMPING_STATE_IS_NOT_JUMPING )
|
||||
{
|
||||
@ -3027,7 +3027,7 @@ bool CTFJumpStateQuestModifier::BPassesModifier( const CTFPlayer *pOwner, Invali
|
||||
#else
|
||||
int nNumJumps = const_cast< CTFPlayer* >( pOwner )->GetGroundEntity() == NULL ? 1 : 0;
|
||||
nNumJumps += pOwner->m_Shared.GetAirDash();
|
||||
nNumJumps += pOwner->m_bScattergunJump;
|
||||
nNumJumps += pOwner->m_Shared.m_bScattergunJump;
|
||||
|
||||
// If we want them on the ground, make sure they're on the ground
|
||||
if ( m_nJumpCount == 0 )
|
||||
|
@ -2110,7 +2110,7 @@ bool CTFFlameThrower::EffectMeterShouldFlash( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
Vector CTFFlameThrower::GetMuzzlePosHelper( bool bVisualPos )
|
||||
{
|
||||
Vector vecMuzzlePos;
|
||||
Vector vecMuzzlePos = vec3_origin;
|
||||
CTFPlayer *pOwner = GetTFPlayerOwner();
|
||||
if ( pOwner )
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
#include "c_rope.h"
|
||||
#include "prediction.h"
|
||||
// Server specific.
|
||||
#else
|
||||
#include "tf_player.h"
|
||||
@ -47,7 +48,10 @@ END_NETWORK_TABLE()
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CTFRocketPack )
|
||||
DEFINE_PRED_FIELD( m_flInitLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flToggleEndTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flRefireTime, FIELD_FLOAT, 0 ),
|
||||
DEFINE_PRED_FIELD( m_bLaunchedFromGround, FIELD_BOOLEAN, 0 ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
@ -211,10 +215,13 @@ bool CTFRocketPack::InitiateLaunch( void )
|
||||
CTFPlayer *pOwner = GetTFPlayerOwner();
|
||||
if ( !pOwner->m_Shared.IsRocketPackReady() )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
CPVSFilter filter( WorldSpaceCenter() );
|
||||
pOwner->EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersNotReady" );
|
||||
#endif // GAME_DLL
|
||||
// note: this is never reached
|
||||
#ifdef CLIENT_DLL
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" );
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -224,16 +231,18 @@ bool CTFRocketPack::InitiateLaunch( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
if ( pOwner->m_Shared.IsLoser() )
|
||||
#ifdef CLIENT_DLL
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
#endif
|
||||
{
|
||||
pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" );
|
||||
CPASAttenuationFilter filter( pOwner );
|
||||
filter.UsePredictionRules();
|
||||
pOwner->EmitSound(
|
||||
filter,
|
||||
entindex(),
|
||||
pOwner->m_Shared.IsLoser() ? "Weapon_RocketPack.BoostersNotReady" : "Weapon_RocketPack.BoostersCharge"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
pOwner->EmitSound( "Weapon_RocketPack.BoostersCharge" );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
|
||||
m_flInitLaunchTime = gpGlobals->curtime;
|
||||
|
||||
@ -369,7 +378,6 @@ bool CTFRocketPack::ShouldDraw()
|
||||
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
#ifdef GAME_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -384,7 +392,7 @@ Vector CTFRocketPack::CalcRocketForceFromPlayer( CTFPlayer *pPlayer )
|
||||
const float flVertPushScale = ( bOnGround ) ? 0.7f : 0.25f; // Less vertical force while airborne
|
||||
|
||||
Vector vecForward, vecRight;
|
||||
QAngle angAim = ( bOnGround ) ? pPlayer->GetAbsAngles() : pPlayer->EyeAngles();
|
||||
QAngle angAim = pPlayer->EyeAngles();
|
||||
AngleVectors( angAim, &vecForward, &vecRight, NULL );
|
||||
bool bNone = !( pPlayer->m_nButtons & IN_FORWARD ) &&
|
||||
!( pPlayer->m_nButtons & IN_BACK ) /* &&
|
||||
@ -468,7 +476,6 @@ void CTFRocketPack::RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecFor
|
||||
|
||||
pPlayer->ApplyAbsVelocityImpulse( vecForce );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
@ -482,7 +489,6 @@ bool CTFRocketPack::PreLaunch( void )
|
||||
pOwner->DoAnimationEvent( PLAYERANIMEVENT_CUSTOM, ACT_MP_ATTACK_STAND_PRIMARYFIRE );
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
// Negate any fall
|
||||
Vector vecVel = pOwner->GetAbsVelocity();
|
||||
if ( vecVel.z < 0.f )
|
||||
@ -496,14 +502,15 @@ bool CTFRocketPack::PreLaunch( void )
|
||||
pOwner->ApplyAbsVelocityImpulse( vForward );
|
||||
pOwner->m_Shared.AddCond( TF_COND_PARACHUTE_ACTIVE );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
const Vector &vecOrigin = pOwner->GetAbsOrigin();
|
||||
CPVSFilter filter( vecOrigin );
|
||||
TE_TFParticleEffect( filter, 0.f, "heavy_ring_of_fire", vecOrigin, vec3_angle );
|
||||
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_L" );
|
||||
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_R" );
|
||||
#endif // GAME_DLL
|
||||
|
||||
m_flLaunchTime = gpGlobals->curtime + tf_rocketpack_launch_delay.GetFloat();
|
||||
#endif // GAME_DLL
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -519,16 +526,20 @@ bool CTFRocketPack::Launch( void )
|
||||
|
||||
pOwner->StopSound( "Weapon_LooseCannon.Charge" );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
m_flLaunchTime = 0.f;
|
||||
pOwner->m_Shared.RemoveCond( TF_COND_PARACHUTE_ACTIVE );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
Vector m_vecLaunchDir;
|
||||
#endif
|
||||
// Launch
|
||||
m_vecLaunchDir = CalcRocketForceFromPlayer( pOwner );
|
||||
RocketLaunchPlayer( pOwner, m_vecLaunchDir, false );
|
||||
|
||||
|
||||
|
||||
#ifdef GAME_DLL
|
||||
SetContextThink( &CTFRocketPack::PassengerDelayLaunchThink, gpGlobals->curtime + TF_ROCKETPACK_PASSENGER_DELAY_LAUNCH, "PassengerDelayLaunchThink" );
|
||||
#endif
|
||||
|
||||
m_flRefireTime = gpGlobals->curtime + 0.5f;
|
||||
|
||||
@ -536,6 +547,7 @@ bool CTFRocketPack::Launch( void )
|
||||
pOwner->m_Shared.SetRocketPackCharge( pOwner->m_Shared.GetRocketPackCharge() - tf_rocketpack_cost.GetFloat() );
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
// Knock-back nearby enemies
|
||||
float flRadius = 150.f;
|
||||
CUtlVector< CTFPlayer* > vecPushedPlayers;
|
||||
@ -594,6 +606,7 @@ bool CTFRocketPack::Launch( void )
|
||||
}
|
||||
|
||||
CPASAttenuationFilter filter( pOwner );
|
||||
filter.UsePredictionRules();
|
||||
pOwner->EmitSound( filter, pOwner->entindex(), "Weapon_RocketPack.BoostersFire" );
|
||||
|
||||
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_launch" );
|
||||
@ -610,7 +623,12 @@ bool CTFRocketPack::Launch( void )
|
||||
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_LA" );
|
||||
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_RA" );
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
#else
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
pOwner->EmitSound( "Weapon_RocketPack.BoostersFire" );
|
||||
}
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -748,7 +766,7 @@ void CTFRocketPack::ItemPostFrame( void )
|
||||
{
|
||||
ResetTransition();
|
||||
#ifdef CLIENT_DLL
|
||||
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() )
|
||||
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
pOwner->EmitSound( "Weapon_RocketPack.BoostersReady" );
|
||||
}
|
||||
@ -757,7 +775,7 @@ void CTFRocketPack::ItemPostFrame( void )
|
||||
else if ( pOwner->m_afButtonPressed & IN_ATTACK2 )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() )
|
||||
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
pOwner->EmitSound( "Player.DenyWeaponSelection" );
|
||||
}
|
||||
@ -841,14 +859,21 @@ const CEconItemView *CTFRocketPack::GetTauntItem() const
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFRocketPack::Deploy( void )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
CTFPlayer *pOwner = GetTFPlayerOwner();
|
||||
if ( pOwner )
|
||||
{
|
||||
EmitSound( "Weapon_RocketPack.BoostersExtend" );
|
||||
#ifdef CLIENT_DLL
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
#endif
|
||||
{
|
||||
CPASAttenuationFilter filter( pOwner );
|
||||
filter.UsePredictionRules();
|
||||
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersExtend" );
|
||||
}
|
||||
#ifdef GAME_DLL
|
||||
SetEnabled( true );
|
||||
#endif
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
@ -861,14 +886,21 @@ void CTFRocketPack::StartHolsterAnim( void )
|
||||
{
|
||||
BaseClass::StartHolsterAnim();
|
||||
|
||||
#ifdef GAME_DLL
|
||||
CTFPlayer *pOwner = GetTFPlayerOwner();
|
||||
if ( pOwner )
|
||||
{
|
||||
EmitSound( "Weapon_RocketPack.BoostersRetract" );
|
||||
#ifdef CLIENT_DLL
|
||||
if ( prediction->IsFirstTimePredicted() )
|
||||
#endif
|
||||
{
|
||||
CPASAttenuationFilter filter( pOwner );
|
||||
filter.UsePredictionRules();
|
||||
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersRetract" );
|
||||
}
|
||||
#ifdef GAME_DLL
|
||||
SetEnabled( false );
|
||||
#endif
|
||||
}
|
||||
#endif // GAME_DLL
|
||||
}
|
||||
|
||||
|
||||
@ -890,7 +922,7 @@ void CTFRocketPack::OnResourceMeterFilled()
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
CBasePlayer *pPlayer = GetPlayerOwner();
|
||||
if ( pPlayer->IsLocalPlayer() )
|
||||
if ( pPlayer->IsLocalPlayer() && prediction->IsFirstTimePredicted() )
|
||||
{
|
||||
pPlayer->EmitSound( "TFPlayer.ReCharged" );
|
||||
}
|
||||
|
@ -71,14 +71,14 @@ private:
|
||||
bool IsTransitionCompleted( void ) const;
|
||||
void WaitToLaunch( void );
|
||||
|
||||
void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger );
|
||||
Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer );
|
||||
#ifdef GAME_DLL
|
||||
void SetEnabled( bool bEnabled );
|
||||
void PassengerDelayLaunchThink( void );
|
||||
void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger );
|
||||
Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer );
|
||||
#else
|
||||
void CleanupParticles( void );
|
||||
#endif // GAME_DLL
|
||||
#endif // CLIENT_DLL
|
||||
|
||||
CNetworkVar( float, m_flInitLaunchTime );
|
||||
CNetworkVar( float, m_flLaunchTime );
|
||||
|
@ -316,7 +316,6 @@ extern float AirBurstDamageForce( const Vector &size, float damage, float scale
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if ( HasKnockback() )
|
||||
{
|
||||
// Perform some knock back.
|
||||
@ -329,9 +328,9 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
|
||||
return;
|
||||
|
||||
// Knock the firer back!
|
||||
if ( !(pOwner->GetFlags() & FL_ONGROUND) && !pPlayer->m_bScattergunJump )
|
||||
if ( !(pOwner->GetFlags() & FL_ONGROUND) && !pPlayer->m_Shared.m_bScattergunJump )
|
||||
{
|
||||
pPlayer->m_bScattergunJump = true;
|
||||
pPlayer->m_Shared.m_bScattergunJump = true;
|
||||
|
||||
pOwner->m_Shared.StunPlayer( 0.3f, 1.f, TF_STUN_MOVEMENT | TF_STUN_MOVEMENT_FORWARD_ONLY );
|
||||
|
||||
@ -341,15 +340,15 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
|
||||
AngleVectors( pOwner->EyeAngles(), &vecForward );
|
||||
Vector vecForce = vecForward * -flForce;
|
||||
|
||||
EntityMatrix mtxPlayer;
|
||||
mtxPlayer.InitFromEntity( pOwner );
|
||||
VMatrix mtxPlayer;
|
||||
mtxPlayer.SetupMatrixOrgAngles( pOwner->GetAbsOrigin(), pOwner->EyeAngles() );
|
||||
Vector vecAbsVelocity = pOwner->GetAbsVelocity();
|
||||
Vector vecAbsVelocityAsPoint = vecAbsVelocity + pOwner->GetAbsOrigin();
|
||||
Vector vecLocalVelocity = mtxPlayer.WorldToLocal( vecAbsVelocityAsPoint );
|
||||
Vector vecLocalVelocity = mtxPlayer.VMul4x3Transpose( vecAbsVelocityAsPoint );
|
||||
|
||||
vecLocalVelocity.x = -300;
|
||||
|
||||
vecAbsVelocityAsPoint = mtxPlayer.LocalToWorld( vecLocalVelocity );
|
||||
vecAbsVelocityAsPoint = mtxPlayer.VMul4x3( vecLocalVelocity );
|
||||
vecAbsVelocity = vecAbsVelocityAsPoint - pOwner->GetAbsOrigin();
|
||||
pOwner->SetAbsVelocity( vecAbsVelocity );
|
||||
|
||||
@ -360,7 +359,6 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
|
||||
pOwner->RemoveFlag( FL_ONGROUND );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseClass::FireBullet( pPlayer );
|
||||
}
|
||||
|
@ -424,6 +424,19 @@ void CTFWeaponBase::Activate( void )
|
||||
GiveDefaultAmmo();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBase::GiveDefaultAmmo( void )
|
||||
{
|
||||
BaseClass::GiveDefaultAmmo();
|
||||
|
||||
if ( IsEnergyWeapon() )
|
||||
{
|
||||
m_flEnergy = Energy_GetMaxEnergy();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -282,6 +282,7 @@ class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner, public IHasGen
|
||||
|
||||
virtual void Spawn();
|
||||
virtual void Activate( void );
|
||||
virtual void GiveDefaultAmmo( void );
|
||||
virtual void Precache();
|
||||
virtual bool IsPredicted() const { return true; }
|
||||
virtual void FallInit( void );
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
@ -43,7 +43,7 @@ END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
@ -43,7 +43,7 @@ END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -155,7 +155,7 @@ float4 main( PS_INPUT i ) : COLOR
|
||||
if( bFlashlight )
|
||||
{
|
||||
float3 worldSpaceNormal;
|
||||
// Make the unbumped version not so fucking stupid and not need tangentSpaceTranspose you knob.
|
||||
// Make the unbumped version not need tangentSpaceTranspose
|
||||
worldSpaceNormal = mul( normal, i.tangentSpaceTranspose );
|
||||
|
||||
int nShadowSampleLevel = 0;
|
||||
|
@ -121,7 +121,7 @@
|
||||
#define FL_INWATER (1<<9) // In water
|
||||
|
||||
// NOTE if you move things up, make sure to change this value
|
||||
#define PLAYER_FLAG_BITS 10
|
||||
#define PLAYER_FLAG_BITS 32
|
||||
|
||||
#define FL_FLY (1<<10) // Changes the SV_Movestep() behavior to not need to be on ground
|
||||
#define FL_SWIM (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
|
||||
|
@ -101,6 +101,7 @@ public:
|
||||
|
||||
virtual ~CProtoBufMsgBase();
|
||||
|
||||
bool BIsInitialized() const;
|
||||
bool InitFromPacket( IMsgNetPacket * pNetPacket );
|
||||
bool BAsyncSend( IProtoBufSendHandler & pSender ) const;
|
||||
bool BAsyncSendWithPreSerializedBody( IProtoBufSendHandler & pSender, const byte *pubBody, uint32 cubBody ) const;
|
||||
|
@ -41,7 +41,11 @@ protected:
|
||||
virtual void PerformLayout();
|
||||
virtual void Paint();
|
||||
MESSAGE_FUNC( OnMenuClose, "MenuClose" );
|
||||
MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel);
|
||||
#ifdef PLATFORM_64BITS
|
||||
MESSAGE_FUNC_PTR( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel );
|
||||
#else
|
||||
MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel );
|
||||
#endif
|
||||
|
||||
private:
|
||||
CUtlVector<MenuButton *> m_pMenuButtons;
|
||||
|
@ -347,6 +347,8 @@ public:
|
||||
bool IsRightAligned(); // returns true if the settings are aligned to the right of the screen
|
||||
bool IsBottomAligned(); // returns true if the settings are aligned to the bottom of the screen
|
||||
|
||||
virtual bool CanAnimate() const { return true; } // If the panel can animate
|
||||
|
||||
// scheme access functions
|
||||
virtual HScheme GetScheme();
|
||||
virtual void SetScheme(const char *tag);
|
||||
|
727
src/vgui2/matsys_controls/QCGenerator.cpp
Normal file
727
src/vgui2/matsys_controls/QCGenerator.cpp
Normal file
@ -0,0 +1,727 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#if defined(WIN32) && !defined( _X360 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "filesystem.h"
|
||||
#include "filesystem_init.h"
|
||||
#include "appframework/IAppSystemGroup.h"
|
||||
#include "appframework/IAppSystem.h"
|
||||
#include "appframework/AppFramework.h"
|
||||
#include "filesystem_helpers.h"
|
||||
|
||||
#include "matsys_controls/QCGenerator.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "tier2/vconfig.h"
|
||||
#include "vgui_controls/ListPanel.h"
|
||||
#include "vgui_controls/TextEntry.h"
|
||||
#include "vgui_controls/Button.h"
|
||||
#include "vgui_controls/FileOpenDialog.h"
|
||||
#include "vgui_controls/DirectorySelectDialog.h"
|
||||
#include "vgui_controls/ComboBox.h"
|
||||
#include "vgui_controls/CheckButton.h"
|
||||
#include "vgui_controls/MessageBox.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui/IInput.h"
|
||||
#include "vgui/Cursor.h"
|
||||
#include "vgui_controls/KeyBoardEditorDialog.h"
|
||||
|
||||
#if defined( _X360 )
|
||||
#include "xbox/xbox_win32stubs.h"
|
||||
#endif
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
#define MAX_KEYVALUE 1024
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns a pointer to the 'count' occurence of a character from the end of a string
|
||||
// returns 0 of there aren't 'count' number of the character in the string
|
||||
//-----------------------------------------------------------------------------
|
||||
char *strrchrcount(char *string, int character, int count )
|
||||
{
|
||||
int j = count;
|
||||
int numChars = V_strlen( string );
|
||||
for( int i = numChars; i > 0; i-- )
|
||||
{
|
||||
if( string[i-1] == character )
|
||||
{
|
||||
j--;
|
||||
}
|
||||
if( j == 0 )
|
||||
{
|
||||
return string + i-1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CModalPreserveMessageBox : public vgui::MessageBox
|
||||
{
|
||||
public:
|
||||
CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
|
||||
: vgui::MessageBox( title, text, parent )
|
||||
{
|
||||
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
|
||||
}
|
||||
|
||||
~CModalPreserveMessageBox()
|
||||
{
|
||||
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
vgui::VPANEL m_PrevAppFocusPanel;
|
||||
};
|
||||
|
||||
void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
|
||||
{
|
||||
char msg[4096];
|
||||
va_list marker;
|
||||
va_start( marker, pMsg );
|
||||
Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
|
||||
va_end( marker );
|
||||
|
||||
vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
|
||||
dlg->DoModal();
|
||||
dlg->Activate();
|
||||
dlg->RequestFocus();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Places all the info from the vgui controls into the QCInfo struct
|
||||
//-----------------------------------------------------------------------------
|
||||
void QCInfo::SyncFromControls()
|
||||
{
|
||||
char tempText[MAX_PATH];
|
||||
|
||||
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
|
||||
bStaticProp = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
|
||||
bMostlyOpaque = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
|
||||
bDisableCollision = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
|
||||
bReferenceAsPhys = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
|
||||
bConcave = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
|
||||
bAutomass = ((CheckButton *)pTargetField)->IsSelected();
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "massField" );
|
||||
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
|
||||
fMass = atof(tempText);
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
|
||||
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
|
||||
fScale = atof(tempText);
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
|
||||
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
|
||||
V_strcpy_safe( pszCollisionPath, tempText );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
|
||||
((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
|
||||
V_strcpy_safe( pszSurfaceProperty, tempText );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
|
||||
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
|
||||
V_strcpy_safe( pszMaterialPath, tempText );
|
||||
|
||||
LODs.RemoveAll();
|
||||
pTargetField = pQCGenerator->FindChildByName( "LODList" );
|
||||
int numLOD = ((ListPanel *)pTargetField)->GetItemCount();
|
||||
for ( int i = 0; i < numLOD; i++ )
|
||||
{
|
||||
KeyValues *key = ((ListPanel *)pTargetField)->GetItem( i );
|
||||
LODInfo newLOD;
|
||||
|
||||
V_strcpy_safe( newLOD.pszFilename, key->GetString( "SMD" ) );
|
||||
newLOD.iLOD = key->GetInt( "LOD" );
|
||||
LODs.AddToTail( newLOD );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called during intialization to setup the initial state of the VGUI controls
|
||||
//-----------------------------------------------------------------------------
|
||||
void QCInfo::SyncToControls()
|
||||
{
|
||||
char tempText[MAX_PATH];
|
||||
|
||||
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bStaticProp );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bMostlyOpaque );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bDisableCollision );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bReferenceAsPhys );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bConcave );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
|
||||
((CheckButton *)pTargetField)->SetSelected( bAutomass );
|
||||
|
||||
Q_snprintf( tempText, 10, "%d", (int)fMass );
|
||||
pTargetField = pQCGenerator->FindChildByName( "massField" );
|
||||
((TextEntry *)pTargetField)->SetText( tempText );
|
||||
|
||||
Q_snprintf( tempText, 10, "%d", (int)fScale );
|
||||
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
|
||||
((TextEntry *)pTargetField)->SetText( tempText );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
|
||||
((TextEntry *)pTargetField)->SetText( pszCollisionPath );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
|
||||
((TextEntry *)pTargetField)->SetText( pszMaterialPath );
|
||||
|
||||
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
|
||||
int numItems = ((ComboBox *)pTargetField)->GetItemCount();
|
||||
for( int i = 0; i < numItems; i++ )
|
||||
{
|
||||
((ComboBox *)pTargetField)->GetItemText( i, tempText, MAX_PATH );
|
||||
if ( !Q_strcmp( tempText, pszSurfaceProperty ) )
|
||||
{
|
||||
((ComboBox *)pTargetField)->SetItemEnabled( i, true );
|
||||
((ComboBox *)pTargetField)->SetText( tempText );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBrowseButton::CBrowseButton( vgui::Panel *pParent ) : BaseClass( pParent, "Browse Button", "...", pParent, "browse" )
|
||||
{
|
||||
SetParent( pParent );
|
||||
pszStartingDirectory = NULL;
|
||||
pszFileFilter = NULL;
|
||||
pszTargetField = NULL;
|
||||
}
|
||||
|
||||
CBrowseButton::~CBrowseButton()
|
||||
{
|
||||
}
|
||||
|
||||
void CBrowseButton::SetCharVar( char **pVar, const char *pszNewText )
|
||||
{
|
||||
if ( *pVar && pszNewText && !Q_strcmp( *pVar, pszNewText ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( *pVar )
|
||||
{
|
||||
delete [] *pVar;
|
||||
*pVar = NULL;
|
||||
}
|
||||
|
||||
if ( pszNewText )
|
||||
{
|
||||
int len = Q_strlen( pszNewText ) + 1;
|
||||
*pVar = new char[ len ];
|
||||
Q_strncpy( *pVar, pszNewText, len );
|
||||
}
|
||||
}
|
||||
|
||||
void CBrowseButton::InitBrowseInfo( int x, int y, const char *pszName, const char *pszDir, const char *pszFilter, const char *pszField )
|
||||
{
|
||||
SetSize( 24, 24 );
|
||||
SetPos( x, y );
|
||||
SetName( pszName );
|
||||
SetCharVar( GetStartingDirectory(), pszDir );
|
||||
SetCharVar( GetFileFilter(), pszFilter );
|
||||
SetCharVar( GetTargetField(), pszField );
|
||||
SetActionMessage();
|
||||
}
|
||||
|
||||
void CBrowseButton::SetActionMessage()
|
||||
{
|
||||
KeyValues *newActionMessage = new KeyValues( "browse", "directory", pszStartingDirectory, "filter", pszFileFilter);
|
||||
newActionMessage->SetString( "targetField", pszTargetField );
|
||||
SetCommand( newActionMessage );
|
||||
}
|
||||
|
||||
const char *ParseKeyvalue( const char *pBuffer, char *key, char *value )
|
||||
{
|
||||
char com_token[1024];
|
||||
|
||||
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
|
||||
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
|
||||
{
|
||||
Q_strncpy( key, com_token, MAX_KEYVALUE );
|
||||
Q_strlower( key );
|
||||
}
|
||||
// no value on a close brace
|
||||
if ( !Q_strcmp( key, "}" ) )
|
||||
{
|
||||
value[0] = 0;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
|
||||
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
|
||||
{
|
||||
Q_strncpy( value, com_token, MAX_KEYVALUE );
|
||||
Q_strlower( value );
|
||||
}
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CQCGenerator::CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ) : BaseClass( pParent, "QCGenerator" )
|
||||
{
|
||||
m_szTargetField[0] = 0;
|
||||
m_nSelectedSequence = 0;
|
||||
m_nSelectedColumn = 0;
|
||||
|
||||
m_QCInfo_t.Init( this );
|
||||
|
||||
SetMinimumSize(846, 770);
|
||||
|
||||
m_pLODPanel = new ListPanel(this, "LODList");
|
||||
m_pLODPanel->SetSelectIndividualCells( true );
|
||||
m_pLODPanel->AddColumnHeader(0, "SMD", "LOD SMD", 450, 0);
|
||||
m_pLODPanel->AddColumnHeader(1, "LOD", "LOD Distance", 50, 0);
|
||||
m_pLODPanel->AddActionSignalTarget( this );
|
||||
m_pLODPanel->SetMouseInputEnabled( true );
|
||||
|
||||
LoadControlSettings( "QCGenerator.res" );
|
||||
|
||||
m_pCollisionBrowseButton = new CBrowseButton( this );
|
||||
m_pCollisionBrowseButton->InitBrowseInfo( 808, 158, "collisionBrowseButton", pszPath, "*.smd", "collisionSMDField" );
|
||||
|
||||
char szTerminatedPath[1024] = "\0";
|
||||
sprintf( szTerminatedPath, "%s\\", pszPath );
|
||||
|
||||
InitializeSMDPaths( szTerminatedPath, pszScene );
|
||||
|
||||
char *pszMaterialsStart = strrchrcount( szTerminatedPath, '\\', 3 ) + 1;
|
||||
char *pszMaterialsEnd = strrchr( szTerminatedPath, '\\');
|
||||
Q_strncpy( m_QCInfo_t.pszMaterialPath, pszMaterialsStart, pszMaterialsEnd - pszMaterialsStart + 1 );
|
||||
|
||||
SetParent( pParent );
|
||||
|
||||
char szGamePath[1024] = "\0";
|
||||
char szSearchPath[1024] = "\0";
|
||||
|
||||
// Get the currently set game configuration
|
||||
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
|
||||
static const char *pSurfacePropFilename = "\\scripts\\surfaceproperties.txt";
|
||||
|
||||
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
|
||||
|
||||
FileHandle_t fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
|
||||
|
||||
if ( !fp )
|
||||
{
|
||||
//the set game configuration didn't have a surfaceproperties file; we are grabbing it from hl2
|
||||
//TODO: This only works if they are in a subdirectory that is a peer to an hl2 directory
|
||||
// that contains the file. It potentially needs to search the entire drive or prompt for the location
|
||||
char *pszEndGamePath = Q_strrchr( szGamePath, '\\' );
|
||||
pszEndGamePath[0] = 0;
|
||||
V_strcat_safe( szGamePath, "\\hl2" );
|
||||
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
|
||||
fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
|
||||
}
|
||||
|
||||
int len = g_pFullFileSystem->Size( fp );
|
||||
|
||||
const char *szSurfacePropContents = new char[len+1];
|
||||
g_pFullFileSystem->Read( (void *)szSurfacePropContents, len, fp );
|
||||
|
||||
char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
|
||||
|
||||
vgui::Panel *pSurfacePropDropDown = FindChildByName( "surfacePropertyDropDown" );
|
||||
|
||||
//filling up the surface property dropdown
|
||||
while ( szSurfacePropContents )
|
||||
{
|
||||
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
|
||||
((ComboBox *)pSurfacePropDropDown)->AddItem( key, NULL );
|
||||
while ( szSurfacePropContents )
|
||||
{
|
||||
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
|
||||
if (!stricmp( key, "}" ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_QCInfo_t.SyncToControls();
|
||||
|
||||
m_pLODEdit = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CQCGenerator::~CQCGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
void CQCGenerator::OnCommand( const char *command )
|
||||
{
|
||||
if ( Q_stricmp( command, "createQC" ) == 0 )
|
||||
{
|
||||
m_QCInfo_t.SyncFromControls();
|
||||
GenerateQCFile();
|
||||
}
|
||||
if ( Q_stricmp( command, "deleteSeq" ) == 0 )
|
||||
{
|
||||
//delete it
|
||||
DeleteLOD();
|
||||
}
|
||||
if ( Q_stricmp( command, "editSeq" ) == 0 )
|
||||
{
|
||||
//edit
|
||||
EditLOD();
|
||||
}
|
||||
|
||||
BaseClass::OnCommand( command );
|
||||
}
|
||||
|
||||
|
||||
void CQCGenerator::OnKeyCodeTyped( KeyCode code )
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case KEY_ENTER:
|
||||
EditLOD();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CQCGenerator::OnBrowse( KeyValues *data )
|
||||
{
|
||||
V_strcpy_safe( m_szTargetField, data->GetString( "targetField" ) );
|
||||
const char *filter = data->GetString( "filter" );
|
||||
|
||||
if ( Q_strlen( filter ) == 0 )
|
||||
{
|
||||
// BrowseDirectory( data );
|
||||
}
|
||||
else
|
||||
{
|
||||
BrowseFile( data );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//This function is no longer used in the current version of the program.
|
||||
void CQCGenerator::BrowseDirectory( KeyValues *data )
|
||||
{
|
||||
DirectorySelectDialog *pDialog = new DirectorySelectDialog( this, "Select Directory" );
|
||||
pDialog->AddActionSignalTarget( this );
|
||||
pDialog->DoModal();
|
||||
pDialog->SetStartDirectory( data->GetString( "directory" ) );
|
||||
}
|
||||
*/
|
||||
|
||||
void CQCGenerator::BrowseFile( KeyValues *data )
|
||||
{
|
||||
const char *filter = data->GetString( "filter" );
|
||||
|
||||
FileOpenDialog *pDialog = new FileOpenDialog( this, "Select File", true );
|
||||
pDialog->AddFilter( filter, filter, true );
|
||||
pDialog->AddActionSignalTarget(this);
|
||||
pDialog->SetStartDirectory( data->GetString( "directory" ) );
|
||||
pDialog->DoModal( true );
|
||||
}
|
||||
|
||||
void CQCGenerator::OnFileSelected( KeyValues *data )
|
||||
{
|
||||
if ( *m_szTargetField )
|
||||
{
|
||||
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
|
||||
((TextEntry *)pTargetField)->SetText( data->GetString( "fullpath" ) );
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void CQCGenerator::OnDirectorySelected( KeyValues *data )
|
||||
{
|
||||
if ( *m_szTargetField )
|
||||
{
|
||||
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
|
||||
((TextEntry *)pTargetField)->SetText( data->GetString( "dir" ) );
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
bool CQCGenerator::GenerateQCFile()
|
||||
{
|
||||
//TODO: clean this up. Consider creating a datatype that includes the string to write out when the QC file is created
|
||||
char *nameBegin = strrchr( m_QCInfo_t.pszSMDPath, '\\' );
|
||||
|
||||
char szPath[MAX_PATH];
|
||||
char szName[MAX_PATH];
|
||||
Q_strncpy( szPath, m_QCInfo_t.pszSMDPath, nameBegin - m_QCInfo_t.pszSMDPath + 2 );
|
||||
V_strcpy_safe( szName, szPath);
|
||||
V_strcat_safe( szName, m_QCInfo_t.pszSceneName);
|
||||
V_strcat_safe( szName, ".qc" );
|
||||
FileHandle_t pSaveFile = g_pFullFileSystem->Open( szName, "wt" );
|
||||
if (!pSaveFile)
|
||||
{
|
||||
char szSaveError[1024] = "";
|
||||
Q_snprintf( szSaveError, 1024, "Save failed: invalid file name '%s'\n\nDirectory '%s' must exist.", szName, szPath );
|
||||
VGUIMessageBox( this, "QC Generator error", szSaveError );
|
||||
return 0;
|
||||
}
|
||||
|
||||
//write qc header
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "//\n// .qc file version 1.0\n\n");
|
||||
//write out modelname info
|
||||
char szModelName[MAX_PATH];
|
||||
char *modelStart = strrchrcount( szName, '\\', 2) + 1;
|
||||
char *modelEnd = strrchr( szName, '.' );
|
||||
Q_strncpy( szModelName, modelStart, modelEnd - modelStart + 1 );
|
||||
V_strcat_safe( szModelName, ".mdl" );
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$modelname %s\n\n", szModelName );
|
||||
//write out scale info
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$scale %f\n", m_QCInfo_t.fScale );
|
||||
//write out body info
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$body \"Body\" \"%s\"\n", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
|
||||
|
||||
if ( m_QCInfo_t.bStaticProp == true )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$staticprop\n" );
|
||||
}
|
||||
|
||||
if ( m_QCInfo_t.bMostlyOpaque == true )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$mostlyopaque\n" );
|
||||
}
|
||||
|
||||
//write out surfaceprop info
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$surfaceprop \"%s\"\n\n", m_QCInfo_t.pszSurfaceProperty );
|
||||
//write materials
|
||||
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$cdmaterials %s\n\n", m_QCInfo_t.pszMaterialPath);
|
||||
|
||||
if ( m_QCInfo_t.bStaticProp || m_QCInfo_t.bNoAnimation )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "// --------- Animation sequences -------\n");
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$sequence \"idle\" \"%s\" fps 30\n\n", strrchr(m_QCInfo_t.pszSMDPath, '\\')+1);
|
||||
}
|
||||
|
||||
//write out lod info
|
||||
for( int i = 0; i < m_QCInfo_t.LODs.Count(); i++ )
|
||||
{
|
||||
LODInfo thisLOD = m_QCInfo_t.LODs.Element( i );
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$lod %d\n{\n\treplacemodel \"%s\" \"%s\"\n}\n\n", thisLOD.iLOD, strrchr(m_QCInfo_t.pszSMDPath, '\\')+1, thisLOD.pszFilename );
|
||||
}
|
||||
|
||||
if ( m_QCInfo_t.bDisableCollision != true )
|
||||
{
|
||||
//write out collision header
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "\n" );
|
||||
//write out collision info
|
||||
if ( m_QCInfo_t.bReferenceAsPhys == true )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( Q_strcmp( m_QCInfo_t.pszCollisionPath, "" ) )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszCollisionPath, '\\' ) + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, " {\n\t// Mass in kilograms\n ");
|
||||
|
||||
if ( m_QCInfo_t.bAutomass == true )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "\t$automass\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "\t$mass %f\n", m_QCInfo_t.fMass );
|
||||
}
|
||||
|
||||
if ( m_QCInfo_t.bConcave == true )
|
||||
{
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "\t$concave\n" );
|
||||
}
|
||||
g_pFullFileSystem->FPrintf( pSaveFile, "}\n\n");
|
||||
}
|
||||
|
||||
g_pFullFileSystem->Close( pSaveFile );
|
||||
|
||||
char szCommand[MAX_PATH];
|
||||
char szGamePath[MAX_PATH];
|
||||
|
||||
char studiomdlPath[512];
|
||||
g_pFullFileSystem->RelativePathToFullPath( "studiomdl.bat", NULL, studiomdlPath, sizeof( studiomdlPath ));
|
||||
|
||||
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
|
||||
|
||||
#ifdef WIN32
|
||||
STARTUPINFO startup;
|
||||
PROCESS_INFORMATION process;
|
||||
|
||||
|
||||
memset(&startup, 0, sizeof(startup));
|
||||
startup.cb = sizeof(startup);
|
||||
|
||||
|
||||
sprintf( szCommand, "%s -game %s %s", studiomdlPath, szGamePath, szName);
|
||||
bool bReturn = CreateProcess( NULL, szCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startup, &process);
|
||||
#else
|
||||
Assert( !"Implement me, why aren't we using a thread tool abstraction?" );
|
||||
bool bReturn = false;
|
||||
#endif
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
void CQCGenerator::InitializeSMDPaths( const char *pszPath, const char *pszScene )
|
||||
{
|
||||
V_strcpy_safe( m_QCInfo_t.pszSceneName, pszScene );
|
||||
|
||||
FileFindHandle_t *pFileHandle = new FileFindHandle_t();
|
||||
|
||||
g_pFullFileSystem->AddSearchPath( pszPath, "SMD_DIR" );
|
||||
|
||||
const char *filename = g_pFullFileSystem->FindFirst( "*.smd", pFileHandle );
|
||||
|
||||
bool bFoundReference = false;
|
||||
bool bFoundCollision = false;
|
||||
bool bFoundLOD = false;
|
||||
|
||||
//iterate through .smd files
|
||||
const char *startName = pszScene;
|
||||
|
||||
int nSearchLength = Q_strlen( pszScene );
|
||||
|
||||
int currentLOD = 1;
|
||||
|
||||
while( filename )
|
||||
{
|
||||
if ( !strncmp( startName, filename, nSearchLength ) )
|
||||
{
|
||||
const char *filenameEnd = filename + nSearchLength;
|
||||
if ( !strncmp( filenameEnd, "_ref", 4 ) || !strncmp( filenameEnd, ".smd", 4 ) )
|
||||
{
|
||||
bFoundReference = true;
|
||||
//we have found the reference smd.
|
||||
V_strcpy_safe( m_QCInfo_t.pszSMDPath, pszPath );
|
||||
V_strcat_safe( m_QCInfo_t.pszSMDPath, filename );
|
||||
}
|
||||
if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
|
||||
{
|
||||
bFoundCollision = true;
|
||||
//we have found the collision smd.
|
||||
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, pszPath );
|
||||
V_strcat_safe( m_QCInfo_t.pszCollisionPath, filename );
|
||||
}
|
||||
if ( !strncmp( filenameEnd, "_lod", 4) )
|
||||
{
|
||||
bFoundLOD = true;
|
||||
//we found an LOD smd.
|
||||
char lodName[255];
|
||||
Q_snprintf( lodName, Q_strlen( lodName ), "lod%d", currentLOD );
|
||||
//we found an LOD
|
||||
KeyValues *newKv = new KeyValues( lodName, "SMD", filename, "LOD", "10" );
|
||||
m_pLODPanel->AddItem( newKv, currentLOD, false, false );
|
||||
currentLOD++;
|
||||
}
|
||||
}
|
||||
filename = g_pFullFileSystem->FindNext( *pFileHandle );
|
||||
}
|
||||
char pszMessage[2048] = "";
|
||||
char pszRefMessage[1024] = "";
|
||||
char pszColMessage[1024] = "";
|
||||
if (!bFoundReference )
|
||||
{
|
||||
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszPath );
|
||||
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszScene );
|
||||
V_strcat_safe( m_QCInfo_t.pszSMDPath, ".smd" );
|
||||
Q_snprintf( pszRefMessage, 1024, "Reference SMD not found.\n\nValid default reference SMDs are %s%s_ref*.smd and %s%s.smd\nUsing default of %s. Model will not compile.\n\n", pszPath, pszScene, pszPath, pszScene, m_QCInfo_t.pszSMDPath );
|
||||
}
|
||||
if ( !bFoundCollision )
|
||||
{
|
||||
Q_snprintf( pszColMessage, 1024, "Collision SMD not found.\n\nThe valid default collision SMD is %s%s_phy*.smd.\nUsing reference SMD as default.\n", pszPath, pszScene );
|
||||
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
|
||||
m_QCInfo_t.bReferenceAsPhys = true;
|
||||
}
|
||||
if ( !bFoundReference || !bFoundCollision)
|
||||
{
|
||||
V_strcpy_safe( pszMessage, pszRefMessage );
|
||||
V_strcat_safe( pszMessage, pszColMessage );
|
||||
VGUIMessageBox( this, "Error Initializing Paths", pszMessage );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CQCGenerator::DeleteLOD()
|
||||
{
|
||||
int numSelected = m_pLODPanel->GetSelectedItemsCount();
|
||||
int selected;
|
||||
for ( int i = numSelected-1; i >= 0; i-- )
|
||||
{
|
||||
selected = m_pLODPanel->GetSelectedItem( i );
|
||||
m_pLODPanel->RemoveItem( selected );
|
||||
}
|
||||
}
|
||||
|
||||
void CQCGenerator::EditLOD()
|
||||
{
|
||||
int numSelected = m_pLODPanel->GetSelectedItemsCount();
|
||||
if ( numSelected == 1 && !m_pLODPanel->IsInEditMode() )
|
||||
{
|
||||
if ( m_pLODEdit )
|
||||
{
|
||||
m_pLODEdit->MarkForDeletion();
|
||||
m_pLODEdit = NULL;
|
||||
}
|
||||
m_pLODEdit = new vgui::TextEntry( this, "Edit" );
|
||||
m_pLODEdit->SendNewLine( true );
|
||||
m_nSelectedSequence = m_pLODPanel->GetSelectedItem( 0 );
|
||||
m_nSelectedColumn = m_pLODPanel->GetSelectedColumn();
|
||||
m_pLODPanel->EnterEditMode( m_nSelectedSequence, m_nSelectedColumn, m_pLODEdit );
|
||||
}
|
||||
}
|
||||
|
||||
void CQCGenerator::OnNewLODText()
|
||||
{
|
||||
KeyValues *pEditItem = m_pLODPanel->GetItem( m_nSelectedSequence );
|
||||
KeyValues *pListItem = pEditItem;
|
||||
wchar_t szEditText[MAX_PATH];
|
||||
|
||||
pEditItem = pEditItem->GetFirstValue();
|
||||
const char *name = pEditItem->GetName();
|
||||
for( int i = 0; i < m_nSelectedColumn; i++ )
|
||||
{
|
||||
pEditItem = pEditItem->GetNextValue();
|
||||
name = pEditItem->GetName();
|
||||
}
|
||||
m_pLODEdit->GetText( szEditText, MAX_PATH );
|
||||
|
||||
pListItem->SetWString( name, szEditText );
|
||||
|
||||
m_pLODPanel->LeaveEditMode();
|
||||
m_pLODPanel->InvalidateLayout();
|
||||
return;
|
||||
}
|
47
src/vgui2/matsys_controls/assetpicker.cpp
Normal file
47
src/vgui2/matsys_controls/assetpicker.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "matsys_controls/assetpicker.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Asset Picker with no preview
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CAssetPicker::CAssetPicker( vgui::Panel *pParent, const char *pAssetType,
|
||||
const char *pExt, const char *pSubDir, const char *pTextType ) :
|
||||
BaseClass( pParent, pAssetType, pExt, pSubDir, pTextType )
|
||||
{
|
||||
CreateStandardControls( this );
|
||||
LoadControlSettingsAndUserConfig( "resource/assetpicker.res" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Modal picker frame
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CAssetPickerFrame::CAssetPickerFrame( vgui::Panel *pParent, const char *pTitle,
|
||||
const char *pAssetType, const char *pExt, const char *pSubDir, const char *pTextType ) :
|
||||
BaseClass( pParent )
|
||||
{
|
||||
SetAssetPicker( new CAssetPicker( this, pAssetType, pExt, pSubDir, pTextType ) );
|
||||
LoadControlSettingsAndUserConfig( "resource/assetpickerframe.res" );
|
||||
SetTitle( pTitle, false );
|
||||
}
|
||||
|
||||
|
||||
|
1625
src/vgui2/matsys_controls/baseassetpicker.cpp
Normal file
1625
src/vgui2/matsys_controls/baseassetpicker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1255
src/vgui2/matsys_controls/colorpickerpanel.cpp
Normal file
1255
src/vgui2/matsys_controls/colorpickerpanel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
200
src/vgui2/matsys_controls/curveeditorpanel.cpp
Normal file
200
src/vgui2/matsys_controls/curveeditorpanel.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "matsys_controls/curveeditorpanel.h"
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui/IInput.h"
|
||||
#include "vgui/MouseCode.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CCurveEditorPanel::CCurveEditorPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
|
||||
{
|
||||
m_nSelectedPoint = -1;
|
||||
SetMouseInputEnabled( true );
|
||||
SetKeyBoardInputEnabled( true );
|
||||
m_nHighlightedPoint = -1;
|
||||
}
|
||||
|
||||
CCurveEditorPanel::~CCurveEditorPanel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Converts screen location to normalized values
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCurveEditorPanel::ScreenToValue( int x, int y, float *pIn, float *pOut )
|
||||
{
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
*pIn = (float)x / (w-1);
|
||||
*pOut = 1.0f - ((float)y / (h-1));
|
||||
}
|
||||
|
||||
void CCurveEditorPanel::ValueToScreen( float flIn, float flOut, int *x, int *y )
|
||||
{
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
*x = (int)(flIn * (w-1) + 0.5f);
|
||||
*y = (h-1) - (int)(flOut * (h-1) + 0.5f);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle input
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCurveEditorPanel::OnMousePressed( vgui::MouseCode code )
|
||||
{
|
||||
BaseClass::OnMousePressed( code );
|
||||
|
||||
int x, y;
|
||||
input()->GetCursorPos( x, y );
|
||||
ScreenToLocal( x, y );
|
||||
|
||||
if ( code == MOUSE_LEFT )
|
||||
{
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
float flIn, flOut;
|
||||
ScreenToValue( x, y, &flIn, &flOut );
|
||||
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
|
||||
m_nSelectedPoint = FindOrAddControlPoint( flIn, flTolerance, flOut );
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorPanel::OnMouseReleased( vgui::MouseCode code )
|
||||
{
|
||||
BaseClass::OnMouseReleased( code );
|
||||
|
||||
if ( code == MOUSE_LEFT )
|
||||
{
|
||||
m_nSelectedPoint = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void CCurveEditorPanel::OnCursorMoved( int x, int y )
|
||||
{
|
||||
BaseClass::OnCursorMoved( x, y );
|
||||
|
||||
float flIn, flOut;
|
||||
ScreenToValue( x, y, &flIn, &flOut );
|
||||
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
|
||||
m_nHighlightedPoint = FindControlPoint( flIn, flTolerance );
|
||||
|
||||
if ( m_nSelectedPoint < 0 )
|
||||
return;
|
||||
m_nSelectedPoint = ModifyControlPoint( m_nSelectedPoint, flIn, flOut );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handles keypresses
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCurveEditorPanel::OnKeyCodePressed( vgui::KeyCode code )
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
|
||||
if ( m_nSelectedPoint >= 0 )
|
||||
{
|
||||
RemoveControlPoint( m_nSelectedPoint );
|
||||
m_nSelectedPoint = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This paints the grid behind the curves
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCurveEditorPanel::PaintBackground( void )
|
||||
{
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
|
||||
vgui::surface()->DrawFilledRect( 0, 0, w, h );
|
||||
|
||||
vgui::surface()->DrawSetColor( 128, 128, 128, 255 );
|
||||
vgui::surface()->DrawLine( 0, h/4, w, h/4 );
|
||||
vgui::surface()->DrawLine( 0, h/2, w, h/2 );
|
||||
vgui::surface()->DrawLine( 0, 3*h/4, w, 3*h/4 );
|
||||
|
||||
vgui::surface()->DrawLine( w/4, 0, w/4, h );
|
||||
vgui::surface()->DrawLine( w/2, 0, w/2, h );
|
||||
vgui::surface()->DrawLine( 3*w/4, 0, 3*w/4, h );
|
||||
|
||||
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
|
||||
vgui::surface()->DrawLine( 0, 0, w, 0 );
|
||||
vgui::surface()->DrawLine( w, 0, w, h );
|
||||
vgui::surface()->DrawLine( w, h, 0, h );
|
||||
vgui::surface()->DrawLine( 0, h, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the color curves operation to edit
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCurveEditorPanel::Paint( void )
|
||||
{
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
int x0 = 0, y0 = 0;
|
||||
|
||||
// FIXME: Add method to draw multiple lines DrawPolyLine connects the 1st and last points... bleah
|
||||
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
|
||||
for ( int i = 0; i < w; ++i )
|
||||
{
|
||||
float flIn = (float)i / (w-1);
|
||||
float flOut = GetValue( flIn );
|
||||
int x = i;
|
||||
int y = (h-1) - (int)(flOut * (h-1) + 0.5f);
|
||||
y = clamp( y, 0, h-1 );
|
||||
|
||||
if ( i != 0 )
|
||||
{
|
||||
vgui::surface()->DrawLine( x0, y0, x, y );
|
||||
}
|
||||
|
||||
x0 = x; y0 = y;
|
||||
}
|
||||
|
||||
|
||||
// This will paint the control points
|
||||
// The currently selected one will be painted red and filled.
|
||||
for ( int i = ControlPointCount(); --i >= 0; )
|
||||
{
|
||||
float flIn, flOut;
|
||||
GetControlPoint( i, &flIn, &flOut );
|
||||
|
||||
int cx, cy;
|
||||
ValueToScreen( flIn, flOut, &cx, &cy );
|
||||
|
||||
if ( (i == m_nSelectedPoint) || ((m_nSelectedPoint == -1) && (i == m_nHighlightedPoint)) )
|
||||
{
|
||||
vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
|
||||
vgui::surface()->DrawFilledRect( cx-3, cy-3, cx+3, cy+3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
|
||||
vgui::surface()->DrawOutlinedRect( cx-3, cy-3, cx+3, cy+3 );
|
||||
}
|
||||
}
|
||||
}
|
301
src/vgui2/matsys_controls/gamefiletreeview.cpp
Normal file
301
src/vgui2/matsys_controls/gamefiletreeview.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#if defined(WIN32) && !defined( _X360 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#undef PropertySheet
|
||||
|
||||
#include "matsys_controls/gamefiletreeview.h"
|
||||
#include "filesystem.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui/Cursor.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// list of all tree view icons
|
||||
//-----------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
IMAGE_FOLDER = 1,
|
||||
IMAGE_OPENFOLDER,
|
||||
IMAGE_FILE,
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameFileTreeView::CGameFileTreeView( Panel *parent, const char *name, const char *pRootFolderName, const char *pRootDir, const char *pExtension ) : BaseClass(parent, name), m_Images( false )
|
||||
{
|
||||
m_RootDir = pRootDir;
|
||||
|
||||
m_Ext = pExtension;
|
||||
m_bUseExt = ( pExtension != NULL );
|
||||
|
||||
m_RootFolderName = pRootFolderName;
|
||||
|
||||
// build our list of images
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) );
|
||||
SetImageList( &m_Images, false );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Refreshes the active file list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::RefreshFileList()
|
||||
{
|
||||
RemoveAll();
|
||||
SetFgColor(Color(216, 222, 211, 255));
|
||||
|
||||
// add the base node
|
||||
KeyValues *pkv = new KeyValues( "root" );
|
||||
pkv->SetString( "text", m_RootFolderName );
|
||||
pkv->SetInt( "root", 1 );
|
||||
pkv->SetInt( "expand", 1 );
|
||||
int iRoot = AddItem( pkv, GetRootItemIndex() );
|
||||
pkv->deleteThis();
|
||||
ExpandItem( iRoot, true );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Selects the root folder
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::SelectRoot()
|
||||
{
|
||||
AddSelectedItem( GetRootItemIndex(), true );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the number of root directories
|
||||
//-----------------------------------------------------------------------------
|
||||
int CGameFileTreeView::GetRootDirectoryCount()
|
||||
{
|
||||
return GetNumChildren( GetRootItemIndex() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the ith root directory
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CGameFileTreeView::GetRootDirectory( int nIndex )
|
||||
{
|
||||
int nItemIndex = GetChild( GetRootItemIndex(), nIndex );
|
||||
KeyValues *kv = GetItemData( nItemIndex );
|
||||
if ( !kv )
|
||||
return NULL;
|
||||
return kv->GetString( "path", NULL );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate the root node (necessary since tree view can't have multiple roots)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::PopulateRootNode( int itemIndex )
|
||||
{
|
||||
AddDirectoriesOfNode( itemIndex, m_RootDir );
|
||||
|
||||
if ( m_bUseExt )
|
||||
{
|
||||
AddFilesOfNode( itemIndex, m_RootDir, m_Ext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate the root node with directories
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CGameFileTreeView::DoesDirectoryHaveSubdirectories( const char *pFilePath )
|
||||
{
|
||||
char pSearchString[MAX_PATH];
|
||||
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
|
||||
|
||||
// get the list of files
|
||||
FileFindHandle_t findHandle;
|
||||
|
||||
// generate children
|
||||
// add all the items
|
||||
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
|
||||
while ( pszFileName )
|
||||
{
|
||||
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
|
||||
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
|
||||
return true;
|
||||
|
||||
pszFileName = g_pFullFileSystem->FindNext( findHandle );
|
||||
}
|
||||
|
||||
g_pFullFileSystem->FindClose( findHandle );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate the root node with directories
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::AddDirectoriesOfNode( int itemIndex, const char *pFilePath )
|
||||
{
|
||||
char pSearchString[MAX_PATH];
|
||||
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
|
||||
|
||||
// get the list of files
|
||||
FileFindHandle_t findHandle;
|
||||
|
||||
// generate children
|
||||
// add all the items
|
||||
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
|
||||
while ( pszFileName )
|
||||
{
|
||||
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
|
||||
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
|
||||
{
|
||||
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
|
||||
|
||||
char pFullPath[MAX_PATH];
|
||||
Q_snprintf( pFullPath, sizeof(pFullPath), "%s/%s", pFilePath, pszFileName );
|
||||
Q_FixSlashes( pFullPath );
|
||||
Q_strlower( pFullPath );
|
||||
bool bHasSubdirectories = DoesDirectoryHaveSubdirectories( pFullPath );
|
||||
kv->SetString( "path", pFullPath );
|
||||
|
||||
kv->SetInt( "expand", bHasSubdirectories );
|
||||
kv->SetInt( "dir", 1 );
|
||||
kv->SetInt( "image", IMAGE_FOLDER );
|
||||
|
||||
int itemID = AddItem(kv, itemIndex);
|
||||
kv->deleteThis();
|
||||
|
||||
// mark directories in orange
|
||||
SetItemColorForDirectories( itemID );
|
||||
}
|
||||
|
||||
pszFileName = g_pFullFileSystem->FindNext( findHandle );
|
||||
}
|
||||
|
||||
g_pFullFileSystem->FindClose( findHandle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Populate the root node with files
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::AddFilesOfNode( int itemIndex, const char *pFilePath, const char *pExt )
|
||||
{
|
||||
char pSearchString[MAX_PATH];
|
||||
Q_snprintf( pSearchString, MAX_PATH, "%s\\*.%s", pFilePath, pExt );
|
||||
|
||||
// get the list of files
|
||||
FileFindHandle_t findHandle;
|
||||
|
||||
// generate children
|
||||
// add all the items
|
||||
const char *pszFileName = g_pFullFileSystem->FindFirst( pSearchString, &findHandle );
|
||||
while ( pszFileName )
|
||||
{
|
||||
if ( !g_pFullFileSystem->FindIsDirectory( findHandle ) )
|
||||
{
|
||||
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
|
||||
|
||||
char pFullPath[MAX_PATH];
|
||||
Q_snprintf( pFullPath, MAX_PATH, "%s\\%s", pFilePath, pszFileName );
|
||||
kv->SetString( "path", pFullPath );
|
||||
kv->SetInt( "image", IMAGE_FILE );
|
||||
|
||||
AddItem(kv, itemIndex);
|
||||
kv->deleteThis();
|
||||
}
|
||||
|
||||
pszFileName = g_pFullFileSystem->FindNext( findHandle );
|
||||
}
|
||||
|
||||
g_pFullFileSystem->FindClose( findHandle );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// override to incremental request and show p4 directories
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::GenerateChildrenOfNode(int itemIndex)
|
||||
{
|
||||
KeyValues *pkv = GetItemData(itemIndex);
|
||||
if ( pkv->GetInt("root") )
|
||||
{
|
||||
PopulateRootNode( itemIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pkv->GetInt("dir"))
|
||||
return;
|
||||
|
||||
const char *pFilePath = pkv->GetString("path", "");
|
||||
if (!pFilePath[0])
|
||||
return;
|
||||
|
||||
surface()->SetCursor(dc_waitarrow);
|
||||
|
||||
AddDirectoriesOfNode( itemIndex, pFilePath );
|
||||
|
||||
if ( m_bUseExt )
|
||||
{
|
||||
AddFilesOfNode( itemIndex, pFilePath, m_Ext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setup a context menu whenever a directory is clicked on
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::GenerateContextMenu( int itemIndex, int x, int y )
|
||||
{
|
||||
return;
|
||||
|
||||
/*
|
||||
KeyValues *pkv = GetItemData(itemIndex);
|
||||
const char *pFilePath = pkv->GetString("path", "");
|
||||
if (!pFilePath[0])
|
||||
return;
|
||||
|
||||
Menu *pContext = new Menu(this, "FileContext");
|
||||
pContext->AddMenuItem("Cloak folder", new KeyValues("CloakFolder", "item", itemIndex), GetParent(), NULL);
|
||||
|
||||
// show the context menu
|
||||
pContext->SetPos(x, y);
|
||||
pContext->SetVisible(true);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets an item to be colored as if its a menu
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::SetItemColorForDirectories( int itemID )
|
||||
{
|
||||
// mark directories in orange
|
||||
SetItemFgColor( itemID, Color(224, 192, 0, 255) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setup a smaller font
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameFileTreeView::ApplySchemeSettings(IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings(pScheme);
|
||||
SetFont( pScheme->GetFont("DefaultSmall") );
|
||||
}
|
||||
|
201
src/vgui2/matsys_controls/manipulator.cpp
Normal file
201
src/vgui2/matsys_controls/manipulator.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
#include "matsys_controls/manipulator.h"
|
||||
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
|
||||
#include "vgui/IVGui.h"
|
||||
#include "vgui/IInput.h"
|
||||
#include "vgui/ISystem.h"
|
||||
#include "vgui/MouseCode.h"
|
||||
|
||||
#include "mathlib/vector.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// local helper functions
|
||||
//-----------------------------------------------------------------------------
|
||||
static float UpdateTime( float &flLastTime )
|
||||
{
|
||||
float flTime = vgui::system()->GetFrameTime();
|
||||
float dt = flTime - flLastTime;
|
||||
flLastTime = flTime;
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Base class for manipulators which operate on transforms
|
||||
//-----------------------------------------------------------------------------
|
||||
CTransformManipulator::CTransformManipulator( matrix3x4_t *pTransform ) :
|
||||
m_pTransform( pTransform )
|
||||
{
|
||||
}
|
||||
|
||||
void CTransformManipulator::SetTransform( matrix3x4_t *pTransform )
|
||||
{
|
||||
m_pTransform = pTransform;
|
||||
}
|
||||
|
||||
matrix3x4_t *CTransformManipulator::GetTransform( void )
|
||||
{
|
||||
return m_pTransform;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CPotteryWheelManip - nendo-style camera manipulator
|
||||
//-----------------------------------------------------------------------------
|
||||
CPotteryWheelManip::CPotteryWheelManip( matrix3x4_t *pTransform ) :
|
||||
CTransformManipulator( pTransform ),
|
||||
m_lastx( -1 ), m_lasty( -1 ),
|
||||
m_zoom( 100.0f ), m_altitude( 0.0f ), m_azimuth( 0.0f ),
|
||||
m_prevZoom( 100.0f ), m_prevAltitude( 0.0f ), m_prevAzimuth( 0.0f ),
|
||||
m_flLastMouseTime( 0.0f ), m_flLastTickTime( 0.0f ),
|
||||
m_flSpin( 0.0f ), m_bSpin( false )
|
||||
{
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnBeginManipulation( void )
|
||||
{
|
||||
m_prevZoom = m_zoom;
|
||||
m_prevAltitude = m_altitude;
|
||||
m_prevAzimuth = m_azimuth;
|
||||
m_flLastMouseTime = m_flLastTickTime = vgui::system()->GetFrameTime();
|
||||
m_flSpin = 0.0f;
|
||||
m_bSpin = false;
|
||||
}
|
||||
|
||||
// Sets the zoom level
|
||||
void CPotteryWheelManip::SetZoom( float flZoom )
|
||||
{
|
||||
m_prevZoom = m_zoom = flZoom;
|
||||
}
|
||||
|
||||
|
||||
void CPotteryWheelManip::OnAcceptManipulation( void )
|
||||
{
|
||||
m_flSpin = 0.0f;
|
||||
m_bSpin = false;
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnCancelManipulation( void )
|
||||
{
|
||||
m_zoom = m_prevZoom;
|
||||
m_altitude = m_prevAltitude;
|
||||
m_azimuth = m_prevAzimuth;
|
||||
m_flSpin = 0.0f;
|
||||
m_bSpin = false;
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
|
||||
void CPotteryWheelManip::OnTick( void )
|
||||
{
|
||||
float dt = UpdateTime( m_flLastTickTime );
|
||||
|
||||
if ( m_bSpin )
|
||||
{
|
||||
m_azimuth += dt * m_flSpin;
|
||||
UpdateTransform();
|
||||
}
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnCursorMoved( int x, int y )
|
||||
{
|
||||
float dt = UpdateTime( m_flLastMouseTime );
|
||||
|
||||
if ( m_bSpin )
|
||||
{
|
||||
m_lastx = x;
|
||||
m_lasty = y;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( input()->IsMouseDown( MOUSE_MIDDLE ) )
|
||||
{
|
||||
int dy = y - m_lasty;
|
||||
int dx = x - m_lastx;
|
||||
|
||||
if ( abs( dx ) < 2 * abs( dy ) )
|
||||
{
|
||||
UpdateZoom( 0.2f * dy );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flSpin = (dt != 0.0f) ? 0.002f * dx / dt : 0.0f;
|
||||
m_azimuth += 0.002f * dx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_azimuth += 0.002f * ( x - m_lastx );
|
||||
m_altitude -= 0.002f * ( y - m_lasty );
|
||||
m_altitude = max( (float)-M_PI/2, min( (float)M_PI/2, m_altitude ) );
|
||||
}
|
||||
m_lastx = x;
|
||||
m_lasty = y;
|
||||
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnMousePressed( vgui::MouseCode code, int x, int y )
|
||||
{
|
||||
UpdateTime( m_flLastMouseTime );
|
||||
m_lastx = x;
|
||||
m_lasty = y;
|
||||
m_bSpin = false;
|
||||
m_flSpin = 0.0f;
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnMouseReleased( vgui::MouseCode code, int x, int y )
|
||||
{
|
||||
UpdateTime( m_flLastMouseTime );
|
||||
|
||||
if ( code == MOUSE_MIDDLE )
|
||||
{
|
||||
m_bSpin = ( fabs( m_flSpin ) > 1.0f );
|
||||
}
|
||||
|
||||
m_lastx = x;
|
||||
m_lasty = y;
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::OnMouseWheeled( int delta )
|
||||
{
|
||||
UpdateTime( m_flLastMouseTime );
|
||||
|
||||
UpdateZoom( -10.0f * delta );
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
void CPotteryWheelManip::UpdateTransform()
|
||||
{
|
||||
if ( !m_pTransform )
|
||||
return;
|
||||
|
||||
float y = m_zoom * sin( m_altitude );
|
||||
float xz = m_zoom * cos( m_altitude );
|
||||
float x = xz * sin( m_azimuth );
|
||||
float z = xz * cos( m_azimuth );
|
||||
|
||||
Vector position(x, y, z);
|
||||
AngleMatrix( RadianEuler( -m_altitude, m_azimuth, 0 ), position, *m_pTransform );
|
||||
}
|
||||
|
||||
|
||||
void CPotteryWheelManip::UpdateZoom( float delta )
|
||||
{
|
||||
m_zoom *= pow( 1.01f, delta );
|
||||
}
|
66
src/vgui2/matsys_controls/matsys_controls.vpc
Normal file
66
src/vgui2/matsys_controls/matsys_controls.vpc
Normal file
@ -0,0 +1,66 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// MATSYS_CONTROLS.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$macro SRCDIR "..\.."
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
|
||||
|
||||
$Project "matsys_controls"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "assetpicker.cpp"
|
||||
$File "baseassetpicker.cpp"
|
||||
$File "colorpickerpanel.cpp"
|
||||
$File "curveeditorpanel.cpp"
|
||||
$File "gamefiletreeview.cpp"
|
||||
$File "manipulator.cpp"
|
||||
$File "matsyscontrols.cpp"
|
||||
$File "mdlpanel.cpp"
|
||||
$File "mdlpicker.cpp"
|
||||
$File "mdlsequencepicker.cpp"
|
||||
$File "picker.cpp"
|
||||
$File "potterywheelpanel.cpp"
|
||||
$File "proceduraltexturepanel.cpp"
|
||||
$File "QCGenerator.cpp"
|
||||
$File "sequencepicker.cpp"
|
||||
$File "tgapreviewpanel.cpp"
|
||||
$File "vmtpicker.cpp"
|
||||
$File "vmtpreviewpanel.cpp"
|
||||
$File "vtfpicker.cpp"
|
||||
$File "vtfpreviewpanel.cpp"
|
||||
$File "vmtpanel.cpp"
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\matsys_controls\assetpicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\baseassetpicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\colorpickerpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\gamefiletreeview.h"
|
||||
$File "$SRCDIR\public\matsys_controls\manipulator.h"
|
||||
$File "$SRCDIR\public\matsys_controls\matsyscontrols.h"
|
||||
$File "$SRCDIR\public\matsys_controls\mdlpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\mdlpicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\mdlsequencepicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\picker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\potterywheelpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\proceduraltexturepanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\QCGenerator.h"
|
||||
$File "$SRCDIR\public\matsys_controls\sequencepicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\tgapreviewpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\vmtpicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\vmtpreviewpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\vtfpicker.h"
|
||||
$File "$SRCDIR\public\matsys_controls\vtfpreviewpanel.h"
|
||||
$File "$SRCDIR\public\matsys_controls\vmtpanel.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib bitmap [$WIN32]
|
||||
}
|
||||
}
|
100
src/vgui2/matsys_controls/matsyscontrols.cpp
Normal file
100
src/vgui2/matsys_controls/matsyscontrols.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
#include <materialsystem/imaterialsystem.h>
|
||||
#include <materialsystem/imaterialsystemhardwareconfig.h>
|
||||
#include <datacache/imdlcache.h>
|
||||
#include <VGuiMatSurface/IMatSystemSurface.h>
|
||||
#include <istudiorender.h>
|
||||
#include "vgui_controls/Controls.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
namespace vgui
|
||||
{
|
||||
|
||||
IMaterialSystem *g_pMaterialSystem = NULL;
|
||||
IMaterialSystem *MaterialSystem()
|
||||
{
|
||||
return g_pMaterialSystem;
|
||||
}
|
||||
|
||||
IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig = NULL;
|
||||
IMaterialSystemHardwareConfig *MaterialSystemHardwareConfig()
|
||||
{
|
||||
return g_pMaterialSystemHardwareConfig;
|
||||
}
|
||||
|
||||
IMDLCache *g_pMDLCache = NULL;
|
||||
IMDLCache *MDLCache()
|
||||
{
|
||||
return g_pMDLCache;
|
||||
}
|
||||
|
||||
IMatSystemSurface *g_pMatSystemSurface = NULL;
|
||||
IMatSystemSurface *MatSystemSurface()
|
||||
{
|
||||
return g_pMatSystemSurface;
|
||||
}
|
||||
|
||||
IStudioRender *g_pStudioRender = NULL;
|
||||
IStudioRender *StudioRender()
|
||||
{
|
||||
return g_pStudioRender;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: finds a particular interface in the factory set
|
||||
//-----------------------------------------------------------------------------
|
||||
static void *InitializeInterface( char const *interfaceName, CreateInterfaceFn *factoryList, int numFactories )
|
||||
{
|
||||
void *retval;
|
||||
|
||||
for ( int i = 0; i < numFactories; i++ )
|
||||
{
|
||||
CreateInterfaceFn factory = factoryList[ i ];
|
||||
if ( !factory )
|
||||
continue;
|
||||
|
||||
retval = factory( interfaceName, NULL );
|
||||
if ( retval )
|
||||
return retval;
|
||||
}
|
||||
|
||||
// No provider for requested interface!!!
|
||||
// Assert( !"No provider for requested interface!!!" );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Initializes the controls
|
||||
//-----------------------------------------------------------------------------
|
||||
bool VGui_InitMatSysInterfacesList( const char *moduleName, CreateInterfaceFn *factoryList, int numFactories )
|
||||
{
|
||||
if ( !vgui::VGui_InitInterfacesList( moduleName, factoryList, numFactories ) )
|
||||
return false;
|
||||
|
||||
g_pMaterialSystem = (IMaterialSystem *)InitializeInterface( MATERIAL_SYSTEM_INTERFACE_VERSION, factoryList, numFactories );
|
||||
g_pMatSystemSurface = (IMatSystemSurface *)InitializeInterface( MAT_SYSTEM_SURFACE_INTERFACE_VERSION, factoryList, numFactories );
|
||||
g_pMDLCache = (IMDLCache *)InitializeInterface( MDLCACHE_INTERFACE_VERSION, factoryList, numFactories );
|
||||
g_pStudioRender = (IStudioRender *)InitializeInterface( STUDIO_RENDER_INTERFACE_VERSION, factoryList, numFactories );
|
||||
g_pMaterialSystemHardwareConfig = (IMaterialSystemHardwareConfig *)InitializeInterface( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, factoryList, numFactories );
|
||||
|
||||
// MDL cache + studiorender are optional
|
||||
return ( g_pMaterialSystem && g_pMatSystemSurface && g_pMaterialSystemHardwareConfig );
|
||||
}
|
||||
|
||||
|
||||
} // namespace vgui
|
||||
|
||||
|
||||
|
981
src/vgui2/matsys_controls/mdlpanel.cpp
Normal file
981
src/vgui2/matsys_controls/mdlpanel.cpp
Normal file
@ -0,0 +1,981 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "matsys_controls/mdlpanel.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
||||
#include "materialsystem/imesh.h"
|
||||
#include "vgui/IVGui.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "vgui_controls/Frame.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/fmtstr.h"
|
||||
#include "istudiorender.h"
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
#include "vcollide.h"
|
||||
#include "vcollide_parse.h"
|
||||
#include "bone_setup.h"
|
||||
#include "vphysics_interface.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
DECLARE_BUILD_FACTORY( CMDLPanel );
|
||||
|
||||
static const int THUMBNAIL_SAFE_ZONE_SIZE = 512;
|
||||
static const int THUMBNAIL_SAFE_ZONE_HEIGHT = 92;
|
||||
static const float THUMBNAIL_SAFE_ZONE_HEIGHT_SCALE = (float)THUMBNAIL_SAFE_ZONE_HEIGHT / THUMBNAIL_SAFE_ZONE_SIZE;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Keeps a global clock to autoplay sequences to run from
|
||||
// Also deals with speedScale changes
|
||||
//-----------------------------------------------------------------------------
|
||||
float GetAutoPlayTime( void )
|
||||
{
|
||||
static int g_prevTicks;
|
||||
static float g_time;
|
||||
|
||||
int ticks = Plat_MSTime();
|
||||
|
||||
// limit delta so that float time doesn't overflow
|
||||
if (g_prevTicks == 0)
|
||||
{
|
||||
g_prevTicks = ticks;
|
||||
}
|
||||
|
||||
g_time += ( ticks - g_prevTicks ) / 1000.0f;
|
||||
g_prevTicks = ticks;
|
||||
|
||||
return g_time;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CMDLPanel::CMDLPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
|
||||
{
|
||||
SetVisible( true );
|
||||
|
||||
// Used to poll input
|
||||
vgui::ivgui()->AddTickSignal( GetVPanel() );
|
||||
|
||||
// Deal with the default cubemap
|
||||
ITexture *pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap", NULL, true );
|
||||
m_DefaultEnvCubemap.Init( pCubemapTexture );
|
||||
pCubemapTexture = vgui::MaterialSystem()->FindTexture( "editor/cubemap.hdr", NULL, true );
|
||||
m_DefaultHDREnvCubemap.Init( pCubemapTexture );
|
||||
|
||||
SetIdentityMatrix( m_RootMDL.m_MDLToWorld );
|
||||
m_RootMDL.m_pStudioHdr = NULL;
|
||||
m_RootMDL.m_unMdlCacheSerial = 0;
|
||||
m_bDrawCollisionModel = false;
|
||||
m_bWireFrame = false;
|
||||
m_bGroundGrid = false;
|
||||
m_bLockView = false;
|
||||
m_bLookAtCamera = true;
|
||||
m_bThumbnailSafeZone = false;
|
||||
m_nNumSequenceLayers = 0;
|
||||
ResetAnimationEventState( &m_EventState );
|
||||
}
|
||||
|
||||
CMDLPanel::~CMDLPanel()
|
||||
{
|
||||
m_aMergeMDLs.Purge();
|
||||
m_DefaultEnvCubemap.Shutdown( );
|
||||
m_DefaultHDREnvCubemap.Shutdown();
|
||||
if ( m_RootMDL.m_pStudioHdr )
|
||||
{
|
||||
delete m_RootMDL.m_pStudioHdr;
|
||||
m_RootMDL.m_pStudioHdr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
SetBackgroundColor( GetBgColor() );
|
||||
SetBorder( pScheme->GetBorder( "MenuBorder") );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Rendering options
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetCollsionModel( bool bVisible )
|
||||
{
|
||||
m_bDrawCollisionModel = bVisible;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetGroundGrid( bool bVisible )
|
||||
{
|
||||
m_bGroundGrid = bVisible;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetWireFrame( bool bVisible )
|
||||
{
|
||||
m_bWireFrame = bVisible;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetLockView( bool bLocked )
|
||||
{
|
||||
m_bLockView = bLocked;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetLookAtCamera( bool bLookAtCamera )
|
||||
{
|
||||
m_bLookAtCamera = bLookAtCamera;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetIgnoreDoubleClick( bool bState )
|
||||
{
|
||||
m_bIgnoreDoubleClick = bState;
|
||||
}
|
||||
|
||||
void CMDLPanel::SetThumbnailSafeZone( bool bVisible )
|
||||
{
|
||||
m_bThumbnailSafeZone = bVisible;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Stores the clip
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetMDL( MDLHandle_t handle, void *pProxyData )
|
||||
{
|
||||
m_RootMDL.m_MDL.SetMDL( handle );
|
||||
if ( m_RootMDL.m_pStudioHdr )
|
||||
{
|
||||
delete m_RootMDL.m_pStudioHdr;
|
||||
}
|
||||
m_RootMDL.m_pStudioHdr = new CStudioHdr( m_RootMDL.m_MDL.GetStudioHdr(), g_pMDLCache );
|
||||
m_RootMDL.m_MDL.m_pProxyData = pProxyData;
|
||||
|
||||
Vector vecMins, vecMaxs;
|
||||
GetMDLBoundingBox( &vecMins, &vecMaxs, handle, m_RootMDL.m_MDL.m_nSequence );
|
||||
|
||||
m_RootMDL.m_MDL.m_bWorldSpaceViewTarget = false;
|
||||
m_RootMDL.m_MDL.m_vecViewTarget.Init( 100.0f, 0.0f, vecMaxs.z );
|
||||
|
||||
m_RootMDL.m_flCycleStartTime = 0.f;
|
||||
|
||||
// Set the pose parameters to the default for the mdl
|
||||
SetPoseParameters( NULL, 0 );
|
||||
|
||||
// Clear any sequence layers
|
||||
SetSequenceLayers( NULL, 0 );
|
||||
|
||||
ResetAnimationEventState( &m_EventState );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An MDL was selected
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetMDL( const char *pMDLName, void *pProxyData )
|
||||
{
|
||||
MDLHandle_t hMDLFindResult = vgui::MDLCache()->FindMDL( pMDLName );
|
||||
MDLHandle_t hMDL = pMDLName ? hMDLFindResult : MDLHANDLE_INVALID;
|
||||
if ( vgui::MDLCache()->IsErrorModel( hMDL ) )
|
||||
{
|
||||
hMDL = MDLHANDLE_INVALID;
|
||||
}
|
||||
|
||||
SetMDL( hMDL, pProxyData );
|
||||
|
||||
// FindMDL takes a reference and the the CMDL will also hold a reference for as long as it sticks around. Release the FindMDL reference.
|
||||
int nRef = vgui::MDLCache()->Release( hMDLFindResult );
|
||||
(void)nRef; // Avoid unreferenced variable warning
|
||||
AssertMsg( hMDL == MDLHANDLE_INVALID || nRef > 0, "CMDLPanel::SetMDL referenced a model that has a zero ref count." );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns a model bounding box.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMDLPanel::GetBoundingBox( Vector &vecBoundsMin, Vector &vecBoundsMax )
|
||||
{
|
||||
// Check to see if we have a valid model to look at.
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
return false;
|
||||
|
||||
GetMDLBoundingBox( &vecBoundsMin, &vecBoundsMax, m_RootMDL.m_MDL.GetMDL(), m_RootMDL.m_MDL.m_nSequence );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns a more accurate bounding sphere
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMDLPanel::GetBoundingSphere( Vector &vecCenter, float &flRadius )
|
||||
{
|
||||
// Check to see if we have a valid model to look at.
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
return false;
|
||||
|
||||
Vector vecEngineCenter;
|
||||
GetMDLBoundingSphere( &vecEngineCenter, &flRadius, m_RootMDL.m_MDL.GetMDL(), m_RootMDL.m_MDL.m_nSequence );
|
||||
VectorTransform( vecEngineCenter, m_RootMDL.m_MDLToWorld, vecCenter );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos )
|
||||
{
|
||||
SetIdentityMatrix( m_RootMDL.m_MDLToWorld );
|
||||
AngleMatrix( angRot, vecPos, m_RootMDL.m_MDLToWorld );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the camera to look at the model
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::LookAtMDL()
|
||||
{
|
||||
// Check to see if we have a valid model to look at.
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
return;
|
||||
|
||||
if ( m_bLockView )
|
||||
return;
|
||||
|
||||
float flRadius;
|
||||
Vector vecCenter;
|
||||
GetBoundingSphere( vecCenter, flRadius );
|
||||
LookAt( vecCenter, flRadius );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FIXME: This should be moved into studiorender
|
||||
//-----------------------------------------------------------------------------
|
||||
static ConVar r_showenvcubemap( "r_showenvcubemap", "0", FCVAR_CHEAT );
|
||||
static ConVar r_eyegloss ( "r_eyegloss", "1", FCVAR_ARCHIVE ); // wet eyes
|
||||
static ConVar r_eyemove ( "r_eyemove", "1", FCVAR_ARCHIVE ); // look around
|
||||
static ConVar r_eyeshift_x ( "r_eyeshift_x", "0", FCVAR_ARCHIVE ); // eye X position
|
||||
static ConVar r_eyeshift_y ( "r_eyeshift_y", "0", FCVAR_ARCHIVE ); // eye Y position
|
||||
static ConVar r_eyeshift_z ( "r_eyeshift_z", "0", FCVAR_ARCHIVE ); // eye Z position
|
||||
static ConVar r_eyesize ( "r_eyesize", "0", FCVAR_ARCHIVE ); // adjustment to iris textures
|
||||
static ConVar mat_softwareskin( "mat_softwareskin", "0", FCVAR_CHEAT );
|
||||
static ConVar r_nohw ( "r_nohw", "0", FCVAR_CHEAT );
|
||||
static ConVar r_nosw ( "r_nosw", "0", FCVAR_CHEAT );
|
||||
static ConVar r_teeth ( "r_teeth", "1" );
|
||||
static ConVar r_drawentities ( "r_drawentities", "1", FCVAR_CHEAT );
|
||||
static ConVar r_flex ( "r_flex", "1" );
|
||||
static ConVar r_eyes ( "r_eyes", "1" );
|
||||
static ConVar r_skin ( "r_skin","0", FCVAR_CHEAT );
|
||||
static ConVar r_maxmodeldecal ( "r_maxmodeldecal", "50" );
|
||||
static ConVar r_modelwireframedecal ( "r_modelwireframedecal", "0", FCVAR_CHEAT );
|
||||
static ConVar mat_normals ( "mat_normals", "0", FCVAR_CHEAT );
|
||||
static ConVar r_eyeglintlodpixels ( "r_eyeglintlodpixels", "0", FCVAR_CHEAT );
|
||||
static ConVar r_rootlod ( "r_rootlod", "0" );
|
||||
|
||||
static StudioRenderConfig_t s_StudioRenderConfig;
|
||||
|
||||
void CMDLPanel::UpdateStudioRenderConfig( void )
|
||||
{
|
||||
memset( &s_StudioRenderConfig, 0, sizeof(s_StudioRenderConfig) );
|
||||
|
||||
s_StudioRenderConfig.bEyeMove = !!r_eyemove.GetInt();
|
||||
s_StudioRenderConfig.fEyeShiftX = r_eyeshift_x.GetFloat();
|
||||
s_StudioRenderConfig.fEyeShiftY = r_eyeshift_y.GetFloat();
|
||||
s_StudioRenderConfig.fEyeShiftZ = r_eyeshift_z.GetFloat();
|
||||
s_StudioRenderConfig.fEyeSize = r_eyesize.GetFloat();
|
||||
if( mat_softwareskin.GetInt() || m_bWireFrame )
|
||||
{
|
||||
s_StudioRenderConfig.bSoftwareSkin = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_StudioRenderConfig.bSoftwareSkin = false;
|
||||
}
|
||||
s_StudioRenderConfig.bNoHardware = !!r_nohw.GetInt();
|
||||
s_StudioRenderConfig.bNoSoftware = !!r_nosw.GetInt();
|
||||
s_StudioRenderConfig.bTeeth = !!r_teeth.GetInt();
|
||||
s_StudioRenderConfig.drawEntities = r_drawentities.GetInt();
|
||||
s_StudioRenderConfig.bFlex = !!r_flex.GetInt();
|
||||
s_StudioRenderConfig.bEyes = !!r_eyes.GetInt();
|
||||
s_StudioRenderConfig.bWireframe = m_bWireFrame;
|
||||
s_StudioRenderConfig.bDrawNormals = mat_normals.GetBool();
|
||||
s_StudioRenderConfig.skin = r_skin.GetInt();
|
||||
s_StudioRenderConfig.maxDecalsPerModel = r_maxmodeldecal.GetInt();
|
||||
s_StudioRenderConfig.bWireframeDecals = r_modelwireframedecal.GetInt() != 0;
|
||||
|
||||
s_StudioRenderConfig.fullbright = false;
|
||||
s_StudioRenderConfig.bSoftwareLighting = false;
|
||||
|
||||
s_StudioRenderConfig.bShowEnvCubemapOnly = r_showenvcubemap.GetInt() ? true : false;
|
||||
s_StudioRenderConfig.fEyeGlintPixelWidthLODThreshold = r_eyeglintlodpixels.GetFloat();
|
||||
|
||||
StudioRender()->UpdateConfig( s_StudioRenderConfig );
|
||||
}
|
||||
|
||||
void CMDLPanel::DrawCollisionModel()
|
||||
{
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vcollide_t *pCollide = MDLCache()->GetVCollide( m_RootMDL.m_MDL.GetMDL() );
|
||||
|
||||
if ( !pCollide || pCollide->solidCount <= 0 )
|
||||
return;
|
||||
|
||||
static color32 color = {255,0,0,0};
|
||||
|
||||
IVPhysicsKeyParser *pParser = g_pPhysicsCollision->VPhysicsKeyParserCreate( pCollide->pKeyValues );
|
||||
CStudioHdr &studioHdr = *m_RootMDL.m_pStudioHdr;
|
||||
|
||||
matrix3x4_t pBoneToWorld[MAXSTUDIOBONES];
|
||||
m_RootMDL.m_MDL.SetUpBones( m_RootMDL.m_MDLToWorld, MAXSTUDIOBONES, pBoneToWorld );
|
||||
|
||||
// PERFORMANCE: Just parse the script each frame. It's fast enough for tools. If you need
|
||||
// this to go faster then cache off the bone index mapping in an array like HLMV does
|
||||
while ( !pParser->Finished() )
|
||||
{
|
||||
const char *pBlock = pParser->GetCurrentBlockName();
|
||||
if ( !stricmp( pBlock, "solid" ) )
|
||||
{
|
||||
solid_t solid;
|
||||
|
||||
pParser->ParseSolid( &solid, NULL );
|
||||
int boneIndex = Studio_BoneIndexByName( &studioHdr, solid.name );
|
||||
Vector *outVerts;
|
||||
int vertCount = g_pPhysicsCollision->CreateDebugMesh( pCollide->solids[solid.index], &outVerts );
|
||||
|
||||
if ( vertCount )
|
||||
{
|
||||
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
||||
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
|
||||
// NOTE: assumes these have been set up already by the model render code
|
||||
// So this is a little bit of a back door to a cache of the bones
|
||||
// this code wouldn't work unless you draw the model this frame before calling
|
||||
// this routine. CMDLPanel always does this, but it's worth noting.
|
||||
// A better solution would be to move the ragdoll visulization into the CDmeMdl
|
||||
// and either draw it there or make it queryable and query/draw here.
|
||||
matrix3x4_t xform;
|
||||
SetIdentityMatrix( xform );
|
||||
if ( boneIndex >= 0 )
|
||||
{
|
||||
MatrixCopy( pBoneToWorld[ boneIndex ], xform );
|
||||
}
|
||||
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_Wireframe );
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, vertCount/3 );
|
||||
|
||||
for ( int j = 0; j < vertCount; j++ )
|
||||
{
|
||||
Vector out;
|
||||
VectorTransform( outVerts[j].Base(), xform, out.Base() );
|
||||
meshBuilder.Position3fv( out.Base() );
|
||||
meshBuilder.Color4ub( color.r, color.g, color.b, color.a );
|
||||
meshBuilder.TexCoord2f( 0, 0, 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
g_pPhysicsCollision->DestroyDebugMesh( vertCount, outVerts );
|
||||
}
|
||||
else
|
||||
{
|
||||
pParser->SkipBlock();
|
||||
}
|
||||
}
|
||||
g_pPhysicsCollision->VPhysicsKeyParserDestroy( pParser );
|
||||
}
|
||||
|
||||
void CMDLPanel::SetupRenderState( int nDisplayWidth, int nDisplayHeight )
|
||||
{
|
||||
int iWidth = nDisplayWidth;
|
||||
int iHeight = nDisplayHeight;
|
||||
if ( m_bThumbnailSafeZone )
|
||||
{
|
||||
iWidth = THUMBNAIL_SAFE_ZONE_SIZE;
|
||||
iHeight = THUMBNAIL_SAFE_ZONE_SIZE;
|
||||
}
|
||||
BaseClass::SetupRenderState( iWidth, iHeight );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// paint it!
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::OnPaint3D()
|
||||
{
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
return;
|
||||
|
||||
// FIXME: Move this call into DrawModel in StudioRender
|
||||
StudioRenderConfig_t oldStudioRenderConfig;
|
||||
StudioRender()->GetCurrentConfig( oldStudioRenderConfig );
|
||||
|
||||
UpdateStudioRenderConfig();
|
||||
|
||||
CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() );
|
||||
if ( vgui::MaterialSystemHardwareConfig()->GetHDRType() == HDR_TYPE_NONE )
|
||||
{
|
||||
ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( false ) : m_DefaultEnvCubemap;
|
||||
pRenderContext->BindLocalCubemap( pMyCube );
|
||||
}
|
||||
else
|
||||
{
|
||||
ITexture *pMyCube = HasLightProbe() ? GetLightProbeCubemap( true ) : m_DefaultHDREnvCubemap;
|
||||
pRenderContext->BindLocalCubemap( pMyCube );
|
||||
}
|
||||
|
||||
PrePaint3D( pRenderContext );
|
||||
|
||||
if ( m_bGroundGrid )
|
||||
{
|
||||
DrawGrid();
|
||||
}
|
||||
|
||||
if ( m_bLookAtCamera )
|
||||
{
|
||||
matrix3x4_t worldToCamera;
|
||||
ComputeCameraTransform( &worldToCamera );
|
||||
|
||||
Vector vecPosition;
|
||||
MatrixGetColumn( worldToCamera, 3, vecPosition );
|
||||
m_RootMDL.m_MDL.m_bWorldSpaceViewTarget = true;
|
||||
m_RootMDL.m_MDL.m_vecViewTarget = vecPosition;
|
||||
}
|
||||
|
||||
// Draw the MDL
|
||||
CStudioHdr &studioHdr = *m_RootMDL.m_pStudioHdr;
|
||||
|
||||
SetupFlexWeights();
|
||||
|
||||
matrix3x4_t *pBoneToWorld = g_pStudioRender->LockBoneMatrices( studioHdr.numbones() );
|
||||
m_RootMDL.m_MDL.SetUpBones( m_RootMDL.m_MDLToWorld, studioHdr.numbones(), pBoneToWorld, m_PoseParameters, m_SequenceLayers, m_nNumSequenceLayers );
|
||||
g_pStudioRender->UnlockBoneMatrices();
|
||||
|
||||
IMaterial* pOverrideMaterial = GetOverrideMaterial( m_RootMDL.m_MDL.GetMDL() );
|
||||
if ( pOverrideMaterial != NULL )
|
||||
g_pStudioRender->ForcedMaterialOverride( pOverrideMaterial );
|
||||
|
||||
m_RootMDL.m_MDL.Draw( m_RootMDL.m_MDLToWorld, pBoneToWorld );
|
||||
|
||||
if ( pOverrideMaterial != NULL )
|
||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
||||
|
||||
pOverrideMaterial = NULL;
|
||||
|
||||
// Draw the merge MDLs.
|
||||
matrix3x4_t matMergeBoneToWorld[MAXSTUDIOBONES];
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[iMerge].m_bDisabled )
|
||||
continue;
|
||||
|
||||
// Get the merge studio header.
|
||||
CStudioHdr *pMergeHdr = m_aMergeMDLs[iMerge].m_pStudioHdr;
|
||||
matrix3x4_t *pMergeBoneToWorld = &matMergeBoneToWorld[0];
|
||||
|
||||
// If we have a valid mesh, bonemerge it. If we have an invalid mesh we can't bonemerge because
|
||||
// it'll crash trying to pull data from the missing header.
|
||||
if ( pMergeHdr != NULL )
|
||||
{
|
||||
CStudioHdr &mergeHdr = *pMergeHdr;
|
||||
m_aMergeMDLs[iMerge].m_MDL.SetupBonesWithBoneMerge( &mergeHdr, pMergeBoneToWorld, &studioHdr, pBoneToWorld, m_RootMDL.m_MDLToWorld );
|
||||
|
||||
pOverrideMaterial = GetOverrideMaterial( m_aMergeMDLs[iMerge].m_MDL.GetMDL() );
|
||||
if ( pOverrideMaterial != NULL )
|
||||
g_pStudioRender->ForcedMaterialOverride( pOverrideMaterial );
|
||||
|
||||
m_aMergeMDLs[iMerge].m_MDL.Draw( m_aMergeMDLs[iMerge].m_MDLToWorld, pMergeBoneToWorld );
|
||||
|
||||
if ( pOverrideMaterial != NULL )
|
||||
g_pStudioRender->ForcedMaterialOverride( NULL );
|
||||
|
||||
// Notify of model render
|
||||
RenderingMergedModel( pRenderContext, &mergeHdr, m_aMergeMDLs[iMerge].m_MDL.GetMDL(), pMergeBoneToWorld );
|
||||
}
|
||||
}
|
||||
|
||||
RenderingRootModel( pRenderContext, &studioHdr, m_RootMDL.m_MDL.GetMDL(), pBoneToWorld );
|
||||
|
||||
PostPaint3D( pRenderContext );
|
||||
|
||||
if ( m_bDrawCollisionModel )
|
||||
{
|
||||
DrawCollisionModel();
|
||||
}
|
||||
|
||||
pRenderContext->Flush();
|
||||
StudioRender()->UpdateConfig( oldStudioRenderConfig );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the current LOD
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetLOD( int nLOD )
|
||||
{
|
||||
m_RootMDL.m_MDL.m_nLOD = nLOD;
|
||||
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
m_aMergeMDLs[iMerge].m_MDL.m_nLOD = nLOD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the current sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetSequence( int nSequence, bool bResetSequence )
|
||||
{
|
||||
m_RootMDL.m_MDL.m_nSequence = nSequence;
|
||||
|
||||
if ( bResetSequence )
|
||||
{
|
||||
m_RootMDL.m_flCycleStartTime = GetAutoPlayTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the current pose parameters. If NULL the pose parameters will be reset
|
||||
// to the default values.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetPoseParameters( const float *pPoseParameters, int nCount )
|
||||
{
|
||||
if ( pPoseParameters )
|
||||
{
|
||||
int nParameters = MIN( MAXSTUDIOPOSEPARAM, nCount );
|
||||
for ( int iParam = 0; iParam < nParameters; ++iParam )
|
||||
{
|
||||
m_PoseParameters[ iParam ] = pPoseParameters[ iParam ];
|
||||
}
|
||||
}
|
||||
else if ( m_RootMDL.m_MDL.GetMDL() != MDLHANDLE_INVALID )
|
||||
{
|
||||
CStudioHdr &studioHdr = *m_RootMDL.m_pStudioHdr;
|
||||
Studio_CalcDefaultPoseParameters( &studioHdr, m_PoseParameters, MAXSTUDIOPOSEPARAM );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set a pose parameter by name
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMDLPanel::SetPoseParameterByName( const char *pszName, float fValue )
|
||||
{
|
||||
if ( !m_RootMDL.m_pStudioHdr )
|
||||
return false;
|
||||
CStudioHdr &studioHdr = *m_RootMDL.m_pStudioHdr;
|
||||
int nPoseCount = studioHdr.GetNumPoseParameters();
|
||||
|
||||
for ( int i = 0; i < nPoseCount; ++i )
|
||||
{
|
||||
const mstudioposeparamdesc_t &Pose = studioHdr.pPoseParameter( i );
|
||||
if ( V_strcasecmp( pszName, Pose.pszName() ) == 0 )
|
||||
{
|
||||
m_PoseParameters[ i ] = fValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the overlay sequence layers
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetSequenceLayers( const MDLSquenceLayer_t *pSequenceLayers, int nCount )
|
||||
{
|
||||
if ( pSequenceLayers )
|
||||
{
|
||||
m_nNumSequenceLayers = MIN( MAX_SEQUENCE_LAYERS, nCount );
|
||||
for ( int iLayer = 0; iLayer < m_nNumSequenceLayers; ++iLayer )
|
||||
{
|
||||
m_SequenceLayers[ iLayer ] = pSequenceLayers[ iLayer ];
|
||||
ResetAnimationEventState( &m_SequenceLayerEventState[ iLayer ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nNumSequenceLayers = 0;
|
||||
V_memset( m_SequenceLayers, 0, sizeof( m_SequenceLayers ) );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the current skin
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetSkin( int nSkin )
|
||||
{
|
||||
m_RootMDL.m_MDL.m_nSkin = nSkin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// called when we're ticked...
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::OnTick()
|
||||
{
|
||||
BaseClass::OnTick();
|
||||
if ( m_RootMDL.m_MDL.GetMDL() != MDLHANDLE_INVALID )
|
||||
{
|
||||
ValidateMDLs();
|
||||
|
||||
m_RootMDL.m_MDL.m_flTime = ( GetAutoPlayTime() - m_RootMDL.m_flCycleStartTime );
|
||||
|
||||
DoAnimationEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void CMDLPanel::Paint()
|
||||
{
|
||||
BaseClass::Paint();
|
||||
|
||||
if ( m_bThumbnailSafeZone )
|
||||
{
|
||||
int iWidth, iHeight;
|
||||
GetSize( iWidth, iHeight );
|
||||
|
||||
CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() );
|
||||
|
||||
IMaterial *safezone = materials->FindMaterial( "vgui/thumbnails_safezone", TEXTURE_GROUP_VGUI, true );
|
||||
if ( safezone )
|
||||
{
|
||||
safezone->IncrementReferenceCount();
|
||||
}
|
||||
|
||||
int screenposx = 0;
|
||||
int screenposy = 0;
|
||||
LocalToScreen( screenposx, screenposy );
|
||||
|
||||
int iScaledHeight = THUMBNAIL_SAFE_ZONE_HEIGHT_SCALE * iHeight;
|
||||
int iRemappedHeight = RemapVal( iScaledHeight, 0, THUMBNAIL_SAFE_ZONE_HEIGHT, 0, iScaledHeight );
|
||||
|
||||
pRenderContext->DrawScreenSpaceRectangle( safezone, screenposx, screenposy, iWidth, iRemappedHeight,
|
||||
0, 0,
|
||||
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_HEIGHT,
|
||||
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_SIZE );
|
||||
|
||||
screenposx = 0;
|
||||
screenposy = iHeight - iRemappedHeight;
|
||||
LocalToScreen( screenposx, screenposy );
|
||||
pRenderContext->DrawScreenSpaceRectangle( safezone, screenposx, screenposy, iWidth, iRemappedHeight,
|
||||
0, 0,
|
||||
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_HEIGHT,
|
||||
THUMBNAIL_SAFE_ZONE_SIZE, THUMBNAIL_SAFE_ZONE_SIZE );
|
||||
|
||||
if ( safezone )
|
||||
{
|
||||
safezone->DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::DoAnimationEvents()
|
||||
{
|
||||
if ( !m_RootMDL.m_pStudioHdr )
|
||||
return;
|
||||
CStudioHdr &studioHdr = *m_RootMDL.m_pStudioHdr;
|
||||
|
||||
// If we don't have any sequences, don't do anything
|
||||
if ( studioHdr.GetNumSeq() < 1 )
|
||||
{
|
||||
Assert( studioHdr.GetNumSeq() >= 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
// we're holding onto model data that can be forced reloaded when importing workshop items
|
||||
// detect the vmodel change here and force an update if so, until we fix the real issue of the studioHdr not being updated itself
|
||||
if ( studioHdr.GetVirtualModel() != nullptr && studioHdr.GetVirtualModel() != studioHdr.GetRenderHdr()->GetVirtualModel() )
|
||||
{
|
||||
studioHdr.ResetVModel( studioHdr.GetRenderHdr()->GetVirtualModel() );
|
||||
}
|
||||
|
||||
DoAnimationEvents( &studioHdr, m_RootMDL.m_MDL.m_nSequence, m_RootMDL.m_MDL.m_flTime, false, &m_EventState );
|
||||
|
||||
for ( int i = 0; i < m_nNumSequenceLayers; ++i )
|
||||
{
|
||||
float flTime = m_RootMDL.m_MDL.m_flTime - m_SequenceLayers[ i ].m_flCycleBeganAt;
|
||||
//Plat_DebugString( CFmtStr("Animation: time = %f, started = %f, delta = %f\n",m_RootMDL.m_MDL.m_flTime,m_SequenceLayers[ i ].m_flCycleBeganAt,flTime ) );
|
||||
DoAnimationEvents( &studioHdr, m_SequenceLayers[ i ].m_nSequenceIndex, flTime, m_SequenceLayers[ i ].m_bNoLoop, &m_SequenceLayerEventState[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::DoAnimationEvents( CStudioHdr *pStudioHdr, int nSeqNum, float flTime, bool bNoLoop, MDLAnimEventState_t *pEventState )
|
||||
{
|
||||
if ( nSeqNum < 0 || nSeqNum >= pStudioHdr->GetNumSeq() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( nSeqNum );
|
||||
if ( seqdesc.numevents == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mstudioevent_t *pevent = seqdesc.pEvent( 0 );
|
||||
|
||||
int nFrameCount = Studio_MaxFrame( pStudioHdr, nSeqNum, m_PoseParameters );
|
||||
if ( nFrameCount == 0 )
|
||||
{
|
||||
nFrameCount = 1;
|
||||
}
|
||||
float flEventCycle = ( flTime * m_RootMDL.m_MDL.m_flPlaybackRate ) / nFrameCount;
|
||||
//Plat_DebugString( CFmtStr("Event cycle: %f, playback rate: %f, frame count: %d\n", flEventCycle, m_RootMDL.m_MDL.m_flPlaybackRate, nFrameCount ) );
|
||||
if ( bNoLoop )
|
||||
{
|
||||
flEventCycle = MIN(flEventCycle, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
flEventCycle -= (int)(flEventCycle);
|
||||
}
|
||||
|
||||
if ( pEventState->m_nEventSequence != nSeqNum )
|
||||
{
|
||||
pEventState->m_nEventSequence = nSeqNum;
|
||||
flEventCycle = 0.0f;
|
||||
pEventState->m_flPrevEventCycle = -0.01f; // back up to get 0'th frame animations
|
||||
}
|
||||
|
||||
if ( flEventCycle == pEventState->m_flPrevEventCycle )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check for looping
|
||||
BOOL bLooped = (flEventCycle < pEventState->m_flPrevEventCycle);
|
||||
|
||||
// This makes sure events that occur at the end of a sequence occur are
|
||||
// sent before events that occur at the beginning of a sequence.
|
||||
if (bLooped)
|
||||
{
|
||||
for (int i = 0; i < (int)seqdesc.numevents; i++)
|
||||
{
|
||||
if ( pevent[i].cycle <= pEventState->m_flPrevEventCycle )
|
||||
continue;
|
||||
|
||||
FireEvent( pevent[ i ].pszEventName(), pevent[ i ].pszOptions() );
|
||||
}
|
||||
|
||||
// Necessary to get the next loop working
|
||||
pEventState->m_flPrevEventCycle = -0.01f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)seqdesc.numevents; i++)
|
||||
{
|
||||
if ( (pevent[i].cycle > pEventState->m_flPrevEventCycle && pevent[i].cycle <= flEventCycle) )
|
||||
{
|
||||
FireEvent( pevent[ i ].pszEventName(), pevent[ i ].pszOptions() );
|
||||
}
|
||||
}
|
||||
|
||||
pEventState->m_flPrevEventCycle = flEventCycle;
|
||||
}
|
||||
|
||||
void CMDLPanel::FireEvent( const char *pszEventName, const char *pszEventOptions )
|
||||
{
|
||||
KeyValues* pKVEvent = new KeyValues( "AnimEvent" );
|
||||
pKVEvent->SetString( "name", pszEventName );
|
||||
pKVEvent->SetString( "options", pszEventOptions );
|
||||
PostActionSignal( pKVEvent );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::ResetAnimationEventState( MDLAnimEventState_t *pEventState )
|
||||
{
|
||||
pEventState->m_nEventSequence = -1;
|
||||
pEventState->m_flPrevEventCycle = -0.01f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// input
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::OnMouseDoublePressed( vgui::MouseCode code )
|
||||
{
|
||||
if ( m_bIgnoreDoubleClick )
|
||||
return;
|
||||
|
||||
float flRadius;
|
||||
Vector vecCenter;
|
||||
GetBoundingSphere( vecCenter, flRadius );
|
||||
LookAt( vecCenter, flRadius );
|
||||
|
||||
BaseClass::OnMouseDoublePressed( code );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::SetMergeMDL( MDLHandle_t handle, void *pProxyData, int nSkin /*= -1 */ )
|
||||
{
|
||||
// Verify that we have a root model to merge to.
|
||||
if ( m_RootMDL.m_MDL.GetMDL() == MDLHANDLE_INVALID )
|
||||
return;
|
||||
|
||||
int iIndex = m_aMergeMDLs.AddToTail();
|
||||
if ( !m_aMergeMDLs.IsValidIndex( iIndex ) )
|
||||
return;
|
||||
|
||||
m_aMergeMDLs[iIndex].m_MDL.SetMDL( handle );
|
||||
|
||||
if ( nSkin != -1 )
|
||||
{
|
||||
m_aMergeMDLs[iIndex].m_MDL.m_nSkin = nSkin;
|
||||
}
|
||||
|
||||
m_aMergeMDLs[iIndex].m_MDL.m_nLOD = m_RootMDL.m_MDL.m_nLOD;
|
||||
|
||||
m_aMergeMDLs[iIndex].m_MDL.m_pProxyData = pProxyData;
|
||||
SetIdentityMatrix( m_aMergeMDLs[iIndex].m_MDLToWorld );
|
||||
|
||||
m_aMergeMDLs[iIndex].m_bDisabled = false;
|
||||
|
||||
m_aMergeMDLs[iIndex].m_pStudioHdr = new CStudioHdr( m_aMergeMDLs[iIndex].m_MDL.GetStudioHdr(), g_pMDLCache );
|
||||
|
||||
// Need to invalidate the layout so the panel will adjust is LookAt for the new model.
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
MDLHandle_t CMDLPanel::SetMergeMDL( const char *pMDLName, void *pProxyData, int nSkin /*= -1 */ )
|
||||
{
|
||||
MDLHandle_t hMDLFindResult = vgui::MDLCache()->FindMDL( pMDLName );
|
||||
MDLHandle_t hMDL = pMDLName ? hMDLFindResult : MDLHANDLE_INVALID;
|
||||
if ( vgui::MDLCache()->IsErrorModel( hMDL ) )
|
||||
{
|
||||
hMDL = MDLHANDLE_INVALID;
|
||||
}
|
||||
|
||||
SetMergeMDL( hMDL, pProxyData, nSkin );
|
||||
|
||||
// FindMDL takes a reference and the the CMDL will also hold a reference for as long as it sticks around. Release the FindMDL reference.
|
||||
int nRef = vgui::MDLCache()->Release( hMDLFindResult );
|
||||
(void)nRef; // Avoid unreferenced variable warning
|
||||
AssertMsg( hMDL == MDLHANDLE_INVALID || nRef > 0, "CMDLPanel::SetMergeMDL referenced a model that has a zero ref count." );
|
||||
|
||||
return hMDL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CMDLPanel::GetMergeMDLIndex( void *pProxyData )
|
||||
{
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[iMerge].m_MDL.m_pProxyData == pProxyData )
|
||||
return iMerge;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CMDLPanel::GetMergeMDLIndex( MDLHandle_t handle )
|
||||
{
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[iMerge].m_MDL.GetMDL() == handle )
|
||||
return iMerge;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CMDL *CMDLPanel::GetMergeMDL( MDLHandle_t handle )
|
||||
{
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[iMerge].m_MDL.GetMDL() == handle )
|
||||
return (&m_aMergeMDLs[iMerge].m_MDL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CStudioHdr *CMDLPanel::GetMergeMDLStudioHdr( MDLHandle_t handle )
|
||||
{
|
||||
int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[ iMerge ].m_MDL.GetMDL() == handle )
|
||||
return ( m_aMergeMDLs[ iMerge ].m_pStudioHdr );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLPanel::ClearMergeMDLs( void )
|
||||
{
|
||||
const int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( !m_aMergeMDLs[iMerge].m_pStudioHdr )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
delete m_aMergeMDLs[iMerge].m_pStudioHdr;
|
||||
m_aMergeMDLs[iMerge].m_pStudioHdr = NULL;
|
||||
}
|
||||
|
||||
m_aMergeMDLs.Purge();
|
||||
}
|
||||
|
||||
void CMDLPanel::ValidateMDLs()
|
||||
{
|
||||
uint32 uMdlCacheSerial = vgui::ivgui()->GetMdlCacheSerial();
|
||||
|
||||
if ( m_RootMDL.m_pStudioHdr && m_RootMDL.m_unMdlCacheSerial != uMdlCacheSerial )
|
||||
{
|
||||
m_RootMDL.m_pStudioHdr = new CStudioHdr( m_RootMDL.m_MDL.GetStudioHdr(), g_pMDLCache );
|
||||
m_RootMDL.m_unMdlCacheSerial = uMdlCacheSerial;
|
||||
}
|
||||
|
||||
const int nMergeCount = m_aMergeMDLs.Count();
|
||||
for ( int iMerge = 0; iMerge < nMergeCount; ++iMerge )
|
||||
{
|
||||
if ( m_aMergeMDLs[iMerge].m_pStudioHdr && m_aMergeMDLs[iMerge].m_unMdlCacheSerial != uMdlCacheSerial )
|
||||
{
|
||||
m_aMergeMDLs[iMerge].m_pStudioHdr = new CStudioHdr( m_aMergeMDLs[iMerge].m_MDL.GetStudioHdr(), g_pMDLCache );
|
||||
m_aMergeMDLs[iMerge].m_unMdlCacheSerial = uMdlCacheSerial;
|
||||
}
|
||||
}
|
||||
}
|
1742
src/vgui2/matsys_controls/mdlpicker.cpp
Normal file
1742
src/vgui2/matsys_controls/mdlpicker.cpp
Normal file
File diff suppressed because it is too large
Load Diff
539
src/vgui2/matsys_controls/mdlsequencepicker.cpp
Normal file
539
src/vgui2/matsys_controls/mdlsequencepicker.cpp
Normal file
@ -0,0 +1,539 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "matsys_controls/mdlsequencepicker.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "tier1/utldict.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "filesystem.h"
|
||||
#include "studio.h"
|
||||
#include "vgui/IVGui.h"
|
||||
#include "vgui/Cursor.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui_controls/Splitter.h"
|
||||
#include "vgui_controls/ComboBox.h"
|
||||
#include "vgui_controls/PropertySheet.h"
|
||||
#include "vgui_controls/PropertyPage.h"
|
||||
#include "vgui_controls/ToolWindow.h"
|
||||
#include "vgui_controls/Button.h"
|
||||
#include "matsys_controls/gamefiletreeview.h"
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// MDL Sequence Picker
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CMDLSequencePicker::CMDLSequencePicker( vgui::Panel *pParent ) : BaseClass(pParent, "MDLSequencePicker"), m_Images(false)
|
||||
{
|
||||
vgui::ivgui()->AddTickSignal( GetVPanel() );
|
||||
|
||||
m_hSelectedMDL = MDLHANDLE_INVALID;
|
||||
|
||||
// Horizontal splitter for mdls
|
||||
m_pMDLSplitter = new Splitter( this, "MDLSplitter", SPLITTER_MODE_VERTICAL, 1 );
|
||||
|
||||
vgui::Panel *pSplitterLeftSide = m_pMDLSplitter->GetChild( 0 );
|
||||
vgui::Panel *pSplitterRightSide = m_pMDLSplitter->GetChild( 1 );
|
||||
|
||||
// filter selection
|
||||
m_pFilterList = new ComboBox( pSplitterLeftSide, "FilterList", 16, true );
|
||||
m_pFilterList->AddActionSignalTarget( this );
|
||||
|
||||
// file browser tree controls
|
||||
m_pFileTree = new CGameFileTreeView( pSplitterLeftSide, "FileTree", "All .MDLs", "models", "mdl" );
|
||||
|
||||
// build our list of images
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
|
||||
m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) );
|
||||
m_pFileTree->SetImageList( &m_Images, false );
|
||||
m_pFileTree->AddActionSignalTarget( this );
|
||||
|
||||
// property sheet - revisions, changes, etc.
|
||||
m_pSequenceSplitter = new Splitter( pSplitterRightSide, "SequenceSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
|
||||
|
||||
vgui::Panel *pSplitterTopSide = m_pSequenceSplitter->GetChild( 0 );
|
||||
vgui::Panel *pSplitterBottomSide = m_pSequenceSplitter->GetChild( 1 );
|
||||
|
||||
// MDL preview
|
||||
m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
|
||||
SetSkipChildDuringPainting( m_pMDLPreview );
|
||||
|
||||
m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
|
||||
m_pViewsSheet->AddActionSignalTarget( this );
|
||||
|
||||
// sequences
|
||||
m_pSequencesPage = new PropertyPage( m_pViewsSheet, "SequencesPage" );
|
||||
m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
|
||||
m_pSequencesList = new ListPanel( m_pSequencesPage, "SequencesList" );
|
||||
m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
|
||||
m_pSequencesList->AddActionSignalTarget( this );
|
||||
m_pSequencesList->SetSelectIndividualCells( true );
|
||||
m_pSequencesList->SetEmptyListText("No .MDL file currently selected.");
|
||||
m_pSequencesList->SetDragEnabled( true );
|
||||
m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
|
||||
|
||||
// Activities
|
||||
m_pActivitiesPage = new PropertyPage( m_pViewsSheet, "ActivitiesPage" );
|
||||
m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
|
||||
m_pActivitiesList = new ListPanel( m_pActivitiesPage, "ActivitiesList" );
|
||||
m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
|
||||
m_pActivitiesList->AddActionSignalTarget( this );
|
||||
m_pActivitiesList->SetSelectIndividualCells( true );
|
||||
m_pActivitiesList->SetEmptyListText( "No .MDL file currently selected." );
|
||||
m_pActivitiesList->SetDragEnabled( true );
|
||||
m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
|
||||
|
||||
// Load layout settings; has to happen before pinning occurs in code
|
||||
LoadControlSettingsAndUserConfig( "resource/mdlsequencepicker.res" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CMDLSequencePicker::~CMDLSequencePicker()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This is a bit of a hack to make sure that the ToolWindow containing this picker punches
|
||||
// a hold for the rendering viewport, too
|
||||
// Input : -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnTick()
|
||||
{
|
||||
BaseClass::OnTick();
|
||||
if ( GetParent() )
|
||||
{
|
||||
ToolWindow *tw = dynamic_cast< ToolWindow * >( GetParent()->GetParent() );
|
||||
|
||||
if ( tw )
|
||||
{
|
||||
tw->SetSkipChildDuringPainting( IsVisible() ? m_pMDLPreview : NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: stops app on close
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnClose()
|
||||
{
|
||||
BaseClass::OnClose();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: called to open
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::Activate()
|
||||
{
|
||||
RefreshFileList();
|
||||
RefreshActivitiesAndSequencesList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Performs layout
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::PerformLayout()
|
||||
{
|
||||
// NOTE: This call should cause auto-resize to occur
|
||||
// which should fix up the width of the panels
|
||||
BaseClass::PerformLayout();
|
||||
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
// Layout the mdl splitter
|
||||
m_pMDLSplitter->SetBounds( 0, 0, w, h );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Refreshes the active file list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::RefreshFileList()
|
||||
{
|
||||
m_pFileTree->RefreshFileList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: rebuilds the list of activities
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::RefreshActivitiesAndSequencesList()
|
||||
{
|
||||
m_pActivitiesList->RemoveAll();
|
||||
m_pSequencesList->RemoveAll();
|
||||
m_pMDLPreview->SetSequence( 0 );
|
||||
|
||||
if ( m_hSelectedMDL == MDLHANDLE_INVALID )
|
||||
{
|
||||
m_pActivitiesList->SetEmptyListText("No .MDL file currently selected");
|
||||
m_pSequencesList->SetEmptyListText("No .MDL file currently selected");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pActivitiesList->SetEmptyListText(".MDL file contains no activities");
|
||||
m_pSequencesList->SetEmptyListText(".MDL file contains no sequences");
|
||||
|
||||
studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
|
||||
CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
|
||||
|
||||
for (int j = 0; j < hdr->GetNumSeq(); j++)
|
||||
{
|
||||
if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
|
||||
{
|
||||
const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
|
||||
if ( pActivityName && pActivityName[0] )
|
||||
{
|
||||
// Multiple sequences can have the same activity name; only add unique activity names
|
||||
if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
|
||||
{
|
||||
KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
|
||||
int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
|
||||
|
||||
KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
|
||||
pDrag->SetString( "texttype", "activityName" );
|
||||
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
|
||||
m_pActivitiesList->SetItemDragData( nItemID, pDrag );
|
||||
|
||||
activityNames.Insert( pActivityName, j );
|
||||
}
|
||||
}
|
||||
|
||||
const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
|
||||
if ( pSequenceName && pSequenceName[0] )
|
||||
{
|
||||
KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
|
||||
pkv->SetInt( "seqindex", j );
|
||||
|
||||
int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
|
||||
|
||||
KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
|
||||
pDrag->SetString( "texttype", "sequenceName" );
|
||||
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
|
||||
m_pSequencesList->SetItemDragData( nItemID, pDrag );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes dialog on text changing
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnTextChanged( vgui::Panel *pPanel, const char *pText )
|
||||
{
|
||||
// m_pFileTree->SetFilter( pText );
|
||||
RefreshFileList();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Selects an sequence based on an activity
|
||||
//-----------------------------------------------------------------------------
|
||||
int SelectWeightedSequence( studiohdr_t *pstudiohdr, int activity, int curSequence )
|
||||
{
|
||||
if (! pstudiohdr)
|
||||
return 0;
|
||||
|
||||
VerifySequenceIndex( pstudiohdr );
|
||||
|
||||
int weighttotal = 0;
|
||||
int seq = ACTIVITY_NOT_AVAILABLE;
|
||||
int weight = 0;
|
||||
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
|
||||
{
|
||||
int curActivity = GetSequenceActivity( pstudiohdr, i, &weight );
|
||||
if (curActivity == activity)
|
||||
{
|
||||
if ( curSequence == i && weight < 0 )
|
||||
{
|
||||
seq = i;
|
||||
break;
|
||||
}
|
||||
weighttotal += iabs(weight);
|
||||
|
||||
int randomValue;
|
||||
if ( IsInPrediction() )
|
||||
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i );
|
||||
else
|
||||
randomValue = RandomInt( 0, weighttotal - 1 );
|
||||
|
||||
if (!weighttotal || randomValue < iabs(weight))
|
||||
seq = i;
|
||||
}
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plays the selected activity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::PlaySelectedActivity( )
|
||||
{
|
||||
int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
|
||||
if ( nIndex < 0 )
|
||||
return;
|
||||
|
||||
KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
|
||||
const char *pActivityName = pkv->GetString( "activity", NULL );
|
||||
if ( !pActivityName )
|
||||
return;
|
||||
|
||||
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
|
||||
{
|
||||
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
|
||||
if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
|
||||
{
|
||||
// FIXME: Add weighted sequence selection logic?
|
||||
m_pMDLPreview->SetSequence( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plays the selected sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::PlaySelectedSequence( )
|
||||
{
|
||||
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
|
||||
if ( nIndex < 0 )
|
||||
return;
|
||||
|
||||
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
|
||||
const char *pSequenceName = pkv->GetString( "sequence", NULL );
|
||||
if ( !pSequenceName )
|
||||
return;
|
||||
|
||||
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
|
||||
{
|
||||
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
|
||||
if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
|
||||
{
|
||||
m_pMDLPreview->SetSequence( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when a page is shown
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnPageChanged( )
|
||||
{
|
||||
if ( m_pViewsSheet->GetActivePage() == m_pSequencesPage )
|
||||
{
|
||||
PlaySelectedSequence();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage )
|
||||
{
|
||||
PlaySelectedActivity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes dialog on text changing
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnItemSelected( KeyValues *kv )
|
||||
{
|
||||
Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
|
||||
if ( pPanel == m_pSequencesList )
|
||||
{
|
||||
PlaySelectedSequence();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pPanel == m_pActivitiesList )
|
||||
{
|
||||
PlaySelectedActivity();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// An MDL was selected
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::SelectMDL( const char *pMDLName )
|
||||
{
|
||||
m_hSelectedMDL = pMDLName ? vgui::MDLCache()->FindMDL( pMDLName ) : MDLHANDLE_INVALID;
|
||||
if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL ) )
|
||||
{
|
||||
m_hSelectedMDL = MDLHANDLE_INVALID;
|
||||
}
|
||||
m_pMDLPreview->SetMDL( m_hSelectedMDL );
|
||||
m_pMDLPreview->LookAtMDL();
|
||||
RefreshActivitiesAndSequencesList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: updates revision view on a file being selected
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMDLSequencePicker::OnFileSelected()
|
||||
{
|
||||
// update list
|
||||
int iItem = m_pFileTree->GetFirstSelectedItem();
|
||||
if ( iItem < 0 )
|
||||
return;
|
||||
|
||||
// Don't bother to change if a directory was selected
|
||||
KeyValues *pkv = m_pFileTree->GetItemData(iItem);
|
||||
if ( pkv->GetInt("dir") || pkv->GetInt("root") )
|
||||
return;
|
||||
|
||||
surface()->SetCursor(dc_waitarrow);
|
||||
|
||||
const char *pFullPathName = pkv->GetString( "path" );
|
||||
|
||||
char pRelativePathName[MAX_PATH];
|
||||
g_pFullFileSystem->FullPathToRelativePath( pFullPathName, pRelativePathName, sizeof(pRelativePathName) );
|
||||
|
||||
// FIXME: Check that we're not actually opening the wrong file!!
|
||||
SelectMDL( pRelativePathName );
|
||||
}
|
||||
|
||||
char const *CMDLSequencePicker::GetModelName()
|
||||
{
|
||||
if ( MDLHANDLE_INVALID == m_hSelectedMDL )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return vgui::MDLCache()->GetModelName( m_hSelectedMDL );
|
||||
}
|
||||
|
||||
char const *CMDLSequencePicker::GetSequenceName()
|
||||
{
|
||||
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
|
||||
if ( nIndex < 0 )
|
||||
return "";
|
||||
|
||||
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
|
||||
const char *pSequenceName = pkv->GetString( "sequence", NULL );
|
||||
if ( !pSequenceName )
|
||||
return "";
|
||||
|
||||
return pSequenceName;
|
||||
}
|
||||
|
||||
int CMDLSequencePicker::GetSequenceNumber()
|
||||
{
|
||||
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
|
||||
if ( nIndex < 0 )
|
||||
return -1;
|
||||
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
|
||||
return pkv->GetInt( "seqindex", -1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sequence picker frame
|
||||
//-----------------------------------------------------------------------------
|
||||
CMDLSequencePickerFrame::CMDLSequencePickerFrame( vgui::Panel *parent, char const *title ) :
|
||||
BaseClass( parent, "MDLSequencePickerFrame" )
|
||||
{
|
||||
m_pMDLSequencePicker = new CMDLSequencePicker( this );
|
||||
SetTitle( title, true );
|
||||
SetSizeable( false );
|
||||
SetCloseButtonVisible( false );
|
||||
SetMoveable( true );
|
||||
SetMinimumSize( 640, 480 );
|
||||
Activate();
|
||||
m_pMDLSequencePicker->Activate();
|
||||
|
||||
m_pOK = new Button( this, "OK", "#vgui_ok", this );
|
||||
m_pOK->SetCommand( new KeyValues( "OnOK" ) );
|
||||
m_pCancel= new Button( this, "Cancel", "#vgui_cancel", this );
|
||||
m_pOK->SetCommand( new KeyValues( "OnCancel" ) );
|
||||
m_pOK->SetEnabled( false );
|
||||
|
||||
vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );
|
||||
}
|
||||
|
||||
CMDLSequencePickerFrame::~CMDLSequencePickerFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void CMDLSequencePickerFrame::OnTick()
|
||||
{
|
||||
BaseClass::OnTick();
|
||||
|
||||
bool bHasModel = m_pMDLSequencePicker->GetModelName()[ 0 ] != 0 ? true : false;
|
||||
bool bHasSequence = m_pMDLSequencePicker->GetSequenceNumber() != -1 ? true : false;
|
||||
|
||||
m_pOK->SetEnabled( bHasModel && bHasSequence );
|
||||
}
|
||||
|
||||
void CMDLSequencePickerFrame::PerformLayout()
|
||||
{
|
||||
BaseClass::PerformLayout();
|
||||
|
||||
int x, y, w, h;
|
||||
GetClientArea( x, y, w, h );
|
||||
h -= 24;
|
||||
m_pMDLSequencePicker->SetBounds( x, y, w, h );
|
||||
|
||||
h += 5;
|
||||
|
||||
|
||||
int bw = 120;
|
||||
int bwwithGap = 2 * bw + 10;
|
||||
|
||||
x = ( w - bwwithGap ) / 2;
|
||||
m_pOK->SetBounds( x, y + h, bw, 16 );
|
||||
x += bw + 10;
|
||||
m_pCancel->SetBounds( x, y + h, bw, 16 );
|
||||
}
|
||||
|
||||
void CMDLSequencePickerFrame::OnCancel()
|
||||
{
|
||||
KeyValues *pActionKeys = new KeyValues( "AssetSelected" );
|
||||
pActionKeys->SetString( "ModelName", m_pMDLSequencePicker->GetModelName() );
|
||||
pActionKeys->SetString( "SequenceName", m_pMDLSequencePicker->GetSequenceName() );
|
||||
pActionKeys->SetInt( "SequenceNumber", m_pMDLSequencePicker->GetSequenceNumber() );
|
||||
|
||||
PostActionSignal( pActionKeys );
|
||||
|
||||
CloseModal();
|
||||
}
|
||||
|
||||
void CMDLSequencePickerFrame::OnOK()
|
||||
{
|
||||
CloseModal();
|
||||
}
|
||||
|
||||
|
318
src/vgui2/matsys_controls/picker.cpp
Normal file
318
src/vgui2/matsys_controls/picker.cpp
Normal file
@ -0,0 +1,318 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "filesystem.h"
|
||||
#include "matsys_controls/picker.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "vgui_controls/ListPanel.h"
|
||||
#include "vgui_controls/TextEntry.h"
|
||||
#include "vgui_controls/Button.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui/IInput.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Base asset Picker
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sort by asset name
|
||||
//-----------------------------------------------------------------------------
|
||||
static int __cdecl PickerBrowserSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
|
||||
{
|
||||
const char *string1 = item1.kv->GetString("choice");
|
||||
const char *string2 = item2.kv->GetString("choice");
|
||||
return stricmp( string1, string2 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CPicker::CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ) :
|
||||
BaseClass( pParent, "Picker" )
|
||||
{
|
||||
m_pPickerType = pColumnHeader;
|
||||
m_pPickerTextType = pTextType;
|
||||
|
||||
// FIXME: Make this an image browser
|
||||
m_pPickerBrowser = new vgui::ListPanel( this, "Browser" );
|
||||
m_pPickerBrowser->AddColumnHeader( 0, "choice", m_pPickerType, 52, 0 );
|
||||
m_pPickerBrowser->SetSelectIndividualCells( true );
|
||||
m_pPickerBrowser->SetEmptyListText( "Nothing to pick" );
|
||||
m_pPickerBrowser->SetDragEnabled( true );
|
||||
m_pPickerBrowser->AddActionSignalTarget( this );
|
||||
m_pPickerBrowser->SetSortFunc( 0, PickerBrowserSortFunc );
|
||||
m_pPickerBrowser->SetSortColumn( 0 );
|
||||
|
||||
// filter selection
|
||||
m_pFilterList = new TextEntry( this, "FilterList" );
|
||||
m_pFilterList->AddActionSignalTarget( this );
|
||||
m_pFilterList->RequestFocus();
|
||||
|
||||
LoadControlSettingsAndUserConfig( "resource/picker.res" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CPicker::~CPicker()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPicker::OnKeyCodePressed( KeyCode code )
|
||||
{
|
||||
if (( code == KEY_UP ) || ( code == KEY_DOWN ) || ( code == KEY_PAGEUP ) || ( code == KEY_PAGEDOWN ))
|
||||
{
|
||||
KeyValues *pMsg = new KeyValues("KeyCodePressed", "code", code);
|
||||
vgui::ipanel()->SendMessage( m_pPickerBrowser->GetVPanel(), pMsg, GetVPanel());
|
||||
pMsg->deleteThis();
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseClass::OnKeyCodePressed( code );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes the asset list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPicker::SetStringList( const PickerList_t &list )
|
||||
{
|
||||
m_Type = list.m_Type;
|
||||
m_pPickerBrowser->RemoveAll();
|
||||
|
||||
int nCount = list.Count();
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
const char *pPickerName = list[i].m_pChoiceString;
|
||||
KeyValues *kv = new KeyValues( "node", "choice", pPickerName );
|
||||
if ( m_Type == PICKER_CHOICE_STRING )
|
||||
{
|
||||
kv->SetString( "value", list[i].m_pChoiceValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
kv->SetPtr( "value", list[i].m_pChoiceValuePtr );
|
||||
}
|
||||
int nItemID = m_pPickerBrowser->AddItem( kv, 0, false, false );
|
||||
|
||||
if ( m_Type == PICKER_CHOICE_STRING )
|
||||
{
|
||||
KeyValues *pDrag = new KeyValues( "drag", "text", list[i].m_pChoiceValue );
|
||||
if ( m_pPickerTextType )
|
||||
{
|
||||
pDrag->SetString( "texttype", m_pPickerTextType );
|
||||
}
|
||||
m_pPickerBrowser->SetItemDragData( nItemID, pDrag );
|
||||
}
|
||||
}
|
||||
RefreshChoiceList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes the choice list
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPicker::RefreshChoiceList( )
|
||||
{
|
||||
// Check the filter matches
|
||||
int nMatchingCount = 0;
|
||||
int nTotalCount = 0;
|
||||
for ( int nItemID = m_pPickerBrowser->FirstItem(); nItemID != m_pPickerBrowser->InvalidItemID(); nItemID = m_pPickerBrowser->NextItem( nItemID ) )
|
||||
{
|
||||
KeyValues *kv = m_pPickerBrowser->GetItem( nItemID );
|
||||
const char *pPickerName = kv->GetString( "choice" );
|
||||
bool bVisible = !m_Filter.Length() || Q_stristr( pPickerName, m_Filter.Get() );
|
||||
m_pPickerBrowser->SetItemVisible( nItemID, bVisible );
|
||||
if ( bVisible )
|
||||
{
|
||||
++nMatchingCount;
|
||||
}
|
||||
++nTotalCount;
|
||||
}
|
||||
|
||||
char pColumnTitle[512];
|
||||
Q_snprintf( pColumnTitle, sizeof(pColumnTitle), "%s (%d/%d)",
|
||||
m_pPickerType, nMatchingCount, nTotalCount );
|
||||
m_pPickerBrowser->SetColumnHeaderText( 0, pColumnTitle );
|
||||
|
||||
m_pPickerBrowser->SortList();
|
||||
if ( ( m_pPickerBrowser->GetSelectedItemsCount() == 0 ) && ( m_pPickerBrowser->GetItemCount() > 0 ) )
|
||||
{
|
||||
int nItemID = m_pPickerBrowser->GetItemIDFromRow( 0 );
|
||||
m_pPickerBrowser->SetSelectedCell( nItemID, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes dialog on text changing
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPicker::OnTextChanged( )
|
||||
{
|
||||
int nLength = m_pFilterList->GetTextLength();
|
||||
m_Filter.SetLength( nLength );
|
||||
if ( nLength > 0 )
|
||||
{
|
||||
m_pFilterList->GetText( m_Filter.GetForModify(), nLength+1 );
|
||||
}
|
||||
RefreshChoiceList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the selected string
|
||||
//-----------------------------------------------------------------------------
|
||||
PickerChoiceType_t CPicker::GetSelectionType() const
|
||||
{
|
||||
return m_Type;
|
||||
}
|
||||
|
||||
const char *CPicker::GetSelectedString( ) const
|
||||
{
|
||||
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
|
||||
return NULL;
|
||||
|
||||
if ( m_Type != PICKER_CHOICE_STRING )
|
||||
return NULL;
|
||||
|
||||
int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
|
||||
KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
|
||||
return pItemKeyValues->GetString( "value" );
|
||||
}
|
||||
|
||||
void *CPicker::GetSelectedPtr( ) const
|
||||
{
|
||||
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
|
||||
return NULL;
|
||||
|
||||
if ( m_Type != PICKER_CHOICE_PTR )
|
||||
return NULL;
|
||||
|
||||
int nIndex = m_pPickerBrowser->GetSelectedItem( 0 );
|
||||
KeyValues *pItemKeyValues = m_pPickerBrowser->GetItem( nIndex );
|
||||
return pItemKeyValues->GetPtr( "value" );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the index of the selected string
|
||||
//-----------------------------------------------------------------------------
|
||||
int CPicker::GetSelectedIndex()
|
||||
{
|
||||
if ( m_pPickerBrowser->GetSelectedItemsCount() == 0 )
|
||||
return -1;
|
||||
|
||||
return m_pPickerBrowser->GetSelectedItem( 0 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Modal picker frame
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CPickerFrame::CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pPickerType, const char *pTextType ) :
|
||||
BaseClass( pParent, "PickerFrame" )
|
||||
{
|
||||
m_pContextKeyValues = NULL;
|
||||
SetDeleteSelfOnClose( true );
|
||||
m_pPicker = new CPicker( this, pPickerType, pTextType );
|
||||
m_pPicker->AddActionSignalTarget( this );
|
||||
m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
|
||||
m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
|
||||
SetBlockDragChaining( true );
|
||||
|
||||
LoadControlSettingsAndUserConfig( "resource/pickerframe.res" );
|
||||
|
||||
SetTitle( pTitle, false );
|
||||
}
|
||||
|
||||
CPickerFrame::~CPickerFrame()
|
||||
{
|
||||
CleanUpMessage();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deletes the message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPickerFrame::CleanUpMessage()
|
||||
{
|
||||
if ( m_pContextKeyValues )
|
||||
{
|
||||
m_pContextKeyValues->deleteThis();
|
||||
m_pContextKeyValues = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Activate the dialog
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPickerFrame::DoModal( const PickerList_t &list, KeyValues *pContextKeyValues )
|
||||
{
|
||||
CleanUpMessage();
|
||||
m_pContextKeyValues = pContextKeyValues;
|
||||
m_pPicker->SetStringList( list );
|
||||
BaseClass::DoModal();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// On command
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPickerFrame::OnCommand( const char *pCommand )
|
||||
{
|
||||
if ( !Q_stricmp( pCommand, "Open" ) )
|
||||
{
|
||||
KeyValues *pActionKeys = new KeyValues( "Picked" );
|
||||
pActionKeys->SetInt( "choiceIndex", m_pPicker->GetSelectedIndex( ) );
|
||||
|
||||
if ( m_pPicker->GetSelectionType() == PICKER_CHOICE_STRING )
|
||||
{
|
||||
const char *pPickerName = m_pPicker->GetSelectedString( );
|
||||
pActionKeys->SetString( "choice", pPickerName );
|
||||
}
|
||||
else
|
||||
{
|
||||
void *pPickerPtr = m_pPicker->GetSelectedPtr( );
|
||||
pActionKeys->SetPtr( "choice", pPickerPtr );
|
||||
}
|
||||
|
||||
if ( m_pContextKeyValues )
|
||||
{
|
||||
pActionKeys->AddSubKey( m_pContextKeyValues );
|
||||
m_pContextKeyValues = NULL;
|
||||
}
|
||||
PostActionSignal( pActionKeys );
|
||||
CloseModal();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( pCommand, "Cancel" ) )
|
||||
{
|
||||
CloseModal();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::OnCommand( pCommand );
|
||||
}
|
||||
|
||||
|
1231
src/vgui2/matsys_controls/potterywheelpanel.cpp
Normal file
1231
src/vgui2/matsys_controls/potterywheelpanel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
239
src/vgui2/matsys_controls/proceduraltexturepanel.cpp
Normal file
239
src/vgui2/matsys_controls/proceduraltexturepanel.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "matsys_controls/proceduraltexturepanel.h"
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "materialsystem/itexture.h"
|
||||
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "pixelwriter.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CProceduralTexturePanel::CProceduralTexturePanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
|
||||
{
|
||||
m_pImageBuffer = NULL;
|
||||
m_bMaintainProportions = false;
|
||||
m_bUsePaintRect = false;
|
||||
m_PaintRect.x = m_PaintRect.y = 0;
|
||||
m_PaintRect.width = m_PaintRect.height = 0;
|
||||
}
|
||||
|
||||
CProceduralTexturePanel::~CProceduralTexturePanel()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// initialization, shutdown
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CProceduralTexturePanel::Init( int nWidth, int nHeight, bool bAllocateImageBuffer )
|
||||
{
|
||||
m_nWidth = nWidth;
|
||||
m_nHeight = nHeight;
|
||||
if ( bAllocateImageBuffer )
|
||||
{
|
||||
m_pImageBuffer = new BGRA8888_t[nWidth * nHeight];
|
||||
}
|
||||
|
||||
m_TextureSubRect.x = m_TextureSubRect.y = 0;
|
||||
m_TextureSubRect.width = nWidth;
|
||||
m_TextureSubRect.height = nHeight;
|
||||
|
||||
char pTemp[512];
|
||||
Q_snprintf( pTemp, 512, "__%s", GetName() );
|
||||
|
||||
ITexture *pTex = MaterialSystem()->CreateProceduralTexture( pTemp, TEXTURE_GROUP_VGUI,
|
||||
m_nWidth, m_nHeight, IMAGE_FORMAT_BGRX8888,
|
||||
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_NOMIP |
|
||||
TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
|
||||
pTex->SetTextureRegenerator( this );
|
||||
m_ProceduralTexture.Init( pTex );
|
||||
|
||||
KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
|
||||
pVMTKeyValues->SetString( "$basetexture", pTemp );
|
||||
pVMTKeyValues->SetInt( "$nocull", 1 );
|
||||
pVMTKeyValues->SetInt( "$nodebug", 1 );
|
||||
m_ProceduralMaterial.Init( MaterialSystem()->CreateMaterial( pTemp, pVMTKeyValues ));
|
||||
|
||||
m_nTextureID = MatSystemSurface()->CreateNewTextureID( false );
|
||||
MatSystemSurface()->DrawSetTextureMaterial( m_nTextureID, m_ProceduralMaterial );
|
||||
return true;
|
||||
}
|
||||
|
||||
void CProceduralTexturePanel::Shutdown()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Maintain proportions when drawing
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::MaintainProportions( bool bEnable )
|
||||
{
|
||||
m_bMaintainProportions = bEnable;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the image buffer + dimensions
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::CleanUp()
|
||||
{
|
||||
if ( (ITexture*)m_ProceduralTexture )
|
||||
{
|
||||
m_ProceduralTexture->SetTextureRegenerator( NULL );
|
||||
}
|
||||
m_ProceduralTexture.Shutdown();
|
||||
m_ProceduralMaterial.Shutdown();
|
||||
|
||||
if ( m_pImageBuffer )
|
||||
{
|
||||
delete[] m_pImageBuffer;
|
||||
m_pImageBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default implementation of regenerate texture bits
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect )
|
||||
{
|
||||
Assert( m_pImageBuffer );
|
||||
Assert( pVTFTexture->FrameCount() == 1 );
|
||||
Assert( pVTFTexture->FaceCount() == 1 );
|
||||
Assert( !pTexture->IsMipmapped() );
|
||||
|
||||
int nWidth, nHeight, nDepth;
|
||||
pVTFTexture->ComputeMipLevelDimensions( 0, &nWidth, &nHeight, &nDepth );
|
||||
Assert( nDepth == 1 );
|
||||
Assert( nWidth == m_nWidth && nHeight == m_nHeight );
|
||||
|
||||
CPixelWriter pixelWriter;
|
||||
pixelWriter.SetPixelMemory( pVTFTexture->Format(),
|
||||
pVTFTexture->ImageData( 0, 0, 0 ), pVTFTexture->RowSizeInBytes( 0 ) );
|
||||
|
||||
for ( int y = 0; y < nHeight; ++y )
|
||||
{
|
||||
pixelWriter.Seek( 0, y );
|
||||
BGRA8888_t *pTexel = &m_pImageBuffer[y * m_nWidth];
|
||||
for ( int x = 0; x < nWidth; ++x, ++pTexel )
|
||||
{
|
||||
pixelWriter.WritePixel( pTexel->r, pTexel->g, pTexel->b, pTexel->a );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the image buffer + dimensions
|
||||
//-----------------------------------------------------------------------------
|
||||
BGRA8888_t *CProceduralTexturePanel::GetImageBuffer()
|
||||
{
|
||||
Assert( m_pImageBuffer );
|
||||
return m_pImageBuffer;
|
||||
}
|
||||
|
||||
int CProceduralTexturePanel::GetImageWidth() const
|
||||
{
|
||||
return m_nWidth;
|
||||
}
|
||||
|
||||
int CProceduralTexturePanel::GetImageHeight() const
|
||||
{
|
||||
return m_nHeight;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the paint rect
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::SetPaintRect( const Rect_t *pPaintRect )
|
||||
{
|
||||
m_bUsePaintRect = ( pPaintRect != NULL );
|
||||
if ( m_bUsePaintRect )
|
||||
{
|
||||
m_PaintRect = *pPaintRect;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the draw rect
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::SetTextureSubRect( const Rect_t &subRect )
|
||||
{
|
||||
m_TextureSubRect = subRect;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Redownloads the procedural texture
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::DownloadTexture()
|
||||
{
|
||||
m_ProceduralTexture->Download();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Paints the texture
|
||||
//-----------------------------------------------------------------------------
|
||||
void CProceduralTexturePanel::Paint( void )
|
||||
{
|
||||
vgui::surface()->DrawSetTexture( m_nTextureID );
|
||||
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
if ( m_bUsePaintRect )
|
||||
{
|
||||
x = m_PaintRect.x;
|
||||
y = m_PaintRect.y;
|
||||
w = m_PaintRect.width;
|
||||
h = m_PaintRect.height;
|
||||
}
|
||||
|
||||
if ( m_bMaintainProportions )
|
||||
{
|
||||
if ( m_TextureSubRect.width > m_TextureSubRect.height )
|
||||
{
|
||||
h = w * m_TextureSubRect.height / m_TextureSubRect.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = h * m_TextureSubRect.width / m_TextureSubRect.height;
|
||||
}
|
||||
}
|
||||
|
||||
// Rotated version of the bitmap!
|
||||
// Rotate about the center of the bitmap
|
||||
vgui::Vertex_t verts[4];
|
||||
verts[0].m_Position.Init( x, y );
|
||||
verts[0].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
|
||||
|
||||
verts[1].m_Position.Init( w+x, y );
|
||||
verts[1].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)m_TextureSubRect.y / m_nHeight );
|
||||
|
||||
verts[2].m_Position.Init( w+x, h+y );
|
||||
verts[2].m_TexCoord.Init( (float)(m_TextureSubRect.x + m_TextureSubRect.width) / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
|
||||
|
||||
verts[3].m_Position.Init( x, h+y );
|
||||
verts[3].m_TexCoord.Init( (float)m_TextureSubRect.x / m_nWidth, (float)(m_TextureSubRect.y + m_TextureSubRect.height) / m_nHeight );
|
||||
|
||||
vgui::surface()->DrawTexturedPolygon( 4, verts );
|
||||
}
|
485
src/vgui2/matsys_controls/sequencepicker.cpp
Normal file
485
src/vgui2/matsys_controls/sequencepicker.cpp
Normal file
@ -0,0 +1,485 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "matsys_controls/sequencepicker.h"
|
||||
|
||||
#include "tier1/utldict.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "studio.h"
|
||||
#include "vgui/IInput.h"
|
||||
#include "vgui/ISurface.h"
|
||||
#include "vgui_controls/Splitter.h"
|
||||
#include "vgui_controls/PropertyPage.h"
|
||||
#include "vgui_controls/PropertySheet.h"
|
||||
#include "vgui_controls/ListPanel.h"
|
||||
#include "vgui_controls/Button.h"
|
||||
#include "matsys_controls/matsyscontrols.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Sequence Picker
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sort by sequence name
|
||||
//-----------------------------------------------------------------------------
|
||||
static int __cdecl SequenceSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
|
||||
{
|
||||
const char *string1 = item1.kv->GetString("sequence");
|
||||
const char *string2 = item2.kv->GetString("sequence");
|
||||
return stricmp( string1, string2 );
|
||||
}
|
||||
|
||||
static int __cdecl ActivitySortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
|
||||
{
|
||||
const char *string1 = item1.kv->GetString("activity");
|
||||
const char *string2 = item2.kv->GetString("activity");
|
||||
return stricmp( string1, string2 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSequencePicker::CSequencePicker( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePicker" )
|
||||
{
|
||||
m_hSelectedMDL = MDLHANDLE_INVALID;
|
||||
|
||||
// property sheet - revisions, changes, etc.
|
||||
m_pPreviewSplitter = new Splitter( this, "PreviewSplitter", SPLITTER_MODE_HORIZONTAL, 1 );
|
||||
|
||||
vgui::Panel *pSplitterTopSide = m_pPreviewSplitter->GetChild( 0 );
|
||||
vgui::Panel *pSplitterBottomSide = m_pPreviewSplitter->GetChild( 1 );
|
||||
|
||||
// MDL preview
|
||||
m_pMDLPreview = new CMDLPanel( pSplitterTopSide, "MDLPreview" );
|
||||
SetSkipChildDuringPainting( m_pMDLPreview );
|
||||
|
||||
m_pViewsSheet = new vgui::PropertySheet( pSplitterBottomSide, "ViewsSheet" );
|
||||
m_pViewsSheet->AddActionSignalTarget( this );
|
||||
|
||||
// sequences
|
||||
m_pSequencesPage = NULL;
|
||||
m_pSequencesList = NULL;
|
||||
if ( nFlags & PICK_SEQUENCES )
|
||||
{
|
||||
m_pSequencesPage = new PropertyPage( m_pViewsSheet, "SequencesPage" );
|
||||
m_pViewsSheet->AddPage( m_pSequencesPage, "Sequences" );
|
||||
m_pSequencesList = new ListPanel( m_pSequencesPage, "SequencesList" );
|
||||
m_pSequencesList->AddColumnHeader( 0, "sequence", "sequence", 52, 0 );
|
||||
m_pSequencesList->AddActionSignalTarget( this );
|
||||
m_pSequencesList->SetSelectIndividualCells( true );
|
||||
m_pSequencesList->SetEmptyListText(".MDL file contains no activities");
|
||||
m_pSequencesList->SetDragEnabled( true );
|
||||
m_pSequencesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
|
||||
m_pSequencesList->SetSortFunc( 0, SequenceSortFunc );
|
||||
m_pSequencesList->SetSortColumn( 0 );
|
||||
}
|
||||
|
||||
// Activities
|
||||
m_pActivitiesPage = NULL;
|
||||
m_pActivitiesList = NULL;
|
||||
if ( nFlags & PICK_ACTIVITIES )
|
||||
{
|
||||
m_pActivitiesPage = new PropertyPage( m_pViewsSheet, "ActivitiesPage" );
|
||||
m_pViewsSheet->AddPage( m_pActivitiesPage, "Activities" );
|
||||
m_pActivitiesList = new ListPanel( m_pActivitiesPage, "ActivitiesList" );
|
||||
m_pActivitiesList->AddColumnHeader( 0, "activity", "activity", 52, 0 );
|
||||
m_pActivitiesList->AddActionSignalTarget( this );
|
||||
m_pActivitiesList->SetSelectIndividualCells( true );
|
||||
m_pActivitiesList->SetEmptyListText( ".MDL file contains no activities" );
|
||||
m_pActivitiesList->SetDragEnabled( true );
|
||||
m_pActivitiesList->SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
|
||||
m_pActivitiesList->SetSortFunc( 0, ActivitySortFunc );
|
||||
m_pActivitiesList->SetSortColumn( 0 );
|
||||
}
|
||||
|
||||
// Load layout settings; has to happen before pinning occurs in code
|
||||
LoadControlSettingsAndUserConfig( "resource/sequencepicker.res" );
|
||||
|
||||
SETUP_PANEL( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CSequencePicker::~CSequencePicker()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Performs layout
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::PerformLayout()
|
||||
{
|
||||
// NOTE: This call should cause auto-resize to occur
|
||||
// which should fix up the width of the panels
|
||||
BaseClass::PerformLayout();
|
||||
|
||||
int w, h;
|
||||
GetSize( w, h );
|
||||
|
||||
// Layout the mdl splitter
|
||||
m_pPreviewSplitter->SetBounds( 0, 0, w, h );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: rebuilds the list of activities + sequences
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::RefreshActivitiesAndSequencesList()
|
||||
{
|
||||
if ( m_pActivitiesList )
|
||||
{
|
||||
m_pActivitiesList->RemoveAll();
|
||||
}
|
||||
|
||||
if ( m_pSequencesList )
|
||||
{
|
||||
m_pSequencesList->RemoveAll();
|
||||
}
|
||||
|
||||
m_pMDLPreview->SetSequence( 0 );
|
||||
|
||||
if ( m_hSelectedMDL == MDLHANDLE_INVALID )
|
||||
return;
|
||||
|
||||
studiohdr_t *hdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
|
||||
CUtlDict<int, unsigned short> activityNames( true, 0, hdr->GetNumSeq() );
|
||||
|
||||
for (int j = 0; j < hdr->GetNumSeq(); j++)
|
||||
{
|
||||
if ( /*g_viewerSettings.showHidden ||*/ !(hdr->pSeqdesc(j).flags & STUDIO_HIDDEN))
|
||||
{
|
||||
const char *pActivityName = hdr->pSeqdesc(j).pszActivityName();
|
||||
if ( m_pActivitiesList && pActivityName && pActivityName[0] )
|
||||
{
|
||||
// Multiple sequences can have the same activity name; only add unique activity names
|
||||
if ( activityNames.Find( pActivityName ) == activityNames.InvalidIndex() )
|
||||
{
|
||||
KeyValues *pkv = new KeyValues("node", "activity", pActivityName );
|
||||
int nItemID = m_pActivitiesList->AddItem( pkv, 0, false, false );
|
||||
|
||||
KeyValues *pDrag = new KeyValues( "drag", "text", pActivityName );
|
||||
pDrag->SetString( "texttype", "activityName" );
|
||||
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
|
||||
m_pActivitiesList->SetItemDragData( nItemID, pDrag );
|
||||
|
||||
activityNames.Insert( pActivityName, j );
|
||||
}
|
||||
}
|
||||
|
||||
const char *pSequenceName = hdr->pSeqdesc(j).pszLabel();
|
||||
if ( m_pSequencesList && pSequenceName && pSequenceName[0] )
|
||||
{
|
||||
KeyValues *pkv = new KeyValues("node", "sequence", pSequenceName);
|
||||
int nItemID = m_pSequencesList->AddItem( pkv, 0, false, false );
|
||||
|
||||
KeyValues *pDrag = new KeyValues( "drag", "text", pSequenceName );
|
||||
pDrag->SetString( "texttype", "sequenceName" );
|
||||
pDrag->SetString( "mdl", vgui::MDLCache()->GetModelName( m_hSelectedMDL ) );
|
||||
m_pSequencesList->SetItemDragData( nItemID, pDrag );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_pSequencesList )
|
||||
{
|
||||
m_pSequencesList->SortList();
|
||||
}
|
||||
|
||||
if ( m_pActivitiesList )
|
||||
{
|
||||
m_pActivitiesList->SortList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Selects an sequence based on an activity
|
||||
//-----------------------------------------------------------------------------
|
||||
int SelectWeightedSequence( studiohdr_t *pstudiohdr, int activity, int curSequence )
|
||||
{
|
||||
if (! pstudiohdr)
|
||||
return 0;
|
||||
|
||||
VerifySequenceIndex( pstudiohdr );
|
||||
|
||||
int weighttotal = 0;
|
||||
int seq = ACTIVITY_NOT_AVAILABLE;
|
||||
int weight = 0;
|
||||
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
|
||||
{
|
||||
int curActivity = GetSequenceActivity( pstudiohdr, i, &weight );
|
||||
if (curActivity == activity)
|
||||
{
|
||||
if ( curSequence == i && weight < 0 )
|
||||
{
|
||||
seq = i;
|
||||
break;
|
||||
}
|
||||
weighttotal += iabs(weight);
|
||||
|
||||
int randomValue;
|
||||
if ( IsInPrediction() )
|
||||
randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i );
|
||||
else
|
||||
randomValue = RandomInt( 0, weighttotal - 1 );
|
||||
|
||||
if (!weighttotal || randomValue < iabs(weight))
|
||||
seq = i;
|
||||
}
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the selected activity/sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
CSequencePicker::PickType_t CSequencePicker::GetSelectedSequenceType( )
|
||||
{
|
||||
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
|
||||
return PICK_SEQUENCES;
|
||||
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
|
||||
return PICK_ACTIVITIES;
|
||||
return PICK_NONE;
|
||||
}
|
||||
|
||||
const char *CSequencePicker::GetSelectedSequenceName( )
|
||||
{
|
||||
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
|
||||
{
|
||||
int nIndex = m_pSequencesList->GetSelectedItem( 0 );
|
||||
if ( nIndex >= 0 )
|
||||
{
|
||||
KeyValues *pkv = m_pSequencesList->GetItem( nIndex );
|
||||
return pkv->GetString( "sequence", NULL );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
|
||||
{
|
||||
int nIndex = m_pActivitiesList->GetSelectedItem( 0 );
|
||||
if ( nIndex >= 0 )
|
||||
{
|
||||
KeyValues *pkv = m_pActivitiesList->GetItem( nIndex );
|
||||
return pkv->GetString( "activity", NULL );
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plays the selected activity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::PlayActivity( const char *pActivityName )
|
||||
{
|
||||
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ )
|
||||
{
|
||||
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
|
||||
if ( stricmp( seqdesc.pszActivityName(), pActivityName ) == 0 )
|
||||
{
|
||||
// FIXME: Add weighted sequence selection logic?
|
||||
m_pMDLPreview->SetSequence( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plays the selected sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::PlaySequence( const char *pSequenceName )
|
||||
{
|
||||
studiohdr_t *pstudiohdr = vgui::MDLCache()->GetStudioHdr( m_hSelectedMDL );
|
||||
for (int i = 0; i < pstudiohdr->GetNumSeq(); i++)
|
||||
{
|
||||
mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i );
|
||||
if ( !Q_stricmp( seqdesc.pszLabel(), pSequenceName ) )
|
||||
{
|
||||
m_pMDLPreview->SetSequence( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when a page is shown
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::OnPageChanged( )
|
||||
{
|
||||
if ( m_pSequencesPage && ( m_pViewsSheet->GetActivePage() == m_pSequencesPage ) )
|
||||
{
|
||||
const char *pSequenceName = GetSelectedSequenceName();
|
||||
if ( pSequenceName )
|
||||
{
|
||||
PlaySequence( pSequenceName );
|
||||
PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_pActivitiesPage && ( m_pViewsSheet->GetActivePage() == m_pActivitiesPage ) )
|
||||
{
|
||||
const char *pActivityName = GetSelectedSequenceName();
|
||||
if ( pActivityName )
|
||||
{
|
||||
PlayActivity( pActivityName );
|
||||
PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: refreshes dialog on text changing
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::OnItemSelected( KeyValues *kv )
|
||||
{
|
||||
Panel *pPanel = (Panel *)kv->GetPtr("panel", NULL);
|
||||
if ( m_pSequencesList && (pPanel == m_pSequencesList ) )
|
||||
{
|
||||
const char *pSequenceName = GetSelectedSequenceName();
|
||||
if ( pSequenceName )
|
||||
{
|
||||
PlaySequence( pSequenceName );
|
||||
PostActionSignal( new KeyValues( "SequencePreviewChanged", "sequence", pSequenceName ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_pActivitiesList && ( pPanel == m_pActivitiesList ) )
|
||||
{
|
||||
const char *pActivityName = GetSelectedSequenceName();
|
||||
if ( pActivityName )
|
||||
{
|
||||
PlayActivity( pActivityName );
|
||||
PostActionSignal( new KeyValues( "SequencePreviewChanged", "activity", pActivityName ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the MDL to select sequences in
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePicker::SetMDL( const char *pMDLName )
|
||||
{
|
||||
m_hSelectedMDL = pMDLName ? vgui::MDLCache()->FindMDL( pMDLName ) : MDLHANDLE_INVALID;
|
||||
if ( vgui::MDLCache()->IsErrorModel( m_hSelectedMDL ) )
|
||||
{
|
||||
m_hSelectedMDL = MDLHANDLE_INVALID;
|
||||
}
|
||||
m_pMDLPreview->SetMDL( m_hSelectedMDL );
|
||||
m_pMDLPreview->LookAtMDL();
|
||||
RefreshActivitiesAndSequencesList();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Purpose: Modal picker frame
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
CSequencePickerFrame::CSequencePickerFrame( vgui::Panel *pParent, int nFlags ) : BaseClass( pParent, "SequencePickerFrame" )
|
||||
{
|
||||
SetDeleteSelfOnClose( true );
|
||||
m_pPicker = new CSequencePicker( this, nFlags );
|
||||
m_pPicker->AddActionSignalTarget( this );
|
||||
m_pOpenButton = new Button( this, "OpenButton", "#FileOpenDialog_Open", this, "Open" );
|
||||
m_pCancelButton = new Button( this, "CancelButton", "#FileOpenDialog_Cancel", this, "Cancel" );
|
||||
SetBlockDragChaining( true );
|
||||
|
||||
LoadControlSettingsAndUserConfig( "resource/sequencepickerframe.res" );
|
||||
|
||||
m_pOpenButton->SetEnabled( false );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Activate the dialog
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePickerFrame::DoModal( const char *pMDLName )
|
||||
{
|
||||
m_pPicker->SetMDL( pMDLName );
|
||||
BaseClass::DoModal();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// On mdl preview changed
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePickerFrame::OnSequencePreviewChanged( KeyValues *pKeyValues )
|
||||
{
|
||||
const char *pSequence = pKeyValues->GetString( "sequence", NULL );
|
||||
const char *pActivity = pKeyValues->GetString( "activity", NULL );
|
||||
m_pOpenButton->SetEnabled( pSequence || pActivity );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// On command
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSequencePickerFrame::OnCommand( const char *pCommand )
|
||||
{
|
||||
if ( !Q_stricmp( pCommand, "Open" ) )
|
||||
{
|
||||
CSequencePicker::PickType_t type = m_pPicker->GetSelectedSequenceType( );
|
||||
if (( type == CSequencePicker::PICK_SEQUENCES ) || ( type == CSequencePicker::PICK_ACTIVITIES ))
|
||||
{
|
||||
const char *pSequenceName = m_pPicker->GetSelectedSequenceName();
|
||||
if ( pSequenceName )
|
||||
{
|
||||
if ( type == CSequencePicker::PICK_SEQUENCES )
|
||||
{
|
||||
PostActionSignal( new KeyValues("SequenceSelected", "sequence", pSequenceName ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PostActionSignal( new KeyValues("SequenceSelected", "activity", pSequenceName ) );
|
||||
}
|
||||
CloseModal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !Q_stricmp( pCommand, "Cancel" ) )
|
||||
{
|
||||
CloseModal();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::OnCommand( pCommand );
|
||||
}
|
||||
|
||||
|
72
src/vgui2/matsys_controls/tgapreviewpanel.cpp
Normal file
72
src/vgui2/matsys_controls/tgapreviewpanel.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "matsys_controls/tgapreviewpanel.h"
|
||||
#include "bitmap/tgaloader.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// TGA Preview panel
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CTGAPreviewPanel::CTGAPreviewPanel( vgui::Panel *pParent, const char *pName ) :
|
||||
BaseClass( pParent, pName )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets the current TGA
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTGAPreviewPanel::SetTGA( const char *pFullPath )
|
||||
{
|
||||
int nWidth, nHeight;
|
||||
ImageFormat format;
|
||||
float flGamma;
|
||||
|
||||
CUtlBuffer buf;
|
||||
if ( !g_pFullFileSystem->ReadFile( pFullPath, NULL, buf ) )
|
||||
{
|
||||
Warning( "Can't open TGA file: %s\n", pFullPath );
|
||||
return;
|
||||
}
|
||||
|
||||
TGALoader::GetInfo( buf, &nWidth, &nHeight, &format, &flGamma );
|
||||
|
||||
Shutdown();
|
||||
Init( nWidth, nHeight, true );
|
||||
m_TGAName = pFullPath;
|
||||
|
||||
buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 );
|
||||
if ( !TGALoader::Load( (unsigned char*)GetImageBuffer(), buf,
|
||||
nWidth, nHeight, IMAGE_FORMAT_BGRA8888, flGamma, false ) )
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
DownloadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the current TGA
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CTGAPreviewPanel::GetTGA() const
|
||||
{
|
||||
return m_TGAName;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user