975f9ea6da8e3db2c16a62862adac64094674320
[blender.git] / source / gameengine / Ketsji / BL_ActionManager.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program 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 this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Mitchell Stokes.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file BL_ActionManager.cpp
24  *  \ingroup ketsji
25  */
26
27 #include "BL_Action.h"
28 #include "BL_ActionManager.h"
29 #include "DNA_ID.h"
30
31 #define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT))
32
33 BL_ActionManager::BL_ActionManager(class KX_GameObject *obj):
34         m_obj(obj),
35         m_prevUpdate(-1.0f)
36 {
37 }
38
39 BL_ActionManager::~BL_ActionManager()
40 {
41         BL_ActionMap::iterator it;
42
43         for (it = m_layers.begin(); it != m_layers.end(); it++)
44                 delete it->second;
45
46         m_layers.clear();
47 }
48
49 BL_Action *BL_ActionManager::GetAction(short layer)
50 {
51         BL_ActionMap::iterator it = m_layers.find(layer);
52
53         return (it != m_layers.end()) ? it->second : 0;
54 }
55
56 BL_Action* BL_ActionManager::AddAction(short layer)
57 {
58         BL_Action *action = new BL_Action(m_obj);
59         m_layers[layer] = action;
60
61         return action;
62 }
63
64 float BL_ActionManager::GetActionFrame(short layer)
65 {
66         BL_Action *action = GetAction(layer);
67
68         return action ? action->GetFrame() : 0.f;
69 }
70
71 void BL_ActionManager::SetActionFrame(short layer, float frame)
72 {
73         BL_Action *action = GetAction(layer);
74
75         if (action) action->SetFrame(frame);
76 }
77
78 struct bAction *BL_ActionManager::GetCurrentAction(short layer)
79 {
80         BL_Action *action = GetAction(layer);
81
82         return action ? action->GetAction() : 0;
83 }
84
85 void BL_ActionManager::SetPlayMode(short layer, short mode)
86 {
87         BL_Action *action = GetAction(layer);
88
89         if (action) action->SetPlayMode(mode);
90 }
91
92 void BL_ActionManager::SetTimes(short layer, float start, float end)
93 {
94         BL_Action *action = GetAction(layer);
95
96         if (action) action->SetTimes(start, end);
97 }
98
99 bool BL_ActionManager::PlayAction(const char* name,
100                                                                 float start,
101                                                                 float end,
102                                                                 short layer,
103                                                                 short priority,
104                                                                 float blendin,
105                                                                 short play_mode,
106                                                                 float layer_weight,
107                                                                 short ipo_flags,
108                                                                 float playback_speed,
109                                                                 short blend_mode)
110 {
111         // Only this method will create layer if non-existent
112         BL_Action *action = GetAction(layer);
113         if (!action)
114                 action = AddAction(layer);
115
116         // Disable layer blending on the first layer
117         if (layer == 0) layer_weight = -1.f;
118
119         return action->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
120 }
121
122 void BL_ActionManager::StopAction(short layer)
123 {
124         BL_Action *action = GetAction(layer);
125
126         if (action) action->Stop();
127 }
128
129 void BL_ActionManager::RemoveTaggedActions()
130 {
131         for (BL_ActionMap::iterator it = m_layers.begin(); it != m_layers.end();) {
132                 if (IS_TAGGED(it->second->GetAction())) {
133                         delete it->second;
134                         m_layers.erase(it++);
135                 }
136                 else
137                         ++it;
138         }
139 }
140
141 bool BL_ActionManager::IsActionDone(short layer)
142 {
143         BL_Action *action = GetAction(layer);
144
145         return action ? action->IsDone() : true;
146 }
147
148 void BL_ActionManager::Update(float curtime)
149 {
150         if (m_prevUpdate == curtime)
151                 return;
152         m_prevUpdate = curtime;
153
154         BL_ActionMap::iterator it;
155         for (it = m_layers.begin(); it != m_layers.end(); )
156         {
157                 if (it->second->IsDone()) {
158                         delete it->second;
159                         m_layers.erase(it++);
160                 }
161                 else {
162                         it->second->Update(curtime);
163                         ++it;
164                 }
165         }
166 }
167
168 void BL_ActionManager::UpdateIPOs()
169 {
170         BL_ActionMap::iterator it;
171         for (it = m_layers.begin(); it != m_layers.end(); ++it)
172         {
173                 if (!it->second->IsDone())
174                         it->second->UpdateIPOs();
175         }
176 }