Salome HOME
c2b29a6858ab4084fd4471b03e950231d14714ec
[modules/visu.git] / src / VISU_I / VISU_TimeAnimation.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : VISU_TimeAnimation.cxx
23 //  Author : Vitaly SMETANNIKOV
24 //  Module : VISU
25 //
26 #include "VISU_TimeAnimation.h"
27
28 #ifdef WNT
29 #include <windows.h>
30 #include <vfw.h>
31 #include <QMessageBox>
32 #endif
33
34 #include "VISUConfig.hh"
35
36 #include "VISU_Result_i.hh"
37 #include "VISU_Prs3d_i.hh"
38 #include "VISU_Mesh_i.hh"
39 #include "VISU_IsoSurfaces_i.hh"
40 #include "VISU_DeformedShape_i.hh"
41 #include "VISU_DeformedShapeAndScalarMap_i.hh"
42 #include "VISU_CutPlanes_i.hh"
43 #include "VISU_Plot3D_i.hh"
44 #include "VISU_CutLines_i.hh"
45 #include "VISU_CutSegment_i.hh"
46 #include "VISU_Vectors_i.hh"
47 #include "VISU_StreamLines_i.hh"
48 #include "VISU_GaussPoints_i.hh"
49 #include "VISU_ViewManager_i.hh"
50 #include "VISU_View_i.hh"
51
52 #include "VISU_ScalarBarActor.hxx"
53 #include "VISU_Actor.h"
54
55 #include "SalomeApp_Study.h"
56
57 #include "SVTK_ViewWindow.h"
58
59 #include "SALOME_Event.h"
60
61 #include "SUIT_ResourceMgr.h"
62 #include "SUIT_Application.h"
63 #include "SUIT_Session.h"
64 #include "SUIT_Study.h"
65 #include "SUIT_MessageBox.h"
66
67 #include "SALOMEDSClient_AttributeString.hxx"
68 #include "SALOMEDSClient_AttributeName.hxx"
69
70 #include "Utils_ExceptHandlers.hxx"
71
72 #include <QPixmap>
73 #include <QImage>
74 #include <QImageWriter>
75 #include <QStringList>
76 #include <QDir>
77
78 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
79 #define NO_CAS_CATCH
80 #endif
81
82 #include <Standard_Failure.hxx>
83
84 #ifdef NO_CAS_CATCH
85 #include <Standard_ErrorHandler.hxx>
86 #endif
87
88 using namespace std;
89
90 //------------------------------------------------------------------------
91 namespace VISU 
92 {
93   //------------------------------------------------------------------------
94   class ExecutionState 
95   {
96     bool myIsActive;
97     QMutex myIsActiveMutex;
98   public:
99     ExecutionState(bool isActive = false)
100       : myIsActive(isActive) {}
101
102     bool IsActive() {
103       bool state;
104       myIsActiveMutex.lock();
105       state = myIsActive;
106       myIsActiveMutex.unlock();
107       return state;
108     }
109     bool SetActive(bool isActive) {
110       bool state;
111       myIsActiveMutex.lock();
112       state = myIsActive;
113       myIsActive = isActive;
114       myIsActiveMutex.unlock();
115       return state;
116     }
117   };
118
119
120   //------------------------------------------------------------------------
121   struct TCompositeMinMaxController : virtual TVTKMinMaxController
122   {
123     typedef ColoredPrs3d_i* TKey;
124     typedef std::map< TKey, VISU::PMinMaxController > TMinMaxContainer;
125     TMinMaxContainer myMinMaxContainer;    
126
127     void
128     AddController(ColoredPrs3d_i* theReference, 
129                   VISU::PMinMaxController theMinMaxController)
130     {
131       myMinMaxContainer[ TKey( theReference ) ] = theMinMaxController;
132     }
133
134     virtual
135     void
136     UpdateReference(ColoredPrs3d_i* theFromPrs3, ColoredPrs3d_i* theToPrs3d)
137     {
138       TMinMaxContainer::iterator anIter = myMinMaxContainer.find( TKey( theFromPrs3 ) );
139       if ( anIter != myMinMaxContainer.end() ) {
140         myMinMaxContainer.erase( anIter );
141         myMinMaxContainer[ TKey( theToPrs3d ) ] = VISU::CreateDefaultMinMaxController( theToPrs3d );      
142       }
143     }
144
145     virtual
146     vtkFloatingPointType
147     GetComponentMin(vtkIdType theCompID)
148     {
149       vtkFloatingPointType aMin = TMinMaxController::GetComponentMin(theCompID);
150       if ( !myMinMaxContainer.empty() ) {
151         TMinMaxContainer::const_iterator anIter = myMinMaxContainer.begin();
152         for(; anIter != myMinMaxContainer.end(); anIter++){
153           VISU::PMinMaxController aMinMaxController = anIter->second;
154           aMin = std::min(aMin, aMinMaxController->GetComponentMin(theCompID));
155         }
156       }
157       return aMin;
158     }
159
160     virtual
161     vtkFloatingPointType
162     GetComponentMax(vtkIdType theCompID)
163     {
164       vtkFloatingPointType aMax = TMinMaxController::GetComponentMax(theCompID);
165       if ( !myMinMaxContainer.empty() ) {
166         TMinMaxContainer::const_iterator anIter = myMinMaxContainer.begin();
167         for(; anIter != myMinMaxContainer.end(); anIter++){
168           VISU::PMinMaxController aMinMaxController = anIter->second;
169           aMax = std::max(aMax, aMinMaxController->GetComponentMax(theCompID));
170         }
171       }
172       return aMax;
173     }
174   };
175
176   typedef SALOME::GenericObjPtr<TCompositeMinMaxController> PCompositeMinMaxController;
177 }
178
179 //------------------------------------------------------------------------
180 VISU_TimeAnimation::VISU_TimeAnimation (_PTR(Study) theStudy,
181                                         VISU::View3D_ptr theView3D)
182 {
183   myStudy = theStudy;
184   myExecutionState = new VISU::ExecutionState(false);
185   myFrame = 0;
186   mySpeed = VISU::GetResourceMgr()->integerValue("VISU", "speed", 1);
187   myProportional = VISU::GetResourceMgr()->booleanValue("VISU", "use_proportional_timing", false);
188   myView = 0;
189
190   if (!CORBA::is_nil(theView3D)) {
191     VISU::View3D_i* pView = dynamic_cast<VISU::View3D_i*>(GetServant(theView3D).in());
192     SUIT_ViewWindow* aVW = pView->GetViewWindow();
193     setViewer( dynamic_cast<SVTK_ViewWindow*>(aVW) );
194   }
195
196   myAnimationMode = VISU::Animation::PARALLEL;
197   myTimeMinVal = 0;
198   myTimeMaxVal = 0;
199   myTimeMin = 0;
200   myTimeMax = 0;
201   myLastError = "";
202   myCycling = VISU::GetResourceMgr()->booleanValue("VISU", "cycled_animation", false);
203   myCleaningMemoryAtEachFrame = VISU::GetResourceMgr()->booleanValue("VISU", "clean_memory_at_each_frame", false);
204
205   myAnimEntry = "";
206
207   myDumpPath = "";
208   myAVIMaker = "jpeg2yuv";
209 }
210
211
212 //------------------------------------------------------------------------
213 VISU_TimeAnimation::~VISU_TimeAnimation()
214 {
215   if (QThread::isRunning() && !QThread::isFinished()) {
216     stopAnimation();
217     QThread::wait(500);
218     if (QThread::isRunning() && !QThread::isFinished()) {
219       QThread::terminate();
220     }
221   }
222
223   for (int i = 0; i < getNbFields() && myView; i++) {
224     clearData(myFieldsLst[i]);
225   }
226   clearFieldData();
227
228   delete myExecutionState;
229
230   myDumpPath = "";
231
232   /* Terminates the execution of the thread. 
233    * The thread may or may not be terminated immediately, 
234    * depending on the operating system's scheduling policies. 
235    *  
236    * Use QThread::wait() after terminate() for synchronous termination.
237    *
238    * When the thread is terminated, all threads waiting for the the thread to finish will be woken up.
239    * 
240    * Warning: This function is dangerous, and its use is discouraged. 
241    * The thread can be terminated at any point in its code path. 
242    * Threads can be terminated while modifying data. 
243    * There is no chance for the thread to cleanup after itself, 
244    * unlock any held mutexes, etc. In short, use this function only if absolutely necessary. 
245    */
246   //QThread::wait(100);
247   //QThread::terminate();
248   //QThread::wait(400);
249 }
250
251
252 //------------------------------------------------------------------------
253 void VISU_TimeAnimation::_connectView()
254 {
255   connect( myView, SIGNAL( destroyed() ), this, SLOT( onViewDeleted() ) );
256 }
257
258 //------------------------------------------------------------------------
259 bool VISU_TimeAnimation::addField (_PTR(SObject) theField)
260 {
261   if (!theField) return false;
262
263   FieldData aNewData;
264   aNewData.myField = theField;
265   aNewData.myNbFrames = 0;
266   aNewData.myPrsType = VISU::TSCALARMAP;
267   aNewData.myOffset[0] = aNewData.myOffset[1] = aNewData.myOffset[2] = 0;
268
269   // initialize myResult in aNewData
270   _PTR(SObject) aSObj = theField->GetFather();
271   aSObj = aSObj->GetFather();
272   aSObj = aSObj->GetFather();
273   CORBA::Object_var anObject = VISU::ClientSObjectToObject(aSObj);
274   if (CORBA::is_nil(anObject)) return false;
275   aNewData.myResult = dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject).in());
276
277   VISU::Storable::TRestoringMap aMap = VISU::Storable::GetStorableMap(aNewData.myField);
278   if(VISU::Storable::FindValue(aMap,"myComment") != "FIELD")
279     return false;
280
281   aNewData.myNbTimes = VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
282
283   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
284     if ( aNewData.myNbTimes < 2 )
285       return false;
286     if ( !myFieldsLst.isEmpty() && myFieldsLst.first().myNbTimes != aNewData.myNbTimes )
287       return false;
288     if ( myFieldsLst.isEmpty() )
289       myFieldsAbsFrames.push_back(aNewData.myNbTimes);
290   }
291   else { // successive animation mode
292     if ( aNewData.myNbTimes < 1 )
293       return false;
294
295     long aNumCompCurr = VISU::Storable::FindValue(aMap, "myNumComponent").toLong();
296     if ( !myFieldsLst.isEmpty() ) {
297       VISU::Storable::TRestoringMap aFMap = VISU::Storable::GetStorableMap(myFieldsLst.first().myField);
298       long aNumComp = VISU::Storable::FindValue(aFMap, "myNumComponent").toLong();
299       if ( aNumCompCurr != aNumComp )
300         return false;
301     }
302
303     if ( !myFieldsLst.isEmpty() )
304       myFieldsAbsFrames.push_back(myFieldsAbsFrames.back() + aNewData.myNbTimes);
305     else
306       myFieldsAbsFrames.push_back(aNewData.myNbTimes);
307   }
308     
309   myFieldsLst.append(aNewData);
310   
311   //find Min/Max timestamps
312   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(theField);
313   anIter->Next(); // First is reference on support
314   if ( myFieldsLst.size() == 1 ) { // the first field
315     myTimeMin = getTimeValue(anIter->Value());
316     myTimeMax = getTimeValue(anIter->Value());
317   }
318   for(; anIter->More(); anIter->Next()) {
319     if ( myTimeMin > getTimeValue(anIter->Value()) )
320       myTimeMin = getTimeValue(anIter->Value());
321     if ( myTimeMax < getTimeValue(anIter->Value()) )
322       myTimeMax = getTimeValue(anIter->Value());
323   }
324   
325   return true;
326 }
327
328 //------------------------------------------------------------------------
329 bool VISU_TimeAnimation::addField (SALOMEDS::SObject_ptr theField)
330 {
331   SALOMEDS::SObject_var theFieldDup = SALOMEDS::SObject::_duplicate(theField);
332   _PTR(SObject) aField = VISU::GetClientSObject(theFieldDup, myStudy);
333   return addField(aField);
334 }
335
336
337 //------------------------------------------------------------------------
338 void VISU_TimeAnimation::_clearData(FieldData& theData) {
339   if (!myView) {
340     MESSAGE("Viewer is not defined for animation");
341     return;
342   }
343   theData.myTiming.clear();
344   vtkRenderer* aRen = myView->getRenderer();
345   if (!theData.myActors.empty()) {
346     for (int i = 0, iEnd = theData.myActors.size(); i < iEnd; i++) {
347       if (theData.myActors[i] != 0) {
348         theData.myActors[i]->RemoveFromRender(aRen);
349       }
350     }
351     theData.myActors.clear();
352   }
353   if (!theData.myPrs.empty()) {
354     for (int i = 0, iEnd = theData.myPrs.size(); i < iEnd; i++)
355       if (theData.myPrs[i] != 0) {
356         theData.myPrs[i]->_remove_ref();
357       }
358     theData.myPrs.clear();
359   }
360   theData.myNbFrames = 0;
361   myView->update();
362 }
363
364 //------------------------------------------------------------------------
365 void VISU_TimeAnimation::clearData(FieldData& theData) {
366   ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_TimeAnimation,FieldData&>
367                    (this,&VISU_TimeAnimation::_clearData,theData));
368 }
369
370 namespace
371 {
372   //------------------------------------------------------------------------
373   template<class TPrs3d>
374   void
375   GeneratePresentations(_PTR(Study) theStudy,
376                         FieldData& theData,
377                         VISU::Result_i* theResult,
378                         bool theIsRangeDefined,
379                         CORBA::Double theTimeMin,
380                         CORBA::Double theTimeMax,
381                         QList<long> theSequence)
382   {
383     _PTR(ChildIterator) anIter = theStudy->NewChildIterator(theData.myField);
384     anIter->Next(); // First is reference on support
385
386     long aSequenceLength = theSequence.count();
387     bool isSequenceDefined = aSequenceLength > 0;
388     if (isSequenceDefined)
389       theData.myPrs.resize(aSequenceLength,NULL);
390
391     long aFrameId = 0;
392     long aSequenceIndex = 1;
393     for(; anIter->More(); anIter->Next(), aSequenceIndex++){
394       if (aFrameId == theData.myNbTimes) {
395         MESSAGE("There are extra timestamps in field");
396         return;
397       }
398       _PTR(SObject) aTimeStamp = anIter->Value();
399       if(!aTimeStamp) 
400         continue;
401
402       long aSequenceId = -1;
403
404       theData.myTiming[aFrameId] = VISU_TimeAnimation::getTimeValue(aTimeStamp);
405       if (theIsRangeDefined) {
406         if (theData.myTiming[aFrameId] < theTimeMin) 
407           continue;
408         if (theData.myTiming[aFrameId] > theTimeMax) 
409           break;
410       }
411       else if (isSequenceDefined) {
412         aSequenceId = theSequence.indexOf( aSequenceIndex );
413         if( aSequenceId == -1 )
414           continue;
415       }
416
417       VISU::Storable::TRestoringMap aTimeMap = VISU::Storable::GetStorableMap(aTimeStamp);
418       QString aMeshName = VISU::Storable::FindValue(aTimeMap,"myMeshName");
419       VISU::Entity anEntity = (VISU::Entity) VISU::Storable::FindValue(aTimeMap,"myEntityId").toInt();
420       QString aFieldName = VISU::Storable::FindValue(aTimeMap,"myFieldName");
421       int aTimeStampId = VISU::Storable::FindValue(aTimeMap,"myTimeStampId").toInt();
422       
423       bool anIsCreated = false;
424       TPrs3d* aPresent = new TPrs3d(VISU::ColoredPrs3d_i::EDoNotPublish);
425       aPresent->SetCResult(theResult);
426       aPresent->SetMeshName(aMeshName.toLatin1().data());
427       aPresent->SetEntity(anEntity);
428       aPresent->SetFieldName(aFieldName.toLatin1().data());
429       aPresent->SetTimeStampNumber(aTimeStampId);
430       try{       
431 #ifdef NO_CAS_CATCH
432         OCC_CATCH_SIGNALS;
433 #endif
434         if(aPresent->Apply(false)){
435           /*
436             if(isSequenceDefined)
437             {
438               theData.myPrs[aSequenceId] = aPresent;
439               aFrameId++;
440             }
441             else
442           */
443           theData.myPrs[aFrameId++] = aPresent;
444           anIsCreated = true;
445         }
446       }catch(Standard_Failure) {
447         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
448         INFOS("Follow signal was occured :\n"<<aFail->GetMessageString());
449       }catch(std::exception& exc){
450         INFOS("Follow exception was occured :\n"<<exc.what());
451       }catch(...){
452         INFOS("Unknown exception was occured!");
453       }
454       if(!anIsCreated)
455         aPresent->_remove_ref();
456     }
457
458     theData.myNbFrames = aFrameId;
459
460     if (theData.myPrsType != VISU::TGAUSSPOINTS) {
461       for(long aFrameId = 0; aFrameId < theData.myNbFrames; aFrameId++) {
462         if (VISU::ScalarMap_i* aPrs = dynamic_cast<VISU::ScalarMap_i*>(theData.myPrs[aFrameId])){
463           aPrs->SetOffset(theData.myOffset);
464         }
465       }
466     }
467   }
468 }
469
470 double getMinFieldsValue( QList<FieldData>& theFieldsLst )
471 {
472   // for successive animation mode only
473   double aRes;
474   for (int i = 0; i < theFieldsLst.count(); i++) {
475     if ( theFieldsLst[i].myPrs[0] ) {
476       aRes = theFieldsLst[i].myPrs[0]->GetMin();
477       break;
478     }
479   }
480
481   for (int i = 1; i < theFieldsLst.count() && theFieldsLst[i].myPrs[0]; i++) {
482     if ( aRes > theFieldsLst[i].myPrs[0]->GetMin() )
483       aRes = theFieldsLst[i].myPrs[0]->GetMin();    
484   }
485   return aRes;
486 }
487
488 double getMaxFieldsValue( QList<FieldData>& theFieldsLst )
489 {
490   // for successive animation mode only
491   double aRes;
492   for (int i = 0; i < theFieldsLst.count(); i++) {
493     if ( theFieldsLst[i].myPrs[0] ) {
494       aRes = theFieldsLst[i].myPrs[0]->GetMax();
495       break;
496     }
497   }
498
499   for (int i = 1; i < theFieldsLst.count() && theFieldsLst[i].myPrs[0]; i++) {
500     if ( aRes < theFieldsLst[i].myPrs[0]->GetMax() )
501       aRes = theFieldsLst[i].myPrs[0]->GetMax();    
502   }
503   return aRes;
504 }
505
506 void VISU_TimeAnimation::generatePresentations(CORBA::Long theFieldNum)
507 {
508   int nbf = myFieldsLst.size();
509   if( theFieldNum<0 || theFieldNum>nbf-1 )
510     return;
511
512   FieldData& aData = myFieldsLst[theFieldNum];
513
514   // Delete previous presentations
515   clearData(aData);
516
517   VISU::Result_i* aResult = createPresent(aData.myField);
518   VISU::Storable::TRestoringMap aMap = VISU::Storable::GetStorableMap(aData.myField);
519   aData.myNbFrames = aData.myNbTimes;
520   //VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
521
522   aData.myPrs.resize(aData.myNbTimes,NULL);
523   aData.myTiming.resize(aData.myNbTimes);
524
525   QList<long> aSequence;
526   if( isSequenceDefined() )
527   {
528     bool ok = getIndicesFromSequence( mySequence, aSequence );
529     if( !ok )
530       return;
531   }
532
533   using namespace VISU;
534   switch (aData.myPrsType) {
535   case VISU::TSCALARMAP:
536     GeneratePresentations<ScalarMap_i>(myStudy,
537                                        aData,
538                                        aResult,
539                                        isRangeDefined(),
540                                        myTimeMinVal,
541                                        myTimeMaxVal,
542                                        aSequence);
543     break;
544   case VISU::TISOSURFACES: // Iso Surfaces
545     GeneratePresentations<IsoSurfaces_i>(myStudy,
546                                          aData,
547                                          aResult,
548                                          isRangeDefined(),
549                                          myTimeMinVal,
550                                          myTimeMaxVal,
551                                          aSequence);
552     break;
553   case VISU::TCUTPLANES: // Cut Planes
554     GeneratePresentations<CutPlanes_i>(myStudy,
555                                        aData,
556                                        aResult,
557                                        isRangeDefined(),
558                                        myTimeMinVal,
559                                        myTimeMaxVal,
560                                        aSequence);
561     break;
562   case VISU::TCUTLINES: // Cut Lines
563     GeneratePresentations<CutLines_i>(myStudy,
564                                       aData,
565                                       aResult,
566                                       isRangeDefined(),
567                                       myTimeMinVal,
568                                       myTimeMaxVal,
569                                       aSequence);
570     break;
571   case VISU::TCUTSEGMENT: // Cut Segment
572     GeneratePresentations<CutSegment_i>(myStudy,
573                                         aData,
574                                         aResult,
575                                         isRangeDefined(),
576                                         myTimeMinVal,
577                                         myTimeMaxVal,
578                                         aSequence);
579     break;
580   case VISU::TPLOT3D: // Plot3d
581     GeneratePresentations<Plot3D_i>(myStudy,
582                                     aData,
583                                     aResult,
584                                     isRangeDefined(),
585                                     myTimeMinVal,
586                                     myTimeMaxVal,
587                                     aSequence);
588     break;
589   case VISU::TDEFORMEDSHAPE: // Deformed Shape
590     GeneratePresentations<DeformedShape_i>(myStudy,
591                                            aData,
592                                            aResult,
593                                            isRangeDefined(),
594                                            myTimeMinVal,
595                                            myTimeMaxVal,
596                                            aSequence);
597     break;
598   case VISU::TVECTORS: // Vectors
599     GeneratePresentations<Vectors_i>(myStudy,
600                                      aData,
601                                      aResult,
602                                      isRangeDefined(),
603                                      myTimeMinVal,
604                                      myTimeMaxVal,
605                                      aSequence);
606     break;
607   case VISU::TSTREAMLINES: // Stream Lines
608     GeneratePresentations<StreamLines_i>(myStudy,
609                                          aData,
610                                          aResult,
611                                          isRangeDefined(),
612                                          myTimeMinVal,
613                                          myTimeMaxVal,
614                                          aSequence);
615     break;
616   case VISU::TGAUSSPOINTS: // Gauss Points
617     GeneratePresentations<GaussPoints_i>(myStudy,
618                                          aData,
619                                          aResult,
620                                          isRangeDefined(),
621                                          myTimeMinVal,
622                                          myTimeMaxVal,
623                                          aSequence);
624     break;
625   case VISU::TSCALARMAPONDEFORMEDSHAPE: // Scalar map on deformed shape
626   case VISU::TDEFORMEDSHAPEANDSCALARMAP:
627     GeneratePresentations<DeformedShapeAndScalarMap_i>(myStudy,
628                                                        aData,
629                                                        aResult,
630                                                        isRangeDefined(),
631                                                        myTimeMinVal,
632                                                        myTimeMaxVal,
633                                                        aSequence);
634     break;
635   default:
636     MESSAGE("Not implemented for this presentation type: " << aData.myPrsType);
637     return;
638   }
639   
640   if ( myAnimationMode == VISU::Animation::SUCCESSIVE ) { // successive animation mode
641     if ( myFieldsAbsFrames.size() == getNbFields() ) 
642       myFieldsAbsFrames.clear();
643     if ( theFieldNum > 0 )
644       myFieldsAbsFrames.push_back(myFieldsAbsFrames.back() + aData.myNbFrames);      
645     else
646       myFieldsAbsFrames.push_back(aData.myNbFrames);
647
648     if (theFieldNum == getNbFields() - 1) {
649       if ( aData.myPrsType != VISU::TGAUSSPOINTS && aData.myPrsType != TDEFORMEDSHAPEANDSCALARMAP && aData.myPrsType != TSCALARMAPONDEFORMEDSHAPE) {
650
651         // Initialize the MinMax controller
652         VISU::PCompositeMinMaxController aMinMaxController(new VISU::TCompositeMinMaxController());
653         if ( myAnimationMode == VISU::Animation::PARALLEL ) {
654           FieldData& aFieldData = getFieldData(theFieldNum);
655           VISU::ColoredPrs3d_i* aPrs3d = aFieldData.myPrs[0];
656           aMinMaxController->AddController( aPrs3d, VISU::CreateDefaultMinMaxController( aPrs3d ) );
657         } else {
658           for (int aFieldId = 0; aFieldId < getNbFields(); aFieldId++) {
659             FieldData& aFieldData = getFieldData(aFieldId);
660             VISU::ColoredPrs3d_i* aPrs3d = aFieldData.myPrs[0];
661             aMinMaxController->AddController( aPrs3d, VISU::CreateDefaultMinMaxController( aPrs3d ) );
662           }
663         }
664
665         double aMin = getMinFieldsValue(myFieldsLst);
666         double aMax = getMaxFieldsValue(myFieldsLst);
667
668         for (int aFieldId = 0; aFieldId < getNbFields(); aFieldId++) {
669           FieldData& aFieldData = getFieldData(aFieldId);
670           for (long aFrameId = 0; aFrameId < aFieldData.myNbFrames; aFrameId++) {
671             VISU::ColoredPrs3d_i* aPrs3d = aFieldData.myPrs[aFrameId];
672             aPrs3d->SetMinMaxController(aMinMaxController);
673             if (VISU::IsoSurfaces_i* anIsoSurfaces = dynamic_cast<VISU::IsoSurfaces_i*>(aPrs3d))
674               anIsoSurfaces->SetSubRange(aMin, aMax);
675           }
676         }
677       }
678     }
679   }
680 }
681
682
683 //------------------------------------------------------------------------
684 CORBA::Boolean VISU_TimeAnimation::_generateFrames() {
685   if (!myView) {
686     MESSAGE("Viewer is not defined for animation");
687     return false;
688   }
689
690   myLastError = QString("Frame(s) for ");
691   bool aNoError = true;
692
693   clearView();
694
695   for (int i = 0; i < getNbFields(); i++) {
696     FieldData& aData = myFieldsLst[i];
697     aData.myActors.resize(aData.myNbFrames,NULL);
698     for (long j = 0; j < aData.myNbFrames; j++) {
699       VISU_Actor* aActor = NULL;
700       try{
701         aData.myPrs[j]->SetOffset(aData.myOffset);
702         aActor = aData.myPrs[j]->CreateActor();
703         myView->AddActor(aActor);
704         bool condition = ( myAnimationMode == VISU::Animation::PARALLEL ) ? (j == 0) : (j == 0 && i == 0);
705         if(condition)
706           aActor->VisibilityOn();
707         else
708           aActor->VisibilityOff();
709       }catch(...){ //catch(std::runtime_error& exc){
710         aNoError = false;
711         myLastError += QString("%1 ").arg(aData.myTiming[j]);
712       }
713       aData.myActors[j] = aActor;
714     }
715   }
716   myFrame = 0;
717   myLastError += QString(" timestamp(s) cannot be created.");
718   ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
719                                                                             myFrame, myFieldsLst[0].myTiming[myFrame]));
720   myView->Repaint();
721   return aNoError;
722 }
723
724 //------------------------------------------------------------------------
725 CORBA::Boolean VISU_TimeAnimation::generateFrames()
726 {
727   return ProcessEvent(new TMemFunEvent<VISU_TimeAnimation,bool>
728                       (this,&VISU_TimeAnimation::_generateFrames));
729 }
730
731 //------------------------------------------------------------------------
732 void VISU_TimeAnimation::_clearView() {
733   if (!myView) {
734     MESSAGE("Viewer is not defined for animation");
735     return;
736   }
737   vtkRenderer* aRen = myView->getRenderer();
738   for (int i = 0; i < getNbFields(); i++) {
739     FieldData& aData = myFieldsLst[i];
740     if (!aData.myActors.empty()) {
741       for (int i = 0, iEnd = aData.myActors.size(); i < iEnd; i++) {
742         if (aData.myActors[i] != 0) {
743           aData.myActors[i]->RemoveFromRender(aRen);
744         }
745       }
746       aData.myActors.clear();
747     }
748   }
749   VISU::RepaintView(myView);
750 }
751
752 //------------------------------------------------------------------------
753 void VISU_TimeAnimation::clearView()
754 {
755   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
756                    (this,&VISU_TimeAnimation::_clearView));
757 }
758
759 //------------------------------------------------------------------------
760 void VISU_TimeAnimation::_visibilityOff(int num_field, int num_frame) {
761   if (!myView) {
762     MESSAGE("Viewer is not defined for animation");
763     return;
764   }
765   if ( num_field < 0 || num_frame < 0 ) return;
766   FieldData& aData = myFieldsLst[num_field];
767   if ( aData.myActors.empty() ) return;
768   VISU_Actor* aActor = aData.myActors[num_frame];
769   if (! myCleaningMemoryAtEachFrame) {
770     //
771     // Usual behaviour : VisibilityOff()
772     // Problem : It don't clean the memory so if there is
773     //           a lot of frames, the memory grows dramatically
774     //
775     aActor->VisibilityOff();
776   } else {
777     //
778     // myCleaningMemoryAtEachFrame behaviour:
779     // Delete the actor and re-creation it with VisibilityOff()
780     // since it takes memory only at VisibilityOn()
781     //
782     // Delete the actor
783     aActor->RemoveFromRender(myView->getRenderer());
784     // Re-create the actor
785     aActor = aData.myPrs[num_frame]->CreateActor();
786     myView->AddActor(aActor);
787     aActor->VisibilityOff();
788     aData.myActors[num_frame] = aActor;
789   }
790 }
791
792 //------------------------------------------------------------------------
793 void VISU_TimeAnimation::visibilityOff(int num_field, int num_frame)
794 {
795   ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,int,int>
796                    (this,&VISU_TimeAnimation::_visibilityOff,num_field,num_frame));
797 }
798
799 //------------------------------------------------------------------------
800 void VISU_TimeAnimation::stopAnimation()
801 {
802   myExecutionState->SetActive(false);
803 }
804
805 //------------------------------------------------------------------------
806 void VISU_TimeAnimation::_startAnimation() {
807   if (!myExecutionState->IsActive()) {
808     myExecutionState->SetActive(true);
809     QThread::start();
810   }
811 }
812
813 //------------------------------------------------------------------------
814 void VISU_TimeAnimation::startAnimation()
815 {
816   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
817                    (this,&VISU_TimeAnimation::_startAnimation));
818 }
819
820 //------------------------------------------------------------------------
821 void VISU_TimeAnimation::_nextFrame() {
822   if (!myView) {
823     MESSAGE("Viewer is not defined for animation");
824     return;
825   }
826   stopAnimation();
827   if (myFrame < getNbFrames() - 1 ) { //(myFieldsLst[0].myNbFrames-1)) {
828     int i;
829     std::pair<int,long> aPair;
830     int aFieldId;
831     long aFrameId;
832
833     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
834       for (i = 0; i < getNbFields(); i++)
835         if (myFieldsLst[i].myActors[myFrame] != 0)
836           visibilityOff(i, myFrame);
837     }
838     else { //successive animation mode
839       aPair = getRelativeFrameNumber(myFrame);
840       aFieldId = aPair.first;
841       aFrameId = aPair.second;
842       if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
843         visibilityOff(aFieldId, aFrameId);
844     }
845
846     myFrame++;
847
848     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
849       for (i = 0; i < getNbFields(); i++)
850         if (myFieldsLst[i].myActors[myFrame] != 0)
851           myFieldsLst[i].myActors[myFrame]->VisibilityOn();
852
853       ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
854                                                                                 myFrame, myFieldsLst[0].myTiming[myFrame]));
855     }
856     else { //successive animation mode
857       aPair = getRelativeFrameNumber(myFrame);
858       aFieldId = aPair.first;
859       aFrameId = aPair.second;
860       if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
861         myFieldsLst[aFieldId].myActors[aFrameId]->VisibilityOn();
862
863       ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
864                                                                                 myFrame, myFieldsLst[aFieldId].myTiming[aFrameId]));
865     }
866     myView->Repaint();
867   }
868 }
869
870 //------------------------------------------------------------------------
871 void VISU_TimeAnimation::nextFrame()
872 {
873   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
874                    (this,&VISU_TimeAnimation::_nextFrame));
875 }
876
877 //------------------------------------------------------------------------
878 void VISU_TimeAnimation::_prevFrame() {
879   if (!myView) {
880     MESSAGE("Viewer is not defined for animation");
881     return;
882   }
883   stopAnimation();
884   if (myFrame > 0) {
885     int i;
886     std::pair<int,long> aPair;
887     int aFieldId;
888     long aFrameId;
889
890     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
891       for (i = 0; i < getNbFields(); i++)
892         if (myFieldsLst[i].myActors[myFrame] != 0)
893           visibilityOff(i, myFrame);
894     }
895     else { //successive animation mode
896       aPair = getRelativeFrameNumber(myFrame);
897       aFieldId = aPair.first;
898       aFrameId = aPair.second;
899       if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
900           visibilityOff(aFieldId, aFrameId);
901     }
902
903     myFrame--;
904
905     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
906       for (i = 0; i < getNbFields(); i++)
907         if (myFieldsLst[i].myActors[myFrame] != 0)
908           myFieldsLst[i].myActors[myFrame]->VisibilityOn();
909
910       ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
911                                                                                 myFrame, myFieldsLst[0].myTiming[myFrame]));
912     }
913     else { //successive animation mode
914       aPair = getRelativeFrameNumber(myFrame);
915       aFieldId = aPair.first;
916       aFrameId = aPair.second;
917       if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
918           myFieldsLst[aFieldId].myActors[aFrameId]->VisibilityOn();
919
920       ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
921                                                                                 myFrame, myFieldsLst[aFieldId].myTiming[aFrameId]));
922     }
923     myView->Repaint();
924   }
925 }
926
927 //------------------------------------------------------------------------
928 void VISU_TimeAnimation::prevFrame()
929 {
930   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
931                    (this,&VISU_TimeAnimation::_prevFrame));
932 }
933
934 //------------------------------------------------------------------------
935 void VISU_TimeAnimation::_firstFrame() {
936   if (!myView) {
937     MESSAGE("Viewer is not defined for animation");
938     return;
939   }
940   stopAnimation();
941   int i;
942   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
943     for (i = 0; i < getNbFields(); i++)
944       if(!myFieldsLst[i].myActors.empty())
945         if (myFieldsLst[i].myActors[myFrame] != 0)
946           visibilityOff(i, myFrame);
947     }
948   else { //successive animation mode
949     std::pair<int,long> aPair = getRelativeFrameNumber(myFrame);
950     int aFieldId = aPair.first;
951     long aFrameId = aPair.second;
952     if(!myFieldsLst[aFieldId].myActors.empty())
953       if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
954         visibilityOff(aFieldId, aFrameId);
955   }
956   myFrame = 0;
957
958   int imax;
959   if ( myAnimationMode == VISU::Animation::PARALLEL ) // parallel animation mode 
960     imax = getNbFields();
961   else //successive animation mode
962     imax = 1;
963
964   for (i = 0; i < imax; i++)
965     if(!myFieldsLst[i].myActors.empty())
966       if (myFieldsLst[i].myActors[myFrame] != 0)
967         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
968
969   if(!myFieldsLst[0].myTiming.empty()){
970     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
971                                                                               myFrame, myFieldsLst[0].myTiming[myFrame]));
972     myView->Repaint();
973   }
974 }
975
976 //------------------------------------------------------------------------
977 void VISU_TimeAnimation::firstFrame()
978 {
979   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
980                    (this,&VISU_TimeAnimation::_firstFrame));
981 }
982
983 //------------------------------------------------------------------------
984 void VISU_TimeAnimation::_lastFrame() {
985   if (!myView) {
986     MESSAGE("Viewer is not defined for animation");
987     return;
988   }
989   stopAnimation();
990   int i;
991   std::pair<int,long> aPair;
992   int aFieldId;
993   long aFrameId;
994
995   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
996     for (i = 0; i < getNbFields(); i++)
997       if (myFieldsLst[i].myActors[myFrame] != 0)
998         visibilityOff(i, myFrame);
999   }
1000   else { //successive animation mode
1001     aPair = getRelativeFrameNumber(myFrame);
1002     aFieldId = aPair.first;
1003     aFrameId = aPair.second;
1004     if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
1005       visibilityOff(aFieldId, aFrameId);
1006   }
1007
1008   myFrame = getNbFrames() - 1; //myFieldsLst[0].myNbFrames-1;
1009
1010   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1011     for (i = 0; i < getNbFields(); i++)
1012       if (myFieldsLst[i].myActors[myFrame] != 0)
1013         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
1014     
1015     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
1016                                                                               myFrame, myFieldsLst[0].myTiming[myFrame]));
1017   }
1018   else { //successive animation mode
1019     aPair = getRelativeFrameNumber(myFrame);
1020     aFieldId = aPair.first;
1021     aFrameId = aPair.second;
1022     if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
1023         myFieldsLst[aFieldId].myActors[aFrameId]->VisibilityOn();
1024
1025     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
1026                                                                               myFrame, myFieldsLst[aFieldId].myTiming[aFrameId]));
1027   }
1028
1029   myView->Repaint();
1030 }
1031
1032 //------------------------------------------------------------------------
1033 void VISU_TimeAnimation::lastFrame()
1034 {
1035   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1036                    (this,&VISU_TimeAnimation::_lastFrame));
1037 }
1038
1039
1040 //------------------------------------------------------------------------
1041 // For Batchmode using
1042 void VISU_TimeAnimation::_gotoFrame(CORBA::Long theFrame) {
1043   if (!myView) {
1044     MESSAGE("Viewer is not defined for animation");
1045     return;
1046   }
1047   if ((theFrame < 0) || (theFrame > (getNbFrames()-1)))
1048     return;
1049   stopAnimation();
1050   int i;
1051   std::pair<int,long> aPair;
1052   int aFieldId;
1053   long aFrameId;
1054   
1055   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1056     for (i = 0; i < getNbFields(); i++)
1057       if (myFieldsLst[i].myActors[myFrame] != 0)
1058         visibilityOff(i, myFrame);
1059   }
1060   else { //successive animation mode
1061     aPair = getRelativeFrameNumber(myFrame);
1062     aFieldId = aPair.first;
1063     aFrameId = aPair.second;
1064     if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
1065         visibilityOff(aFieldId, aFrameId);
1066   }
1067
1068   myFrame = theFrame;
1069
1070   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1071     for (i = 0; i < getNbFields(); i++)
1072       if (myFieldsLst[i].myActors[myFrame] != 0)
1073         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
1074
1075     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
1076                                                                               myFrame, myFieldsLst[0].myTiming[myFrame]));
1077   }
1078   else { //successive animation mode
1079     aPair = getRelativeFrameNumber(myFrame);
1080     aFieldId = aPair.first;
1081     aFrameId = aPair.second;
1082     if (myFieldsLst[aFieldId].myActors[aFrameId] != 0)
1083         myFieldsLst[aFieldId].myActors[aFrameId]->VisibilityOn();
1084
1085     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>(this, &VISU_TimeAnimation::_emitFrameChanged,
1086                                                                               myFrame, myFieldsLst[aFieldId].myTiming[aFrameId]));
1087   }
1088
1089   myView->Repaint();
1090 }
1091
1092 //------------------------------------------------------------------------
1093 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame)
1094 {
1095   ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_TimeAnimation,CORBA::Long>
1096                    (this,&VISU_TimeAnimation::_gotoFrame,theFrame));
1097 }
1098
1099 //------------------------------------------------------------------------
1100 void VISU_TimeAnimation::_emitFrameChanged(long theNewFrame, double theTime)
1101 {
1102   emit frameChanged(theNewFrame, theTime);
1103 }
1104
1105 //------------------------------------------------------------------------
1106 void VISU_TimeAnimation::_emitStopped()
1107 {
1108   emit stopped();
1109 }
1110
1111 //------------------------------------------------------------------------
1112 VISU::ColoredPrs3d_ptr VISU_TimeAnimation::getPresentation(CORBA::Long theField, CORBA::Long theFrame) {
1113   if ((theField > getNbFields()) || (theField < 0))
1114     return VISU::ColoredPrs3d::_nil();
1115   if ((theFrame < 0) || (theFrame > (myFieldsLst[theField].myNbFrames - 1)))
1116     return VISU::ColoredPrs3d::_nil();
1117   return myFieldsLst[theField].myPrs[theFrame]->_this();
1118 }
1119
1120 //------------------------------------------------------------------------
1121 void VISU_TimeAnimation::setPresentationType(CORBA::Long theFieldNum, VISU::VISUType theType) {
1122   if ( theFieldNum < 0 || theFieldNum >= myFieldsLst.size() )
1123     return;
1124
1125   myFieldsLst[theFieldNum].myPrsType = theType;
1126 }
1127
1128 //------------------------------------------------------------------------
1129 VISU::VISUType VISU_TimeAnimation::getPresentationType(CORBA::Long theFieldNum) {
1130   if ( theFieldNum < 0 || theFieldNum >= myFieldsLst.size() )
1131     return VISU::TNONE;
1132   
1133   return myFieldsLst[theFieldNum].myPrsType;
1134 }
1135
1136 //------------------------------------------------------------------------
1137 CORBA::Long VISU_TimeAnimation::getNbFrames() {
1138   if ( myAnimationMode == VISU::Animation::PARALLEL ) // parallel animation mode
1139     return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
1140   else //successive animation mode
1141     return (getNbFields() > 0 && !myFieldsAbsFrames.empty()) ? myFieldsAbsFrames[myFieldsAbsFrames.size()-1] : 0;
1142 }
1143
1144 //------------------------------------------------------------------------
1145 long VISU_TimeAnimation::getAbsoluteFrameNumber(std::pair<int,long> theFieldTimeStamp)
1146 {
1147   long aRes = -1;
1148   if ( getNbFields() > 0 ) {
1149     int aFieldId = theFieldTimeStamp.first;
1150     long aFrameNum = theFieldTimeStamp.second + 1;
1151     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1152       if ( aFrameNum <= myFieldsAbsFrames[0] )
1153         aRes = aFrameNum;
1154     }
1155     else { //successive animation mode
1156       if ( aFieldId == 0 && aFrameNum <= myFieldsAbsFrames[aFieldId] )
1157         aRes = aFrameNum;
1158       else if ( aFieldId && aFrameNum <= myFieldsAbsFrames[aFieldId] - myFieldsAbsFrames[aFieldId-1] )
1159         aRes = myFieldsAbsFrames[aFieldId-1] + aFrameNum;
1160     }
1161   }
1162   return aRes - 1;
1163 }
1164
1165 //------------------------------------------------------------------------
1166 std::pair<int,long> VISU_TimeAnimation::getRelativeFrameNumber(long theFrame)
1167 {
1168   std::pair<int,long> aRes;
1169   if ( getNbFields() > 0 && theFrame < getNbFrames() ) {
1170     theFrame = theFrame + 1;
1171     if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1172       aRes.first = 0;
1173       aRes.second = theFrame - 1;
1174     }
1175     else { //successive animation mode
1176       for (int i = 0, iEnd = myFieldsAbsFrames.size(); i < iEnd; i++)
1177         if ( myFieldsAbsFrames[i] >= theFrame ) {
1178           aRes.first = i;
1179           if ( i == 0 )
1180             aRes.second = theFrame - 1;
1181           else
1182             aRes.second = theFrame-myFieldsAbsFrames[i-1] - 1;
1183           break;
1184         }
1185     }
1186   }
1187   return aRes;
1188 }
1189
1190 //------------------------------------------------------------------------
1191 void VISU_TimeAnimation::parallelAnimation( bool& theIsDumping, QList<int>& theIndexList )
1192 {
1193   double k = 1;
1194   double aOneVal = 1;
1195   FieldData& aFirstFieldData = myFieldsLst[0];
1196   if (aFirstFieldData.myNbFrames > 2)
1197     aOneVal = ( myTimeMax - myTimeMin ) / getNbFrames();
1198   int aNbFiles = 0;
1199
1200   bool aHasNextFrame = aFirstFieldData.myField && aFirstFieldData.myNbFrames > 0;
1201   while (aHasNextFrame && myExecutionState->IsActive()) {
1202     ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>
1203                      (this, &VISU_TimeAnimation::_emitFrameChanged,
1204                       myFrame, aFirstFieldData.myTiming[myFrame]));
1205     if (myExecutionState->IsActive()) {
1206       for (int i = 0; i < getNbFields(); i++) {
1207         FieldData& aData = myFieldsLst[i];
1208         if (aData.myNbFrames == 0)
1209           continue;
1210         if (myFrame > 0) {
1211           if (aData.myActors[myFrame-1] != 0)
1212             visibilityOff(i, myFrame-1);
1213         } else {
1214           if (aData.myActors[aData.myNbFrames-1] != 0)
1215             visibilityOff(i, aData.myNbFrames-1);
1216         }
1217         if (aData.myActors[myFrame] != 0 && myView) {
1218           ProcessVoidEvent(new TVoidMemFunEvent<VISU_Actor>(aData.myActors[myFrame],
1219                                                             &VISU_Actor::VisibilityOn));
1220         }
1221       }
1222       if (!myView)
1223         return;
1224       bool repainArg = false;
1225       ProcessVoidEvent(new TVoidMemFun1ArgEvent<SVTK_ViewWindow,bool>(myView,
1226                                                                       &SVTK_ViewWindow::Repaint,
1227                                                                       repainArg));
1228     }
1229
1230     k = 1;
1231     if (myProportional) {
1232       switch (myFrame) {
1233       case 0:
1234         break;
1235       case 1:
1236         if (aFirstFieldData.myNbFrames > 2)
1237           k = (aFirstFieldData.myTiming[myFrame+1] -
1238                aFirstFieldData.myTiming[myFrame]) / aOneVal;
1239         break;
1240       default:
1241         if (myFrame < (aFirstFieldData.myNbFrames - 1))
1242           k = (aFirstFieldData.myTiming[myFrame+1] -
1243                aFirstFieldData.myTiming[myFrame]) / aOneVal;
1244       }
1245     }
1246     int delay = (int)(1000. * k / mySpeed);
1247     theIsDumping = !myDumpPath.isEmpty();
1248     if (delay < 1 && theIsDumping) {
1249       // We must unlock mutex for some time before grabbing to allow view updating
1250       delay = 1;
1251     }
1252     msleep(delay);
1253     if (!myExecutionState->IsActive()) 
1254       return;
1255
1256     if (theIsDumping) {
1257       // We must unlock mutex for some time before grabbing to allow view updating
1258       msleep(delay);
1259       if (!myExecutionState->IsActive()) 
1260         return;
1261
1262       if (!(aFirstFieldData.myField)) // break, if field was deleted.
1263         break;
1264
1265       saveImages( 0, aOneVal, aNbFiles, theIndexList );
1266     }
1267
1268     if (!myExecutionState->IsActive()) 
1269       break;
1270
1271     myFrame++;
1272     if (myFrame == aFirstFieldData.myNbFrames) {
1273       if (!myCycling) {
1274         aHasNextFrame = false;
1275         myFrame--;
1276       }
1277       else
1278         myFrame = 0;
1279     }
1280   } // while (aHasNextFrame && myExecutionState->IsActive())
1281 }
1282
1283 //------------------------------------------------------------------------
1284 void VISU_TimeAnimation::successiveAnimation( bool& theIsDumping, QList<int>& theIndexList )
1285 {
1286   if (myFrame >= getNbFrames() - 1)
1287   {
1288     myExecutionState->SetActive(false);
1289     return;
1290   }
1291
1292   double k = 1;
1293   double aOneVal = 1;
1294   FieldData& aFirstFieldData = myFieldsLst[0];
1295   if (aFirstFieldData.myNbFrames > 2)
1296     aOneVal = ( myTimeMax - myTimeMin ) / getNbFrames();
1297   int aNbFiles = 0;
1298   long aFrame = myFrame;
1299
1300   bool aHasNextFrame = true;
1301   while (aHasNextFrame && myExecutionState->IsActive())
1302   {
1303     for (int aFieldId = 0;
1304          (aFieldId < getNbFields()) && (myFieldsLst[aFieldId].myField);
1305          aFieldId++, aFrame = 0)
1306     {
1307       if (!myExecutionState->IsActive()) break;
1308
1309       FieldData& aData = myFieldsLst[aFieldId];
1310       if ( !aData.myPrs[0] ) continue;
1311       for (; aFrame < aData.myNbFrames && myExecutionState->IsActive(); aFrame++, myFrame++)
1312       {
1313         ProcessVoidEvent(new TVoidMemFun2ArgEvent<VISU_TimeAnimation,long,double>
1314                          (this, &VISU_TimeAnimation::_emitFrameChanged,
1315                           myFrame, myFieldsLst[aFieldId].myTiming[aFrame]));
1316
1317         if (myExecutionState->IsActive()) {
1318           if (aFrame > 0) {
1319             if (aData.myActors[aFrame-1] != 0)
1320               visibilityOff(aFieldId, aFrame-1);
1321           } else if ( myFrame > 0) {
1322             if (myFieldsLst[aFieldId-1].myActors[myFieldsLst[aFieldId-1].myNbFrames-1] != 0)
1323               visibilityOff(aFieldId-1, myFieldsLst[aFieldId-1].myNbFrames-1);
1324           } else if ( myCycling ) {
1325             if (myFieldsLst[getNbFields()-1].myActors[myFieldsLst[getNbFields()-1].myNbFrames-1] != 0)
1326               visibilityOff(getNbFields()-1, myFieldsLst[getNbFields()-1].myNbFrames-1);
1327           } else {
1328             if (aData.myActors[aData.myNbFrames-1] != 0)
1329               visibilityOff(aFieldId, aData.myNbFrames-1);
1330           }
1331           if (aData.myActors[aFrame] != 0 && myView) {
1332             ProcessVoidEvent(new TVoidMemFunEvent<VISU_Actor>(aData.myActors[aFrame],
1333                                                               &VISU_Actor::VisibilityOn));
1334           }
1335
1336           if (!myView)
1337             return;
1338           bool repainArg = false;
1339           ProcessVoidEvent(new TVoidMemFun1ArgEvent<SVTK_ViewWindow,bool>(myView,
1340                                                                           &SVTK_ViewWindow::Repaint,
1341                                                                           repainArg));
1342         }
1343
1344         k = 1;
1345         if (myProportional) {
1346           switch (aFrame) {
1347           case 0:
1348             break;
1349           case 1:
1350             if (aFirstFieldData.myNbFrames > 2)
1351               k = (aFirstFieldData.myTiming[aFrame+1] -
1352                    aFirstFieldData.myTiming[aFrame]) / aOneVal;
1353             break;
1354           default:
1355             if (aFrame < (aFirstFieldData.myNbFrames - 1))
1356               k = (aFirstFieldData.myTiming[aFrame+1] -
1357                    aFirstFieldData.myTiming[aFrame]) / aOneVal;
1358           }
1359         }
1360         int delay = (int)(1000. * k / mySpeed);
1361         theIsDumping = !myDumpPath.isEmpty();
1362         if (delay < 1 && theIsDumping) {
1363           // We must unlock mutex for some time before grabbing to allow view updating
1364           delay = 1;
1365         }
1366         msleep(delay);
1367
1368         if (!myExecutionState->IsActive()) return;
1369
1370         if (theIsDumping) {
1371           // We must unlock mutex for some time before grabbing to allow view updating
1372           msleep(delay);
1373           if (!myExecutionState->IsActive()) return;
1374
1375           if (!(myFieldsLst[aFieldId].myField)) // break, if field was deleted.
1376             break;
1377
1378           saveImages( aFieldId, aOneVal, aNbFiles, theIndexList );
1379         }
1380       } // for (; aFrame < aData.myNbFrames && myExecutionState->IsActive(); aFrame++, myFrame++)
1381     } // for (int aFieldId = 0;
1382
1383     if (!myCycling) {
1384       aHasNextFrame = false;
1385       myFrame--;
1386     }
1387     else {
1388       myFrame = 0;
1389       aFrame = myFrame;
1390     }
1391   } // while (aHasNextFrame && myExecutionState->IsActive())
1392 }
1393
1394 //------------------------------------------------------------------------
1395 void VISU_TimeAnimation::saveImages( int theFieldId, 
1396                                      double& theOneVal, int& theNbFiles, 
1397                                      QList<int>& theIndexList )
1398 {
1399   if (myDumpFormat.compare("AVI") != 0) {
1400     QString aFile(myDumpPath);
1401
1402     int aFrameNb = myFrame; // parallel animation mode
1403     if ( myAnimationMode == VISU::Animation::SUCCESSIVE ) // successive animation mode
1404       aFrameNb = getRelativeFrameNumber(myFrame).second;
1405
1406     int aMaxNb = myFieldsLst[theFieldId].myTiming.size();
1407     int nbDigits = QString("%1").arg(aMaxNb).length();
1408     QString aFormat = QString("%.%1d_").arg(nbDigits);
1409
1410     QString aName;
1411     aName.sprintf(aFormat.toLatin1().data(), aFrameNb);
1412     aName += QString("%1").arg(myFieldsLst[theFieldId].myTiming[aFrameNb]);
1413
1414     int aPos = -1;
1415     while ((aPos = aName.indexOf(".")) > -1 )
1416       aName.replace(aPos, 1, "_");
1417     aFile += aName;
1418     aFile += ".";
1419     aFile += myDumpFormat.toLower();
1420     ProcessVoidEvent(new TVoidMemFunEvent<SVTK_ViewWindow>
1421                      (myView,&SVTK_ViewWindow::RefreshDumpImage)); // IPAL13602
1422     ProcessEvent(new TMemFun2ArgEvent<SUIT_ViewWindow,bool,const QString&,const QString&>
1423                  (myView,&SUIT_ViewWindow::dumpViewToFormat,aFile,myDumpFormat));
1424   } else {
1425     QFileInfo aFileInfo(myDumpPath);
1426     QString aDirPath = aFileInfo.absolutePath();
1427     QString aBaseName = aFileInfo.fileName();
1428     
1429     switch (myFrame) {
1430     case 0: 
1431       break;
1432     case 1:
1433       myFileIndex += 5;
1434       break;
1435     default:
1436       if (myProportional) {
1437         FieldData& aFirstFieldData = myFieldsLst[0];
1438         double p = (aFirstFieldData.myTiming[myFrame] -
1439                     aFirstFieldData.myTiming[myFrame-1]) / theOneVal;
1440         myFileIndex += (long) (5*p);
1441       } else {
1442         myFileIndex += 5;
1443       }
1444     }
1445     
1446     QString aFile = aDirPath + QDir::separator() + aBaseName;
1447     aFile += "_";
1448     aFile += QString("%1").arg(myFileIndex).rightJustified(8, '0');
1449     aFile += ".jpeg";
1450     
1451     /* check image size is divisable 16
1452        myView->dumpViewToFormat(aFile,"JPEG");
1453     */
1454     SUIT_ViewWindow* aView = myView;
1455     ProcessVoidEvent(new TVoidMemFunEvent<SVTK_ViewWindow>(myView,&SVTK_ViewWindow::RefreshDumpImage)); // IPAL13602
1456     QImage img = ProcessEvent(new TMemFunEvent<SUIT_ViewWindow,QImage>(aView,&SUIT_ViewWindow::dumpView));
1457     if (!img.isNull()) {
1458       int width = img.width(); width = (width/16)*16;
1459       int height = img.height(); height = (height/16)*16;
1460       QImage copy = img.copy(0, 0, width, height);
1461       if (copy.save(aFile, "JPEG")) {
1462         theIndexList.append(myFileIndex);
1463         theNbFiles++;
1464       }
1465     }
1466   }
1467 }
1468
1469 //------------------------------------------------------------------------
1470 void VISU_TimeAnimation::run()
1471 {
1472   if (!myView) {
1473     MESSAGE("Viewer is not defined for animation");
1474     return;
1475   }
1476
1477   bool isDumping = !myDumpPath.isEmpty();
1478   myFileIndex = 0;
1479   QList<int> anIndexList;
1480
1481   if ( myAnimationMode == VISU::Animation::PARALLEL ) // parallel animation mode
1482     parallelAnimation( isDumping, anIndexList );
1483   else //successive animation mode
1484     successiveAnimation( isDumping, anIndexList );
1485
1486   // make AVI file if need
1487   if (isDumping && myDumpFormat.compare("AVI") == 0 && myExecutionState->IsActive()) {
1488     double aFPS = 17.3 * mySpeed;
1489
1490     QFileInfo aFileInfo(myDumpPath);
1491     QString aDirPath = aFileInfo.absolutePath();
1492     QString aBaseName = aFileInfo.fileName();
1493
1494     // add missing files
1495     if (anIndexList.count() > 1) {
1496       QString aFFile = aDirPath + QDir::separator() + aBaseName;
1497       aFFile += QString("_%1.jpeg");
1498       int aStartIndex = anIndexList[0], anEndIndex;
1499       for (int i = 1; i < anIndexList.count(); i++) {
1500         anEndIndex = anIndexList[i];
1501         QString aCurFile = aFFile.arg(QString::number(aStartIndex).rightJustified(8, '0'));
1502         QStringList aCommands;
1503         for (int j = aStartIndex+1; j < anEndIndex; j++) {
1504           QString aFile = aFFile.arg(QString::number(j).rightJustified(8, '0'));
1505           aCommands.append(QString("ln -s %1 %2").arg(aCurFile).arg(aFile));
1506         }
1507         system(aCommands.join(" ; \\\n").toLatin1().data());
1508         aStartIndex = anEndIndex;
1509       }
1510     }
1511
1512     // make AVI file
1513     QString aPattern = aDirPath + QDir::separator() + aBaseName;
1514     aPattern += "_\%08d.jpeg";
1515
1516     QString aCmd = myAVIMaker;
1517     aCmd += " -I p";
1518     aCmd += " -v 0";
1519     aCmd += QString(" -f %1").arg(aFPS);
1520     // aCmd += QString(" -n %1").arg(aNbFiles);
1521     aCmd += QString(" -n %1").arg(myFileIndex+1);
1522     aCmd += QString(" -j %1").arg(aPattern);
1523     aCmd += " | yuv2lav";
1524     aCmd += QString(" -o %1").arg(myDumpPath);
1525     system(aCmd.toLatin1().data());
1526
1527     // remove temporary jpeg files
1528     aCmd = "( ";
1529     aCmd += QString("cd %1").arg(aDirPath);
1530     aCmd += "; ls";
1531     aCmd += QString(" | egrep '%1_[0-9]*.jpeg'").arg(aBaseName);
1532     aCmd += " | xargs rm";
1533     aCmd += " )";
1534     system(aCmd.toLatin1().data());
1535   }
1536
1537   if (myExecutionState->IsActive())
1538     ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>(this,&VISU_TimeAnimation::_emitStopped));
1539   myExecutionState->SetActive(false);
1540 }
1541
1542 //------------------------------------------------------------------------
1543 VISU::Result_i* VISU_TimeAnimation::createPresent (_PTR(SObject) theField)
1544 {
1545   _PTR(SObject) aSObj = theField->GetFather();
1546   aSObj = aSObj->GetFather();
1547   aSObj = aSObj->GetFather();
1548   CORBA::Object_var anObject = VISU::ClientSObjectToObject(aSObj);
1549   if (CORBA::is_nil(anObject)) return NULL;
1550   return dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject).in());
1551 }
1552
1553 //------------------------------------------------------------------------
1554 double VISU_TimeAnimation::getTimeValue (_PTR(SObject) theTimeStamp)
1555 {
1556   _PTR(GenericAttribute) anAttr;
1557   if (theTimeStamp->FindAttribute(anAttr, "AttributeName")) {
1558     _PTR(AttributeName) aName (anAttr);
1559     QString aNameString (aName->Value().c_str());
1560     int time_len = aNameString.indexOf(',');
1561     if (time_len > -1)
1562       return aNameString.left(time_len).toDouble();
1563     else
1564       return aNameString.toDouble();
1565   }
1566   return -1.0;
1567 }
1568
1569 //------------------------------------------------------------------------
1570 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed)
1571 {
1572   mySpeed = (theSpeed<1)? 1 : theSpeed;
1573 }
1574
1575 //------------------------------------------------------------------------
1576 void VISU_TimeAnimation::setAnimationSequence(const char* theSequence)
1577 {
1578   mySequence = QString( theSequence );
1579 }
1580
1581 //------------------------------------------------------------------------
1582 char* VISU_TimeAnimation::getAnimationSequence()
1583 {
1584   return strdup( mySequence.toLatin1().data() );
1585 }
1586
1587 //------------------------------------------------------------------------
1588 CORBA::Boolean VISU_TimeAnimation::isSequenceDefined()
1589 {
1590   return !mySequence.isEmpty();
1591 }
1592
1593 //------------------------------------------------------------------------
1594 bool VISU_TimeAnimation::getIndicesFromSequence( QString theSequence, QList<long>& theIndices )
1595 {
1596   bool isCorrect = true;
1597
1598   theIndices.clear();
1599
1600   QStringList aList = theSequence.split( ",", QString::SkipEmptyParts );
1601   QStringList::iterator it = aList.begin();
1602   QStringList::iterator itEnd = aList.end();
1603   for( ; it != itEnd; ++it )
1604   {
1605     if( !isCorrect )
1606       break;
1607
1608     isCorrect = false;
1609
1610     QString aString = *it;
1611     if( aString.isEmpty() )
1612       continue;
1613
1614     bool ok = false;
1615     int aSingleIndex = aString.toLong( &ok );
1616     if( ok )
1617     {
1618       theIndices.append( aSingleIndex );
1619       isCorrect = true;
1620     }
1621     else if( aString.contains( '-' ) == 1 )
1622     {
1623       QString aLeftIndexStr = aString.section( '-', 0, 0 );
1624       QString aRightIndexStr = aString.section( '-', -1 );
1625
1626       ok = false;
1627       int aLeftIndex = aLeftIndexStr.toLong( &ok );
1628       if( !ok )
1629         continue;
1630
1631       ok = false;
1632       int aRightIndex = aRightIndexStr.toLong( &ok );
1633       if( !ok )
1634         continue;
1635
1636       if( aLeftIndex >= aRightIndex )
1637         continue;
1638
1639       for( int i = aLeftIndex; i <= aRightIndex; i++ )
1640         theIndices.append( i );
1641
1642       isCorrect = true;
1643     }
1644   }
1645
1646   return isCorrect;
1647 }
1648
1649 //------------------------------------------------------------------------
1650 std::string VISU_TimeAnimation::setDumpFormat(const char* theFormat)
1651 {
1652   myDumpFormat = theFormat;
1653   QList<QByteArray> aDumpFormats = QImageWriter::supportedImageFormats();
1654   if (myDumpFormat.isEmpty() || 
1655       (aDumpFormats.indexOf(theFormat) < 0 && myDumpFormat.compare("AVI") != 0)) {
1656     if (aDumpFormats.indexOf("JPEG"))
1657       myDumpFormat = "JPEG";
1658     else
1659       myDumpFormat = aDumpFormats.at(0);
1660   }
1661   return myDumpFormat.toLatin1().data();
1662 }
1663
1664 //------------------------------------------------------------------------
1665 bool VISU_TimeAnimation::checkAVIMaker() const
1666 {
1667   QList<QByteArray> aDumpFormats = QImageWriter::supportedImageFormats();
1668   if (aDumpFormats.indexOf("JPEG") < 0) return false;
1669
1670   QString aCmd("which ");
1671   aCmd += myAVIMaker;
1672   aCmd += " >& /dev/null";
1673   int iErr = system(aCmd.toLatin1().data());
1674   return (iErr == 0);
1675 }
1676
1677 //************************************************************************
1678 int VISU_TimeAnimation::myNBAnimations = 0;
1679 QString VISU_TimeAnimation::GenerateName()
1680 {
1681   return VISU::GenerateName("Animation", myNBAnimations++);
1682 }
1683
1684 //------------------------------------------------------------------------
1685 std::string GetPresentationComment (VISU::VISUType thePrsType)
1686 {
1687   std::string aPrsCmt;
1688   switch (thePrsType) {
1689   case VISU::TSCALARMAP:
1690     aPrsCmt = VISU::ScalarMap_i::myComment;
1691     break;
1692   case VISU::TISOSURFACES:
1693     aPrsCmt = VISU::IsoSurfaces_i::myComment;
1694     break;
1695   case VISU::TCUTPLANES:
1696     aPrsCmt = VISU::CutPlanes_i::myComment;
1697     break;
1698   case VISU::TCUTLINES:
1699     aPrsCmt = VISU::CutLines_i::myComment;
1700     break;
1701   case VISU::TCUTSEGMENT:
1702     aPrsCmt = VISU::CutSegment_i::myComment;
1703     break;
1704   case VISU::TPLOT3D:
1705     aPrsCmt = VISU::Plot3D_i::myComment;
1706     break;
1707   case VISU::TDEFORMEDSHAPE:
1708     aPrsCmt = VISU::DeformedShape_i::myComment;
1709     break;
1710   case VISU::TVECTORS:
1711     aPrsCmt = VISU::Vectors_i::myComment;
1712     break;
1713   case VISU::TSTREAMLINES:
1714     aPrsCmt = VISU::StreamLines_i::myComment;
1715     break;
1716   case VISU::TGAUSSPOINTS:
1717     aPrsCmt = VISU::GaussPoints_i::myComment;
1718     break;
1719   case VISU::TSCALARMAPONDEFORMEDSHAPE:
1720   case VISU::TDEFORMEDSHAPEANDSCALARMAP:
1721     aPrsCmt = VISU::DeformedShapeAndScalarMap_i::myComment;
1722     break;
1723   default:
1724     aPrsCmt = "Unknown presentation";
1725     break;
1726   }
1727   return aPrsCmt;
1728 }
1729
1730 //------------------------------------------------------------------------
1731 SALOMEDS::SObject_ptr VISU_TimeAnimation::publishInStudy()
1732 {
1733   if (myStudy->GetProperties()->IsLocked()) {
1734     SUIT_MessageBox::warning(0,
1735                              QObject::tr("WRN_VISU_WARNING"),
1736                              QObject::tr("WRN_STUDY_LOCKED"),
1737                              QObject::tr("BUT_OK"));
1738     return SALOMEDS::SObject::_nil();
1739   }
1740
1741   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
1742   aStudyBuilder->NewCommand();  // There is a transaction
1743   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
1744   std::string aSComponentEntry = aSComponent->GetID();
1745
1746   QString aComment;
1747   aComment.sprintf("myComment=ANIMATION;myTimeMinVal=%g;myTimeMaxVal=%g;mySequence=%s;myMode=%d",
1748                    myTimeMinVal,
1749                    myTimeMaxVal,
1750                    mySequence.toLatin1().data(),
1751                    myAnimationMode);
1752
1753   string anEntry = VISU::CreateAttributes(myStudy,
1754                                           aSComponentEntry.c_str(),
1755                                           VISU::NO_ICON,
1756                                           VISU::NO_IOR,
1757                                           GenerateName().toLatin1().data(),
1758                                           VISU::NO_PERFSITENT_REF,
1759                                           aComment.toLatin1().data(),
1760                                           true);
1761   myAnimEntry = anEntry.c_str();
1762   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(anEntry.c_str());
1763
1764   for (int i = 0; i < getNbFields(); i++) {
1765     FieldData& aData = myFieldsLst[i];
1766     if (aData.myPrs.empty()) {
1767       generatePresentations(i);
1768     }
1769     if ( !aData.myPrs.empty() ) {
1770       _PTR(SObject) newObj = aStudyBuilder->NewObject(aAnimSObject);
1771       aStudyBuilder->Addreference(newObj, aData.myField);
1772       
1773       ostringstream strOut;
1774       aData.myPrs[0]->ToStream(strOut);
1775       string aPrsComment = strOut.str();
1776       string aPrsMyComment = aData.myPrs[0]->GetComment();
1777       if(aPrsMyComment == "PRSMERGER")
1778         aPrsMyComment = "SCALARMAP";
1779       VISU::CreateAttributes(myStudy, 
1780                              newObj->GetID().c_str(),
1781                              VISU::NO_ICON,
1782                              VISU::NO_IOR,
1783                              aPrsMyComment.c_str(),
1784                              VISU::NO_PERFSITENT_REF,
1785                              aPrsComment.c_str(),
1786                              true);
1787     }
1788   }
1789   aStudyBuilder->CommitCommand();
1790
1791   return VISU::GetSObject(aAnimSObject)._retn();
1792 }
1793
1794 //------------------------------------------------------------------------
1795 void VISU_TimeAnimation::saveAnimation()
1796 {
1797   if (myStudy->GetProperties()->IsLocked()) return;
1798   if (myAnimEntry.isEmpty()) return;
1799
1800   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(myAnimEntry.toLatin1().data());
1801   if (!aAnimSObject) return;
1802
1803   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
1804   aStudyBuilder->NewCommand();  // There is a transaction
1805   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
1806   std::string aSComponentEntry = aSComponent->GetID();
1807
1808   QString aComment;
1809   aComment.sprintf("myComment=ANIMATION;myTimeMinVal=%g;myTimeMaxVal=%g;mySequence=%s;myMode=%d",
1810                    myTimeMinVal,
1811                    myTimeMaxVal,
1812                    mySequence.toLatin1().data(),
1813                    myAnimationMode);
1814
1815   _PTR(GenericAttribute) anAttr;
1816   anAttr = aStudyBuilder->FindOrCreateAttribute(aAnimSObject, "AttributeString");
1817   _PTR(AttributeString) aCmnt (anAttr);
1818   aCmnt->SetValue(aComment.toLatin1().data());
1819
1820   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
1821   int i = 0, nbf = getNbFields();
1822   for (anIter->Init(); anIter->More(); anIter->Next(), i++) {
1823     if (i >= nbf) break; // it must not be
1824     FieldData& aData = myFieldsLst[i];
1825
1826     // Get presentation name and comment
1827     if (aData.myPrs.empty()) {
1828       generatePresentations(i);
1829     }
1830     ostringstream strOut;
1831     aData.myPrs[0]->ToStream(strOut);
1832     string aPrsComment = strOut.str();
1833     string aPrsNameTxt = aData.myPrs[0]->GetComment();
1834     if(aPrsNameTxt == "PRSMERGER")
1835       aPrsNameTxt = "SCALARMAP";
1836     // Save in study
1837     _PTR(SObject) aRefObj = anIter->Value();
1838     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
1839     anPrsIter->Init();
1840
1841     if (anPrsIter->More()) {
1842       _PTR(SObject) aPrsObj = anPrsIter->Value();
1843       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeString");
1844       aCmnt = _PTR(AttributeString)(anAttr);
1845       aCmnt->SetValue(aPrsComment.c_str());
1846
1847       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeName");
1848       _PTR(AttributeName) aPrsName (anAttr);
1849       aPrsName->SetValue(aPrsNameTxt);
1850
1851     } else {
1852       VISU::CreateAttributes(myStudy, 
1853                              aRefObj->GetID().c_str(),
1854                              VISU::NO_ICON,
1855                              VISU::NO_IOR,
1856                              aPrsNameTxt.c_str(),
1857                              VISU::NO_PERFSITENT_REF,
1858                              aPrsComment.c_str(),
1859                              true);
1860     }
1861   }
1862   aStudyBuilder->CommitCommand();
1863 }
1864
1865 //------------------------------------------------------------------------
1866 void VISU_TimeAnimation::restoreFromStudy(SALOMEDS::SObject_ptr theField)
1867 {
1868   _PTR(SObject) aAnimSObject = VISU::GetClientSObject(theField, myStudy);
1869   restoreFromStudy(aAnimSObject);
1870 }
1871
1872 void VISU_TimeAnimation::restoreFromStudy(_PTR(SObject) theField)
1873 {
1874   _PTR(SObject) aAnimSObject = theField;
1875
1876   VISU::Storable::TRestoringMap aMap = VISU::Storable::GetStorableMap(aAnimSObject);
1877   if (aMap.empty()) 
1878     return;
1879
1880   bool isExist;
1881   myTimeMinVal = VISU::Storable::FindValue(aMap,"myTimeMinVal",&isExist).toDouble();
1882   myTimeMaxVal = VISU::Storable::FindValue(aMap,"myTimeMaxVal",&isExist).toDouble();
1883   mySequence = VISU::Storable::FindValue(aMap,"mySequence",&isExist);
1884   myAnimationMode = VISU::Animation::AnimationMode(VISU::Storable::FindValue(aMap,"myMode",&isExist).toInt());
1885
1886   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
1887   for (anIter->Init(); anIter->More(); anIter->Next()) {
1888     _PTR(SObject) aRefObj = anIter->Value();
1889     _PTR(SObject) aFieldObj;
1890
1891     if (!aRefObj->ReferencedObject(aFieldObj) ) 
1892       continue;
1893
1894     int nbAttr = aFieldObj->GetAllAttributes().size();
1895     //std::string name1 = aFieldObj->GetName();
1896     if(nbAttr<1)
1897       continue;
1898
1899     addField(aFieldObj);
1900     if ( isRangeDefined() || isSequenceDefined() ) 
1901       myFieldsAbsFrames.pop_back();
1902
1903     FieldData& aData = getFieldData(getNbFields()-1);
1904     
1905     // Get Presentation object
1906     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
1907     anPrsIter->Init();
1908     if (!anPrsIter->More()) 
1909       continue;
1910     _PTR(SObject) aPrsObj = anPrsIter->Value();
1911     _PTR(GenericAttribute) anAttr;
1912     if (!aPrsObj->FindAttribute(anAttr, "AttributeName")) 
1913       continue;
1914     _PTR(AttributeName) aName (anAttr);
1915     string aStr = aName->Value();
1916     QString strName (aStr.c_str());
1917
1918     if (strName == VISU::ScalarMap_i::myComment.c_str())
1919       aData.myPrsType = VISU::TSCALARMAP;
1920     else if (strName == VISU::IsoSurfaces_i::myComment.c_str())
1921       aData.myPrsType = VISU::TISOSURFACES;
1922     else if (strName == VISU::CutPlanes_i::myComment.c_str())
1923       aData.myPrsType = VISU::TCUTPLANES;
1924     else if (strName == VISU::CutLines_i::myComment.c_str())
1925       aData.myPrsType = VISU::TCUTLINES;
1926     else if (strName == VISU::CutSegment_i::myComment.c_str())
1927       aData.myPrsType = VISU::TCUTSEGMENT;
1928     else if (strName == VISU::Plot3D_i::myComment.c_str())
1929       aData.myPrsType = VISU::TPLOT3D;
1930     else if (strName == VISU::DeformedShape_i::myComment.c_str())
1931       aData.myPrsType = VISU::TDEFORMEDSHAPE;
1932     else if (strName == VISU::Vectors_i::myComment.c_str())
1933       aData.myPrsType = VISU::TVECTORS;
1934     else if (strName == VISU::StreamLines_i::myComment.c_str())
1935       aData.myPrsType = VISU::TSTREAMLINES;
1936     else if (strName == VISU::GaussPoints_i::myComment.c_str())
1937       aData.myPrsType = VISU::TGAUSSPOINTS;
1938     else if (strName == VISU::DeformedShapeAndScalarMap_i::myComment.c_str())
1939       aData.myPrsType = VISU::TDEFORMEDSHAPEANDSCALARMAP;
1940     else
1941       continue;
1942     generatePresentations(getNbFields()-1);
1943
1944     VISU::Storable::TRestoringMap aPrsMap = VISU::Storable::GetStorableMap(aPrsObj);
1945     if (aPrsMap.empty())
1946       continue;
1947     if (aData.myPrs[0]) {
1948       aData.myPrs[0]->Restore(VISU::GetSObject(aData.myField), aPrsMap);
1949       aData.myPrs[0]->GetOffset(aData.myOffset);
1950     }
1951     for (int i = 1; i < aData.myNbFrames; i++) {
1952       if (!aData.myPrs[0])
1953         continue;
1954       bool anIsFixedRange = false;
1955       if (aData.myPrsType != VISU::TGAUSSPOINTS) {
1956         if (VISU::ScalarMap_i* aPrs = dynamic_cast<VISU::ScalarMap_i*>(aData.myPrs[i]))
1957           anIsFixedRange = aPrs->IsRangeFixed();
1958       }
1959       if (aData.myPrsType == VISU::TDEFORMEDSHAPEANDSCALARMAP) {
1960         if (VISU::DeformedShapeAndScalarMap_i* aDeformedPrs =
1961             dynamic_cast<VISU::DeformedShapeAndScalarMap_i*>(aData.myPrs[i])) {
1962           //Set correct time stamp number
1963           int aTimeStampNum = aDeformedPrs->GetScalarTimeStampNumber();
1964           aDeformedPrs->SameAs(aData.myPrs[0]);
1965           aDeformedPrs->SetScalarField(aDeformedPrs->GetScalarEntity(),
1966                                        aDeformedPrs->GetScalarFieldName(),
1967                                        aTimeStampNum);
1968         }
1969       }
1970       else
1971         aData.myPrs[i]->SameAs(aData.myPrs[0]);
1972     }
1973   }
1974   string aStr = aAnimSObject->GetID();
1975   myAnimEntry = aStr.c_str();
1976 }
1977
1978 void VISU_TimeAnimation::onViewDeleted()
1979 {
1980   myView = 0;
1981   stopAnimation();
1982 }
1983
1984 void VISU_TimeAnimation::ApplyProperties(CORBA::Long theFieldNum, VISU::ColoredPrs3d_ptr thePrs)
1985   throw (SALOME::SALOME_Exception)
1986 {
1987   Unexpect aCatch(SALOME_SalomeException);
1988
1989   VISU::ColoredPrs3d_i* aPrs_i = dynamic_cast<VISU::ColoredPrs3d_i*>(GetServant(thePrs).in());
1990
1991   if ( !aPrs_i ) 
1992     THROW_SALOME_CORBA_EXCEPTION("Error : invalid dynamic cast of the given presentation to VISU::ColoredPrs3d_i",
1993                                  SALOME::INTERNAL_ERROR);
1994   
1995   if ( myAnimationMode == VISU::Animation::PARALLEL ) { // parallel animation mode
1996     FieldData& aData = myFieldsLst[theFieldNum];
1997     
1998     if ( aData.myPrs.empty() )
1999       THROW_SALOME_CORBA_EXCEPTION("Error : presentations for the given field is not yet created!",
2000                                    SALOME::INTERNAL_ERROR);
2001     
2002     if ( aPrs_i->GetCResult() != aData.myPrs[0]->GetCResult() )
2003       THROW_SALOME_CORBA_EXCEPTION("Error : the MED file is not the same!",
2004                                    SALOME::INTERNAL_ERROR);
2005     
2006     for (int i = 0; i < aData.myNbFrames; i++) {
2007       bool anIsFixedRange = false;
2008       if (aData.myPrsType != VISU::TGAUSSPOINTS) {
2009         if (VISU::ScalarMap_i* aPrs = dynamic_cast<VISU::ScalarMap_i*>(aData.myPrs[i]))
2010           anIsFixedRange = aPrs->IsRangeFixed();
2011       }
2012       aData.myPrs[i]->SameAs(aPrs_i);
2013     }
2014   }
2015   else if ( myAnimationMode == VISU::Animation::SUCCESSIVE ) { // successive animation mode
2016     for (int f = 0; f < getNbFields(); f++) {
2017       FieldData& aData = myFieldsLst[f];
2018       
2019       if ( aData.myPrs.empty() )
2020         THROW_SALOME_CORBA_EXCEPTION("Error : presentations for the given field is not yet created!",
2021                                      SALOME::INTERNAL_ERROR);
2022       
2023       for (int i = 0; i < aData.myNbFrames; i++) {
2024         aData.myPrs[i]->SameAs(aPrs_i);
2025       }
2026     }
2027   }
2028 }
2029
2030 //========================================================================
2031 //========================================================================
2032 //========================================================================
2033 struct TNewAnimationEvent: public SALOME_Event
2034 {
2035   std::string myStudyName;
2036   VISU::View3D_ptr myView3D;
2037
2038   typedef VISU_TimeAnimation* TResult;
2039   TResult myResult;
2040
2041   TNewAnimationEvent (std::string theStudyName, VISU::View3D_ptr theView3D):
2042     myStudyName(theStudyName),
2043     myView3D(VISU::View3D::_duplicate(theView3D)),
2044     myResult(NULL)
2045   {}
2046
2047   virtual
2048   void
2049   Execute()
2050   {
2051     SUIT_Session* aSession = SUIT_Session::session();
2052     QList<SUIT_Application*> anApplications = aSession->applications();
2053     QList<SUIT_Application*>::Iterator anIter = anApplications.begin();
2054     while ( anIter !=  anApplications.end() ) {
2055       SUIT_Application* anApp = *anIter;
2056       if (SUIT_Study* aSStudy = anApp->activeStudy()) {
2057         if (SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(aSStudy)) {
2058           if (_PTR(Study) aCStudy = aStudy->studyDS()) {
2059             if (myStudyName == aCStudy->Name()) {
2060               myResult = new VISU_TimeAnimation (aCStudy, myView3D);
2061               break;
2062             }
2063           }
2064         }
2065       }
2066       anIter++;
2067     }
2068   }
2069 };
2070
2071 VISU_TimeAnimation_i::VISU_TimeAnimation_i (SALOMEDS::Study_ptr theStudy,
2072                                             VISU::View3D_ptr theView3D)
2073 {
2074   std::string aStudyName = theStudy->Name();
2075   myAnim = ProcessEvent(new TNewAnimationEvent (aStudyName, theView3D));
2076 }
2077
2078 VISU_TimeAnimation_i::~VISU_TimeAnimation_i()
2079 {
2080   delete myAnim;
2081 }
2082
2083 bool VISU_TimeAnimation_i::addField (SALOMEDS::SObject_ptr theField)
2084 {
2085   return myAnim->addField(theField);
2086 }
2087
2088 void VISU_TimeAnimation_i::clearFields ()
2089 {
2090   for (int i = 0; i < myAnim->getNbFields(); i++) {
2091     myAnim->clearData(myAnim->getFieldData(i));
2092   }
2093   myAnim->clearFieldData();
2094 }
2095
2096 CORBA::Boolean VISU_TimeAnimation_i::generateFrames()
2097 {
2098   //return ProcessEvent(new TMemFunEvent<VISU_TimeAnimation,bool>
2099   //                    (myAnim,&VISU_TimeAnimation::generateFrames));
2100   return myAnim->generateFrames();
2101 }
2102
2103 void VISU_TimeAnimation_i::generatePresentations (CORBA::Long theFieldNum)
2104 {
2105   myAnim->generatePresentations(theFieldNum);
2106 }
2107
2108 void VISU_TimeAnimation_i::clearView()
2109 {
2110   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2111   //                 (myAnim,&VISU_TimeAnimation::clearView));
2112   myAnim->clearView();
2113 }
2114
2115 void VISU_TimeAnimation_i::stopAnimation()
2116 {
2117   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2118   //                 (myAnim,&VISU_TimeAnimation::stopAnimation));
2119   myAnim->stopAnimation();
2120 }
2121
2122 void VISU_TimeAnimation_i::startAnimation()
2123 {
2124   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2125   //                 (myAnim,&VISU_TimeAnimation::startAnimation));
2126   myAnim->startAnimation();
2127 }
2128
2129 void VISU_TimeAnimation_i::nextFrame()
2130 {
2131   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2132   //                 (myAnim,&VISU_TimeAnimation::nextFrame));
2133   myAnim->nextFrame();
2134 }
2135
2136 void VISU_TimeAnimation_i::prevFrame()
2137 {
2138   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2139   //                 (myAnim,&VISU_TimeAnimation::prevFrame));
2140   myAnim->prevFrame();
2141 }
2142
2143 void VISU_TimeAnimation_i::firstFrame()
2144 {
2145   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2146   //                 (myAnim,&VISU_TimeAnimation::firstFrame));
2147   myAnim->firstFrame();
2148 }
2149
2150 void VISU_TimeAnimation_i::lastFrame()
2151 {
2152   //ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
2153   //                 (myAnim,&VISU_TimeAnimation::lastFrame));
2154   myAnim->lastFrame();
2155 }
2156
2157 void VISU_TimeAnimation_i::gotoFrame(CORBA::Long theFrame)
2158 {
2159   //ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_TimeAnimation,CORBA::Long>
2160   //                 (myAnim,&VISU_TimeAnimation::gotoFrame,theFrame));
2161   myAnim->gotoFrame(theFrame);
2162 }
2163
2164 CORBA::Long VISU_TimeAnimation_i::getNbFields()
2165 {
2166   return myAnim->getNbFields();
2167 }
2168
2169 CORBA::Long VISU_TimeAnimation_i::getNbFrames()
2170 {
2171   return myAnim->getNbFrames();
2172 }
2173
2174 CORBA::Boolean VISU_TimeAnimation_i::isRunning()
2175 {
2176   return myAnim->isRunning();
2177 }
2178
2179 CORBA::Long VISU_TimeAnimation_i::getCurrentFrame()
2180 {
2181   return myAnim->getCurrentFrame();
2182 }
2183
2184 VISU::ColoredPrs3d_ptr VISU_TimeAnimation_i::getPresentation
2185                     (CORBA::Long theField, CORBA::Long theFrame)
2186 {
2187   return myAnim->getPresentation(theField,theFrame);
2188 }
2189
2190 void VISU_TimeAnimation_i::setPresentationType (CORBA::Long theFieldNum,
2191                                                 VISU::VISUType theType)
2192 {
2193   myAnim->setPresentationType(theFieldNum,theType);
2194 }
2195
2196 VISU::VISUType VISU_TimeAnimation_i::getPresentationType (CORBA::Long theFieldNum)
2197 {
2198   return myAnim->getPresentationType(theFieldNum);
2199 }
2200
2201 void VISU_TimeAnimation_i::setSpeed(CORBA::Long theSpeed)
2202 {
2203   myAnim->setSpeed(theSpeed);
2204 }
2205
2206 CORBA::Long VISU_TimeAnimation_i::getSpeed()
2207 {
2208   return myAnim->getSpeed();
2209 }
2210
2211 CORBA::Boolean VISU_TimeAnimation_i::isProportional()
2212 {
2213   return myAnim->isProportional();
2214 }
2215
2216 void VISU_TimeAnimation_i::setAnimationRange (CORBA::Double theMin,
2217                                               CORBA::Double theMax)
2218 {
2219   myAnim->setAnimationRange(theMin,theMax);
2220 }
2221
2222 CORBA::Double VISU_TimeAnimation_i::getMinRange()
2223 {
2224   return myAnim->getMinRange();
2225 }
2226
2227 CORBA::Double VISU_TimeAnimation_i::getMaxRange()
2228 {
2229   return myAnim->getMaxRange();
2230 }
2231
2232 CORBA::Boolean VISU_TimeAnimation_i::isRangeDefined()
2233 {
2234   return myAnim->isRangeDefined();
2235 }
2236
2237 void VISU_TimeAnimation_i::setAnimationSequence (const char* theSequence)
2238 {
2239   myAnim->setAnimationSequence(theSequence);
2240 }
2241
2242 char* VISU_TimeAnimation_i::getAnimationSequence()
2243 {
2244   return myAnim->getAnimationSequence();
2245 }
2246
2247 CORBA::Boolean VISU_TimeAnimation_i::isSequenceDefined()
2248 {
2249   return myAnim->isSequenceDefined();
2250 }
2251
2252 void VISU_TimeAnimation_i::dumpTo (const char* thePath)
2253 {
2254   myAnim->dumpTo(thePath);
2255 }
2256
2257 char* VISU_TimeAnimation_i::setDumpFormat (const char* theFormat)
2258 {
2259   string aDumpFormat = myAnim->setDumpFormat(theFormat);
2260   return CORBA::string_dup(aDumpFormat.c_str());
2261 }
2262
2263 CORBA::Boolean VISU_TimeAnimation_i::isCycling()
2264 {
2265   return myAnim->isCycling();
2266 }
2267
2268 CORBA::Boolean VISU_TimeAnimation_i::isCleaningMemoryAtEachFrame(){
2269   return myAnim->isCleaningMemoryAtEachFrame();
2270 }
2271
2272 CORBA::Double VISU_TimeAnimation_i::getMinTime()
2273 {
2274   return myAnim->getMinTime();
2275 }
2276
2277 CORBA::Double VISU_TimeAnimation_i::getMaxTime()
2278 {
2279   return myAnim->getMaxTime();
2280 }
2281
2282 void VISU_TimeAnimation_i::setProportional (CORBA::Boolean theProp)
2283 {
2284   myAnim->setProportional(theProp);
2285 }
2286
2287 void VISU_TimeAnimation_i::setCycling (CORBA::Boolean theCycle)
2288 {
2289   myAnim->setCycling(theCycle);
2290 }
2291
2292 void VISU_TimeAnimation_i::setCleaningMemoryAtEachFrame(CORBA::Boolean theCycle){
2293   myAnim->setCleaningMemoryAtEachFrame(theCycle);
2294 }
2295
2296 SALOMEDS::SObject_ptr VISU_TimeAnimation_i::publishInStudy()
2297 {
2298   return myAnim->publishInStudy();
2299 }
2300
2301 void VISU_TimeAnimation_i::restoreFromStudy(SALOMEDS::SObject_ptr theObj)
2302 {
2303   myAnim->restoreFromStudy(theObj);
2304 }
2305
2306 CORBA::Boolean VISU_TimeAnimation_i::isSavedInStudy()
2307 {
2308   return myAnim->isSavedInStudy();
2309 }
2310
2311 void VISU_TimeAnimation_i::saveAnimation()
2312 {
2313   myAnim->saveAnimation();
2314 }
2315
2316 void VISU_TimeAnimation_i::setAnimationMode(VISU::Animation::AnimationMode theMode)
2317 {
2318   myAnim->setAnimationMode(theMode);
2319 }
2320
2321 VISU::Animation::AnimationMode VISU_TimeAnimation_i::getAnimationMode()
2322 {
2323   return VISU::Animation::AnimationMode(myAnim->getAnimationMode());
2324 }
2325
2326 void VISU_TimeAnimation_i::ApplyProperties(CORBA::Long theFieldNum, VISU::ColoredPrs3d_ptr thePrs)
2327   throw (SALOME::SALOME_Exception)
2328 {
2329   myAnim->ApplyProperties(theFieldNum, thePrs);
2330 }