Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_UNITANIMATION
19 : #define INCLUDED_UNITANIMATION
20 :
21 : #include "ps/CStr.h"
22 :
23 : #include "simulation2/system/Entity.h"
24 :
25 : #include <vector>
26 :
27 : class CUnit;
28 : class CModel;
29 : class CSkeletonAnim;
30 : class CObjectEntry;
31 :
32 : /**
33 : * Deals with synchronisation issues between raw animation data (CModel, CSkeletonAnim)
34 : * and the simulation system (via CUnit), providing a simple fire-and-forget API to play animations.
35 : * (This is really just a component of CUnit and could probably be merged back into that class.)
36 : */
37 0 : class CUnitAnimation
38 : {
39 : NONCOPYABLE(CUnitAnimation);
40 : public:
41 : /**
42 : * Construct for a given unit, defaulting to the "idle" animation.
43 : */
44 : CUnitAnimation(entity_id_t ent, CModel* model, CObjectEntry* object);
45 :
46 : /**
47 : * Change the entity ID associated with this animation
48 : * (currently used for playing locational sound effects).
49 : */
50 : void SetEntityID(entity_id_t ent);
51 :
52 : /**
53 : * Start playing an animation.
54 : * The unit's actor defines the available animations, and if more than one is available
55 : * then one is picked at random (with a new random choice each loop).
56 : * By default, animations start immediately and run at the given speed with no syncing.
57 : * Use SetAnimationSync after this to force a specific timing, if it needs to match the
58 : * simulation timing.
59 : * Alternatively, set @p desync to a non-zero value (e.g. 0.05) to slightly randomise the
60 : * offset and speed, so units don't all move in lockstep.
61 : * @param name animation's name ("idle", "walk", etc)
62 : * @param once if true then the animation freezes on its last frame; otherwise it loops
63 : * @param speed fraction of actor-defined speed to play back at (should typically be 1.0)
64 : * @param desync maximum fraction of length/speed to randomly adjust timings (or 0.0 for no desyncing)
65 : * @param actionSound sound group name to be played at the 'action' point in the animation, or empty string
66 : */
67 : void SetAnimationState(const CStr& name, bool once, float speed, float desync, const CStrW& actionSound);
68 :
69 : /**
70 : * Adjust the speed of the current animation, so that Update(repeatTime) will do a
71 : * complete animation loop.
72 : * @param repeatTime time for complete loop of animation, in msec
73 : */
74 : void SetAnimationSyncRepeat(float repeatTime);
75 :
76 : /**
77 : * Adjust the offset of the current animation, so that Update(actionTime) will advance it
78 : * to the 'action' point defined in the actor.
79 : * This must be called after SetAnimationSyncRepeat sets the speed.
80 : * @param actionTime time between now and when the action should occur, in msec
81 : */
82 : void SetAnimationSyncOffset(float actionTime);
83 :
84 : /**
85 : * Advance the animation state.
86 : * @param time advance time in msec
87 : */
88 : void Update(float time);
89 :
90 : /**
91 : * Regenerate internal animation state from the models in the current unit.
92 : * This should be called whenever the unit is changed externally, to keep this in sync.
93 : */
94 : void ReloadUnit(CModel* model, const CObjectEntry* object);
95 :
96 : /**
97 : * Reload animation so any changes take immediate effect.
98 : */
99 : void ReloadAnimation();
100 :
101 : private:
102 :
103 : /**
104 : * Picks a new animation ID from our current state
105 : */
106 : void PickAnimationID();
107 :
108 : struct SModelAnimState
109 : {
110 : CModel* model;
111 : CSkeletonAnim* anim;
112 : const CObjectEntry* object;
113 : float time;
114 : bool pastLoadPos;
115 : bool pastActionPos;
116 : bool pastSoundPos;
117 : };
118 :
119 : std::vector<SModelAnimState> m_AnimStates;
120 :
121 : /**
122 : * True if all the current AnimStates are static, so Update() doesn't need
123 : * to do any work at all
124 : */
125 : bool m_AnimStatesAreStatic;
126 :
127 : void AddModel(CModel* model, const CObjectEntry* object);
128 :
129 : entity_id_t m_Entity;
130 : CModel* m_Model;
131 : const CObjectEntry* m_Object;
132 : CStr m_State;
133 : CStr m_AnimationID = "";
134 : bool m_Looping;
135 : float m_OriginalSpeed;
136 : float m_Speed;
137 : float m_SyncRepeatTime;
138 : float m_Desync;
139 : CStrW m_ActionSound;
140 : };
141 :
142 : #endif // INCLUDED_UNITANIMATION
|