541 lines
16 KiB
C++
541 lines
16 KiB
C++
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
|
//
|
|
//
|
|
//
|
|
//===============================================================================
|
|
|
|
#ifndef SOS_SYSTEM_H
|
|
#define SOS_SYSTEM_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "tier1/UtlStringMap.h"
|
|
#include "tier1/utlstring.h"
|
|
#include "tier1/utlsymbol.h"
|
|
#include "toolframework/itoolframework.h"
|
|
#include "snd_dma.h"
|
|
#include "snd_channels.h"
|
|
#include "sos_entry_match_system.h"
|
|
|
|
|
|
|
|
class CSosOperator;
|
|
class CSosOperatorStack;
|
|
// Externs the logging channel
|
|
DECLARE_LOGGING_CHANNEL( LOG_SND_OPERATORS );
|
|
|
|
extern bool IsSoundSourceViewEntity( int soundsource );
|
|
|
|
|
|
extern ConVar snd_sos_show_operator_updates;
|
|
extern ConVar snd_sos_show_operator_start;
|
|
extern ConVar snd_sos_show_operator_prestart;
|
|
extern ConVar snd_sos_show_operator_entry_filter;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#define SOS_INVALID_TRACK_NUMBER -1
|
|
|
|
|
|
struct track_data_t
|
|
{
|
|
void SetDefaults( )
|
|
{
|
|
m_pTrackName = NULL;
|
|
m_pSyncTrackName = NULL;
|
|
m_nTrackNumber = SOS_INVALID_TRACK_NUMBER;
|
|
m_nTrackPriority = 0;
|
|
m_bPriorityOverride = false;
|
|
m_bBlockEqualPriority = false;
|
|
m_nSyncTrackNumber = SOS_INVALID_TRACK_NUMBER;
|
|
m_flStartPoint = 0.0;
|
|
m_flEndPoint = 0.0;
|
|
};
|
|
|
|
const char *m_pTrackName;
|
|
const char *m_pSyncTrackName;
|
|
int m_nTrackNumber;
|
|
int m_nTrackPriority;
|
|
bool m_bPriorityOverride;
|
|
bool m_bBlockEqualPriority;
|
|
int m_nSyncTrackNumber;
|
|
float m_flStartPoint;
|
|
float m_flEndPoint;
|
|
|
|
};
|
|
bool S_TrackHasPriority( track_data_t &newTrackData, track_data_t &existingTrackData );
|
|
|
|
struct stack_data_t
|
|
{
|
|
stack_data_t( )
|
|
{
|
|
m_nGuid = -1;
|
|
m_flStartTime = -1.0;
|
|
m_pOperatorsKV = NULL;
|
|
m_nSoundScriptHash = SOUNDEMITTER_INVALID_HASH;
|
|
};
|
|
|
|
int m_nGuid;
|
|
float m_flStartTime;
|
|
KeyValues *m_pOperatorsKV;
|
|
HSOUNDSCRIPTHASH m_nSoundScriptHash;
|
|
|
|
};
|
|
bool S_GetTrackData( KeyValues *pOperatorsKV, track_data_t &trackData );
|
|
|
|
extern CSosOperatorStackList *S_InitChannelOperators( stack_data_t &stackData );
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#define SO_MAX_DATA_SIZE SO_MAX_SPEAKERS
|
|
#define SO_MAX_SPEAKERS ( CCHANVOLUMES / 2 )
|
|
#define SO_POSITION_ARRAY_SIZE 3
|
|
#define XPOSITION 0
|
|
#define YPOSITION 1
|
|
#define ZPOSITION 2
|
|
#define SO_ANGLE_ARRAY_SIZE 3
|
|
#define XANGLE 0
|
|
#define YANGLE 1
|
|
#define ZANGLE 2
|
|
|
|
//
|
|
//
|
|
//
|
|
class CScratchPad
|
|
{
|
|
|
|
public:
|
|
|
|
void Clear()
|
|
{
|
|
m_bIsPlayerSound = false;
|
|
m_bIsLooping = false;
|
|
|
|
// cleared before update loop, needs to go away anyway
|
|
// m_vBlendedListenerOrigin.Init( 0, 0, 0 );
|
|
m_UtlVecMultiOrigins.RemoveAll( );
|
|
m_nChannel = 6;
|
|
m_nSoundSource = 0;
|
|
m_flDelay = 0.0;
|
|
m_bBlockStart = false;
|
|
m_nSoundScriptHash = SOUNDEMITTER_INVALID_HASH;
|
|
m_flDelayToQueue = 0.0;
|
|
}
|
|
|
|
// void SetPerUpdate();
|
|
void SetPerExecution( channel_t *pChannel, StartSoundParams_t *pStartParams )
|
|
{
|
|
Clear();
|
|
|
|
if( pChannel )
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// channel params
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
VectorCopy( pChannel->origin, m_vEmitterInfoOrigin );
|
|
VectorCopy( pChannel->direction, m_vEmitterInfoDirection );
|
|
m_nSoundSource = pChannel->soundsource;
|
|
m_nChannel = pChannel->entchannel;
|
|
pChannel->sfx ? pChannel->sfx->getname( m_emitterInfoSoundName, sizeof( m_emitterInfoSoundName ) ) : "";
|
|
m_flEmitterInfoMasterVolume = ( (float) pChannel->master_vol ) / 255.0f;
|
|
m_vEmitterInfoSoundLevel = DIST_MULT_TO_SNDLVL( pChannel->dist_mult );
|
|
m_flEmitterInfoPitch = pChannel->basePitch * 0.01f;
|
|
m_nEmitterInfoSpeakerEntity = pChannel->speakerentity;
|
|
m_nEmitterInfoRadius = pChannel->radius;
|
|
|
|
CAudioSource *pSource = pChannel->sfx ? pChannel->sfx->pSource : NULL;
|
|
if ( pSource )
|
|
{
|
|
m_bIsLooping = pSource->IsLooped();
|
|
}
|
|
|
|
m_nSoundScriptHash = pChannel->m_nSoundScriptHash;
|
|
}
|
|
else if ( pStartParams )
|
|
{
|
|
char m_emitterInfoSoundName[MAX_PATH];
|
|
pStartParams->pSfx ? pStartParams->pSfx->getname( m_emitterInfoSoundName, sizeof( m_emitterInfoSoundName ) ) : "";
|
|
// MORASKY: handle emitter angles throughout scratchpad
|
|
//VectorCopy( pStartParams.direction, g_scratchpad.m_vEmitterInfoAngle );
|
|
VectorCopy( pStartParams->origin, m_vEmitterInfoOrigin );
|
|
VectorCopy( pStartParams->direction, m_vEmitterInfoDirection );
|
|
m_nSoundSource = pStartParams->soundsource;
|
|
m_nChannel = pStartParams->entchannel;
|
|
m_vEmitterInfoSoundLevel = pStartParams->soundlevel;
|
|
m_flEmitterInfoPitch = pStartParams->pitch * 0.01f;
|
|
m_nEmitterInfoSpeakerEntity = pStartParams->speakerentity;
|
|
m_flEmitterInfoMasterVolume = pStartParams->fvol;
|
|
m_nEmitterInfoRadius = dB_To_Radius( m_vEmitterInfoSoundLevel );
|
|
|
|
CAudioSource *pSource = pStartParams->pSfx ? pStartParams->pSfx->pSource : NULL;
|
|
if ( pSource )
|
|
{
|
|
m_bIsLooping = pSource->IsLooped();
|
|
}
|
|
|
|
if( pStartParams->m_bIsScriptHandle )
|
|
{
|
|
m_nSoundScriptHash = pStartParams->m_nSoundScriptHash;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// is this a player originated sound and not a tool sound?
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if ( IsSoundSourceViewEntity( m_nSoundSource ) && !toolframework->InToolMode() )
|
|
{
|
|
// sounds coming from listener actually come from a short distance directly in front of listener
|
|
// in tool mode however, the view entity is meaningless, since we're viewing from arbitrary locations in space
|
|
m_bIsPlayerSound = true;
|
|
}
|
|
}
|
|
|
|
HSOUNDSCRIPTHASH m_nSoundScriptHash;
|
|
|
|
// listener(s)
|
|
// NOTE: should be made 1 listener per updated and use iterators
|
|
Vector m_vPlayerOrigin[ MAX_SPLITSCREEN_CLIENTS ];
|
|
Vector m_vPlayerForward[ MAX_SPLITSCREEN_CLIENTS ];
|
|
Vector m_vPlayerRight[ MAX_SPLITSCREEN_CLIENTS ];
|
|
Vector m_vPlayerUp[ MAX_SPLITSCREEN_CLIENTS ];
|
|
Vector m_vClientSourceVectors[ MAX_SPLITSCREEN_CLIENTS ];
|
|
Vector m_vBlendedListenerOrigin;
|
|
|
|
// source info
|
|
bool m_bIsLooping;
|
|
bool m_bIsPlayerSound;
|
|
|
|
// emitter info
|
|
int m_nChannel;
|
|
int m_nSoundSource;
|
|
char m_emitterInfoSoundName[MAX_PATH];
|
|
Vector m_vEmitterInfoOrigin;
|
|
Vector m_vEmitterInfoDirection;
|
|
soundlevel_t m_vEmitterInfoSoundLevel;
|
|
float m_flEmitterInfoPitch;
|
|
int m_nEmitterInfoSpeakerEntity;
|
|
float m_flEmitterInfoMasterVolume; // channel actually? ie: it's been altered by operators?
|
|
float m_nEmitterInfoRadius;
|
|
|
|
// not passed to scratchpad from StartSoundParams_t
|
|
// CSfxTable *pSfx;
|
|
// int flags;
|
|
// float delay;
|
|
// int initialStreamPosition;
|
|
// HSOUNDSCRIPTHANDLE m_nSoundScriptHandle;
|
|
// const char *m_pSoundEntryName;
|
|
//
|
|
// bool staticsound : 1;
|
|
// bool bUpdatePositions : 1;
|
|
// bool fromserver : 1;
|
|
// bool bToolSound : 1;
|
|
// bool m_bIsScriptHandle : 1;
|
|
|
|
// entity info
|
|
QAngle m_vEntityInfoAngle;
|
|
Vector m_vEntityInfoOrigin;
|
|
float m_flEntityInfoRadius;
|
|
CUtlVector< Vector > m_UtlVecMultiOrigins;
|
|
|
|
|
|
// outputs
|
|
float m_flDelay;
|
|
bool m_bBlockStart;
|
|
float m_flDelayToQueue;
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
enum SODataType_t
|
|
{
|
|
SO_FLOAT = 0,
|
|
};
|
|
|
|
#define SO_SINGLE 1
|
|
#define SO_VEC3 3
|
|
#define SO_SPEAKERS SO_MAX_SPEAKERS
|
|
#define SO_VEC3_X_8 3 * 8
|
|
|
|
|
|
// enum SODataCount_t
|
|
// {
|
|
// SO_FLOAT_1 = 1,
|
|
// SO_VEC3 = 3,
|
|
// SO_SPEAKERS = SO_MAX_SPEAKERS,
|
|
// SO_VEC3_X_8 = 3 * 8,
|
|
//
|
|
// };
|
|
|
|
|
|
// SIZES MUST MATCH ABOVE INDICES
|
|
// short SODataSizes[] = { sizeof( float ), sizeof( float ) * 3, sizeof( float ) * SO_MAX_SPEAKERS, sizeof( float ) * 3 * 8 };
|
|
//
|
|
// short SODataIndices[] = { 1, 3, SO_MAX_SPEAKERS, 3 * 8 };
|
|
|
|
enum SOSStopType_t
|
|
{
|
|
SOS_STOP_NONE = 0,
|
|
SOS_STOP_NORM,
|
|
SOS_STOP_FORCE,
|
|
SOS_STOP_HOLD,
|
|
SOS_STOP_QUEUE
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// The CSosOperatorStack class:
|
|
//
|
|
// Manages a "stack" of operators.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
class CSosOperatorStack
|
|
{
|
|
public:
|
|
|
|
enum SosStackType_t
|
|
{
|
|
SOS_NONE = 0,
|
|
SOS_UPDATE,
|
|
SOS_CUE,
|
|
SOS_START,
|
|
SOS_STOP,
|
|
|
|
};
|
|
|
|
CSosOperatorStack( SosStackType_t SosType, stack_data_t &stackData );
|
|
~CSosOperatorStack();
|
|
|
|
SosStackType_t GetType() { return m_SOSType; }
|
|
|
|
void SetName( const char *pName ) { V_strcpy_safe( m_nName, pName ); }
|
|
const char *GetName() { return m_nName; }
|
|
void SetChannelGuid( int nGuid ) { m_nChannelGuid = nGuid; }
|
|
int GetChannelGuid( ) const { return m_nChannelGuid; }
|
|
void SetStartTime( float flStartTime ) { m_flStartTime = flStartTime; }
|
|
float GetStartTime( ) const { return m_flStartTime; }
|
|
float GetElapsedTime( ) const { return g_pSoundServices->GetHostTime() - m_flStartTime; }
|
|
void SetStopTime( float flStopTime ) { m_flStopTime = flStopTime; }
|
|
float GetStopTime( ) const { return m_flStopTime; }
|
|
float GetElapsedStopTime( ) const { return m_flStopTime < 0.0 ? -1.0 : g_pSoundServices->GetHostTime() - m_flStopTime; }
|
|
void SetScriptHash( HSOUNDSCRIPTHASH nHash );
|
|
HSOUNDSCRIPTHASH GetScriptHash( ) const { return m_nScriptHash; }
|
|
void SetOperatorsKV( KeyValues *pOpKV ) { m_pOperatorsKV = pOpKV; }
|
|
KeyValues *GetOperatorsKV( ) const { return m_pOperatorsKV; }
|
|
void SetStopType( SOSStopType_t stopType );
|
|
SOSStopType_t GetStopType( ) const { return m_stopType; }
|
|
|
|
KeyValues *GetSyncPointsKV( KeyValues *pOperatorsKV, const char *pListName );
|
|
KeyValues *GetSyncPointsKV( const char *pListName );
|
|
|
|
void GetTrackData( track_data_t &trackData ) const;
|
|
|
|
void AddToTail( CSosOperator *pOperator, const char *pName );
|
|
|
|
int FindOperatorViaOffset( size_t nOffset );
|
|
CSosOperator *FindOperator( const char *pName, void **pStructHandle );
|
|
int FindOperator( const char *pName );
|
|
const char* GetOperatorName( int nOpIndex ) { return m_vOperatorMap.GetElementName( nOpIndex ); }
|
|
int GetOperatorOffset( int nIndex );
|
|
int GetOperatorOutputOffset( const char *pOperatorName, const char *pOutputName );
|
|
void *GetMemPtr() { return m_pMemPool; }
|
|
size_t GetSize() { return m_nMemSize; }
|
|
void Execute( channel_t *pChannel, CScratchPad *pScratchPad );
|
|
void ExecuteIterator( channel_t *pChannel, CScratchPad *pScratchPad, const void *pVoidMem, const char *pOperatorName, int * pnOperatorIndex );
|
|
void Init( );
|
|
void Shutdown( );
|
|
|
|
inline bool IsType( SosStackType_t SosType ) { return ( SosType == m_SOSType ); }
|
|
|
|
void Print( int nLevel );
|
|
void Copy( CSosOperatorStack *pDstStack, size_t nMemOffset );
|
|
void ParseKV( KeyValues *pParamKV );
|
|
bool ShouldPrintOperators( ) const;
|
|
bool ShouldPrintOperatorUpdates( ) const;
|
|
// void OverParseKV( KeyValues *pOperatorsKV );
|
|
|
|
|
|
private:
|
|
|
|
char m_nName[64];
|
|
SosStackType_t m_SOSType;
|
|
void *m_pMemPool;
|
|
size_t m_nMemSize;
|
|
CUtlVector< CSosOperator * > m_vStack;
|
|
CUtlDict < int, int > m_vOperatorMap;
|
|
|
|
int m_nChannelGuid;
|
|
float m_flStartTime;
|
|
HSOUNDSCRIPTHASH m_nScriptHash;
|
|
KeyValues *m_pOperatorsKV;
|
|
SOSStopType_t m_stopType;
|
|
float m_flStopTime;
|
|
|
|
public:
|
|
const char *m_pCurrentOperatorName;
|
|
|
|
};
|
|
|
|
extern CSosOperatorStack *S_GetStack( CSosOperatorStack::SosStackType_t stackType, stack_data_t &stackData );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// The CSosOperatorStackList class:
|
|
//
|
|
// Manages a "stack" of operators.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
class CSosOperatorStackList
|
|
{
|
|
|
|
public:
|
|
CSosOperatorStackList();
|
|
~CSosOperatorStackList();
|
|
|
|
void SetStopType( SOSStopType_t stopType );
|
|
SOSStopType_t GetStopType( ) const { return m_stopType; }
|
|
void SetStopTime( float flStopTime );
|
|
float GetStartTime( ) const { return m_flStopTime; }
|
|
float GetElapsedStopTime( ) const { return m_flStopTime < 0.0 ? 0.0 : g_pSoundServices->GetHostTime() - m_flStopTime; }
|
|
|
|
bool HasStack( CSosOperatorStack::SosStackType_t SosType );
|
|
|
|
void Execute( CSosOperatorStack::SosStackType_t SosType, channel_t *pChannel, CScratchPad *pScratchPad );
|
|
|
|
void SetChannelGuid( int nGuid );
|
|
void SetStartTime( float flStartTime );
|
|
void SetScriptHash( HSOUNDSCRIPTHASH nHash );
|
|
void SetStack( CSosOperatorStack *pStack );
|
|
CSosOperatorStack *GetStack( CSosOperatorStack::SosStackType_t SosType );
|
|
void StopStacks( SOSStopType_t stopType );
|
|
bool IsStopped( ) const { return ( m_stopType != SOS_STOP_NONE && m_stopType!= SOS_STOP_HOLD && m_stopType!= SOS_STOP_QUEUE ); }
|
|
bool IsStopping( ) const { return ( m_stopType != SOS_STOP_NONE ); }
|
|
void ParseKV( stack_data_t &stackData );
|
|
void Print( );
|
|
|
|
private:
|
|
|
|
CSosOperatorStack *m_vUpdateStack;
|
|
CSosOperatorStack *m_vStartStack;
|
|
CSosOperatorStack *m_vStopStack;
|
|
CSosOperatorStack *m_vCueStack;
|
|
SOSStopType_t m_stopType;
|
|
float m_flStopTime;
|
|
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// The CSosOperatorStackCollection class:
|
|
//
|
|
// Manages a "stack" of operators.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
class CSosOperatorStackCollection
|
|
{
|
|
|
|
public:
|
|
~CSosOperatorStackCollection();
|
|
void Clear();
|
|
|
|
CSosOperatorStack *GetStack( const char *pStackName );
|
|
CSosOperatorStack *GetStack( CSosOperatorStack::SosStackType_t SosType, const char *pStackName );
|
|
|
|
void Print();
|
|
void ParseKV( CSosOperatorStack::SosStackType_t SosType, KeyValues *pParamKV );
|
|
|
|
private:
|
|
|
|
CUtlDict <CSosOperatorStack *, int> m_vAllStacks;
|
|
CUtlDict <CSosOperatorStack *, int> m_vUpdateStacks;
|
|
CUtlDict <CSosOperatorStack *, int> m_vStartStacks;
|
|
CUtlDict <CSosOperatorStack *, int> m_vStopStacks;
|
|
CUtlDict <CSosOperatorStack *, int> m_vCueStacks;
|
|
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
class SosStopQueueData_t
|
|
{
|
|
public:
|
|
int m_nChannelGuid;
|
|
float m_nStopTime;
|
|
};
|
|
class SosStartQueueData_t
|
|
{
|
|
public:
|
|
StartSoundParams_t m_startSoundParams;
|
|
float m_nStartTime;
|
|
bool m_bFromPrestart;
|
|
};
|
|
|
|
class CSosOperatorSystem
|
|
{
|
|
public:
|
|
CSosOperatorSystem();
|
|
~CSosOperatorSystem();
|
|
|
|
void Init();
|
|
void Update();
|
|
void Shutdown();
|
|
void Flush();
|
|
void PrintOperatorList();
|
|
|
|
void ClearSubSystems();
|
|
|
|
void QueueStartEntry( StartSoundParams_t &startParams, float flDelay = 0.0, bool bFromPrestart = false );
|
|
void StartQueuedEntries();
|
|
|
|
void QueueStopChannel( int nChannelGuid, float flDelay = 0.0 );
|
|
void StopQueuedChannels();
|
|
bool IsInStopQueue( int nChannelGuid );
|
|
|
|
void StopChannelOnTrack( const char *pTrackName, bool bStopAll = false, float flStopDelay = 0.0 );
|
|
void SetChannelOnTrack( const char *pTrackName, channel_t *pChannel );
|
|
void RemoveChannelFromTracks( int nGuid );
|
|
void RemoveChannelFromTrack( const char *pTrackName, int nGuid );
|
|
void DEBUG_ShowTrackList( void );
|
|
|
|
channel_t *GetChannelOnTrack( const char *pTrackName );
|
|
HSOUNDSCRIPTHASH GetSoundEntryOnTrack( const char *pTrackName );
|
|
bool GetTrackDataOnTrack( const char *pTrackName, track_data_t &trackData );
|
|
|
|
bool SetOpVarFloat( const char *pString, float flVariable );
|
|
bool GetOpVarFloat( const char *pString, float &flVariable );
|
|
void DEBUG_ShowOpvarList( void );
|
|
|
|
|
|
public:
|
|
CSosOperatorStackCollection m_MasterStackCollection;
|
|
CUtlDict <CSosOperator*, int> m_vOperatorCollection;
|
|
|
|
CSosEntryMatchList m_sosEntryBlockList;
|
|
|
|
CUtlDict <channel_t *, int> m_vTrackDict;
|
|
|
|
|
|
// NOT THREAD PROTECTED!
|
|
CUtlVector < SosStopQueueData_t * > m_sosStopChannelQueue;
|
|
CUtlVector< SosStartQueueData_t * > m_sosStartEntryQueue;
|
|
|
|
// CTSQueue< StartSoundParams_t > m_sosStartEntryQueue;
|
|
// CTSQueue< sos_stop_queue_t > m_sosStopChannelQueue;
|
|
|
|
static CSosOperatorSystem *GetSoundOperatorSystem();
|
|
|
|
// Used to generate random numbers
|
|
CUniformRandomStream m_operatorRandomStream;
|
|
|
|
private:
|
|
bool m_bHasInitialized;
|
|
// CUtlStringMap < float > m_sosFloatOpvarMap;
|
|
CUtlDict < float, int > m_sosOpVarFloatMap;
|
|
};
|
|
|
|
#define g_pSoundOperatorSystem CSosOperatorSystem::GetSoundOperatorSystem()
|
|
|
|
#endif // SOS_SYSTEM_H
|