aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/choreoscene.h
blob: d8203c14024426e8236ad91b3f3281ab65c84e3a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

#ifndef CHOREOSCENE_H
#define CHOREOSCENE_H
#ifdef _WIN32
#pragma once
#endif

class CChoreoEvent;
class CChoreoChannel;
class CChoreoActor;
class IChoreoEventCallback;
class CEventRelativeTag;
class CUtlBuffer;
class CFlexAnimationTrack;
class ISceneTokenProcessor;
class IChoreoStringPool;

#include "tier1/utlvector.h"
#include "tier1/utldict.h"
#include "bitvec.h"
#include "expressionsample.h"
#include "choreoevent.h"

#define DEFAULT_SCENE_FPS	60
#define MIN_SCENE_FPS		10
#define MAX_SCENE_FPS		240

#define SCENE_BINARY_TAG		MAKEID( 'b', 'v', 'c', 'd' )
#define SCENE_BINARY_VERSION	0x04

//-----------------------------------------------------------------------------
// Purpose: Container for choreographed scene of events for actors
//-----------------------------------------------------------------------------
class CChoreoScene : public ICurveDataAccessor
{
	typedef enum 
	{
		PROCESSING_TYPE_IGNORE = 0,
		PROCESSING_TYPE_START,
		PROCESSING_TYPE_START_RESUMECONDITION,
		PROCESSING_TYPE_CONTINUE,
		PROCESSING_TYPE_STOP,
	} PROCESSING_TYPE;

	struct ActiveList
	{
		PROCESSING_TYPE		pt;
		CChoreoEvent		*e;
	};

public:
	// Construction
					CChoreoScene( IChoreoEventCallback *callback );
					~CChoreoScene( void );

	// Assignment
	CChoreoScene&	operator=(const CChoreoScene& src );

	// ICurveDataAccessor methods
	virtual float	GetDuration() { return FindStopTime(); };
	virtual bool	CurveHasEndTime();
	virtual int		GetDefaultCurveType();

