File: UnitAnimation.h

package info (click to toggle)
0ad 0.0.23.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 78,292 kB
  • sloc: cpp: 245,166; ansic: 200,249; python: 13,754; sh: 6,104; perl: 4,620; makefile: 977; xml: 810; java: 533; ruby: 229; erlang: 46; pascal: 30; sql: 21; tcl: 4
file content (140 lines) | stat: -rw-r--r-- 4,498 bytes parent folder | download | duplicates (2)
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
/* Copyright (C) 2018 Wildfire Games.
 * This file is part of 0 A.D.
 *
 * 0 A.D. is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0 A.D. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef INCLUDED_UNITANIMATION
#define INCLUDED_UNITANIMATION

#include "ps/CStr.h"

#include "simulation2/system/Entity.h"

class CUnit;
class CModel;
class CSkeletonAnim;
class CObjectEntry;

/**
 * Deals with synchronisation issues between raw animation data (CModel, CSkeletonAnim)
 * and the simulation system (via CUnit), providing a simple fire-and-forget API to play animations.
 * (This is really just a component of CUnit and could probably be merged back into that class.)
 */
class CUnitAnimation
{
	NONCOPYABLE(CUnitAnimation);
public:
	/**
	 * Construct for a given unit, defaulting to the "idle" animation.
	 */
	CUnitAnimation(entity_id_t ent, CModel* model, CObjectEntry* object);

	/**
	 * Change the entity ID associated with this animation
	 * (currently used for playing locational sound effects).
	 */
	void SetEntityID(entity_id_t ent);

	/**
	 * Start playing an animation.
	 * The unit's actor defines the available animations, and if more than one is available
	 * then one is picked at random (with a new random choice each loop).
	 * By default, animations start immediately and run at the given speed with no syncing.
	 * Use SetAnimationSync after this to force a specific timing, if it needs to match the
	 * simulation timing.
	 * Alternatively, set @p desync to a non-zero value (e.g. 0.05) to slightly randomise the
	 * offset and speed, so units don't all move in lockstep.
	 * @param name animation's name ("idle", "walk", etc)
	 * @param once if true then the animation freezes on its last frame; otherwise it loops
	 * @param speed fraction of actor-defined speed to play back at (should typically be 1.0)
	 * @param desync maximum fraction of length/speed to randomly adjust timings (or 0.0 for no desyncing)
	 * @param actionSound sound group name to be played at the 'action' point in the animation, or empty string
	 */
	void SetAnimationState(const CStr& name, bool once, float speed, float desync, const CStrW& actionSound);

	/**
	 * Adjust the speed of the current animation, so that Update(repeatTime) will do a
	 * complete animation loop.
	 * @param repeatTime time for complete loop of animation, in msec
	 */
	void SetAnimationSyncRepeat(float repeatTime);

	/**
	 * Adjust the offset of the current animation, so that Update(actionTime) will advance it
	 * to the 'action' point defined in the actor.
	 * This must be called after SetAnimationSyncRepeat sets the speed.
	 * @param actionTime time between now and when the action should occur, in msec
	 */
	void SetAnimationSyncOffset(float actionTime);

	/**
	 * Advance the animation state.
	 * @param time advance time in msec
	 */
	void Update(float time);

	/**
	 * Regenerate internal animation state from the models in the current unit.
	 * This should be called whenever the unit is changed externally, to keep this in sync.
	 */
	void ReloadUnit(CModel* model, const CObjectEntry* object);

	/**
	 * Reload animation so any changes take immediate effect.
	 */
	void ReloadAnimation();

private:

	/**
	 * Picks a new animation ID from our current state
	 */
	void UpdateAnimationID();

	struct SModelAnimState
	{
		CModel* model;
		CSkeletonAnim* anim;
		const CObjectEntry* object;
		float time;
		bool pastLoadPos;
		bool pastActionPos;
		bool pastSoundPos;
	};

	std::vector<SModelAnimState> m_AnimStates;

	/**
	 * True if all the current AnimStates are static, so Update() doesn't need
	 * to do any work at all
	 */
	bool m_AnimStatesAreStatic;

	void AddModel(CModel* model, const CObjectEntry* object);

	entity_id_t m_Entity;
	CModel* m_Model;
	const CObjectEntry* m_Object;
	CStr m_State;
	CStr m_AnimationID = "";
	bool m_Looping;
	float m_OriginalSpeed;
	float m_Speed;
	float m_SyncRepeatTime;
	float m_Desync;
	CStrW m_ActionSound;
};

#endif // INCLUDED_UNITANIMATION