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