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