1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkAnimationScene.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkAnimationScene.h"
16
17 #include "vtkCollection.h"
18 #include "vtkCollectionIterator.h"
19 #include "vtkCommand.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkTimerLog.h"
22
23 vtkStandardNewMacro(vtkAnimationScene);
24
25 //----------------------------------------------------------------------------
vtkAnimationScene()26 vtkAnimationScene::vtkAnimationScene()
27 {
28 this->PlayMode = PLAYMODE_SEQUENCE;
29 this->FrameRate = 10.0;
30 this->Loop = 0;
31 this->InPlay = 0;
32 this->StopPlay = 0;
33 this->AnimationTime = 0.0;
34
35 this->AnimationCues = vtkCollection::New();
36 this->AnimationCuesIterator = this->AnimationCues->NewIterator();
37 this->AnimationTimer = vtkTimerLog::New();
38 }
39
40 //----------------------------------------------------------------------------
~vtkAnimationScene()41 vtkAnimationScene::~vtkAnimationScene()
42 {
43 if (this->InPlay)
44 {
45 this->Stop();
46 }
47 this->AnimationCues->Delete();
48 this->AnimationCuesIterator->Delete();
49 this->AnimationTimer->Delete();
50 }
51
52 //----------------------------------------------------------------------------
AddCue(vtkAnimationCue * cue)53 void vtkAnimationScene::AddCue(vtkAnimationCue* cue)
54 {
55 if (this->AnimationCues->IsItemPresent(cue))
56 {
57 vtkErrorMacro("Animation cue already present in the scene");
58 return;
59 }
60 if (this->TimeMode == vtkAnimationCue::TIMEMODE_NORMALIZED &&
61 cue->GetTimeMode() != vtkAnimationCue::TIMEMODE_NORMALIZED)
62 {
63 vtkErrorMacro("A cue with relative time mode cannot be added to a scene "
64 "with normalized time mode.");
65 return;
66 }
67 this->AnimationCues->AddItem(cue);
68 }
69
70 //----------------------------------------------------------------------------
RemoveCue(vtkAnimationCue * cue)71 void vtkAnimationScene::RemoveCue(vtkAnimationCue* cue)
72 {
73 this->AnimationCues->RemoveItem(cue);
74 }
75
76 //----------------------------------------------------------------------------
RemoveAllCues()77 void vtkAnimationScene::RemoveAllCues()
78 {
79 this->AnimationCues->RemoveAllItems();
80 }
81 //----------------------------------------------------------------------------
GetNumberOfCues()82 int vtkAnimationScene::GetNumberOfCues()
83 {
84 return this->AnimationCues->GetNumberOfItems();
85 }
86 //----------------------------------------------------------------------------
SetTimeMode(int mode)87 void vtkAnimationScene::SetTimeMode(int mode)
88 {
89 if (mode == vtkAnimationCue::TIMEMODE_NORMALIZED)
90 {
91 // If noralized time mode is being set on the scene,
92 // ensure that none of the contained cues need relative times.
93 vtkCollectionIterator *it = this->AnimationCuesIterator;
94 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
95 {
96 vtkAnimationCue* cue =
97 vtkAnimationCue::SafeDownCast(it->GetCurrentObject());
98 if (cue && cue->GetTimeMode() != vtkAnimationCue::TIMEMODE_NORMALIZED)
99 {
100 vtkErrorMacro("Scene contains a cue in relative mode. It must be removed "
101 "or chaged to normalized mode before changing the scene time mode");
102 return;
103 }
104 }
105 }
106 this->Superclass::SetTimeMode(mode);
107 }
108
109 //----------------------------------------------------------------------------
InitializeChildren()110 void vtkAnimationScene::InitializeChildren()
111 {
112 // run thr all the cues and init them.
113 vtkCollectionIterator *it = this->AnimationCuesIterator;
114 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
115 {
116 vtkAnimationCue* cue =
117 vtkAnimationCue::SafeDownCast(it->GetCurrentObject());
118 if (cue)
119 {
120 cue->Initialize();
121 }
122 }
123 }
124
125 //----------------------------------------------------------------------------
FinalizeChildren()126 void vtkAnimationScene::FinalizeChildren()
127 {
128 vtkCollectionIterator *it = this->AnimationCuesIterator;
129 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
130 {
131 vtkAnimationCue* cue =
132 vtkAnimationCue::SafeDownCast(it->GetCurrentObject());
133 if (cue)
134 {
135 cue->Finalize();
136 }
137 }
138 }
139
140 //----------------------------------------------------------------------------
Play()141 void vtkAnimationScene::Play()
142 {
143 if (this->InPlay)
144 {
145 return;
146 }
147
148 if (this->TimeMode == vtkAnimationCue::TIMEMODE_NORMALIZED)
149 {
150 vtkErrorMacro("Cannot play a scene with normalized time mode");
151 return;
152 }
153 if (this->EndTime <= this->StartTime)
154 {
155 vtkErrorMacro("Scene start and end times are not suitable for playing");
156 return;
157 }
158
159 this->InvokeEvent(vtkCommand::StartEvent);
160
161 this->InPlay = 1;
162 this->StopPlay = 0;
163 this->FrameRate = (!this->FrameRate)? 1.0 : this->FrameRate;
164 // the actual play loop, check for StopPlay flag.
165
166 double currenttime = this->AnimationTime;
167 // adjust currenttime to a valid time.
168 currenttime = (currenttime < this->StartTime || currenttime >= this->EndTime)?
169 this->StartTime : currenttime;
170
171 double time_per_frame =
172 (this->PlayMode == PLAYMODE_SEQUENCE)? (1.0 / this->FrameRate) : 1;
173 do
174 {
175 this->Initialize(); // Set the Scene in unintialized mode.
176 this->AnimationTimer->StartTimer();
177 double timer_start_time = currenttime;
178 double deltatime = 0.0;
179 do
180 {
181 this->Tick(currenttime, deltatime, currenttime);
182
183 // needed to compute delta times.
184 double previous_tick_time = currenttime;
185
186 switch (this->PlayMode)
187 {
188 case PLAYMODE_REALTIME:
189 this->AnimationTimer->StopTimer();
190 currenttime = this->AnimationTimer->GetElapsedTime() +
191 timer_start_time;
192 break;
193
194 case PLAYMODE_SEQUENCE:
195 currenttime += time_per_frame;
196 break;
197
198 default:
199 vtkErrorMacro("Invalid Play Mode");
200 this->StopPlay = 1;
201 }
202
203 deltatime = currenttime - previous_tick_time;
204 deltatime = (deltatime < 0)? -1*deltatime : deltatime;
205 } while (!this->StopPlay && this->CueState != vtkAnimationCue::INACTIVE);
206 // End of loop for 1 cycle.
207
208 // restart the loop.
209 currenttime = this->StartTime;
210 } while (this->Loop && !this->StopPlay);
211
212 this->StopPlay = 0;
213 this->InPlay = 0;
214
215 this->InvokeEvent(vtkCommand::EndEvent);
216 }
217
218 //----------------------------------------------------------------------------
Stop()219 void vtkAnimationScene::Stop()
220 {
221 if (!this->InPlay)
222 {
223 return;
224 }
225 this->StopPlay = 1;
226 }
227
228 //----------------------------------------------------------------------------
TickInternal(double currenttime,double deltatime,double clocktime)229 void vtkAnimationScene::TickInternal(
230 double currenttime, double deltatime, double clocktime)
231 {
232 this->AnimationTime = currenttime;
233 this->ClockTime = clocktime;
234
235 vtkCollectionIterator* iter = this->AnimationCuesIterator;
236 for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
237 {
238 vtkAnimationCue* cue = vtkAnimationCue::SafeDownCast(
239 iter->GetCurrentObject());
240 if (cue)
241 {
242 switch(cue->GetTimeMode())
243 {
244 case vtkAnimationCue::TIMEMODE_RELATIVE:
245 cue->Tick(currenttime - this->StartTime, deltatime, clocktime);
246 break;
247
248 case vtkAnimationCue::TIMEMODE_NORMALIZED:
249 cue->Tick( (currenttime - this->StartTime) / (this->EndTime - this->StartTime),
250 deltatime / (this->EndTime - this->StartTime), clocktime);
251 break;
252
253 default:
254 vtkErrorMacro("Invalid cue time mode");
255 }
256 }
257 }
258
259 this->Superclass::TickInternal(currenttime, deltatime, clocktime);
260 }
261
262 //----------------------------------------------------------------------------
StartCueInternal()263 void vtkAnimationScene::StartCueInternal()
264 {
265 this->Superclass::StartCueInternal();
266 this->InitializeChildren();
267 }
268
269 //----------------------------------------------------------------------------
EndCueInternal()270 void vtkAnimationScene::EndCueInternal()
271 {
272 this->FinalizeChildren();
273 this->Superclass::EndCueInternal();
274 }
275
276 //----------------------------------------------------------------------------
SetAnimationTime(double currenttime)277 void vtkAnimationScene::SetAnimationTime(double currenttime)
278 {
279 if (this->InPlay)
280 {
281 vtkErrorMacro("SetAnimationTime cannot be called while playing");
282 return;
283 }
284 this->Initialize();
285 this->Tick(currenttime, 0.0, currenttime);
286 if (this->CueState == vtkAnimationCue::INACTIVE)
287 {
288 this->Finalize();
289 }
290 }
291
292 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)293 void vtkAnimationScene::PrintSelf(ostream& os, vtkIndent indent)
294 {
295 this->Superclass::PrintSelf(os, indent);
296 os << indent << "PlayMode: " << this->PlayMode << endl;
297 os << indent << "FrameRate: " << this->FrameRate << endl;
298 os << indent << "Loop: " << this->Loop << endl;
299 os << indent << "InPlay: " << this->InPlay << endl;
300 os << indent << "StopPlay: " << this->StopPlay << endl;
301 os << indent << "AnimationTime: " << this->AnimationTime << endl;
302 }
303