Salome HOME
Allow drag and drop berween items; change z layers assigning algo.
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_OCCDisplayer.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HYDROGUI_OCCDisplayer.h"
24
25 #include "HYDROGUI_DataModel.h"
26 #include "HYDROGUI_Module.h"
27 #include "HYDROGUI_Tool.h"
28 #include "HYDROGUI_Shape.h"
29 #include "HYDROGUI_Operation.h"
30 #include "HYDROGUI_DataObject.h"
31
32 #include <AIS_InteractiveContext.hxx>
33 #include <AIS_ListIteratorOfListOfInteractive.hxx>
34 #include <AIS_ListOfInteractive.hxx>
35
36 #include <TColStd_SequenceOfInteger.hxx>
37
38 #include <LightApp_Application.h>
39 #include <SUIT_Study.h>
40
41 #include <OCCViewer_ViewManager.h>
42 #include <OCCViewer_ViewModel.h>
43 #include <OCCViewer_ViewWindow.h>
44
45 HYDROGUI_OCCDisplayer::HYDROGUI_OCCDisplayer( HYDROGUI_Module* theModule )
46 : HYDROGUI_AbstractDisplayer( theModule )
47 {
48 }
49
50 HYDROGUI_OCCDisplayer::~HYDROGUI_OCCDisplayer()
51 {
52 }
53
54 void HYDROGUI_OCCDisplayer::SetToUpdate( const HYDROData_SequenceOfObjects& theObjs,
55                                          const int                          theViewerId )
56 {
57   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
58   if( !aViewer )
59     return;
60
61   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
62   {
63     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
64     if( anObj.IsNull() )
65       continue;
66
67     HYDROGUI_Shape* anObjShape = module()->getObjectShape( (size_t)aViewer, anObj );
68     if ( !anObjShape )
69       continue;
70     
71     anObjShape->setIsToUpdate( true );
72   }
73 }
74
75 int HYDROGUI_OCCDisplayer::AddTopZLayer( OCCViewer_ViewManager* theMgr )
76 {
77   int aLayer = -1;
78   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
79   if ( !aViewer )
80     return aLayer;
81
82   Standard_Integer aNewId = -1;
83   if ( aViewer->getViewer3d()->AddZLayer( aNewId ) )
84     aLayer = aNewId;
85
86   return aLayer;
87 }
88
89 void HYDROGUI_OCCDisplayer::RemoveZLayer( OCCViewer_ViewManager* theMgr,
90                                           const int theLayer )
91 {
92   if ( theLayer < 0 )
93     return;
94
95   OCCViewer_Viewer* aViewer = theMgr->getOCCViewer();
96   if ( !aViewer )
97     return;
98
99   // Get existing Z layers
100   TColStd_SequenceOfInteger anExistingZLayers;
101   aViewer->getViewer3d()->GetAllZLayers( anExistingZLayers );
102   int aNbLayers = anExistingZLayers.Length();
103   
104   if ( theLayer < aNbLayers )
105     aViewer->getViewer3d()->RemoveZLayer( theLayer );
106 }
107
108 void HYDROGUI_OCCDisplayer::EraseAll( const int theViewerId )
109 {
110   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
111   if( !aViewer )
112     return;
113
114   module()->removeViewShapes( (size_t)aViewer );
115 }
116
117 void HYDROGUI_OCCDisplayer::Erase( const HYDROData_SequenceOfObjects& theObjs,
118                                    const int                          theViewerId )
119 {
120   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
121   if( !aViewer )
122     return;
123
124   for ( int i = 1, n = theObjs.Length(); i <= n; i++ )
125   {
126     Handle(HYDROData_Entity) anObj = theObjs.Value( i );
127     if( anObj.IsNull() )
128       continue;
129
130     module()->removeObjectShape( (size_t)aViewer, anObj );
131   }
132   aViewer->update();
133 }
134
135 HYDROGUI_Shape* HYDROGUI_OCCDisplayer::createShape( const int                             theViewerId,
136                                                     const Handle(AIS_InteractiveContext)& theContext,
137                                                     const Handle(HYDROData_Entity)&       theObject )
138 {
139   HYDROGUI_Shape* aResShape = NULL;
140   if ( theContext.IsNull() || theObject.IsNull() )
141     return aResShape;
142
143   if ( !HYDROGUI_Tool::IsObjectHasPresentation( theObject, OCCViewer_Viewer::Type() ) )
144     return aResShape;
145
146   aResShape = new HYDROGUI_Shape( theContext, theObject );
147   module()->setObjectShape( theViewerId, theObject, aResShape );
148
149   return aResShape;
150 }
151
152 void HYDROGUI_OCCDisplayer::Display( const HYDROData_SequenceOfObjects& theObjs,
153                                      const int                          theViewerId,
154                                      const bool                         theIsForced,
155                                      const bool theDoFitAll )
156 {
157   // Get OCC viewer by id
158   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
159   if( !aViewer )
160     return;
161
162   // Get interactive context
163   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
164   if( aCtx.IsNull() )
165     return;
166
167   // Get the document
168   Handle(HYDROData_Document) aDoc = HYDROData_Document::Document( module()->getStudyId() );
169   if ( !aDoc )
170     return;
171   
172   // Assign Z layer indexes to the objects
173   aDoc->Show( theObjs );
174
175   // Sort objects by display order ( needed for Z layers assignment only )
176   HYDROData_SequenceOfObjects anUnorderedToDisplay = theObjs;
177   HYDROData_SequenceOfObjects anOrderedToDisplay;
178   HYDROData_SequenceOfObjects anAllOrderedObjects = aDoc->GetObjectsLayerOrder();
179
180   HYDROData_SequenceOfObjects::Iterator anAllOrderedIter( anAllOrderedObjects );
181   for ( ; anAllOrderedIter.More(); anAllOrderedIter.Next() ) {
182     QString anOrderedEntry = 
183       HYDROGUI_DataObject::dataObjectEntry( anAllOrderedIter.Value() );
184     
185     HYDROData_SequenceOfObjects::Iterator aToDisplayIter( anUnorderedToDisplay );
186     for ( ; aToDisplayIter.More(); aToDisplayIter.Next() ) {
187       Handle(HYDROData_Entity) anObjToDisplay = aToDisplayIter.Value();
188       QString anEntry = HYDROGUI_DataObject::dataObjectEntry( anObjToDisplay );
189       if ( anEntry == anOrderedEntry ) {
190         anOrderedToDisplay.Prepend( anObjToDisplay );
191         anUnorderedToDisplay.Remove( aToDisplayIter );
192         break;
193       }
194     }
195   }
196   
197   // Get 3d viewer
198   Handle(V3d_Viewer) aViewer3d = aViewer->getViewer3d();
199
200   // Get existing Z layers
201   TColStd_SequenceOfInteger anExistingZLayers;
202   aViewer3d->GetAllZLayers( anExistingZLayers );
203   int aNbLayers = anExistingZLayers.Length();
204
205   // Display objects
206   int aNextZLayerIndex = 2; // don't use the first default Z layer ( which index = 1 )
207
208   // 1. Display the ordered objects:
209   HYDROData_SequenceOfObjects::Iterator anOrderedIter( anOrderedToDisplay );
210   for ( ; anOrderedIter.More(); anOrderedIter.Next() ) {
211     Handle(HYDROData_Entity) anObj = anOrderedIter.Value();
212     if ( Display( anObj, aViewer, theIsForced, aNextZLayerIndex, true ) ) {
213       aNextZLayerIndex++;
214     }
215   }
216
217   // 2. Display the unordered objects:
218   bool isDisplayed = false;
219   HYDROData_SequenceOfObjects::Iterator anUnorderedIter( anUnorderedToDisplay );
220   for ( ; anUnorderedIter.More(); anUnorderedIter.Next() ) {
221     Handle(HYDROData_Entity) anObj = anUnorderedIter.Value();
222     if ( Display( anObj, aViewer, theIsForced, aNextZLayerIndex, false ) ) {
223       isDisplayed = true;
224     }
225   }
226   
227   // 3. Update the top Z layer index
228   if ( isDisplayed ) {
229     aNextZLayerIndex++;
230   }
231
232   // Update Z layer of the active operation
233   aViewer3d->GetAllZLayers( anExistingZLayers );
234
235   HYDROGUI_Module* aModule = module();
236   SUIT_Operation* anOp = aModule->activeOperation();
237   HYDROGUI_Operation* aHOp = anOp ? dynamic_cast<HYDROGUI_Operation*>( anOp ) : 0;
238   if ( aHOp && aHOp->getPreviewZLayer() >= 0 ) {
239     Standard_Integer aLayerId = -1;
240     if ( aNextZLayerIndex <= aNbLayers )
241       aLayerId = anExistingZLayers.Value( aNextZLayerIndex );
242     else {
243       Standard_Integer aNewId = -1;
244       if ( aViewer->getViewer3d()->AddZLayer( aNewId ) ) {
245         aLayerId = aNewId;
246       }
247     }
248     aHOp->updatePreviewZLayer( aLayerId );
249   }
250
251   if ( theDoFitAll )
252   {
253     OCCViewer_ViewManager* aViewManager
254       = ::qobject_cast<OCCViewer_ViewManager*>( aViewer->getViewManager() );
255     if ( aViewManager )
256     {
257       OCCViewer_ViewWindow* aViewWindow = 
258         ::qobject_cast<OCCViewer_ViewWindow*>( aViewManager->getActiveView() );
259       if ( aViewWindow )
260       {
261         aViewWindow->onFitAll();
262       }
263     }
264   }
265   else if ( !aCtx.IsNull() ) // TODO: determine if this code is necessary (added as a fix for issue# 359)
266   {
267     aCtx->UpdateSelected();
268   }
269 }
270
271 void HYDROGUI_OCCDisplayer::purgeObjects( const int theViewerId )
272 {
273   OCCViewer_Viewer* aViewer = module()->getOCCViewer( theViewerId );
274   if( !aViewer )
275     return;
276
277   Handle(AIS_InteractiveContext) aCtx = aViewer->getAISContext();
278   if( aCtx.IsNull() )
279     return;
280
281   AIS_ListOfInteractive aDisplayedObjects;
282   aCtx->DisplayedObjects( aDisplayedObjects );
283
284   AIS_ListIteratorOfListOfInteractive aListIter( aDisplayedObjects );
285   for ( ; aListIter.More(); aListIter.Next() )
286   {
287     Handle(AIS_InteractiveObject) aPrsObj = aListIter.Value();
288     if ( aPrsObj.IsNull() )
289       continue;
290
291     Handle(HYDROData_Entity) anOwnerObj = 
292       Handle(HYDROData_Entity)::DownCast( aPrsObj->GetOwner() );
293     if ( !anOwnerObj.IsNull() && anOwnerObj->IsRemoved() )
294       module()->removeObjectShape( (size_t)aViewer, anOwnerObj );
295   }
296 }
297
298 QString HYDROGUI_OCCDisplayer::GetType() const
299 {
300   return OCCViewer_Viewer::Type();
301 }
302
303 bool HYDROGUI_OCCDisplayer::Display( const Handle(HYDROData_Entity)& theObject,
304                                      const OCCViewer_Viewer* theViewer,
305                                      const bool theIsForced,
306                                      const int theZLayerIndex,
307                                      const bool theIsOrdered )
308 {
309   bool aRes = false;
310
311   if ( theObject.IsNull() || theObject->IsRemoved() || !theViewer ) {
312     return aRes;
313   }
314
315   // Get interactive context
316   Handle(AIS_InteractiveContext) aCtx = theViewer->getAISContext();
317   if( aCtx.IsNull() ) {
318     return aRes;
319   }
320
321   // Viewer id
322   size_t aViewerId = (size_t)theViewer;
323
324   // Object shape 
325   HYDROGUI_Shape* anObjShape = module()->getObjectShape( aViewerId, theObject );
326   // create if needed
327   if ( !anObjShape ) {
328     anObjShape = createShape( aViewerId, aCtx, theObject );
329     anObjShape->setIsToUpdate( true );
330   }
331   
332   // Process the shape
333   if ( anObjShape ) {
334     // update if needed
335     if ( anObjShape->getIsToUpdate() || theIsForced ) {
336       anObjShape->update( false );
337     }
338
339     // Set visibility
340     bool anIsVisible = module()->isObjectVisible( aViewerId, theObject );
341     anObjShape->setVisible( anIsVisible, false );
342
343     // Set Z layer
344     Handle(V3d_Viewer) aViewer3d = theViewer->getViewer3d();
345     if ( !aViewer3d.IsNull() ) {
346       // Get existing layers
347       TColStd_SequenceOfInteger anExistingZLayers;
348       aViewer3d->GetAllZLayers( anExistingZLayers );
349       int aNbLayers = anExistingZLayers.Length();
350       
351       // Get or create the appropriate layer
352       Standard_Integer aLayerId = -1;
353       if ( theZLayerIndex <= aNbLayers ) {
354         aLayerId = anExistingZLayers.Value( theZLayerIndex );
355       } else {
356         Standard_Integer aNewId = -1;
357         if ( aViewer3d->AddZLayer( aNewId ) ) {
358           aLayerId = aNewId;
359         }
360       }
361
362       if ( aLayerId >= 0 ) {
363         // set Z layer
364         aCtx->SetZLayer( anObjShape->getAISShape(), aLayerId );
365           
366         // set Z layer settings for the 3d viewer:
367         // current settings
368         Graphic3d_ZLayerSettings aSettings = aViewer3d->ZLayerSettings( aLayerId );
369         // enable depth write
370         aSettings.EnableSetting( Graphic3d_ZLayerDepthWrite );
371         // disable depth clear
372         aSettings.DisableSetting( Graphic3d_ZLayerDepthClear );
373         if ( theIsOrdered ) {
374           // disable depth test
375           aSettings.DisableSetting( Graphic3d_ZLayerDepthTest );
376           // disable depth offset
377           aSettings.DisableSetting( Graphic3d_ZLayerDepthOffset );
378         } else {
379           // enable depth test
380           aSettings.EnableSetting( Graphic3d_ZLayerDepthTest );
381           // set depth offset
382           aSettings.SetDepthOffsetPositive();
383         }
384
385         // set new settings
386         aViewer3d->SetZLayerSettings( aLayerId, aSettings );
387
388         aRes = true;
389       }
390     }
391   }
392
393   return aRes;
394 }