fba30b6cf06b0d9e48670d89edcb5d77e6bca789
[occt.git] / src / AIS / AIS_InteractiveObject.cxx
1 // Created on: 1996-12-18
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1996-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 <AIS_InteractiveObject.hxx>
18
19 #include <AIS_GraphicTool.hxx>
20 #include <AIS_InteractiveContext.hxx>
21 #include <Aspect_PolygonOffsetMode.hxx>
22 #include <Bnd_Box.hxx>
23 #include <Graphic3d_AspectFillArea3d.hxx>
24 #include <Graphic3d_AspectLine3d.hxx>
25 #include <Graphic3d_AspectMarker3d.hxx>
26 #include <Graphic3d_AspectText3d.hxx>
27 #include <Graphic3d_BndBox4f.hxx>
28 #include <Graphic3d_CStructure.hxx>
29 #include <Graphic3d_Group.hxx>
30 #include <Graphic3d_MaterialAspect.hxx>
31 #include <Graphic3d_Structure.hxx>
32 #include <Prs3d_BasicAspect.hxx>
33 #include <Prs3d_LineAspect.hxx>
34 #include <Prs3d_PointAspect.hxx>
35 #include <Prs3d_Presentation.hxx>
36 #include <Prs3d_Root.hxx>
37 #include <Prs3d_ShadingAspect.hxx>
38 #include <Prs3d_TextAspect.hxx>
39 #include <PrsMgr_ModedPresentation.hxx>
40 #include <PrsMgr_PresentationManager3d.hxx>
41 #include <Quantity_Color.hxx>
42 #include <Standard_Transient.hxx>
43 #include <Standard_Type.hxx>
44 #include <TColStd_ListIteratorOfListOfInteger.hxx>
45
46 IMPLEMENT_STANDARD_RTTIEXT(AIS_InteractiveObject,SelectMgr_SelectableObject)
47
48 //=======================================================================
49 //function : AIS_InteractiveObject
50 //purpose  : 
51 //=======================================================================
52 AIS_InteractiveObject::AIS_InteractiveObject (const PrsMgr_TypeOfPresentation3d aTypeOfPresentation3d)
53 : SelectMgr_SelectableObject (aTypeOfPresentation3d),
54   myCTXPtr (NULL),
55   myOwnWidth (0.0),
56   myCurrentFacingModel (Aspect_TOFM_BOTH_SIDE),
57   myInfiniteState (Standard_False),
58   hasOwnColor (Standard_False),
59   hasOwnMaterial (Standard_False),
60   myRecomputeEveryPrs (Standard_True)
61 {
62   SetCurrentFacingModel();
63 }
64
65 //=======================================================================
66 //function : Redisplay
67 //purpose  :
68 //=======================================================================
69 void AIS_InteractiveObject::Redisplay (const Standard_Boolean AllModes)
70 {
71   if (myCTXPtr == NULL)
72     return;
73
74   myCTXPtr->Redisplay (this, Standard_False, AllModes);
75 }
76
77 //=======================================================================
78 //function : Type
79 //purpose  : 
80 //=======================================================================
81
82 AIS_KindOfInteractive AIS_InteractiveObject::Type() const 
83 {return AIS_KOI_None;}
84
85 //=======================================================================
86 //function : Signature
87 //purpose  : 
88 //=======================================================================
89
90 Standard_Integer AIS_InteractiveObject::Signature() const 
91 {return -1;}
92
93 //=======================================================================
94 //function : RecomputeEveryPrs
95 //purpose  : 
96 //=======================================================================
97
98 Standard_Boolean  AIS_InteractiveObject::RecomputeEveryPrs() const 
99 {return myRecomputeEveryPrs;}
100
101 //=======================================================================
102 //function : 
103 //purpose  : 
104 //=======================================================================
105 Handle(AIS_InteractiveContext) AIS_InteractiveObject::GetContext() const 
106 {
107   return myCTXPtr;
108 }
109
110 //=======================================================================
111 //function : SetContext
112 //purpose  :
113 //=======================================================================
114 void AIS_InteractiveObject::SetContext (const Handle(AIS_InteractiveContext)& theCtx)
115 {
116   if (myCTXPtr == theCtx.get())
117   {
118     return;
119   }
120
121   myCTXPtr = theCtx.get();
122   if (!theCtx.IsNull())
123   {
124     myDrawer->Link (theCtx->DefaultDrawer());
125   }
126 }
127
128 //=======================================================================
129 //function : 
130 //purpose  : 
131 //=======================================================================
132 Standard_Boolean AIS_InteractiveObject::HasOwner() const 
133 {
134   return (!myOwner.IsNull());
135 }
136
137
138
139 //=======================================================================
140 //function : 
141 //purpose  : 
142 //=======================================================================
143 void AIS_InteractiveObject::ClearOwner()
144 {
145   myOwner.Nullify();
146 }
147
148 //=======================================================================
149 //function : SetDisplayMode
150 //purpose  :
151 //=======================================================================
152 void AIS_InteractiveObject::SetDisplayMode (const Standard_Integer theMode)
153 {
154   if (AcceptDisplayMode (theMode))
155   {
156     myDrawer->SetDisplayMode (theMode);
157   }
158 }
159
160 //=======================================================================
161 //function : 
162 //purpose  : 
163 //=======================================================================
164 void AIS_InteractiveObject::SetCurrentFacingModel(const Aspect_TypeOfFacingModel aModel) {
165   myCurrentFacingModel = aModel;
166 }
167
168 //=======================================================================
169 //function : CurrentFacingModel
170 //purpose  : 
171 //=======================================================================
172
173 Aspect_TypeOfFacingModel AIS_InteractiveObject::CurrentFacingModel() const {
174   return myCurrentFacingModel;
175 }
176
177 //=======================================================================
178 //function : SetColor
179 //purpose  : 
180 //=======================================================================
181
182 void AIS_InteractiveObject::SetColor(const Quantity_Color& theColor)
183 {
184   myDrawer->SetColor (theColor);
185   hasOwnColor = Standard_True;
186 }
187
188 //=======================================================================
189 //function : UnsetColor
190 //purpose  : 
191 //=======================================================================
192 void AIS_InteractiveObject::UnsetColor()
193 {
194   hasOwnColor = Standard_False;
195 }
196
197 //=======================================================================
198 //function : 
199 //purpose  : 
200 //=======================================================================
201 void AIS_InteractiveObject::SetWidth(const Standard_Real aValue)
202 {
203   myOwnWidth = aValue;
204 }
205
206 //=======================================================================
207 //function : 
208 //purpose  : 
209 //=======================================================================
210 void AIS_InteractiveObject::UnsetWidth()
211 {
212   myOwnWidth = 0.;
213 }
214
215 //=======================================================================
216 //function : Material
217 //purpose  :
218 //=======================================================================
219 Graphic3d_NameOfMaterial AIS_InteractiveObject::Material() const
220 {
221   return myDrawer->ShadingAspect()->Material().Name();
222 }
223
224 //=======================================================================
225 //function : SetMaterial
226 //purpose  :
227 //=======================================================================
228 void AIS_InteractiveObject::SetMaterial (const Graphic3d_MaterialAspect& theMaterial)
229 {
230   if (!myDrawer->HasOwnShadingAspect())
231   {
232     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
233     if (myDrawer->HasLink())
234     {
235       *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
236     }
237   }
238
239   myDrawer->ShadingAspect()->SetMaterial (theMaterial);
240   hasOwnMaterial = Standard_True;
241 }
242
243 //=======================================================================
244 //function : UnsetMaterial
245 //purpose  :
246 //=======================================================================
247 void AIS_InteractiveObject::UnsetMaterial()
248 {
249   if (!HasMaterial())
250   {
251     return;
252   }
253
254   if (HasColor() || IsTransparent())
255   {
256     if(myDrawer->HasLink())
257     {
258       myDrawer->ShadingAspect()->SetMaterial (AIS_GraphicTool::GetMaterial (myDrawer->Link()));
259     }
260
261     if (HasColor())
262     {
263       SetColor (myDrawer->Color());
264     }
265
266     if (IsTransparent())
267     {
268       SetTransparency (myDrawer->Transparency());
269     }
270   }
271   else
272   {
273     Handle(Prs3d_ShadingAspect) anAspect;
274     myDrawer->SetShadingAspect (anAspect);
275   }
276
277   hasOwnMaterial = Standard_False;
278 }
279
280 //=======================================================================
281 //function : SetTransparency
282 //purpose  :
283 //=======================================================================
284 void AIS_InteractiveObject::SetTransparency (const Standard_Real theValue)
285 {
286   if (!myDrawer->HasOwnShadingAspect())
287   {
288     myDrawer->SetShadingAspect(new Prs3d_ShadingAspect());
289     if(myDrawer->HasLink())
290       myDrawer->ShadingAspect()->SetMaterial(AIS_GraphicTool::GetMaterial(myDrawer->Link()));
291   }
292
293   myDrawer->ShadingAspect()->Aspect()->ChangeFrontMaterial().SetTransparency (Standard_ShortReal(theValue));
294   myDrawer->ShadingAspect()->Aspect()->ChangeBackMaterial() .SetTransparency (Standard_ShortReal(theValue));
295   myDrawer->SetTransparency (Standard_ShortReal(theValue));
296 }
297
298 //=======================================================================
299 //function : UnsetTransparency
300 //purpose  : 
301 //=======================================================================
302 void AIS_InteractiveObject::UnsetTransparency()
303 {
304   if(HasColor() || HasMaterial() )
305   {
306     myDrawer->ShadingAspect()->Aspect()->ChangeFrontMaterial().SetTransparency (0.0f);
307     myDrawer->ShadingAspect()->Aspect()->ChangeBackMaterial() .SetTransparency (0.0f);
308   }
309   else{
310     Handle (Prs3d_ShadingAspect) SA;
311     myDrawer->SetShadingAspect(SA);
312   }
313   myDrawer->SetTransparency (0.0f);
314 }
315 //=======================================================================
316 //function : Transparency
317 //purpose  : 
318 //=======================================================================
319 Standard_Real AIS_InteractiveObject::Transparency() const 
320 {
321   return (myDrawer->Transparency() <= 0.005f ? 0.0 : myDrawer->Transparency());
322 // Graphic3d_MaterialAspect Mat = myDrawer->ShadingAspect()->Aspect()->FrontMaterial();
323 // return Mat.Transparency();
324 }
325
326 //=======================================================================
327 //function : UnsetAttributes
328 //purpose  : 
329 //=======================================================================
330 void AIS_InteractiveObject::UnsetAttributes()
331 {
332   SelectMgr_SelectableObject::UnsetAttributes();
333
334   hasOwnColor    = Standard_False;
335   hasOwnMaterial = Standard_False;
336   myOwnWidth     = 0.0;
337   myDrawer->SetTransparency (0.0f);
338 }
339
340 //=======================================================================
341 //function : 
342 //purpose  : 
343 //=======================================================================
344 void AIS_InteractiveObject::MustRecomputePrs(const Standard_Integer ) const 
345 {}
346
347 //=======================================================================
348 //function : 
349 //purpose  : 
350 //=======================================================================
351 const TColStd_ListOfInteger& AIS_InteractiveObject::ListOfRecomputeModes() const 
352 {return myToRecomputeModes;}
353
354 //=======================================================================
355 //function : 
356 //purpose  : 
357 //=======================================================================
358 void AIS_InteractiveObject::SetRecomputeOk()
359 {myToRecomputeModes.Clear();}
360
361
362 //=======================================================================
363 //function : AcceptDisplayMode
364 //purpose  : 
365 //=======================================================================
366
367 Standard_Boolean  AIS_InteractiveObject::AcceptDisplayMode(const Standard_Integer ) const
368 {return Standard_True;}
369
370 //=======================================================================
371 //function : DefaultDisplayMode
372 //purpose  : 
373 //=======================================================================
374
375 Standard_Integer AIS_InteractiveObject::DefaultDisplayMode() const
376 {return 0;}
377
378
379 //=======================================================================
380 //function : SetInfiniteState
381 //purpose  : 
382 //=======================================================================
383 void AIS_InteractiveObject::SetInfiniteState(const Standard_Boolean aFlag)
384 {
385   myInfiniteState = aFlag;
386   Handle(Prs3d_Presentation) P;
387
388   for(Standard_Integer i =1; i<=myPresentations.Length();i++)
389   {
390     P = myPresentations(i).Presentation()->Presentation();
391     if(!P.IsNull())
392       P->SetInfiniteState(myInfiniteState);
393   }
394 }
395
396 //=======================================================================
397 //function : HasPresentation
398 //purpose  :
399 //=======================================================================
400 Standard_Boolean AIS_InteractiveObject::HasPresentation() const
401 {
402   return HasInteractiveContext()
403       && myCTXPtr->MainPrsMgr()->HasPresentation (this, myDrawer->DisplayMode());
404 }
405
406 //=======================================================================
407 //function : Presentation
408 //purpose  :
409 //=======================================================================
410 Handle(Prs3d_Presentation) AIS_InteractiveObject::Presentation() const
411 {
412   if (!HasInteractiveContext())
413   {
414     return Handle(Prs3d_Presentation)();
415   }
416
417   Handle(PrsMgr_Presentation) aPrs = myCTXPtr->MainPrsMgr()->Presentation (this, myDrawer->DisplayMode(), false);
418   return !aPrs.IsNull()
419        ? aPrs->Presentation()
420        : Handle(Prs3d_Presentation)();
421 }
422
423 //=======================================================================
424 //function : SetAspect 
425 //purpose  : 
426 //=======================================================================
427 void AIS_InteractiveObject::SetAspect(const Handle(Prs3d_BasicAspect)& anAspect)
428 {
429
430   if( HasPresentation() ) {
431     Handle(Prs3d_Presentation) prs = Presentation();
432     { Handle(Prs3d_ShadingAspect) aspect =
433                         Handle(Prs3d_ShadingAspect)::DownCast(anAspect);
434       if( !aspect.IsNull() ) {
435         Prs3d_Root::CurrentGroup(prs)->SetGroupPrimitivesAspect(aspect->Aspect());
436         return;
437       }
438     }
439     { Handle(Prs3d_LineAspect) aspect =
440                         Handle(Prs3d_LineAspect)::DownCast(anAspect);
441       if( !aspect.IsNull() ) {
442         Prs3d_Root::CurrentGroup(prs)->SetGroupPrimitivesAspect(aspect->Aspect());
443         return;
444       }
445     }
446     { Handle(Prs3d_PointAspect) aspect =
447                         Handle(Prs3d_PointAspect)::DownCast(anAspect);
448       if( !aspect.IsNull() ) {
449         Prs3d_Root::CurrentGroup(prs)->SetGroupPrimitivesAspect(aspect->Aspect());
450         return;
451       }
452     }
453     { Handle(Prs3d_TextAspect) aspect =
454                         Handle(Prs3d_TextAspect)::DownCast(anAspect);
455       if( !aspect.IsNull() ) {
456         Prs3d_Root::CurrentGroup(prs)->SetGroupPrimitivesAspect(aspect->Aspect());
457         return;
458       }
459     }
460   }
461 }
462
463 //=======================================================================
464 //function : SetPolygonOffsets 
465 //purpose  : 
466 //======================================================================= 
467 void AIS_InteractiveObject::SetPolygonOffsets(const Standard_Integer    aMode,
468                                               const Standard_ShortReal  aFactor,
469                                               const Standard_ShortReal  aUnits) 
470 {
471   if ( !HasPolygonOffsets() )
472     myDrawer->SetShadingAspect(new Prs3d_ShadingAspect());
473
474   myDrawer->ShadingAspect()->Aspect()->SetPolygonOffsets( aMode, aFactor, aUnits );
475
476   // Modify existing presentations 
477   for (Standard_Integer aPrsIter = 1, n = myPresentations.Length(); aPrsIter <= n; ++aPrsIter)
478   {
479     const Handle(PrsMgr_Presentation)& aPrs3d = myPresentations (aPrsIter).Presentation();
480     if ( !aPrs3d.IsNull() ) {
481       const Handle(Graphic3d_Structure)& aStruct = aPrs3d->Presentation();
482       if( !aStruct.IsNull() ) {
483         // Workaround for issue 23115: Need to update also groups, because their
484         // face aspect ALWAYS overrides the structure's.
485         const Graphic3d_SequenceOfGroup& aGroups = aStruct->Groups();
486         for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aGroups); aGroupIter.More(); aGroupIter.Next())
487         {
488           Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue();
489           if (aGrp.IsNull()
490           || !aGrp->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
491           {
492             continue;
493           }
494
495           Handle(Graphic3d_AspectFillArea3d) aFaceAsp = aGrp->FillAreaAspect();
496           aFaceAsp->SetPolygonOffsets(aMode, aFactor, aUnits);
497           aGrp->SetGroupPrimitivesAspect(aFaceAsp);
498         }
499       }
500     }
501   }
502 }
503
504 //=======================================================================
505 //function : HasPolygonOffsets 
506 //purpose  : 
507 //=======================================================================
508 Standard_Boolean AIS_InteractiveObject::HasPolygonOffsets() const
509 {
510   return !( myDrawer->ShadingAspect().IsNull() || 
511           ( myDrawer->HasLink() &&
512           myDrawer->ShadingAspect() == myDrawer->Link()->ShadingAspect() ) );
513 }
514
515 //=======================================================================
516 //function : PolygonOffsets 
517 //purpose  : 
518 //=======================================================================
519 void AIS_InteractiveObject::PolygonOffsets(Standard_Integer&    aMode,
520                                            Standard_ShortReal&  aFactor,
521                                            Standard_ShortReal&  aUnits) const 
522 {
523   if( HasPolygonOffsets() )
524     myDrawer->ShadingAspect()->Aspect()->PolygonOffsets( aMode, aFactor, aUnits );
525 }
526
527 //=======================================================================
528 //function : BoundingBox
529 //purpose  : Returns bounding box of object correspondingly to its
530 //           current display mode
531 //=======================================================================
532 void AIS_InteractiveObject::BoundingBox (Bnd_Box& theBndBox)
533 {
534   if (myDrawer->DisplayMode() == -1)
535   {
536     if (!myPresentations.IsEmpty())
537     {
538       const Handle(PrsMgr_Presentation)& aPrs3d = myPresentations.First().Presentation();
539       const Handle(Graphic3d_Structure)& aStruct = aPrs3d->Presentation();
540       const Graphic3d_BndBox3d& aBndBox = aStruct->CStructure()->BoundingBox();
541
542       if (!aBndBox.IsValid())
543       {
544         theBndBox.SetVoid();
545         return;
546       }
547
548       theBndBox.Update (aBndBox.CornerMin().x(), aBndBox.CornerMin().y(), aBndBox.CornerMin().z(),
549                         aBndBox.CornerMax().x(), aBndBox.CornerMax().y(), aBndBox.CornerMax().z());
550       return;
551     }
552     else
553     {
554       for (PrsMgr_ListOfPresentableObjectsIter aPrsIter (Children()); aPrsIter.More(); aPrsIter.Next())
555       {
556         Handle(AIS_InteractiveObject) aChild (Handle(AIS_InteractiveObject)::DownCast (aPrsIter.Value()));
557         if (aChild.IsNull())
558         {
559           continue;
560         }
561         Bnd_Box aBox;
562         aChild->BoundingBox (aBox);
563         theBndBox.Add (aBox);
564       }
565       return;
566     }
567   }
568   else
569   {
570     for (Standard_Integer aPrsIter = 1; aPrsIter <= myPresentations.Length(); ++aPrsIter)
571     {
572       if (myPresentations (aPrsIter).Mode() == myDrawer->DisplayMode())
573       {
574         const Handle(PrsMgr_Presentation)& aPrs3d = myPresentations (aPrsIter).Presentation();
575         const Handle(Graphic3d_Structure)& aStruct = aPrs3d->Presentation();
576         const Graphic3d_BndBox3d& aBndBox = aStruct->CStructure()->BoundingBox();
577
578         if (!aBndBox.IsValid())
579         {
580           theBndBox.SetVoid();
581           return;
582         }
583
584         theBndBox.Update (aBndBox.CornerMin().x(), aBndBox.CornerMin().y(), aBndBox.CornerMin().z(),
585                           aBndBox.CornerMax().x(), aBndBox.CornerMax().y(), aBndBox.CornerMax().z());
586         return;
587       }
588     }
589   }
590 }
591
592 //=======================================================================
593 //function : SetIsoOnTriangulation
594 //purpose  : Enables or disables isoline on triangulation building
595 //=======================================================================
596 void AIS_InteractiveObject::SetIsoOnTriangulation (const Standard_Boolean theIsEnabled)
597 {
598   myDrawer->SetIsoOnTriangulation (theIsEnabled);
599 }
600
601 //=======================================================================
602 //function : SynchronizeAspects
603 //purpose  :
604 //=======================================================================
605 void AIS_InteractiveObject::SynchronizeAspects()
606 {
607   for (PrsMgr_Presentations::Iterator aPrsIter (myPresentations); aPrsIter.More(); aPrsIter.Next())
608   {
609     const Handle(PrsMgr_Presentation)& aPrs3d = aPrsIter.ChangeValue().Presentation();
610     if (aPrs3d.IsNull()
611      || aPrs3d->Presentation().IsNull())
612     {
613       continue;
614     }
615
616     for (Graphic3d_SequenceOfGroup::Iterator aGroupIter (aPrs3d->Presentation()->Groups()); aGroupIter.More(); aGroupIter.Next())
617     {
618       Handle(Graphic3d_Group)& aGrp = aGroupIter.ChangeValue();
619       if (aGrp.IsNull())
620       {
621         continue;
622       }
623
624       Handle(Graphic3d_AspectLine3d)     aLineAspect   = aGrp->LineAspect();
625       Handle(Graphic3d_AspectFillArea3d) aFaceAspect   = aGrp->FillAreaAspect();
626       Handle(Graphic3d_AspectMarker3d)   aMarkerAspect = aGrp->MarkerAspect();
627       Handle(Graphic3d_AspectText3d)     aTextAspect   = aGrp->TextAspect();
628       if (!aLineAspect.IsNull())
629       {
630         aGrp->SetGroupPrimitivesAspect (aLineAspect);
631       }
632       if (!aFaceAspect.IsNull())
633       {
634         aGrp->SetGroupPrimitivesAspect (aFaceAspect);
635       }
636       if (!aMarkerAspect.IsNull())
637       {
638         aGrp->SetGroupPrimitivesAspect (aMarkerAspect);
639       }
640       if (!aTextAspect.IsNull())
641       {
642         aGrp->SetGroupPrimitivesAspect (aTextAspect);
643       }
644     }
645   }
646 }