Salome HOME
c1db8093ddd405f3201c51f57c8751832da4c621
[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::TCUTLINES: // Cut Lines
275     GeneratePresentations<CutLines_i>(myStudy,
276                                       aData,
277                                       aResult,
278                                       isRangeDefined(),
279                                       myMinVal,
280                                       myMaxVal,
281                                       myTimeMin,
282                                       myTimeMax);
283     break;
284   case VISU::TPLOT3D: // Plot3d
285     GeneratePresentations<Plot3D_i>(myStudy,
286                                     aData,
287                                     aResult,
288                                     isRangeDefined(),
289                                     myMinVal,
290                                     myMaxVal,
291                                     myTimeMin,
292                                     myTimeMax);
293     break;
294   case VISU::TDEFORMEDSHAPE: // Deformed Shape
295     GeneratePresentations<DeformedShape_i>(myStudy,
296                                            aData,
297                                            aResult,
298                                            isRangeDefined(),
299                                            myMinVal,
300                                            myMaxVal,
301                                            myTimeMin,
302                                            myTimeMax);
303     break;
304   case VISU::TVECTORS: // Vectors
305     GeneratePresentations<Vectors_i>(myStudy,
306                                      aData,
307                                      aResult,
308                                      isRangeDefined(),
309                                      myMinVal,
310                                      myMaxVal,
311                                      myTimeMin,
312                                      myTimeMax);
313     break;
314   case VISU::TSTREAMLINES: // Stream Lines
315     GeneratePresentations<StreamLines_i>(myStudy,
316                                          aData,
317                                          aResult,
318                                          isRangeDefined(),
319                                          myMinVal,
320                                          myMaxVal,
321                                          myTimeMin,
322                                          myTimeMax);
323     break;
324   case VISU::TGAUSSPOINTS: // Gauss Points
325     GeneratePresentations<GaussPoints_i>(myStudy,
326                                          aData,
327                                          aResult,
328                                          isRangeDefined(),
329                                          myMinVal,
330                                          myMaxVal,
331                                          myTimeMin,
332                                          myTimeMax);
333     break;
334   case VISU::TSCALARMAPONDEFORMEDSHAPE: // Scalar map on deformed shape
335     GeneratePresentations<ScalarMapOnDeformedShape_i>(myStudy,
336                                                       aData,
337                                                       aResult,
338                                                       isRangeDefined(),
339                                                       myMinVal,
340                                                       myMaxVal,
341                                                       myTimeMin,
342                                                       myTimeMax);
343     break;
344   default:
345     MESSAGE("Not implemented for this presentation type: " << aData.myPrsType);
346     return;
347   }
348 }
349
350
351 //------------------------------------------------------------------------
352 CORBA::Boolean VISU_TimeAnimation::generateFrames() {
353   if (!myView) {
354     MESSAGE("Viewer is not defined for animation");
355     return false;
356   }
357
358   myLastError = QString("Frame(s) for ");
359   bool aNoError = true;
360
361   clearView();
362
363   for (int i = 0; i < getNbFields(); i++) {
364     FieldData& aData = myFieldsLst[i];
365     aData.myActors.resize(aData.myNbFrames,NULL);
366     for (long j = 0; j < aData.myNbFrames; j++) {
367       VISU_Actor* aActor = NULL;
368       try{
369         aData.myPrs[j]->SetOffset(aData.myOffset);
370         aActor = aData.myPrs[j]->CreateActor();
371         myView->AddActor(aActor);
372         if(j == 0)
373           aActor->VisibilityOn();
374         else
375           aActor->VisibilityOff();
376       }catch(...){ //catch(std::runtime_error& exc){
377         aNoError = false;
378         myLastError += QString("%1 ").arg(aData.myTiming[j]);
379       }
380       aData.myActors[j] = aActor;
381     }
382   }
383   myFrame = 0;
384   myLastError += QString(" timestamp(s) cannot be created.");
385   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
386   myView->Repaint();
387   return aNoError;
388 }
389
390 //------------------------------------------------------------------------
391 void VISU_TimeAnimation::clearView() {
392   if (!myView) {
393     MESSAGE("Viewer is not defined for animation");
394     return;
395   }
396   vtkRenderer* aRen = myView->getRenderer();
397   for (int i = 0; i < getNbFields(); i++) {
398     FieldData& aData = myFieldsLst[i];
399     if (!aData.myActors.empty()) {
400       for (int i = 0, iEnd = aData.myActors.size(); i < iEnd; i++) {
401         if (aData.myActors[i] != 0) {
402           aData.myActors[i]->RemoveFromRender(aRen);
403         }
404       }
405       aData.myActors.clear();
406     }
407   }
408   VISU::RepaintView(myView);
409 }
410
411 //------------------------------------------------------------------------
412 void VISU_TimeAnimation::stopAnimation() {
413   myIsActive = false;
414 }
415
416 //------------------------------------------------------------------------
417 void VISU_TimeAnimation::startAnimation() {
418   if (!myIsActive) {
419     myIsActive = true;
420     QThread::start();
421   }
422 }
423
424 //------------------------------------------------------------------------
425 void VISU_TimeAnimation::nextFrame() {
426   if (!myView) {
427     MESSAGE("Viewer is not defined for animation");
428     return;
429   }
430   stopAnimation();
431   if (myFrame < (myFieldsLst[0].myNbFrames-1)) {
432     int i;
433     for (i = 0; i < getNbFields(); i++)
434       if (myFieldsLst[i].myActors[myFrame] != 0)
435         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
436
437     myFrame++;
438     for (i = 0; i < getNbFields(); i++)
439       if (myFieldsLst[i].myActors[myFrame] != 0)
440         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
441
442     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
443     myView->Repaint();
444   }
445 }
446
447 //------------------------------------------------------------------------
448 void VISU_TimeAnimation::prevFrame() {
449   if (!myView) {
450     MESSAGE("Viewer is not defined for animation");
451     return;
452   }
453   stopAnimation();
454   if (myFrame > 0) {
455     int i;
456     for (i = 0; i < getNbFields(); i++)
457       if (myFieldsLst[i].myActors[myFrame] != 0)
458         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
459
460     myFrame--;
461     for (i = 0; i < getNbFields(); i++)
462       if (myFieldsLst[i].myActors[myFrame] != 0)
463         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
464
465     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
466     myView->Repaint();
467   }
468 }
469
470 //------------------------------------------------------------------------
471 void VISU_TimeAnimation::firstFrame() {
472   if (!myView) {
473     MESSAGE("Viewer is not defined for animation");
474     return;
475   }
476   stopAnimation();
477   int i;
478   for (i = 0; i < getNbFields(); i++)
479     if(!myFieldsLst[i].myActors.empty())
480       if (myFieldsLst[i].myActors[myFrame] != 0)
481         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
482   myFrame = 0;
483   for (i = 0; i < getNbFields(); i++)
484     if(!myFieldsLst[i].myActors.empty())
485       if (myFieldsLst[i].myActors[myFrame] != 0)
486         myFieldsLst[i].myActors[myFrame]->VisibilityOn();
487   if(!myFieldsLst[0].myTiming.empty()){
488     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
489     myView->Repaint();
490   }
491 }
492
493 //------------------------------------------------------------------------
494 void VISU_TimeAnimation::lastFrame() {
495   if (!myView) {
496     MESSAGE("Viewer is not defined for animation");
497     return;
498   }
499   stopAnimation();
500   int i;
501   for (i = 0; i < getNbFields(); i++)
502    if (myFieldsLst[i].myActors[myFrame] != 0)
503       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
504
505   myFrame = myFieldsLst[0].myNbFrames-1;
506   for (i = 0; i < getNbFields(); i++)
507     if (myFieldsLst[i].myActors[myFrame] != 0)
508       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
509
510   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
511   myView->Repaint();
512 }
513
514
515 //------------------------------------------------------------------------
516 // For Batchmode using
517 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame) {
518   if (!myView) {
519     MESSAGE("Viewer is not defined for animation");
520     return;
521   }
522   if ((theFrame < 0) || (theFrame > (getNbFrames()-1)))
523     return;
524   stopAnimation();
525   qApp->lock();
526   qApp->syncX();
527   int i;
528   for (i = 0; i < getNbFields(); i++)
529     if (myFieldsLst[i].myActors[myFrame] != 0)
530       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
531
532   myFrame = theFrame;
533   for (i = 0; i < getNbFields(); i++)
534     if (myFieldsLst[i].myActors[myFrame] != 0)
535       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
536
537   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
538   myView->Repaint();
539   qApp->flushX();
540   qApp->processEvents(3);
541   qApp->unlock();
542 }
543
544
545 //------------------------------------------------------------------------
546 VISU::ColoredPrs3d_ptr VISU_TimeAnimation::getPresentation(CORBA::Long theField, CORBA::Long theFrame) {
547   if ((theField > getNbFields()) || (theField < 0))
548     return VISU::ColoredPrs3d::_nil();
549   if ((theFrame < 0) || (theFrame > (myFieldsLst[theField].myNbFrames - 1)))
550     return VISU::ColoredPrs3d::_nil();
551   return myFieldsLst[theField].myPrs[theFrame]->_this();
552 }
553
554
555 //------------------------------------------------------------------------
556 CORBA::Long VISU_TimeAnimation::getNbFrames() {
557   return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
558 }
559
560
561 //------------------------------------------------------------------------
562 void VISU_TimeAnimation::run()
563 {
564   if (!myView) {
565     MESSAGE("Viewer is not defined for animation");
566     return;
567   }
568   double k = 1;
569   bool   isDumping = !myDumpPath.isEmpty();
570   double aOneVal = 1;
571   if (myFieldsLst[0].myNbFrames > 2)
572     aOneVal = myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0];
573   qApp->lock();
574   while (myIsActive) {
575     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
576     for (int i = 0; i < getNbFields(); i++) {
577       FieldData& aData = myFieldsLst[i];
578       if (myFrame > 0) {
579         if (aData.myActors[myFrame-1] != 0)
580           aData.myActors[myFrame-1]->VisibilityOff();
581       } else {
582         if (aData.myActors[aData.myNbFrames-1] != 0)
583           aData.myActors[aData.myNbFrames-1]->VisibilityOff();
584       }
585       if (aData.myActors[myFrame] != 0) {
586         aData.myActors[myFrame]->VisibilityOn();
587       }
588     }
589     myView->Repaint(false);
590
591     k = 1;
592     if (myProportional) {
593       switch (myFrame) {
594       case 0:
595         break;
596       case 1:
597         if (myFieldsLst[0].myNbFrames > 2)
598           k = (myFieldsLst[0].myTiming[myFrame+1] -
599                myFieldsLst[0].myTiming[myFrame]) / aOneVal;
600         break;
601       default:
602         if (myFrame < (myFieldsLst[0].myNbFrames - 1))
603           k = (myFieldsLst[0].myTiming[myFrame+1] -
604                myFieldsLst[0].myTiming[myFrame]) / aOneVal;
605       }
606     }
607     int delay = (int)(1000. * k / mySpeed);
608     if (delay < 1 && isDumping) {
609       // We must unlock mutex for some time before grabbing to allow view updating
610       delay = 1;
611     }
612     qApp->unlock();
613     msleep(delay);
614     qApp->lock();
615
616     if (isDumping) {
617       // We must unlock mutex for some time before grabbing to allow view updating
618       qApp->unlock();
619       msleep(100);
620       qApp->lock();
621
622       QPixmap px = QPixmap::grabWindow(myView->winId());
623       QString aFile(myDumpPath);
624       QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
625       int aPos = -1;
626       while ((aPos = aName.find(".")) > -1 )
627         aName.replace(aPos, 1, "_");
628       aFile += aName;
629       aFile += ".";
630       aFile += myDumpFormat.lower();
631       px.save(aFile, myDumpFormat);
632     }
633
634     if (!myIsActive) break;
635
636     myFrame++;
637     if (myFrame == myFieldsLst[0].myNbFrames) {
638       if (!myCycling) {
639         myIsActive = false;
640         myFrame--;
641         break;
642       } else
643         myFrame = 0;
644     }
645   }
646   emit stopped();
647   qApp->unlock();
648   QThread::exit();
649 }
650
651 //------------------------------------------------------------------------
652 VISU::Result_i* VISU_TimeAnimation::createPresent (_PTR(SObject) theField)
653 {
654   _PTR(SObject) aSObj = theField->GetFather();
655   aSObj = aSObj->GetFather();
656   aSObj = aSObj->GetFather();
657   CORBA::Object_var anObject = VISU::ClientSObjectToObject(aSObj);
658   if (CORBA::is_nil(anObject)) return NULL;
659   return dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject).in());
660 }
661
662 //------------------------------------------------------------------------
663 VISU::Storable::TRestoringMap VISU_TimeAnimation::getMapOfValue (_PTR(SObject) theSObject)
664 {
665   VISU::Storable::TRestoringMap aMap;
666   if (theSObject) {
667     _PTR(GenericAttribute) anAttr;
668     if (theSObject->FindAttribute(anAttr, "AttributeComment")) {
669       _PTR(AttributeComment) aComment (anAttr);
670       std::string aString = aComment->Value();
671       QString strIn (aString.c_str());
672       VISU::Storable::StrToMap(strIn, aMap);
673     }
674   }
675   return aMap;
676 }
677
678 //------------------------------------------------------------------------
679 double VISU_TimeAnimation::getTimeValue (_PTR(SObject) theTimeStamp)
680 {
681   _PTR(GenericAttribute) anAttr;
682   if (theTimeStamp->FindAttribute(anAttr, "AttributeName")) {
683     _PTR(AttributeName) aName (anAttr);
684     QString aNameString (aName->Value().c_str());
685     int time_len = aNameString.find(',');
686     if (time_len > -1)
687       return aNameString.left(time_len).toDouble();
688     else
689       return aNameString.toDouble();
690   }
691   return -1.0;
692 }
693
694 //------------------------------------------------------------------------
695 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed)
696 {
697   mySpeed = (theSpeed<1)? 1 : theSpeed;
698 }
699
700 std::string VISU_TimeAnimation::setDumpFormat(const char* theFormat)
701 {
702   myDumpFormat = theFormat;
703   QStrList aDumpFormats = QImageIO::outputFormats();
704   if (myDumpFormat.isEmpty() || aDumpFormats.find(theFormat) < 0) {
705     if (aDumpFormats.find("JPEG"))
706       myDumpFormat = "JPEG";
707     else
708       myDumpFormat = aDumpFormats.at(0);
709   }
710   return myDumpFormat.latin1();
711 }
712
713 //************************************************************************
714 int VISU_TimeAnimation::myNBAnimations = 0;
715 QString VISU_TimeAnimation::GenerateName()
716 {
717   return VISU::GenerateName("Animation", myNBAnimations++);
718 }
719
720 //------------------------------------------------------------------------
721 std::string GetPresentationComment (VISU::VISUType thePrsType)
722 {
723   std::string aPrsCmt;
724   switch (thePrsType) {
725   case VISU::TSCALARMAP:
726     aPrsCmt = VISU::ScalarMap_i::myComment;
727     break;
728   case VISU::TISOSURFACE:
729     aPrsCmt = VISU::IsoSurfaces_i::myComment;
730     break;
731   case VISU::TCUTPLANES:
732     aPrsCmt = VISU::CutPlanes_i::myComment;
733     break;
734   case VISU::TCUTLINES:
735     aPrsCmt = VISU::CutLines_i::myComment;
736     break;
737   case VISU::TPLOT3D:
738     aPrsCmt = VISU::Plot3D_i::myComment;
739     break;
740   case VISU::TDEFORMEDSHAPE:
741     aPrsCmt = VISU::DeformedShape_i::myComment;
742     break;
743   case VISU::TVECTORS:
744     aPrsCmt = VISU::Vectors_i::myComment;
745     break;
746   case VISU::TSTREAMLINES:
747     aPrsCmt = VISU::StreamLines_i::myComment;
748     break;
749   case VISU::TGAUSSPOINTS:
750     aPrsCmt = VISU::GaussPoints_i::myComment;
751     break;
752   case VISU::TSCALARMAPONDEFORMEDSHAPE:
753     aPrsCmt = VISU::ScalarMapOnDeformedShape_i::myComment;
754     break;
755   default:
756     aPrsCmt = "Unknown presentation";
757     break;
758   }
759   return aPrsCmt;
760 }
761
762 //------------------------------------------------------------------------
763 SALOMEDS::SObject_ptr VISU_TimeAnimation::publishInStudy()
764 {
765   if (myStudy->GetProperties()->IsLocked())
766     return SALOMEDS::SObject::_nil();
767
768   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
769   aStudyBuilder->NewCommand();  // There is a transaction
770   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
771   std::string aSComponentEntry = aSComponent->GetID();
772
773   QString aComment;
774   aComment.sprintf("myComment=ANIMATION;myType=%d;myMinVal=%g;myMaxVal=%g",
775                    VISU::TANIMATION,myMinVal,myMaxVal);
776
777   string anEntry = VISU::CreateAttributes(myStudy,aSComponentEntry.c_str(),"","",
778                                           GenerateName(),"",aComment,true);
779   myAnimEntry = anEntry.c_str();
780   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(anEntry.c_str());
781
782   for (int i = 0; i < getNbFields(); i++) {
783     FieldData& aData = myFieldsLst[i];
784
785     _PTR(SObject) newObj = aStudyBuilder->NewObject(aAnimSObject);
786     aStudyBuilder->Addreference(newObj, aData.myField);
787
788     if (aData.myPrs.empty()) {
789       generatePresentations(i);
790     }
791     ostringstream strOut;
792     aData.myPrs[0]->ToStream(strOut);
793     string aPrsComment = strOut.str();
794     VISU::CreateAttributes(myStudy, newObj->GetID().c_str(),"","",
795                            aData.myPrs[0]->GetComment(),"",aPrsComment.c_str(),true);
796   }
797   aStudyBuilder->CommitCommand();
798
799   return VISU::GetSObject(aAnimSObject);
800 }
801
802 //------------------------------------------------------------------------
803 void VISU_TimeAnimation::saveAnimation()
804 {
805   if (myStudy->GetProperties()->IsLocked()) return;
806   if (myAnimEntry.isEmpty()) return;
807
808   _PTR(SObject) aAnimSObject = myStudy->FindObjectID(myAnimEntry.latin1());
809   if (!aAnimSObject) return;
810
811   _PTR(StudyBuilder) aStudyBuilder = myStudy->NewBuilder();
812   aStudyBuilder->NewCommand();  // There is a transaction
813   _PTR(SComponent) aSComponent = VISU::ClientFindOrCreateVisuComponent(myStudy);
814   std::string aSComponentEntry = aSComponent->GetID();
815
816   QString aComment;
817   aComment.sprintf("myComment=ANIMATION;myType=%d;myMinVal=%g;myMaxVal=%g",
818                    VISU::TANIMATION,myMinVal,myMaxVal);
819
820   _PTR(GenericAttribute) anAttr;
821   anAttr = aStudyBuilder->FindOrCreateAttribute(aAnimSObject, "AttributeComment");
822   _PTR(AttributeComment) aCmnt (anAttr);
823   aCmnt->SetValue(aComment.latin1());
824
825   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
826   int i = 0, nbf = getNbFields();
827   for (anIter->Init(); anIter->More(); anIter->Next(), i++) {
828     if (i >= nbf) break; // it must not be
829     FieldData& aData = myFieldsLst[i];
830
831     // Get presentation name and comment
832     if (aData.myPrs.empty()) {
833       generatePresentations(i);
834     }
835     ostringstream strOut;
836     aData.myPrs[0]->ToStream(strOut);
837     string aPrsComment = strOut.str();
838     string aPrsNameTxt = aData.myPrs[0]->GetComment();
839
840     // Save in study
841     _PTR(SObject) aRefObj = anIter->Value();
842     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
843     anPrsIter->Init();
844
845     if (anPrsIter->More()) {
846       _PTR(SObject) aPrsObj = anPrsIter->Value();
847       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeComment");
848       aCmnt = _PTR(AttributeComment)(anAttr);
849       aCmnt->SetValue(aPrsComment.c_str());
850
851       anAttr = aStudyBuilder->FindOrCreateAttribute(aPrsObj, "AttributeName");
852       _PTR(AttributeName) aPrsName (anAttr);
853       aPrsName->SetValue(aPrsNameTxt);
854
855     } else {
856       VISU::CreateAttributes(myStudy, aRefObj->GetID().c_str(),"","",
857                              aPrsNameTxt.c_str(),"",aPrsComment.c_str(),true);
858     }
859   }
860   aStudyBuilder->CommitCommand();
861 }
862
863 //------------------------------------------------------------------------
864 void VISU_TimeAnimation::restoreFromStudy(SALOMEDS::SObject_ptr theField)
865 {
866   _PTR(SObject) aAnimSObject = VISU::GetClientSObject(theField, myStudy);
867   restoreFromStudy(aAnimSObject);
868 }
869
870 void VISU_TimeAnimation::restoreFromStudy(_PTR(SObject) theField)
871 {
872   _PTR(SObject) aAnimSObject = theField;
873
874   VISU::Storable::TRestoringMap aMap;
875   _PTR(GenericAttribute) anAttr;
876   if (!aAnimSObject->FindAttribute(anAttr, "AttributeComment")) return;
877
878   _PTR(AttributeComment) aComment (anAttr);
879   string aComm = aComment->Value();
880   QString strIn (aComm.c_str());
881   VISU::Storable::StrToMap(strIn,aMap);
882   bool isExist;
883
884   myMinVal = VISU::Storable::FindValue(aMap,"myMinVal",&isExist).toDouble();
885   myMaxVal = VISU::Storable::FindValue(aMap,"myMaxVal",&isExist).toDouble();
886
887   _PTR(ChildIterator) anIter = myStudy->NewChildIterator(aAnimSObject);
888   for (anIter->Init(); anIter->More(); anIter->Next()) {
889     _PTR(SObject) aRefObj = anIter->Value();
890     _PTR(SObject) aFieldObj;
891     if (!aRefObj->ReferencedObject(aFieldObj) ) continue;
892     addField(aFieldObj);
893     FieldData& aData = getFieldData(getNbFields()-1);
894
895     // Get Presentation object
896     _PTR(ChildIterator) anPrsIter = myStudy->NewChildIterator(aRefObj);
897     anPrsIter->Init();
898     if (!anPrsIter->More()) continue;
899     _PTR(SObject) aPrsObj = anPrsIter->Value();
900     if (!aPrsObj->FindAttribute(anAttr, "AttributeName")) continue;
901     _PTR(AttributeName) aName (anAttr);
902     string aStr = aName->Value();
903     QString strName (aStr.c_str());
904
905     if (strName == VISU::ScalarMap_i::myComment.c_str())
906       aData.myPrsType = VISU::TSCALARMAP;
907     else if (strName == VISU::IsoSurfaces_i::myComment.c_str())
908       aData.myPrsType = VISU::TISOSURFACE;
909     else if (strName == VISU::CutPlanes_i::myComment.c_str())
910       aData.myPrsType = VISU::TCUTPLANES;
911     else if (strName == VISU::CutLines_i::myComment.c_str())
912       aData.myPrsType = VISU::TCUTLINES;
913     else if (strName == VISU::Plot3D_i::myComment.c_str())
914       aData.myPrsType = VISU::TPLOT3D;
915     else if (strName == VISU::DeformedShape_i::myComment.c_str())
916       aData.myPrsType = VISU::TDEFORMEDSHAPE;
917     else if (strName == VISU::Vectors_i::myComment.c_str())
918       aData.myPrsType = VISU::TVECTORS;
919     else if (strName == VISU::StreamLines_i::myComment.c_str())
920       aData.myPrsType = VISU::TSTREAMLINES;
921     else if (strName == VISU::GaussPoints_i::myComment.c_str())
922       aData.myPrsType = VISU::TGAUSSPOINTS;
923     else if (strName == VISU::ScalarMapOnDeformedShape_i::myComment.c_str())
924       aData.myPrsType = VISU::TSCALARMAPONDEFORMEDSHAPE;
925     else
926       continue;
927     generatePresentations(getNbFields()-1);
928
929     if (!aPrsObj->FindAttribute(anAttr, "AttributeComment")) continue;
930     _PTR(AttributeComment) aPrsComment (anAttr);
931     string aPrsComm = aPrsComment->Value();
932     if (aPrsComm.length() > 0) {
933       QString strPrsIn (aPrsComm.c_str());
934       VISU::Storable::TRestoringMap aPrsMap;
935       VISU::Storable::StrToMap(strPrsIn,aPrsMap);
936
937       aData.myPrs[0]->Restore(aPrsMap);
938     }
939     aData.myPrs[0]->GetOffset(aData.myOffset);
940     for (int i = 1; i < aData.myNbFrames; i++) {
941       //jfa 03.08.2005:aData.myPrs[i]->SameAs(aData.myPrs[0]);
942       //enk 06.02.2006:aData.myPrs[i]->SameAsParams(aData.myPrs[0]);//jfa 03.08.2005
943       aData.myPrs[i]->SameAsParams(aData.myPrs[i-1]);//enk 06.02.2006: initializing from previous presentation
944     }
945   }
946   string aStr = aAnimSObject->GetID();
947   myAnimEntry = aStr.c_str();
948 }
949
950 void VISU_TimeAnimation::onViewDeleted()
951 {
952   myView = 0;
953 }
954
955
956 //========================================================================
957 //========================================================================
958 //========================================================================
959 struct TNewAnimationEvent: public SALOME_Event
960 {
961   std::string myStudyName;
962   VISU::View3D_ptr myView3D;
963
964   typedef VISU_TimeAnimation* TResult;
965   TResult myResult;
966
967   TNewAnimationEvent (std::string theStudyName, VISU::View3D_ptr theView3D):
968     myStudyName(theStudyName),
969     myView3D(VISU::View3D::_duplicate(theView3D)),
970     myResult(NULL)
971   {}
972
973   virtual
974   void
975   Execute()
976   {
977     SUIT_Session* aSession = SUIT_Session::session();
978     QPtrList<SUIT_Application> anApplications = aSession->applications();
979     QPtrListIterator<SUIT_Application> anIter (anApplications);
980     while (SUIT_Application* anApp = anIter.current()) {
981       ++anIter;
982       if (SUIT_Study* aSStudy = anApp->activeStudy()) {
983         if (SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(aSStudy)) {
984           if (_PTR(Study) aCStudy = aStudy->studyDS()) {
985             if (myStudyName == aCStudy->Name()) {
986               myResult = new VISU_TimeAnimation (aCStudy, myView3D);
987               break;
988             }
989           }
990         }
991       }
992     }
993   }
994 };
995
996 VISU_TimeAnimation_i::VISU_TimeAnimation_i (SALOMEDS::Study_ptr theStudy,
997                                             VISU::View3D_ptr theView3D)
998 {
999   std::string aStudyName = theStudy->Name();
1000   myAnim = ProcessEvent(new TNewAnimationEvent (aStudyName, theView3D));
1001 }
1002
1003 VISU_TimeAnimation_i::~VISU_TimeAnimation_i()
1004 {
1005   delete myAnim;
1006 }
1007
1008 void VISU_TimeAnimation_i::addField (SALOMEDS::SObject_ptr theField)
1009 {
1010   myAnim->addField(theField);
1011 }
1012
1013 CORBA::Boolean VISU_TimeAnimation_i::generateFrames()
1014 {
1015   return ProcessEvent(new TMemFunEvent<VISU_TimeAnimation,bool>
1016                       (myAnim,&VISU_TimeAnimation::generateFrames));
1017 }
1018
1019 void VISU_TimeAnimation_i::generatePresentations (CORBA::Long theFieldNum)
1020 {
1021   myAnim->generatePresentations(theFieldNum);
1022 }
1023
1024 void VISU_TimeAnimation_i::clearView()
1025 {
1026   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1027                    (myAnim,&VISU_TimeAnimation::clearView));
1028 }
1029
1030 void VISU_TimeAnimation_i::stopAnimation()
1031 {
1032   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1033                    (myAnim,&VISU_TimeAnimation::stopAnimation));
1034 }
1035
1036 void VISU_TimeAnimation_i::startAnimation()
1037 {
1038   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1039                    (myAnim,&VISU_TimeAnimation::startAnimation));
1040 }
1041
1042 void VISU_TimeAnimation_i::nextFrame()
1043 {
1044   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1045                    (myAnim,&VISU_TimeAnimation::nextFrame));
1046 }
1047
1048 void VISU_TimeAnimation_i::prevFrame()
1049 {
1050   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1051                    (myAnim,&VISU_TimeAnimation::prevFrame));
1052 }
1053
1054 void VISU_TimeAnimation_i::firstFrame()
1055 {
1056   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1057                    (myAnim,&VISU_TimeAnimation::firstFrame));
1058 }
1059
1060 void VISU_TimeAnimation_i::lastFrame()
1061 {
1062   ProcessVoidEvent(new TVoidMemFunEvent<VISU_TimeAnimation>
1063                    (myAnim,&VISU_TimeAnimation::lastFrame));
1064 }
1065
1066 void VISU_TimeAnimation_i::gotoFrame(CORBA::Long theFrame)
1067 {
1068   ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_TimeAnimation,CORBA::Long>
1069                    (myAnim,&VISU_TimeAnimation::gotoFrame,theFrame));
1070 }
1071
1072 CORBA::Long VISU_TimeAnimation_i::getNbFields()
1073 {
1074   return myAnim->getNbFields();
1075 }
1076
1077 CORBA::Long VISU_TimeAnimation_i::getNbFrames()
1078 {
1079   return myAnim->getNbFrames();
1080 }
1081
1082 CORBA::Boolean VISU_TimeAnimation_i::isRunning()
1083 {
1084   return myAnim->isRunning();
1085 }
1086
1087 CORBA::Long VISU_TimeAnimation_i::getCurrentFrame()
1088 {
1089   return myAnim->getCurrentFrame();
1090 }
1091
1092 VISU::ColoredPrs3d_ptr VISU_TimeAnimation_i::getPresentation
1093                     (CORBA::Long theField, CORBA::Long theFrame)
1094 {
1095   return myAnim->getPresentation(theField,theFrame);
1096 }
1097
1098 void VISU_TimeAnimation_i::setPresentationType (CORBA::Long theFieldNum,
1099                                                 VISU::VISUType theType)
1100 {
1101   myAnim->setPresentationType(theFieldNum,theType);
1102 }
1103
1104 VISU::VISUType VISU_TimeAnimation_i::getPresentationType (CORBA::Long theFieldNum)
1105 {
1106   return myAnim->getPresentationType(theFieldNum);
1107 }
1108
1109 void VISU_TimeAnimation_i::setSpeed(CORBA::Long theSpeed)
1110 {
1111   myAnim->setSpeed(theSpeed);
1112 }
1113
1114 CORBA::Long VISU_TimeAnimation_i::getSpeed()
1115 {
1116   return myAnim->getSpeed();
1117 }
1118
1119 CORBA::Boolean VISU_TimeAnimation_i::isProportional()
1120 {
1121   return myAnim->isProportional();
1122 }
1123
1124 void VISU_TimeAnimation_i::setAnimationRange (CORBA::Double theMin,
1125                                               CORBA::Double theMax)
1126 {
1127   myAnim->setAnimationRange(theMin,theMax);
1128 }
1129
1130 CORBA::Double VISU_TimeAnimation_i::getMinRange()
1131 {
1132   return myAnim->getMinRange();
1133 }
1134
1135 CORBA::Double VISU_TimeAnimation_i::getMaxRange()
1136 {
1137   return myAnim->getMaxRange();
1138 }
1139
1140 CORBA::Boolean VISU_TimeAnimation_i::isRangeDefined()
1141 {
1142   return myAnim->isRangeDefined();
1143 }
1144
1145 void VISU_TimeAnimation_i::dumpTo (const char* thePath)
1146 {
1147   myAnim->dumpTo(thePath);
1148 }
1149
1150 char* VISU_TimeAnimation_i::setDumpFormat (const char* theFormat)
1151 {
1152   string aDumpFormat = myAnim->setDumpFormat(theFormat);
1153   return CORBA::string_dup(aDumpFormat.c_str());
1154 }
1155
1156 CORBA::Boolean VISU_TimeAnimation_i::isCycling()
1157 {
1158   return myAnim->isCycling();
1159 }
1160
1161 CORBA::Double VISU_TimeAnimation_i::getMinTime()
1162 {
1163   return myAnim->getMinTime();
1164 }
1165
1166 CORBA::Double VISU_TimeAnimation_i::getMaxTime()
1167 {
1168   return myAnim->getMaxTime();
1169 }
1170
1171 void VISU_TimeAnimation_i::setProportional (CORBA::Boolean theProp)
1172 {
1173   myAnim->setProportional(theProp);
1174 }
1175
1176 void VISU_TimeAnimation_i::setCycling (CORBA::Boolean theCycle)
1177 {
1178   myAnim->setCycling(theCycle);
1179 }
1180
1181 SALOMEDS::SObject_ptr VISU_TimeAnimation_i::publishInStudy()
1182 {
1183   return myAnim->publishInStudy();
1184 }
1185
1186 void VISU_TimeAnimation_i::restoreFromStudy(SALOMEDS::SObject_ptr theObj)
1187 {
1188   myAnim->restoreFromStudy(theObj);
1189 }
1190
1191 CORBA::Boolean VISU_TimeAnimation_i::isSavedInStudy()
1192 {
1193   return myAnim->isSavedInStudy();
1194 }
1195
1196 void VISU_TimeAnimation_i::saveAnimation()
1197 {
1198   myAnim->saveAnimation();
1199 }