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