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