]> SALOME platform Git repositories - modules/visu.git/blob - src/VISU_I/VISU_TimeAnimation.cxx
Salome HOME
Fix for Bug IPAL11495
[modules/visu.git] / src / VISU_I / VISU_TimeAnimation.cxx
1 //  Copyright (C) 2003  CEA/DEN, EDF R&D
2 //
3 //
4 //
5 //  File   : VISU_TimeAnimation.cxx
6 //  Author : Vitaly SMETANNIKOV
7 //  Module : VISU
8
9 #include "VISU_TimeAnimation.h"
10
11 #include "VISUConfig.hh"
12
13 #include "VISU_Result_i.hh"
14 #include "VISU_Prs3d_i.hh"
15 #include "VISU_Mesh_i.hh"
16 #include "VISU_ScalarMap_i.hh"
17 #include "VISU_IsoSurfaces_i.hh"
18 #include "VISU_DeformedShape_i.hh"
19 #include "VISU_ScalarMapOnDeformedShape_i.hh"
20 #include "VISU_CutPlanes_i.hh"
21 #include "VISU_Plot3D_i.hh"
22 #include "VISU_CutLines_i.hh"
23 #include "VISU_Vectors_i.hh"
24 #include "VISU_StreamLines_i.hh"
25 #include "VISU_GaussPoints_i.hh"
26 #include "VISU_ViewManager_i.hh"
27 #include "VISU_View_i.hh"
28
29 #include "VISU_ScalarBarActor.hxx"
30 #include "VISU_Actor.h"
31
32 #include "SalomeApp_Study.h"
33
34 #include "SVTK_ViewWindow.h"
35
36 #include "SALOME_Event.hxx"
37
38 #include "SUIT_ResourceMgr.h"
39 #include "SUIT_Application.h"
40 #include "SUIT_Session.h"
41 #include "SUIT_Study.h"
42
43 #include "SALOMEDSClient_AttributeComment.hxx"
44 #include "SALOMEDSClient_AttributeName.hxx"
45
46 #include <qpixmap.h>
47 #include <qimage.h>
48 #include <qstrlist.h>
49
50 using namespace std;
51
52
53 //------------------------------------------------------------------------
54 VISU_TimeAnimation::VISU_TimeAnimation (_PTR(Study) theStudy,
55                                         VISU::View3D_ptr theView3D)
56 {
57   myStudy = theStudy;
58   myIsActive = false;
59   myFrame = 0;
60   mySpeed = 1;
61   myProportional = false;
62   myView = 0;
63
64   if (!CORBA::is_nil(theView3D)) {
65     VISU::View3D_i* pView = dynamic_cast<VISU::View3D_i*>(GetServant(theView3D).in());
66     SUIT_ViewWindow* aVW = pView->GetViewWindow();
67     myView = VISU::GetViewWindow(aVW);
68     connect( myView, SIGNAL( destroyed() ), this, SLOT( onViewDeleted() ) );
69   }
70
71   myMaxVal = 0;
72   myMinVal = 0;
73   myTimeMin = 0;
74   myTimeMax = 0;
75   myLastError = "";
76   myCycling = false;
77
78   myAnimEntry = "";
79 }
80
81
82 //------------------------------------------------------------------------
83 VISU_TimeAnimation::~VISU_TimeAnimation()
84 {
85   if (!myView) {
86     MESSAGE("Viewer is not defined for animation");
87     return;
88   }
89
90   for (int i = 0; i < getNbFields(); i++) {
91     clearData(myFieldsLst[i]);
92   }
93 }
94
95
96 //------------------------------------------------------------------------
97 void VISU_TimeAnimation::addField (_PTR(SObject) theField)
98 {
99   FieldData aNewData;
100   aNewData.myField = theField;
101   aNewData.myNbFrames = 0;
102   aNewData.myPrsType = VISU::TSCALARMAP;
103   aNewData.myOffset[0] = aNewData.myOffset[1] = aNewData.myOffset[2] = 0;
104   VISU::Storable::TRestoringMap aMap = getMapOfValue(aNewData.myField);
105   aNewData.myNbTimes = VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
106   myFieldsLst.append(aNewData);
107
108   //find Min/Max timestamps
109   if ((myTimeMin == 0) && (myTimeMax == 0)) {
110     _PTR(ChildIterator) anIter = myStudy->NewChildIterator(theField);
111     anIter->Next(); // First is reference on support
112     myTimeMin = getTimeValue(anIter->Value());
113     for(; anIter->More(); anIter->Next()) {
114       myTimeMax = getTimeValue(anIter->Value());
115     }
116   }
117 }
118
119 //------------------------------------------------------------------------
120 void VISU_TimeAnimation::addField (SALOMEDS::SObject_ptr theField)
121 {
122   SALOMEDS::SObject_var theFieldDup = SALOMEDS::SObject::_duplicate(theField);
123   _PTR(SObject) aField = VISU::GetClientSObject(theFieldDup, myStudy);
124   addField(aField);
125 }
126
127
128 //------------------------------------------------------------------------
129 void VISU_TimeAnimation::clearData(FieldData& theData) {
130   if (!myView) {
131     MESSAGE("Viewer is not defined for animation");
132     return;
133   }
134   theData.myTiming.clear();
135   vtkRenderer* aRen = myView->getRenderer();
136   if (!theData.myActors.empty()) {
137     for (int i = 0, iEnd = theData.myActors.size(); i < iEnd; i++) {
138       if (theData.myActors[i] != 0) {
139         theData.myActors[i]->RemoveFromRender(aRen);
140       }
141     }
142     theData.myActors.clear();
143   }
144   if (!theData.myPrs.empty()) {
145     for (int i = 0, iEnd = theData.myPrs.size(); i < iEnd; i++)
146       if (theData.myPrs[i] != 0) {
147         theData.myPrs[i]->_remove_ref();
148       }
149     theData.myPrs.clear();
150   }
151   theData.myNbFrames = 0;
152   myView->update();
153 }
154
155
156 namespace
157 {
158   //------------------------------------------------------------------------
159   template<class TPrs3d>
160   void
161   GeneratePresentations(_PTR(Study) theStudy,
162                         FieldData& theData,
163                         VISU::Result_i* theResult,
164                         bool theIsRangeDefined,
165                         CORBA::Double& theMinVal,
166                         CORBA::Double& theMaxVal,
167                         CORBA::Double theTimeMin,
168                         CORBA::Double theTimeMax)
169   {
170     theMinVal = VTK_LARGE_FLOAT;
171     theMaxVal = -VTK_LARGE_FLOAT;
172
173     _PTR(ChildIterator) anIter = theStudy->NewChildIterator(theData.myField);
174     anIter->Next(); // First is reference on support
175
176     long aFrameId = 0;
177     for(; anIter->More(); anIter->Next()){
178       if (aFrameId == theData.myNbTimes) {
179         MESSAGE("There are extra timestamps in field");
180         return;
181       }
182       _PTR(SObject) aTimeStamp = anIter->Value();
183       if(!aTimeStamp) 
184         continue;
185
186       theData.myTiming[aFrameId] = VISU_TimeAnimation::getTimeValue(aTimeStamp);
187       if (theIsRangeDefined) {
188         if (theData.myTiming[aFrameId] < theTimeMin) 
189           continue;
190         if (theData.myTiming[aFrameId] > theTimeMax) 
191           break;
192       }
193
194       VISU::Storable::TRestoringMap aTimeMap = VISU_TimeAnimation::getMapOfValue(aTimeStamp);
195       QString aMeshName = VISU::Storable::FindValue(aTimeMap,"myMeshName");
196       VISU::Entity anEntity = (VISU::Entity) VISU::Storable::FindValue(aTimeMap,"myEntityId").toInt();
197       QString aFieldName = VISU::Storable::FindValue(aTimeMap,"myFieldName");
198       int aTimeStampId = VISU::Storable::FindValue(aTimeMap,"myTimeStampId").toInt();
199       
200       TPrs3d* aPresent = new TPrs3d(theResult, false);
201       aPresent->Create(aMeshName.latin1(), anEntity,
202                        aFieldName.latin1(), aTimeStampId);
203       theData.myPrs[aFrameId++] = aPresent;
204
205       theMinVal = std::min(aPresent->GetMin(),theMinVal);
206       theMaxVal = std::max(aPresent->GetMax(),theMaxVal);
207     }
208     theData.myNbFrames = aFrameId;
209
210     if (theData.myPrsType != VISU::TGAUSSPOINTS){
211       int aRangeType = VISU::GetResourceMgr()->integerValue("VISU" , "scalar_range_type", 0);
212       if( aRangeType != 1 ){
213         for(long aFrameId = 0; aFrameId < theData.myNbFrames; aFrameId++) {
214           if (VISU::ScalarMap_i* aPrs = dynamic_cast<VISU::ScalarMap_i*>(theData.myPrs[aFrameId])){
215             aPrs->SetRange(theMinVal, theMaxVal);
216             aPrs->SetOffset(theData.myOffset);
217           }
218         }
219       }
220       if (theData.myPrsType == VISU::TISOSURFACE)
221         for (long aFrameId = 0; aFrameId < theData.myNbFrames; aFrameId++)
222           if (VISU::IsoSurfaces_i* aPrs = dynamic_cast<VISU::IsoSurfaces_i*>(theData.myPrs[aFrameId]))
223             aPrs->SetSubRange(theMinVal, theMaxVal);
224     }
225   }
226 }
227   
228 void VISU_TimeAnimation::generatePresentations(CORBA::Long theFieldNum) {
229   FieldData& aData = myFieldsLst[theFieldNum];
230
231   // Delete previous presentations
232   clearData(aData);
233
234   VISU::Result_i* aResult = createPresent(aData.myField);
235   VISU::Storable::TRestoringMap aMap = getMapOfValue(aData.myField);
236   aData.myNbFrames = aData.myNbTimes;
237   //VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
238
239   aData.myPrs.resize(aData.myNbTimes,NULL);
240   aData.myTiming.resize(aData.myNbTimes);
241
242   using namespace VISU;
243   switch (aData.myPrsType) {
244   case VISU::TSCALARMAP: // ScalarMap
245     GeneratePresentations<ScalarMap_i>(myStudy,
246                                        aData,
247                                        aResult,
248                                        isRangeDefined(),
249                                        myMinVal,
250                                        myMaxVal,
251                                        myTimeMin,
252                                        myTimeMax);
253     break;
254   case VISU::TISOSURFACE: // Iso Surfaces
255     GeneratePresentations<IsoSurfaces_i>(myStudy,
256                                          aData,
257                                          aResult,
258                                          isRangeDefined(),
259                                          myMinVal,
260                                          myMaxVal,
261                                          myTimeMin,
262                                          myTimeMax);
263     break;
264   case VISU::TCUTPLANES: // Cut Planes
265     GeneratePresentations<CutPlanes_i>(myStudy,
266                                        aData,
267                                        aResult,
268                                        isRangeDefined(),
269                                        myMinVal,
270                                        myMaxVal,
271                                        myTimeMin,
272                                        myTimeMax);
273     break;
274   case VISU::TPLOT3D: // Plot3d
275     GeneratePresentations<Plot3D_i>(myStudy,
276                                     aData,
277                                     aResult,
278                                     isRangeDefined(),
279                                     myMinVal,
280                                     myMaxVal,
281                                     myTimeMin,
282                                     myTimeMax);
283     break;
284   case VISU::TDEFORMEDSHAPE: // Deformed Shape
285     GeneratePresentations<DeformedShape_i>(myStudy,
286                                            aData,
287                                            aResult,
288                                            isRangeDefined(),
289                                            myMinVal,
290                                            myMaxVal,
291                                            myTimeMin,
292                                            myTimeMax);
293     break;
294   case VISU::TVECTORS: // Vectors
295     GeneratePresentations<Vectors_i>(myStudy,
296                                      aData,
297                                      aResult,
298                                      isRangeDefined(),
299                                      myMinVal,
300                                      myMaxVal,
301                                      myTimeMin,
302                                      myTimeMax);
303     break;
304   case VISU::TSTREAMLINES: // Stream Lines
305     GeneratePresentations<StreamLines_i>(myStudy,
306                                          aData,
307                                          aResult,
308                                          isRangeDefined(),
309                                          myMinVal,
310                                          myMaxVal,
311                                          myTimeMin,
312                                          myTimeMax);
313     break;
314   case VISU::TGAUSSPOINTS: // Gauss Points
315     GeneratePresentations<GaussPoints_i>(myStudy,
316                                          aData,
317                                          aResult,
318                                          isRangeDefined(),
319                                          myMinVal,
320                                          myMaxVal,
321                                          myTimeMin,
322                                          myTimeMax);
323     break;
324   case VISU::TSCALARMAPONDEFORMEDSHAPE: // Scalar map on deformed shape
325     GeneratePresentations<ScalarMapOnDeformedShape_i>(myStudy,
326                                                       aData,
327                                                       aResult,
328                                                       isRangeDefined(),
329                                                       myMinVal,
330                                                       myMaxVal,
331                                                       myTimeMin,
332                                                       myTimeMax);
333     break;
334   default:
335     MESSAGE("Not implemented for this presentation type: " << aData.myPrsType);
336     return;
337   }
338 }
339
340
341 //------------------------------------------------------------------------
342 CORBA::Boolean VISU_TimeAnimation::generateFrames() {
343   if (!myView) {
344     MESSAGE("Viewer is not defined for animation");
345     return false;
346   }
347
348   myLastError = QString("Frame(s) for ");
349   bool aNoError = true;
350
351   clearView();
352
353   for (int i = 0; i < getNbFields(); i++) {
354     FieldData& aData = myFieldsLst[i];
355     aData.myActors.resize(aData.myNbFrames,NULL);
356     for (long j = 0; j < aData.myNbFrames; j++) {
357       VISU_Actor* aActor = NULL;
358       try{
359         aData.myPrs[j]->SetOffset(aData.myOffset);
360         aActor = aData.myPrs[j]->CreateActor();
361         myView->AddActor(aActor);
362         if(j == 0)
363           aActor->VisibilityOn();
364         else
365           aActor->VisibilityOff();
366       }catch(...){ //catch(std::runtime_error& exc){
367         aNoError = false;
368         myLastError += QString("%1 ").arg(aData.myTiming[j]);
369       }
370       aData.myActors[j] = aActor;
371     }
372   }
373   myFrame = 0;
374   myLastError += QString(" timestamp(s) cannot be created.");
375   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
376   myView->Repaint();
377   return aNoError;
378 }
379
380 //------------------------------------------------------------------------
381 void VISU_TimeAnimation::clearView() {
382   if (!myView) {
383     MESSAGE("Viewer is not defined for animation");
384     return;
385   }
386   vtkRenderer* aRen = myView->getRenderer();
387   for (int i = 0; i < getNbFields(); i++) {
388     FieldData& aData = myFieldsLst[i];
389     if (!aData.myActors.empty()) {
390       for (int i = 0, iEnd = aData.myActors.size(); i < iEnd; i++) {
391         if (aData.myActors[i] != 0) {
392           aData.myActors[i]->RemoveFromRender(aRen);
393         }
394       }
395       aData.myActors.clear();
396     }
397   }
398   VISU::RepaintView(myView);
399 }
400
401 //------------------------------------------------------------------------
402 void VISU_TimeAnimation::stopAnimation() {
403   myIsActive = false;
404 }
405
406 //------------------------------------------------------------------------
407 void VISU_TimeAnimation::startAnimation() {
408   if (!myIsActive) {
409     myIsActive = true;
410     QThread::start();
411   }
412 }
413
414 //------------------------------------------------------------------------
415 void VISU_TimeAnimation::nextFrame() {
416   if (!myView) {
417     MESSAGE("Viewer is not defined for animation");
418     return;
419   }
420   stopAnimation();
421   if (myFrame < (myFieldsLst[0].myNbFrames-1)) {
422     int i;
423     for (i = 0; i < getNbFields(); i++)
424       if (myFieldsLst[i].myActors[myFrame] != 0)
425         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
426
427     myFrame++;
428     for (i = 0; i < getNbFields(); i++)
429       if (myFieldsLst[i].myActors[myFrame] != 0)
430         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
431
432     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
433     myView->Repaint();
434   }
435 }
436
437 //------------------------------------------------------------------------
438 void VISU_TimeAnimation::prevFrame() {
439   if (!myView) {
440     MESSAGE("Viewer is not defined for animation");
441     return;
442   }
443   stopAnimation();
444   if (myFrame > 0) {
445     int i;
446     for (i = 0; i < getNbFields(); i++)
447       if (myFieldsLst[i].myActors[myFrame] != 0)
448         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
449
450     myFrame--;
451     for (i = 0; i < getNbFields(); i++)
452       if (myFieldsLst[i].myActors[myFrame] != 0)
453         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
454
455     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
456     myView->Repaint();
457   }
458 }
459
460 //------------------------------------------------------------------------
461 void VISU_TimeAnimation::firstFrame() {
462   if (!myView) {
463     MESSAGE("Viewer is not defined for animation");
464     return;
465   }
466   stopAnimation();
467   int i;
468   for (i = 0; i < getNbFields(); i++)
469     if(!myFieldsLst[i].myActors.empty())
470       if (myFieldsLst[i].myActors[myFrame] != 0)
471         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
472   myFrame = 0;
473   for (i = 0; i < getNbFields(); i++)
474     if(!myFieldsLst[i].myActors.empty())
475       if (myFieldsLst[i].myActors[myFrame] != 0)
476         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
477   if(!myFieldsLst[0].myTiming.empty()){
478     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
479     myView->Repaint();
480   }
481 }
482
483 //------------------------------------------------------------------------
484 void VISU_TimeAnimation::lastFrame() {
485   if (!myView) {
486     MESSAGE("Viewer is not defined for animation");
487     return;
488   }
489   stopAnimation();
490   int i;
491   for (i = 0; i < getNbFields(); i++)
492    if (myFieldsLst[i].myActors[myFrame] != 0)
493       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
494
495   myFrame = myFieldsLst[0].myNbFrames-1;
496   for (i = 0; i < getNbFields(); i++)
497     if (myFieldsLst[i].myActors[myFrame] != 0)
498       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
499
500   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
501   myView->Repaint();
502 }
503
504
505 //------------------------------------------------------------------------
506 // For Batchmode using
507 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame) {
508   if (!myView) {
509     MESSAGE("Viewer is not defined for animation");
510     return;
511   }
512   if ((theFrame < 0) || (theFrame > (getNbFrames()-1)))
513     return;
514   stopAnimation();
515   qApp->lock();
516   qApp->syncX();
517   int i;
518   for (i = 0; i < getNbFields(); i++)
519     if (myFieldsLst[i].myActors[myFrame] != 0)
520       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
521
522   myFrame = theFrame;
523   for (i = 0; i < getNbFields(); i++)
524     if (myFieldsLst[i].myActors[myFrame] != 0)
525       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
526
527   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
528   myView->Repaint();
529   qApp->flushX();
530   qApp->processEvents(3);
531   qApp->unlock();
532 }
533
534
535 //------------------------------------------------------------------------
536 VISU::ColoredPrs3d_ptr VISU_TimeAnimation::getPresentation(CORBA::Long theField, CORBA::Long theFrame) {
537   if ((theField > getNbFields()) || (theField < 0))
538     return VISU::ColoredPrs3d::_nil();
539   if ((theFrame < 0) || (theFrame > (myFieldsLst[theField].myNbFrames - 1)))
540     return VISU::ColoredPrs3d::_nil();
541   return myFieldsLst[theField].myPrs[theFrame]->_this();
542 }
543
544
545 //------------------------------------------------------------------------
546 CORBA::Long VISU_TimeAnimation::getNbFrames() {
547   return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
548 }
549
550
551 //------------------------------------------------------------------------
552 void VISU_TimeAnimation::run()
553 {
554   if (!myView) {
555     MESSAGE("Viewer is not defined for animation");
556     return;
557   }
558   double k = 1;
559   bool   isDumping = !myDumpPath.isEmpty();
560   double aOneVal = 1;
561   if (myFieldsLst[0].myNbFrames > 2)
562     aOneVal = myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0];
563   qApp->lock();
564   while (myIsActive) {
565     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
566     for (int i = 0; i < getNbFields(); i++) {
567       FieldData& aData = myFieldsLst[i];
568       if (myFrame > 0) {
569         if (aData.myActors[myFrame-1] != 0)
570           aData.myActors[myFrame-1]->VisibilityOff();
571       } else {
572         if (aData.myActors[aData.myNbFrames-1] != 0)
573           aData.myActors[aData.myNbFrames-1]->VisibilityOff();
574       }
575       if (aData.myActors[myFrame] != 0) {
576         aData.myActors[myFrame]->VisibilityOn();
577       }
578     }
579     myView->Repaint(false);
580
581     k = 1;
582     if (myProportional) {
583       switch (myFrame) {
584       case 0:
585         break;
586       case 1:
587         if (myFieldsLst[0].myNbFrames > 2)
588           k = (myFieldsLst[0].myTiming[myFrame+1] -
589                myFieldsLst[0].myTiming[myFrame]) / aOneVal;
590         break;
591       default:
592         if (myFrame < (myFieldsLst[0].myNbFrames - 1))
593           k = (myFieldsLst[0].myTiming[myFrame+1] -
594                myFieldsLst[0].myTiming[myFrame]) / aOneVal;
595       }
596     }
597     int delay = (int)(1000. * k / mySpeed);
598     if (delay < 1 && isDumping) {
599       // We must unlock mutex for some time before grabbing to allow view updating
600       delay = 1;
601     }
602     qApp->unlock();
603     msleep(delay);
604     qApp->lock();
605
606     if (isDumping) {
607       // We must unlock mutex for some time before grabbing to allow view updating
608       qApp->unlock();
609       msleep(100);
610       qApp->lock();
611
612       QPixmap px = QPixmap::grabWindow(myView->winId());
613       QString aFile(myDumpPath);
614       QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
615       int aPos = -1;
616       while ((aPos = aName.find(".")) > -1 )
617         aName.replace(aPos, 1, "_");
618       aFile += aName;
619       aFile += ".";
620       aFile += myDumpFormat.lower();
621       px.save(aFile, myDumpFormat);
622     }
623
624     if (!myIsActive) break;
625
626     myFrame++;
627     if (myFrame == myFieldsLst[0].myNbFrames) {
628       if (!myCycling) {
629         myIsActive = false;
630         myFrame--;
631         break;
632       } else
633         myFrame = 0;
634     }
635   }
636   emit stopped();
637   qApp->unlock();
638   QThread::exit();
639 }
640
641 //------------------------------------------------------------------------
642 VISU::Result_i* VISU_TimeAnimation::createPresent (_PTR(SObject) theField)
643 {
644   _PTR(SObject) aSObj = theField->GetFather();
645   aSObj = aSObj->GetFather();
646   aSObj = aSObj->GetFather();
647   CORBA::Object_var anObject = VISU::ClientSObjectToObject(aSObj);
648   if (CORBA::is_nil(anObject)) return NULL;
649   return dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject).in());
650 }
651
652 //------------------------------------------------------------------------
653 VISU::Storable::TRestoringMap VISU_TimeAnimation::getMapOfValue (_PTR(SObject) theSObject)
654 {
655   VISU::Storable::TRestoringMap aMap;
656   if (theSObject) {
657     _PTR(GenericAttribute) anAttr;
658     if (theSObject->FindAttribute(anAttr, "AttributeComment")) {
659       _PTR(AttributeComment) aComment (anAttr);
660       std::string aString = aComment->Value();
661       QString strIn (aString.c_str());
662       VISU::Storable::StrToMap(strIn, aMap);
663     }
664   }
665   return aMap;
666 }
667
668 //------------------------------------------------------------------------
669 double VISU_TimeAnimation::getTimeValue (_PTR(SObject) theTimeStamp)
670 {
671   _PTR(GenericAttribute) anAttr;
672   if (theTimeStamp->FindAttribute(anAttr, "AttributeName")) {
673     _PTR(AttributeName) aName (anAttr);
674     QString aNameString (aName->Value().c_str());
675     int time_len = aNameString.find(',');
676     if (time_len > -1)
677       return aNameString.left(time_len).toDouble();
678     else
679       return aNameString.toDouble();
680   }
681   return -1.0;
682 }
683
684 //------------------------------------------------------------------------
685 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed)
686 {
687   mySpeed = (theSpeed<1)? 1 : theSpeed;
688 }
689
690 std::string VISU_TimeAnimation::setDumpFormat(const char* theFormat)
691 {
692   myDumpFormat = theFormat;
693   QStrList aDumpFormats = QImageIO::outputFormats();
694   if (myDumpFormat.isEmpty() || aDumpFormats.find(theFormat) < 0) {
695     if (aDumpFormats.find("JPEG"))
696       myDumpFormat = "JPEG";
697     else
698       myDumpFormat = aDumpFormats.at(0);
699   }
700   return myDumpFormat.latin1();
701 }
702
703 //************************************************************************
704 int VISU_TimeAnimation::myNBAnimations = 0;
705 QString VISU_TimeAnimation::GenerateName()
706 {
707   return VISU::GenerateName("Animation", myNBAnimations++);
708 }
709
710 //------------------------------------------------------------------------
711 std::string GetPresentationComment (VISU::VISUType thePrsType)
712 {
713   std::string aPrsCmt;
714   switch (thePrsType) {
715   case VISU::TSCALARMAP:
716     aPrsCmt = VISU::ScalarMap_i::myComment;
717     break;
718   case VISU::TISOSURFACE:
719     aPrsCmt = VISU::IsoSurfaces_i::myComment;
720     break;
721   case VISU::TCUTPLANES:
722     aPrsCmt = VISU::CutPlanes_i::myComment;
723     break;
724   case VISU::TPLOT3D:
725     aPrsCmt = VISU::Plot3D_i::myComment;
726     break;
727   case VISU::TDEFORMEDSHAPE:
728     aPrsCmt = VISU::DeformedShape_i::myComment;
729     break;
730   case VISU::TVECTORS:
731     aPrsCmt = VISU::Vectors_i::myComment;
732     break;
733   case VISU::TSTREAMLINES:
734     aPrsCmt = VISU::StreamLines_i::myComment;
735     break;
736   case VISU::TGAUSSPOINTS:
737     aPrsCmt = VISU::GaussPoints_i::myComment;
738     break;
739   case VISU::TSCALARMAPONDEFORMEDSHAPE:
740     aPrsCmt = VISU::ScalarMapOnDeformedShape_i::myComment;
741     break;
742   default:
743     aPrsCmt = "Unknown presentation";
744     break;
745   }
746   return aPrsCmt;
747 }
748
749 //------------------------------------------------------------------------
750 SALOMEDS::SObject_ptr VISU_TimeAnimation::publishInStudy()
751 {
752   if (myStudy->GetProperties()->IsLocked())
753     return SALOMEDS::SObject::_nil();
754
755   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
756   aStudyBuilder->NewCommand();  // There is a transaction
757   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
758   std::string aSComponentEntry = aSComponent->GetID();
759
760   QString aComment;
761   aComment.sprintf("myComment=ANIMATION;myType=%d;myMinVal=%g;myMaxVal=%g",
762                    VISU::TANIMATION,myMinVal,myMaxVal);
763
764   string anEntry = VISU::CreateAttributes(myStudy,aSComponentEntry.c_str(),"","",
765                                           GenerateName(),"",aComment,true);
766   myAnimEntry = anEntry.c_str();
767   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(anEntry.c_str());
768
769   for (int i = 0; i < getNbFields(); i++) {
770     FieldData& aData = myFieldsLst[i];
771
772     _PTR(SObject) newObj = aStudyBuilder->NewObject(aAnimSObject);
773     aStudyBuilder->Addreference(newObj, aData.myField);
774
775     if (aData.myPrs.empty()) {
776       generatePresentations(i);
777     }
778     ostringstream strOut;
779     aData.myPrs[0]->ToStream(strOut);
780     string aPrsComment = strOut.str();
781     VISU::CreateAttributes(myStudy, newObj->GetID().c_str(),"","",
782                            aData.myPrs[0]->GetComment(),"",aPrsComment.c_str(),true);
783   }
784   aStudyBuilder->CommitCommand();
785
786   return VISU::GetSObject(aAnimSObject);
787 }
788
789 //------------------------------------------------------------------------
790 void VISU_TimeAnimation::saveAnimation()
791 {
792   if (myStudy->GetProperties()->IsLocked()) return;
793   if (myAnimEntry.isEmpty()) return;
794
795   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(myAnimEntry.latin1());
796   if (!aAnimSObject) return;
797
798   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
799   aStudyBuilder->NewCommand();  // There is a transaction
800   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
801   std::string aSComponentEntry = aSComponent->GetID();
802
803   QString aComment;
804   aComment.sprintf("myComment=ANIMATION;myType=%d;myMinVal=%g;myMaxVal=%g",
805                    VISU::TANIMATION,myMinVal,myMaxVal);
806
807   _PTR(GenericAttribute) anAttr;
808   anAttr = aStudyBuilder->FindOrCreateAttribute(aAnimSObject, "AttributeComment");
809   _PTR(AttributeComment) aCmnt (anAttr);
810   aCmnt->SetValue(aComment.latin1());
811
812   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
813   int i = 0, nbf = getNbFields();
814   for (anIter->Init(); anIter->More(); anIter->Next(), i++) {
815     if (i >= nbf) break; // it must not be
816     FieldData& aData = myFieldsLst[i];
817
818     // Get presentation name and comment
819     if (aData.myPrs.empty()) {
820       generatePresentations(i);
821     }
822     ostringstream strOut;
823     aData.myPrs[0]->ToStream(strOut);
824     string aPrsComment = strOut.str();
825     string aPrsNameTxt = aData.myPrs[0]->GetComment();
826
827     // Save in study
828     _PTR(SObject) aRefObj = anIter->Value();
829     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
830     anPrsIter->Init();
831
832     if (anPrsIter->More()) {
833       _PTR(SObject) aPrsObj = anPrsIter->Value();
834       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeComment");
835       aCmnt = _PTR(AttributeComment)(anAttr);
836       aCmnt->SetValue(aPrsComment.c_str());
837
838       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeName");
839       _PTR(AttributeName) aPrsName (anAttr);
840       aPrsName->SetValue(aPrsNameTxt);
841
842     } else {
843       VISU::CreateAttributes(myStudy, aRefObj->GetID().c_str(),"","",
844                              aPrsNameTxt.c_str(),"",aPrsComment.c_str(),true);
845     }
846   }
847   aStudyBuilder->CommitCommand();
848 }
849
850 //------------------------------------------------------------------------
851 void VISU_TimeAnimation::restoreFromStudy(SALOMEDS::SObject_ptr theField)
852 {
853   _PTR(SObject) aAnimSObject = VISU::GetClientSObject(theField, myStudy);
854   restoreFromStudy(aAnimSObject);
855 }
856
857 void VISU_TimeAnimation::restoreFromStudy(_PTR(SObject) theField)
858 {
859   _PTR(SObject) aAnimSObject = theField;
860
861   VISU::Storable::TRestoringMap aMap;
862   _PTR(GenericAttribute) anAttr;
863   if (!aAnimSObject->FindAttribute(anAttr, "AttributeComment")) return;
864
865   _PTR(AttributeComment) aComment (anAttr);
866   string aComm = aComment->Value();
867   QString strIn (aComm.c_str());
868   VISU::Storable::StrToMap(strIn,aMap);
869   bool isExist;
870
871   myMinVal = VISU::Storable::FindValue(aMap,"myMinVal",&isExist).toDouble();
872   myMaxVal = VISU::Storable::FindValue(aMap,"myMaxVal",&isExist).toDouble();
873
874   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
875   for (anIter->Init(); anIter->More(); anIter->Next()) {
876     _PTR(SObject) aRefObj = anIter->Value();
877     _PTR(SObject) aFieldObj;
878     if (!aRefObj->ReferencedObject(aFieldObj) ) continue;
879     addField(aFieldObj);
880     FieldData& aData = getFieldData(getNbFields()-1);
881
882     // Get Presentation object
883     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
884     anPrsIter->Init();
885     if (!anPrsIter->More()) continue;
886     _PTR(SObject) aPrsObj = anPrsIter->Value();
887     if (!aPrsObj->FindAttribute(anAttr, "AttributeName")) continue;
888     _PTR(AttributeName) aName (anAttr);
889     string aStr = aName->Value();
890     QString strName (aStr.c_str());
891
892     if (strName == VISU::ScalarMap_i::myComment.c_str())
893       aData.myPrsType = VISU::TSCALARMAP;
894     else if (strName == VISU::IsoSurfaces_i::myComment.c_str())
895       aData.myPrsType = VISU::TISOSURFACE;
896     else if (strName == VISU::CutPlanes_i::myComment.c_str())
897       aData.myPrsType = VISU::TCUTPLANES;
898     else if (strName == VISU::Plot3D_i::myComment.c_str())
899       aData.myPrsType = VISU::TPLOT3D;
900     else if (strName == VISU::DeformedShape_i::myComment.c_str())
901       aData.myPrsType = VISU::TDEFORMEDSHAPE;
902     else if (strName == VISU::Vectors_i::myComment.c_str())
903       aData.myPrsType = VISU::TVECTORS;
904     else if (strName == VISU::StreamLines_i::myComment.c_str())
905       aData.myPrsType = VISU::TSTREAMLINES;
906     else if (strName == VISU::GaussPoints_i::myComment.c_str())
907       aData.myPrsType = VISU::TGAUSSPOINTS;
908     else if (strName == VISU::ScalarMapOnDeformedShape_i::myComment.c_str())
909       aData.myPrsType = VISU::TSCALARMAPONDEFORMEDSHAPE;
910     else
911       continue;
912     generatePresentations(getNbFields()-1);
913
914     if (!aPrsObj->FindAttribute(anAttr, "AttributeComment")) continue;
915     _PTR(AttributeComment) aPrsComment (anAttr);
916     string aPrsComm = aPrsComment->Value();
917     if (aPrsComm.length() > 0) {
918       QString strPrsIn (aPrsComm.c_str());
919       VISU::Storable::TRestoringMap aPrsMap;
920       VISU::Storable::StrToMap(strPrsIn,aPrsMap);
921
922       aData.myPrs[0]->Restore(aPrsMap);
923     }
924     aData.myPrs[0]->GetOffset(aData.myOffset);
925     for (int i = 1; i < aData.myNbFrames; i++) {
926       //jfa 03.08.2005:aData.myPrs[i]->SameAs(aData.myPrs[0]);
927       //enk 06.02.2006:aData.myPrs[i]->SameAsParams(aData.myPrs[0]);//jfa 03.08.2005
928       aData.myPrs[i]->SameAsParams(aData.myPrs[i-1]);//enk 06.02.2006: initializing from previous presentation
929     }
930   }
931   string aStr = aAnimSObject->GetID();
932   myAnimEntry = aStr.c_str();
933 }
934
935 void VISU_TimeAnimation::onViewDeleted()
936 {
937   myView = 0;
938 }
939
940
941 //========================================================================
942 //========================================================================
943 //========================================================================
944 struct TNewAnimationEvent: public SALOME_Event
945 {
946   std::string myStudyName;
947   VISU::View3D_ptr myView3D;
948
949   typedef VISU_TimeAnimation* TResult;
950   TResult myResult;
951
952   TNewAnimationEvent (std::string theStudyName, VISU::View3D_ptr theView3D):
953     myStudyName(theStudyName),
954     myView3D(VISU::View3D::_duplicate(theView3D)),
955     myResult(NULL)
956   {}
957
958   virtual
959   void
960   Execute()
961   {
962     SUIT_Session* aSession = SUIT_Session::session();
963     QPtrList<SUIT_Application> anApplications = aSession->applications();
964     QPtrListIterator<SUIT_Application> anIter (anApplications);
965     while (SUIT_Application* anApp = anIter.current()) {
966       ++anIter;
967       if (SUIT_Study* aSStudy = anApp->activeStudy()) {
968         if (SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(aSStudy)) {
969           if (_PTR(Study) aCStudy = aStudy->studyDS()) {
970             if (myStudyName == aCStudy->Name()) {
971               myResult = new VISU_TimeAnimation (aCStudy, myView3D);
972               break;
973             }
974           }
975         }
976       }
977     }
978   }
979 };
980
981 VISU_TimeAnimation_i::VISU_TimeAnimation_i (SALOMEDS::Study_ptr theStudy,
982                                             VISU::View3D_ptr theView3D)
983 {
984   std::string aStudyName = theStudy->Name();
985   myAnim = ProcessEvent(new TNewAnimationEvent (aStudyName, theView3D));
986 }
987
988 VISU_TimeAnimation_i::~VISU_TimeAnimation_i()
989 {
990   delete myAnim;
991 }
992
993 void VISU_TimeAnimation_i::addField (SALOMEDS::SObject_ptr theField)
994 {
995   myAnim->addField(theField);
996 }
997
998 CORBA::Boolean VISU_TimeAnimation_i::generateFrames()
999 {
1000   return ProcessEvent(new TMemFunEvent<VISU_TimeAnimation,bool>
1001                       (myAnim,&VISU_TimeAnimation::generateFrames));
1002 }
1003
1004 void VISU_TimeAnimation_i::generatePresentations (CORBA::Long theFieldNum)
1005 {
1006   myAnim->generatePresentations(theFieldNum);
1007 }
1008
1009 void VISU_TimeAnimation_i::clearView()
1010 {
1011   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1012                    (myAnim,&VISU_TimeAnimation::clearView));
1013 }
1014
1015 void VISU_TimeAnimation_i::stopAnimation()
1016 {
1017   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1018                    (myAnim,&VISU_TimeAnimation::stopAnimation));
1019 }
1020
1021 void VISU_TimeAnimation_i::startAnimation()
1022 {
1023   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1024                    (myAnim,&VISU_TimeAnimation::startAnimation));
1025 }
1026
1027 void VISU_TimeAnimation_i::nextFrame()
1028 {
1029   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1030                    (myAnim,&VISU_TimeAnimation::nextFrame));
1031 }
1032
1033 void VISU_TimeAnimation_i::prevFrame()
1034 {
1035   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1036                    (myAnim,&VISU_TimeAnimation::prevFrame));
1037 }
1038
1039 void VISU_TimeAnimation_i::firstFrame()
1040 {
1041   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1042                    (myAnim,&VISU_TimeAnimation::firstFrame));
1043 }
1044
1045 void VISU_TimeAnimation_i::lastFrame()
1046 {
1047   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1048                    (myAnim,&VISU_TimeAnimation::lastFrame));
1049 }
1050
1051 void VISU_TimeAnimation_i::gotoFrame(CORBA::Long theFrame)
1052 {
1053   ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_TimeAnimation,CORBA::Long>
1054                    (myAnim,&VISU_TimeAnimation::gotoFrame,theFrame));
1055 }
1056
1057 CORBA::Long VISU_TimeAnimation_i::getNbFields()
1058 {
1059   return myAnim->getNbFields();
1060 }
1061
1062 CORBA::Long VISU_TimeAnimation_i::getNbFrames()
1063 {
1064   return myAnim->getNbFrames();
1065 }
1066
1067 CORBA::Boolean VISU_TimeAnimation_i::isRunning()
1068 {
1069   return myAnim->isRunning();
1070 }
1071
1072 CORBA::Long VISU_TimeAnimation_i::getCurrentFrame()
1073 {
1074   return myAnim->getCurrentFrame();
1075 }
1076
1077 VISU::ColoredPrs3d_ptr VISU_TimeAnimation_i::getPresentation
1078                     (CORBA::Long theField, CORBA::Long theFrame)
1079 {
1080   return myAnim->getPresentation(theField,theFrame);
1081 }
1082
1083 void VISU_TimeAnimation_i::setPresentationType (CORBA::Long theFieldNum,
1084                                                 VISU::VISUType theType)
1085 {
1086   myAnim->setPresentationType(theFieldNum,theType);
1087 }
1088
1089 VISU::VISUType VISU_TimeAnimation_i::getPresentationType (CORBA::Long theFieldNum)
1090 {
1091   return myAnim->getPresentationType(theFieldNum);
1092 }
1093
1094 void VISU_TimeAnimation_i::setSpeed(CORBA::Long theSpeed)
1095 {
1096   myAnim->setSpeed(theSpeed);
1097 }
1098
1099 CORBA::Long VISU_TimeAnimation_i::getSpeed()
1100 {
1101   return myAnim->getSpeed();
1102 }
1103
1104 CORBA::Boolean VISU_TimeAnimation_i::isProportional()
1105 {
1106   return myAnim->isProportional();
1107 }
1108
1109 void VISU_TimeAnimation_i::setAnimationRange (CORBA::Double theMin,
1110                                               CORBA::Double theMax)
1111 {
1112   myAnim->setAnimationRange(theMin,theMax);
1113 }
1114
1115 CORBA::Double VISU_TimeAnimation_i::getMinRange()
1116 {
1117   return myAnim->getMinRange();
1118 }
1119
1120 CORBA::Double VISU_TimeAnimation_i::getMaxRange()
1121 {
1122   return myAnim->getMaxRange();
1123 }
1124
1125 CORBA::Boolean VISU_TimeAnimation_i::isRangeDefined()
1126 {
1127   return myAnim->isRangeDefined();
1128 }
1129
1130 void VISU_TimeAnimation_i::dumpTo (const char* thePath)
1131 {
1132   myAnim->dumpTo(thePath);
1133 }
1134
1135 char* VISU_TimeAnimation_i::setDumpFormat (const char* theFormat)
1136 {
1137   string aDumpFormat = myAnim->setDumpFormat(theFormat);
1138   return CORBA::string_dup(aDumpFormat.c_str());
1139 }
1140
1141 CORBA::Boolean VISU_TimeAnimation_i::isCycling()
1142 {
1143   return myAnim->isCycling();
1144 }
1145
1146 CORBA::Double VISU_TimeAnimation_i::getMinTime()
1147 {
1148   return myAnim->getMinTime();
1149 }
1150
1151 CORBA::Double VISU_TimeAnimation_i::getMaxTime()
1152 {
1153   return myAnim->getMaxTime();
1154 }
1155
1156 void VISU_TimeAnimation_i::setProportional (CORBA::Boolean theProp)
1157 {
1158   myAnim->setProportional(theProp);
1159 }
1160
1161 void VISU_TimeAnimation_i::setCycling (CORBA::Boolean theCycle)
1162 {
1163   myAnim->setCycling(theCycle);
1164 }
1165
1166 SALOMEDS::SObject_ptr VISU_TimeAnimation_i::publishInStudy()
1167 {
1168   return myAnim->publishInStudy();
1169 }
1170
1171 void VISU_TimeAnimation_i::restoreFromStudy(SALOMEDS::SObject_ptr theObj)
1172 {
1173   myAnim->restoreFromStudy(theObj);
1174 }
1175
1176 CORBA::Boolean VISU_TimeAnimation_i::isSavedInStudy()
1177 {
1178   return myAnim->isSavedInStudy();
1179 }
1180
1181 void VISU_TimeAnimation_i::saveAnimation()
1182 {
1183   myAnim->saveAnimation();
1184 }