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