aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/client/replay/replay_ragdoll.h
blob: 10112030fb1731685a061b28daea7f277070c509 (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//----------------------------------------------------------------------------------------

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

//--------------------------------------------------------------------------------

class C_BaseAnimating;

//--------------------------------------------------------------------------------

struct RagdollSimulationFrame_t
{
	RagdollSimulationFrame_t() : pPositions(NULL), pAngles(NULL), nTick(-1) {}

	static RagdollSimulationFrame_t* Alloc( int nNumBones );

	int			nTick;
	Vector*		pPositions;
	QAngle*		pAngles;
	Vector		vRootPosition;
	QAngle		angRootAngles;
};

//--------------------------------------------------------------------------------

struct RagdollSimulationData_t
{
	RagdollSimulationData_t( C_BaseAnimating* pEntity = NULL, int nStartTick = 0, int nNumBones = 0 );

	void Record();

	int	m_nEntityIndex;
	int	m_nStartTick;
	int	m_nDuration;
	int m_nNumBones;

	typedef unsigned short Iterator_t;

	CUtlLinkedList< RagdollSimulationFrame_t*, Iterator_t > m_lstFrames;
	C_BaseAnimating* m_pEntity;
};

//--------------------------------------------------------------------------------

// TODO: Refactor this into an interface and hide implementation in cpp file

class CReplayRagdollRecorder
{
private:
	CReplayRagdollRecorder();
	~CReplayRagdollRecorder();

public:
	static CReplayRagdollRecorder& Instance();

	void Init();
	void Shutdown();

	void Think();

	void AddEntry( C_BaseAnimating* pEntity, int nStartTick, int nNumBones );
	void StopRecordingRagdoll( C_BaseAnimating* pEntity );

	void CleanupStartupTicksAndDurations( int nStartTick );
	bool DumpRagdollsToDisk( char const* pszFilename ) const;

	bool IsRecording() const		{ return m_bIsRecording; }

private:
	typedef unsigned short Iterator_t;

	void StopRecordingRagdollAtIndex( Iterator_t nIndex );

	void StopRecordingSleepingRagdolls();
	void Record();

	bool FindEntryInRecordingList( C_BaseAnimating* pEntity, Iterator_t& nOutIndex );

	void PrintDebug();

	CUtlLinkedList< RagdollSimulationData_t*, Iterator_t > m_lstRagdolls;
	CUtlLinkedList< RagdollSimulationData_t*, Iterator_t > m_lstRagdollsToRecord;	// Contains some of the elements from m_lstRagdolls -
																					// the ones which are still recording
	bool m_bIsRecording;
};

//--------------------------------------------------------------------------------

class CReplayRagdollCache
{
private:
	CReplayRagdollCache();

public:
	static CReplayRagdollCache& Instance();

	bool Init( char const* pszFilename );
	void Shutdown();

	void Think();

	bool IsInitialized() const				{ return m_bInit; }

	//
	// Returns false is no frame exists for the given entity at the given tick.
	// Otherwise, returns a 
	//
	bool GetFrame( C_BaseAnimating* pEntity, int nTick, bool* pBoneSimulated, CBoneAccessor* pBoneAccessor ) const;

private:
	RagdollSimulationData_t* FindRagdollEntry( C_BaseAnimating* pEntity, int nTick );
	const RagdollSimulationData_t* FindRagdollEntry( C_BaseAnimating* pEntity, int nTick ) const;

	bool FindFrame( RagdollSimulationFrame_t*& pFrameOut, RagdollSimulationFrame_t*& pNextFrameOut,
		const RagdollSimulationData_t* pRagdollEntry, int nTick );
	bool FindFrame( RagdollSimulationFrame_t*& pFrameOut, RagdollSimulationFrame_t*& pNextFrameOut,
		const RagdollSimulationData_t* pRagdollEntry, int nTick ) const;

	typedef unsigned short Iterator_t;
	bool m_bInit;

	CUtlLinkedList< RagdollSimulationData_t*, Iterator_t > m_lstRagdolls;
};

//--------------------------------------------------------------------------------

bool Replay_CacheRagdolls( const char* pFilename, int nStartTick );

//--------------------------------------------------------------------------------

inline const RagdollSimulationData_t* CReplayRagdollCache::FindRagdollEntry( C_BaseAnimating* pEntity, int nTick ) const
{
	return const_cast< CReplayRagdollCache* >( this )->FindRagdollEntry( pEntity, nTick );
}

inline bool CReplayRagdollCache::FindFrame( RagdollSimulationFrame_t*& pFrameOut, RagdollSimulationFrame_t*& pNextFrameOut,
											const RagdollSimulationData_t* pRagdollEntry, int nTick ) const
{
	return const_cast< CReplayRagdollCache* >( this )->FindFrame( pFrameOut, pNextFrameOut, pRagdollEntry, nTick );
}

//--------------------------------------------------------------------------------

#endif // REPLAY_RAGDOLL_H