0031909: Visualization, AIS_Trihedron - replace maps with arrays
[occt.git] / src / AIS / AIS_Animation.cxx
1 // Created by: Anastasia BORISOVA
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_Animation.hxx>
16
17 #include <Standard_Assert.hxx>
18
19 IMPLEMENT_STANDARD_RTTIEXT(AIS_Animation, Standard_Transient)
20
21 //=============================================================================
22 //function : Constructor
23 //purpose  :
24 //=============================================================================
25 AIS_Animation::AIS_Animation (const TCollection_AsciiString& theAnimationName)
26 : myName (theAnimationName),
27   myState (AnimationState_Stopped),
28   myPtsStart (0.0),
29   myOwnDuration (0.0),
30   myChildrenDuration (0.0)
31 {
32   //
33 }
34
35 //=============================================================================
36 //function : ~AIS_Animation
37 //purpose  :
38 //=============================================================================
39 AIS_Animation::~AIS_Animation()
40 {
41   Clear();
42 }
43
44 //=============================================================================
45 //function : Clear
46 //purpose  :
47 //=============================================================================
48 void AIS_Animation::Clear()
49 {
50   myAnimations.Clear();
51   myOwnDuration = 0.0;
52 }
53
54 //=============================================================================
55 //function : Add
56 //purpose  :
57 //=============================================================================
58 void AIS_Animation::Add (const Handle(AIS_Animation)& theAnimation)
59 {
60   if (theAnimation.IsNull())
61   {
62     throw Standard_ProgramError("AIS_Animation::Add() - attempt to add a NULL animation!");
63   }
64
65   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
66   {
67     if (anIter.Value() == theAnimation)
68     {
69       UpdateTotalDuration();
70       return;
71     }
72   }
73
74   myAnimations.Append (theAnimation);
75   UpdateTotalDuration();
76 }
77
78 //=============================================================================
79 //function : Find
80 //purpose  :
81 //=============================================================================
82 Handle(AIS_Animation) AIS_Animation::Find (const TCollection_AsciiString& theAnimationName) const
83 {
84   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
85   {
86     if (anIter.Value()->Name() == theAnimationName)
87     {
88       return anIter.Value();
89     }
90   }
91   return Handle(AIS_Animation)();
92 }
93
94 //=============================================================================
95 //function : Remove
96 //purpose  :
97 //=============================================================================
98 Standard_Boolean AIS_Animation::Remove (const Handle(AIS_Animation)& theAnimation)
99 {
100   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
101   {
102     if (anIter.Value() == theAnimation)
103     {
104       myAnimations.Remove (anIter);
105       UpdateTotalDuration();
106       return Standard_True;
107     }
108   }
109   return Standard_False;
110 }
111
112 //=============================================================================
113 //function : Replace
114 //purpose  :
115 //=============================================================================
116 Standard_Boolean AIS_Animation::Replace (const Handle(AIS_Animation)& theAnimationOld,
117                                          const Handle(AIS_Animation)& theAnimationNew)
118 {
119   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
120   {
121     if (anIter.Value() == theAnimationOld)
122     {
123       anIter.ChangeValue() = theAnimationNew;
124       UpdateTotalDuration();
125       return Standard_True;
126     }
127   }
128   return Standard_False;
129 }
130
131 //=============================================================================
132 //function : CopyFrom
133 //purpose  :
134 //=============================================================================
135 void AIS_Animation::CopyFrom (const Handle(AIS_Animation)& theOther)
136 {
137   myAnimations.Clear();
138   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (theOther->myAnimations); anIter.More(); anIter.Next())
139   {
140     myAnimations.Append (anIter.Value());
141   }
142   UpdateTotalDuration();
143   myPtsStart    = theOther->myPtsStart;
144   myOwnDuration = theOther->myOwnDuration;
145 }
146
147 //=============================================================================
148 //function : UpdateTotalDuration
149 //purpose  :
150 //=============================================================================
151 void AIS_Animation::UpdateTotalDuration()
152 {
153   myChildrenDuration = 0.0;
154   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
155   {
156     myChildrenDuration = Max (myChildrenDuration, anIter.Value()->StartPts() + anIter.Value()->Duration());
157   }
158 }
159
160 //=============================================================================
161 //function : StartTimer
162 //purpose  :
163 //=============================================================================
164 void AIS_Animation::StartTimer (const Standard_Real    theStartPts,
165                                 const Standard_Real    thePlaySpeed,
166                                 const Standard_Boolean theToUpdate,
167                                 const Standard_Boolean theToStopTimer)
168 {
169   if (myTimer.IsNull())
170   {
171     myTimer = new Media_Timer();
172   }
173   myTimer->Stop();
174   myTimer->Seek (theStartPts);
175   myTimer->SetPlaybackSpeed (thePlaySpeed);
176   Start (theToUpdate);
177   if (theToStopTimer)
178   {
179     myTimer->Stop();
180     myTimer->Seek (theStartPts);
181   }
182 }
183
184 //=============================================================================
185 //function : UpdateTimer
186 //purpose  :
187 //=============================================================================
188 Standard_Real AIS_Animation::UpdateTimer()
189 {
190   if (myTimer.IsNull())
191   {
192     throw Standard_ProgramError("AIS_Animation::UpdateTimer() - timer was not created!");
193   }
194
195   const Standard_Real anElapsedTime = myTimer->ElapsedTime();
196   Update (anElapsedTime);
197   return anElapsedTime;
198 }
199
200 //=============================================================================
201 //function : Start
202 //purpose  :
203 //=============================================================================
204 void AIS_Animation::Start (const Standard_Boolean theToUpdate)
205 {
206   UpdateTotalDuration();
207   myState = AnimationState_Started;
208   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
209   {
210     anIter.ChangeValue()->Start (Standard_False);
211   }
212
213   if (theToUpdate)
214   {
215     const Standard_Real anElapsedTime = !myTimer.IsNull()
216                                        ? myTimer->ElapsedTime()
217                                        : 0.0;
218     Update (anElapsedTime);
219   }
220
221   if (!myTimer.IsNull())
222   {
223     myTimer->Start();
224   }
225 }
226
227 //=============================================================================
228 //function : Pause
229 //purpose  :
230 //=============================================================================
231 void AIS_Animation::Pause()
232 {
233   myState = AnimationState_Paused;
234   if (!myTimer.IsNull())
235   {
236     myTimer->Pause();
237   }
238
239   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
240   {
241     anIter.ChangeValue()->Stop();
242   }
243 }
244
245 //=============================================================================
246 //function : Stop
247 //purpose  :
248 //=============================================================================
249 void AIS_Animation::Stop()
250 {
251   myState = AnimationState_Stopped;
252   if (!myTimer.IsNull())
253   {
254     myTimer->Stop();
255   }
256
257   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
258   {
259     anIter.ChangeValue()->Stop();
260   }
261 }
262
263 //=============================================================================
264 //function : Update
265 //purpose  :
266 //=============================================================================
267 Standard_Boolean AIS_Animation::Update (const Standard_Real thePts)
268 {
269   AIS_AnimationProgress aPosition;
270   aPosition.Pts             = thePts;
271   aPosition.LocalPts        = thePts - myPtsStart;
272   aPosition.LocalNormalized = HasOwnDuration()
273                             ? (aPosition.LocalPts / myOwnDuration)
274                             : 0.0;
275   aPosition.LocalNormalized = Max (0.0, aPosition.LocalNormalized);
276   aPosition.LocalNormalized = Min (1.0, aPosition.LocalNormalized);
277   updateWithChildren (aPosition);
278   return thePts < myPtsStart + Duration();
279 }
280
281 //=============================================================================
282 //function : updateWithChildren
283 //purpose  :
284 //=============================================================================
285 void AIS_Animation::updateWithChildren (const AIS_AnimationProgress& thePosition)
286 {
287   if (thePosition.LocalPts < 0.0
288    || IsStopped())
289   {
290     return;
291   }
292
293   for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anIter (myAnimations); anIter.More(); anIter.Next())
294   {
295     const Handle(AIS_Animation)& anAnim = anIter.Value();
296     AIS_AnimationProgress aPosition = thePosition;
297     aPosition.LocalPts        = aPosition.LocalPts - anAnim->StartPts();
298     aPosition.LocalNormalized = anAnim->HasOwnDuration()
299                               ? (aPosition.LocalPts / anAnim->OwnDuration())
300                               : 0.0;
301     aPosition.LocalNormalized = Max (0.0, aPosition.LocalNormalized);
302     aPosition.LocalNormalized = Min (1.0, aPosition.LocalNormalized);
303     anAnim->updateWithChildren (aPosition);
304   }
305
306   if (thePosition.LocalPts >= Duration())
307   {
308     Stop();
309   }
310
311   update (thePosition);
312 }