0024837: Visualization - revise design and implementation of connected Interactive...
[occt.git] / src / AIS / AIS_MultipleConnectedInteractive.cxx
1 // Created on: 1997-04-22
2 // Created by: Guest Design
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Standard_NotImplemented.hxx>
18
19 #include <AIS_MultipleConnectedInteractive.ixx>
20 #include <AIS_ConnectedInteractive.hxx>
21 #include <AIS_InteractiveContext.hxx>
22
23 #include <PrsMgr_ModedPresentation.hxx>
24 #include <PrsMgr_Presentation.hxx>
25 #include <SelectMgr_EntityOwner.hxx>
26 #include <Select3D_SensitiveEntity.hxx>
27 #include <TopLoc_Location.hxx>
28 #include <NCollection_DataMap.hxx>
29
30 namespace
31 {
32   //! SelectMgr_AssemblyEntityOwner replaces original owners in sensitive entities
33   //! copied from reference objects to AIS_MultipleConnectedInteractive in order to
34   //! redirect all selection queries to multiply connected (assembly).
35   class SelectMgr_AssemblyEntityOwner : public SelectMgr_EntityOwner
36   {
37
38   public:
39
40     // Copies another SelectMgr_EntityOwner.
41     SelectMgr_AssemblyEntityOwner (const Handle(SelectMgr_EntityOwner) theOwner,
42                                    SelectMgr_SelectableObject* theAssembly);
43
44     void SetAssembly (SelectMgr_SelectableObject* theAssembly)
45     {
46       myAssembly = theAssembly;
47     }
48
49     //! Selectable() method modified to return myAssembly.
50     virtual Handle_SelectMgr_SelectableObject Selectable() const;
51
52     Standard_Boolean IsHilighted (const Handle(PrsMgr_PresentationManager)& PM,const Standard_Integer aMode) const;
53
54     void Hilight (const Handle(PrsMgr_PresentationManager)& PM,const Standard_Integer aMode);
55
56     void HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& PM,
57                            const Quantity_NameOfColor aColor,
58                            const Standard_Integer aMode);
59
60     void Unhilight (const Handle(PrsMgr_PresentationManager)& PM, const Standard_Integer aMode);
61
62   private:
63
64     SelectMgr_SelectableObject* myAssembly;
65   };
66
67 }
68
69 //=======================================================================
70 //function : SelectMgr_AssemblyEntityOwner
71 //purpose  : 
72 //=======================================================================
73 SelectMgr_AssemblyEntityOwner::SelectMgr_AssemblyEntityOwner (const Handle(SelectMgr_EntityOwner) theOwner,
74                                                               SelectMgr_SelectableObject* theAssembly)
75 :
76   SelectMgr_EntityOwner (theOwner),
77   myAssembly (theAssembly)
78 {
79 }
80
81 //=======================================================================
82 //function : Selectable
83 //purpose  : 
84 //=======================================================================
85 Handle(SelectMgr_SelectableObject) SelectMgr_AssemblyEntityOwner::Selectable() const
86 {  
87   return myAssembly;
88 }
89
90 //=======================================================================
91 //function : IsHilighted
92 //purpose  : 
93 //=======================================================================
94 Standard_Boolean SelectMgr_AssemblyEntityOwner::IsHilighted (const Handle(PrsMgr_PresentationManager)& PM,
95                                                              const Standard_Integer aMode) const 
96 {
97   if (HasSelectable())
98   {
99    return PM->IsHighlighted (myAssembly, aMode);
100   }
101
102   return Standard_False;
103 }
104
105 //=======================================================================
106 //function : Hilight
107 //purpose  : 
108 //=======================================================================
109 void SelectMgr_AssemblyEntityOwner::Hilight (const Handle(PrsMgr_PresentationManager)& PM,
110                                              const Standard_Integer aMode)
111 {
112   if (HasSelectable())
113   {
114    PM->Highlight (myAssembly, aMode);
115   }
116 }
117
118 //=======================================================================
119 //function : HilightWithColor
120 //purpose  : 
121 //=======================================================================
122 void SelectMgr_AssemblyEntityOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& PM,
123                                                       const Quantity_NameOfColor aColor,
124                                                       const Standard_Integer aMode)
125 {
126   if (HasSelectable())
127   {
128     if (IsAutoHilight())
129     {
130       PM->Color (myAssembly, aColor, aMode);
131     }
132     else
133     {
134       myAssembly->HilightOwnerWithColor (PM, aColor, this);
135     }
136   }
137 }
138
139 //=======================================================================
140 //function : Unhilight
141 //purpose  : 
142 //=======================================================================
143 void SelectMgr_AssemblyEntityOwner::Unhilight (const Handle(PrsMgr_PresentationManager)& PM,
144                                                const Standard_Integer aMode)
145 {
146   if (HasSelectable())
147   {
148     PM->Unhighlight (myAssembly, aMode);
149   }
150 }
151
152
153 //=======================================================================
154 //function : AIS_MultipleConnectedInteractive
155 //purpose  : 
156 //=======================================================================
157
158 AIS_MultipleConnectedInteractive::AIS_MultipleConnectedInteractive()
159   : AIS_InteractiveObject (PrsMgr_TOP_AllView)
160 {
161   myHasOwnPresentations = Standard_False;
162   SetHilightMode (0);
163 }
164
165 //=======================================================================
166 //function : Type
167 //purpose  : 
168 //=======================================================================
169 AIS_KindOfInteractive AIS_MultipleConnectedInteractive::Type() const
170 {
171   return AIS_KOI_Object;
172 }
173
174 //=======================================================================
175 //function : Signature
176 //purpose  : 
177 //=======================================================================
178 Standard_Integer AIS_MultipleConnectedInteractive::Signature() const
179 {
180   return 1;
181 }
182
183 //=======================================================================
184 //function : Connect
185 //purpose  : 
186 //=======================================================================
187 void AIS_MultipleConnectedInteractive::Connect (const Handle(AIS_InteractiveObject)& theAnotherObj,
188                                                 const gp_Trsf&                       theTransformation)
189 {
190   Handle(AIS_InteractiveObject) anObjectToAdd;
191
192   Handle(AIS_MultipleConnectedInteractive) aMultiConnected = Handle(AIS_MultipleConnectedInteractive)::DownCast (theAnotherObj);
193   if (!aMultiConnected.IsNull())
194   { 
195     Handle(AIS_MultipleConnectedInteractive) aNewMultiConnected = new AIS_MultipleConnectedInteractive();
196     aNewMultiConnected->SetLocalTransformation (aMultiConnected->LocalTransformation());
197
198     // Perform deep copy of instance tree
199     for (PrsMgr_ListOfPresentableObjectsIter anIter (aMultiConnected->Children()); anIter.More(); anIter.Next())
200     {
201       Handle(AIS_InteractiveObject) anInteractive = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
202       if (anInteractive.IsNull())
203       {
204         continue;
205       }
206
207       aNewMultiConnected->Connect (anInteractive);     
208     }
209
210     anObjectToAdd = aNewMultiConnected;
211   }
212   else
213   {
214     Handle(AIS_ConnectedInteractive) aNewConnected = new AIS_ConnectedInteractive();
215     aNewConnected->Connect (theAnotherObj);
216     aNewConnected->SetLocalTransformation (theAnotherObj->LocalTransformation());
217
218     anObjectToAdd = aNewConnected;
219   }
220
221   anObjectToAdd->SetLocalTransformation (theTransformation);
222   AddChild (anObjectToAdd);
223 }
224
225 //=======================================================================
226 //function : Connect
227 //purpose  : 
228 //=======================================================================
229 void AIS_MultipleConnectedInteractive::Connect (const Handle(AIS_InteractiveObject)& theAnotherObj)
230 {
231   Connect (theAnotherObj, theAnotherObj->LocalTransformation());
232 }
233
234 //=======================================================================
235 //function : HasConnection
236 //purpose  : 
237 //=======================================================================
238 Standard_Boolean AIS_MultipleConnectedInteractive::HasConnection() const 
239 {
240   return (Children().Size() != 0);
241 }
242
243 //=======================================================================
244 //function : Disconnect
245 //purpose  : 
246 //=======================================================================
247
248 void AIS_MultipleConnectedInteractive::Disconnect(const Handle(AIS_InteractiveObject)& anotherIObj)
249 {
250   RemoveChild (anotherIObj);
251 }
252
253 //=======================================================================
254 //function : DisconnectAll
255 //purpose  : 
256 //=======================================================================
257
258 void AIS_MultipleConnectedInteractive::DisconnectAll()
259 {
260   Standard_Integer aNbItemsToRemove = Children().Size();
261   for (Standard_Integer anIter = 0; anIter < aNbItemsToRemove; ++anIter)
262   {
263     RemoveChild (Children().First());
264   }
265 }
266
267 //=======================================================================
268 //function : Compute
269 //purpose  :
270 //=======================================================================
271 void AIS_MultipleConnectedInteractive::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
272                                                 const Handle(Prs3d_Presentation)&           /*thePrs*/,
273                                                 const Standard_Integer                      /*theMode*/)
274 {
275   for (PrsMgr_ListOfPresentableObjectsIter anIter (Children()); anIter.More(); anIter.Next())
276   {
277     Handle(AIS_InteractiveObject) aChild = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
278     if (aChild.IsNull())
279     {
280       continue;
281     }
282
283     if (!aChild->HasInteractiveContext())
284     {
285       aChild->SetContext (GetContext());
286     }
287   }
288 }
289
290 //=======================================================================
291 //function : Compute
292 //purpose  : 
293 //=======================================================================
294
295 void AIS_MultipleConnectedInteractive::Compute(const Handle(Prs3d_Projector)& aProjector,
296                                                const Handle(Prs3d_Presentation)& aPresentation)
297 {
298   PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
299 }
300
301 //=======================================================================
302 //function : Compute
303 //purpose  : 
304 //=======================================================================
305
306 void AIS_MultipleConnectedInteractive::Compute(const Handle(Prs3d_Projector)& aProjector,
307                                                const Handle(Geom_Transformation)& aTransformation,
308                                                const Handle(Prs3d_Presentation)& aPresentation)
309 {
310   PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
311 }
312
313 //=======================================================================
314 //function : AcceptShapeDecomposition
315 //purpose  : 
316 //=======================================================================
317 Standard_Boolean AIS_MultipleConnectedInteractive::AcceptShapeDecomposition() const 
318 {
319   for (PrsMgr_ListOfPresentableObjectsIter anIter (Children()); anIter.More(); anIter.Next())
320   {
321     Handle(AIS_InteractiveObject) aChild = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
322     if (aChild.IsNull())
323     {
324       continue;
325     }
326
327     if (aChild->AcceptShapeDecomposition())
328     {
329       return Standard_True;
330     }
331   }
332   return Standard_False;
333 }
334
335 //=======================================================================
336 //function : ComputeSelection
337 //purpose  : 
338 //=======================================================================
339 void AIS_MultipleConnectedInteractive::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
340                                                          const Standard_Integer             theMode)
341 {
342   if (theMode != 0)
343   {
344     for (PrsMgr_ListOfPresentableObjectsIter anIter (Children()); anIter.More(); anIter.Next())
345     {
346       Handle(AIS_InteractiveObject) aChild = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
347       if (aChild.IsNull())
348       {
349         continue;
350       }
351
352       if (!aChild->HasSelection(theMode))
353       {
354         aChild->UpdateSelection(theMode);
355       }
356
357       aChild->ComputeSelection (theSelection, theMode);
358     }
359
360     return;
361   }
362
363   for (PrsMgr_ListOfPresentableObjectsIter anIter (Children()); anIter.More(); anIter.Next())
364   {
365     Handle(AIS_InteractiveObject) aChild = Handle(AIS_InteractiveObject)::DownCast (anIter.Value());
366     if (aChild.IsNull())
367     {
368       continue;
369     }
370
371     if (!aChild->HasSelection (theMode))
372     {
373       aChild->UpdateSelection (theMode);
374     }
375
376     const Handle(SelectMgr_Selection)& TheRefSel = aChild->Selection (theMode);
377
378     // To redirect selection we must replace owners in sensitives, but we don't want new owner for each SE.
379     // Only for each existing owner.
380     NCollection_DataMap <Handle(SelectMgr_EntityOwner), Handle(SelectMgr_EntityOwner)> anOwnerMap;
381
382     Handle(Select3D_SensitiveEntity) aSensitive, aNewSensitive;
383
384     if (TheRefSel->IsEmpty())
385     {
386       aChild->UpdateSelection(theMode);
387     }
388
389     for (TheRefSel->Init(); TheRefSel->More(); TheRefSel->Next())
390     {
391       aSensitive = Handle(Select3D_SensitiveEntity)::DownCast(TheRefSel->Sensitive());
392
393       if (!aSensitive.IsNull())
394       {
395         TopLoc_Location aLocation (Transformation());
396         // Get the copy of aSensitive
397         aNewSensitive = aSensitive->GetConnected (aLocation);
398         Handle(SelectMgr_EntityOwner) anOwner = Handle(SelectMgr_EntityOwner)::DownCast (aNewSensitive->OwnerId());
399
400         if (!anOwnerMap.IsBound (anOwner))
401         {
402           Handle(SelectMgr_EntityOwner) aNewOwner = new SelectMgr_AssemblyEntityOwner (anOwner, this);
403           anOwnerMap.Bind (anOwner, aNewOwner);
404         }
405
406         aNewSensitive->Set (anOwnerMap.Find (anOwner));
407         // In case if aSensitive caches some location-dependent data
408         // that must be updated after setting OWN
409         aNewSensitive->SetLocation (aLocation);
410
411         theSelection->Add (aNewSensitive);
412       }
413     }
414   }
415 }