	// Binary serialization
	bool			SaveBinary( char const *pszBinaryFileName, char const *pPathID, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool );
	void			SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool );
	bool			RestoreFromBinaryBuffer( CUtlBuffer& buf, char const *filename, IChoreoStringPool *pStringPool );
	static bool		GetCRCFromBinaryBuffer( CUtlBuffer& buf, unsigned int& crc );

	// We do some things differently while restoring from a save.
	inline void		SetRestoring( bool bRestoring );
	inline bool		IsRestoring();

	enum
	{
		MAX_SCENE_FILENAME = 128,
	};

	// Event callback handler
	void			SetEventCallbackInterface( IChoreoEventCallback *callback );

	// Loading
	bool			ParseFromBuffer( char const *pFilename, ISceneTokenProcessor *tokenizer );
	void			SetPrintFunc( void ( *pfn )( PRINTF_FORMAT_STRING const char *fmt, ... ) );

	// Saving
	bool			SaveToFile( const char *filename );
	bool			ExportMarkedToFile( const char *filename );
	void			MarkForSaveAll( bool mark );

	// Merges two .vcd's together, returns true if any data was merged
	bool			Merge( CChoreoScene *other );

	static void		FileSaveFlexAnimationTrack( CUtlBuffer& buf, int level, CFlexAnimationTrack *track, int nDefaultCurveType );
	static void		FileSaveFlexAnimations( CUtlBuffer& buf, int level, CChoreoEvent *e );
	static void		FileSaveRamp( CUtlBuffer& buf, int level, CChoreoEvent *e );
	void			FileSaveSceneRamp( CUtlBuffer& buf, int level );
	static void		FileSaveScaleSettings( CUtlBuffer& buf, int level, CChoreoScene *scene );

	static void		ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreoEvent *e, bool removeold = true );
	static void		ParseRamp( ISceneTokenProcessor *tokenizer, CChoreoEvent *e );
	static void		ParseSceneRamp( ISceneTokenProcessor *tokenizer, CChoreoScene *scene );
	static void		ParseScaleSettings( ISceneTokenProcessor *tokenizer, CChoreoScene *scene );
	static void		ParseEdgeInfo( ISceneTokenProcessor *tokenizer, EdgeInfo_t *edgeinfo );

	// Debugging
	void			SceneMsg( PRINTF_FORMAT_STRING const char *pFormat, ... );
	void			Print( void );

	// Sound system needs to have sounds pre-queued by this much time
	void			SetSoundFileStartupLatency( float time );

	// Simulation
	void			Think( float curtime );
	float			LoopThink( float curtime );
	void			ProcessActiveListEntry( ActiveList *entry );
	// Retrieves time in simulation
	float			GetTime( void );
	// Retrieves start/stop time for looped/debug scene
	void			GetSceneTimes( float& start, float& end );

	void			SetTime( float t );
	void			LoopToTime( float t );

	// Has simulation finished
	bool			SimulationFinished( void );
	// Reset simulation
	void			ResetSimulation( bool forward = true, float starttime = 0.0f, float endtime = 0.0f );
	// Find time at which last simulation event is triggered
	float			FindStopTime( void );

	void			ResumeSimulation( void );

	// Have all the pause events happened
	bool			CheckEventCompletion( void );

	// Find named actor in scene data
	CChoreoActor	*FindActor( const char *name );
	// Remove actor from scene
	void			RemoveActor( CChoreoActor *actor );
	// Find index for actor
	int				FindActorIndex( CChoreoActor *actor );

	// Swap actors in the data
	void			SwapActors( int a1, int a2 );

	// General data access
	int				GetNumEvents( void );
	CChoreoEvent	*GetEvent( int event );

	int				GetNumActors( void );
	CChoreoActor	*GetActor( int actor );
	
	int				GetNumChannels( void );
	CChoreoChannel	*GetChannel( int channel );

	// Object allocation/destruction
	void			DeleteReferencedObjects( CChoreoActor *actor );
	void			DeleteReferencedObjects( CChoreoChannel *channel );
	void			DeleteReferencedObjects( CChoreoEvent *event );

	CChoreoActor	*AllocActor( void );
	CChoreoChannel	*AllocChannel( void );
	CChoreoEvent	*AllocEvent( void );

	void			AddEventToScene( CChoreoEvent *event );
	void			AddActorToScene( CChoreoActor *actor );
	void			AddChannelToScene( CChoreoChannel *channel );

	// Fixup simulation times for channel gestures
	void			ReconcileGestureTimes( void );

	// Go through all elements and update relative tags, removing any orphaned
	// tags and updating the timestamp of normal tags
	void			ReconcileTags( void );
	CEventRelativeTag	*FindTagByName( const char *wavname, const char *name );
	CChoreoEvent	*FindTargetingEvent( const char *wavname, const char *name );

	// Used by UI to provide target actor names
	char const		*GetMapname( void );
	void			SetMapname( const char *name );

	void			ExportEvents( const char *filename, CUtlVector< CChoreoEvent * >& events );
	void			ImportEvents( ISceneTokenProcessor *tokenizer, CChoreoActor *actor, CChoreoChannel *channel );

	// Subscene support
	void			SetSubScene( bool sub );
	bool			IsSubScene( void ) const;

	int				GetSceneFPS( void ) const;
	void			SetSceneFPS( int fps );
	bool			IsUsingFrameSnap( void ) const;
	void			SetUsingFrameSnap( bool snap );

	float			SnapTime( float t );

	int				GetSceneRampCount( void ) { return m_SceneRamp.GetCount(); };
	CExpressionSample *GetSceneRamp( int index ) { return m_SceneRamp.Get( index ); };
	CExpressionSample *AddSceneRamp( float time, float value, bool selected ) { return m_SceneRamp.Add( time, value, selected ); };
	void			DeleteSceneRamp( int index ) { m_SceneRamp.Delete( index ); };
	void			ClearSceneRamp( void ) { m_SceneRamp.Clear(); };
	void			ResortSceneRamp( void ) { m_SceneRamp.Resort( this ); };

	CCurveData		*GetSceneRamp( void ) { return &m_SceneRamp; };


	// Global intensity for scene
	float			GetSceneRampIntensity( float time ) { return m_SceneRamp.GetIntensity( this, time ); }

	int				GetTimeZoom( char const *tool );
	void			SetTimeZoom( char const *tool, int tz );
	int				TimeZoomFirst();
	int				TimeZoomNext( int i );
	int				TimeZoomInvalid() const;
	char const		*TimeZoomName( int i );

	void			ReconcileCloseCaption();

	char const		*GetFilename() const;
	void			SetFileName( char const *fn );

	bool			GetPlayingSoundName( char *pchBuff, int iBuffLength );
	bool			HasUnplayedSpeech();
	bool			HasFlexAnimation();
	void			SetBackground( bool bIsBackground );
	bool			IsBackground( void );

	void			ClearPauseEventDependencies();

	bool			HasEventsOfType( CChoreoEvent::EVENTTYPE type ) const;
	void			RemoveEventsExceptTypes( int* typeList, int count );

	void IgnorePhonemes( bool bIgnore );
	bool ShouldIgnorePhonemes() const;

	// This is set by the engine to signify that we're not modifying the data and 
	//  therefore we can precompute the end time
	static	bool	s_bEditingDisabled; 

