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