private:

	// Simulation stuff
	enum
	{
		IN_RANGE = 0,
		BEFORE_RANGE,
		AFTER_RANGE
	};

	int				IsTimeInRange( float t, float starttime, float endtime );

	static bool EventLess( const CChoreoScene::ActiveList &al0, const CChoreoScene::ActiveList &al1 );

	int				EventThink( CChoreoEvent *e, 
						float frame_start_time, 
						float frame_end_time,
						bool playing_forward, PROCESSING_TYPE& disposition );

	// Prints to debug console, etc
	void			choreoprintf( int level, PRINTF_FORMAT_STRING const char *fmt, ... );

	// Initialize scene
	void			Init( IChoreoEventCallback *callback );

	float			FindAdjustedStartTime( void );
	float			FindAdjustedEndTime( void );

	CChoreoEvent	*FindPauseBetweenTimes( float starttime, float endtime );

	// Parse scenes from token buffer
	CChoreoEvent	*ParseEvent( CChoreoActor *actor, CChoreoChannel *channel );
	CChoreoChannel	*ParseChannel( CChoreoActor *actor );
	CChoreoActor	*ParseActor( void );
	   
	void			ParseFPS( void );
	void			ParseSnap( void );
	void			ParseIgnorePhonemes( void );

	// Map file for retrieving named objects
	void			ParseMapname( void );
	// When previewing actor in hlfaceposer, this is the model to associate
	void			ParseFacePoserModel( CChoreoActor *actor );

	// Print to printfunc
	void			PrintEvent( int level, CChoreoEvent *e );
	void			PrintChannel( int level, CChoreoChannel *c );
	void			PrintActor( int level, CChoreoActor *a );

	// File I/O
public:
	static void		FilePrintf( CUtlBuffer& buf, int level, PRINTF_FORMAT_STRING const char *fmt, ... );
private:
	void			FileSaveEvent( CUtlBuffer& buf, int level, CChoreoEvent *e );
	void			FileSaveChannel( CUtlBuffer& buf, int level, CChoreoChannel *c );
	void			FileSaveActor( CUtlBuffer& buf, int level, CChoreoActor *a );
	void			FileSaveHeader( CUtlBuffer& buf );

	// Object destruction
	void			DestroyActor( CChoreoActor *actor );
	void			DestroyChannel( CChoreoChannel *channel );
	void			DestroyEvent( CChoreoEvent *event );


	void			AddPauseEventDependency( CChoreoEvent *pauseEvent, CChoreoEvent *suppressed );

	void			InternalDetermineEventTypes();

	// Global object storage
	CUtlVector < CChoreoEvent * >	m_Events;
	CUtlVector < CChoreoActor * >	m_Actors;
	CUtlVector < CChoreoChannel	* >	m_Channels;

	// These are just pointers, the actual objects are in m_Events
	CUtlVector < CChoreoEvent * >	m_ResumeConditions;
	// These are just pointers, the actual objects are in m_Events
	CUtlVector < CChoreoEvent * >	m_ActiveResumeConditions;
	// These are just pointers, the actual objects are in m_Events
	CUtlVector < CChoreoEvent * >	m_PauseEvents;

	// Current simulation time
	float			m_flCurrentTime;

	float			m_flStartLoopTime;

	float			m_flStartTime;
	float			m_flEndTime;

	float			m_flEarliestTime;
	float			m_flLatestTime;
	int				m_nActiveEvents;

	// Wave file playback needs to issue play commands a bit ahead of time
	//  in order to hit exact marks
	float			m_flSoundSystemLatency;

	// Scene's linger a bit after finishing to let blends reset themselves
	float			m_flLastActiveTime;

	// Print callback function
	void ( *m_pfnPrint )( PRINTF_FORMAT_STRING const char *fmt, ... );

	IChoreoEventCallback			*m_pIChoreoEventCallback;

	ISceneTokenProcessor			*m_pTokenizer;

	enum
	{
		MAX_MAPNAME = 128
	};

	char			m_szMapname[ MAX_MAPNAME ];

	int				m_nSceneFPS;

	CCurveData		m_SceneRamp;

	CUtlDict< int, int >	m_TimeZoomLookup;
	char			m_szFileName[ MAX_SCENE_FILENAME ];

	CBitVec< CChoreoEvent::NUM_TYPES > m_bitvecHasEventOfType;

	// tag to suppress vcd when others are playing
	bool			m_bIsBackground : 1;
	bool			m_bIgnorePhonemes : 1;
	bool			m_bSubScene : 1;
	bool			m_bUseFrameSnap : 1;
	bool			m_bRestoring : 1;

	int				m_nLastPauseEvent;
	// This only gets updated if it's loaded from a buffer which means we're not in an editor
	float			m_flPrecomputedStopTime;
};


bool CChoreoScene::IsRestoring()
{
	return m_bRestoring;
}


void CChoreoScene::SetRestoring( bool bRestoring )
{
	m_bRestoring = bRestoring;
}


abstract_class IChoreoStringPool
{
public:
	virtual short	FindOrAddString( const char *pString ) = 0;
	virtual bool	GetString( short stringId, char *buff, int buffSize ) = 0; 	
};

CChoreoScene *ChoreoLoadScene( 
	char const *filename,
	IChoreoEventCallback *callback, 
	ISceneTokenProcessor *tokenizer,
	void ( *pfn ) ( PRINTF_FORMAT_STRING const char *fmt, ... ) );

bool IsBufferBinaryVCD( char *pBuffer, int bufferSize );

#endif // CHOREOSCENE_H