1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkProp3DButtonRepresentation.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkPickingManager.h"
16 #include "vtkProp3DButtonRepresentation.h"
17 #include "vtkProp3D.h"
18 #include "vtkPropPicker.h"
19 #include "vtkProp3DFollower.h"
20 #include "vtkRenderer.h"
21 #include "vtkRenderWindowInteractor.h"
22 #include "vtkAssemblyPath.h"
23 #include "vtkInteractorObserver.h"
24 #include "vtkCoordinate.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkCamera.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkSmartPointer.h"
29 #include "vtkMath.h"
30 #include <map>
31 
32 vtkStandardNewMacro(vtkProp3DButtonRepresentation);
33 
34 struct vtkScaledProp
35 {
36   vtkSmartPointer<vtkProp3D> Prop;
37   double Origin[3];
38   double Scale;
39   double Translation[3];
vtkScaledPropvtkScaledProp40   vtkScaledProp()
41   {
42       this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0;
43       this->Scale = 1.0;
44       this->Translation[0] = this->Translation[1] = this->Translation[2] = 0.0;
45   }
46 };
47 
48 // Map of textures
49 class vtkPropArray : public std::map<int,vtkScaledProp> {};
50 typedef std::map<int,vtkScaledProp>::iterator vtkPropArrayIterator;
51 
52 
53 //----------------------------------------------------------------------
vtkProp3DButtonRepresentation()54 vtkProp3DButtonRepresentation::vtkProp3DButtonRepresentation()
55 {
56   // Current button representation
57   this->CurrentProp = nullptr;
58 
59   // Following
60   this->FollowCamera = 0;
61   this->Follower = vtkProp3DFollower::New();
62 
63   // List of textures
64   this->PropArray = new vtkPropArray;
65 
66   this->Picker = vtkPropPicker::New();
67   this->Picker->PickFromListOn();
68 }
69 
70 //----------------------------------------------------------------------
~vtkProp3DButtonRepresentation()71 vtkProp3DButtonRepresentation::~vtkProp3DButtonRepresentation()
72 {
73   this->Follower->Delete();
74 
75   delete this->PropArray;
76 
77   this->Picker->Delete();
78 }
79 
80 //-------------------------------------------------------------------------
SetState(int state)81 void vtkProp3DButtonRepresentation::SetState(int state)
82 {
83   this->Superclass::SetState(state);
84 
85   this->CurrentProp = this->GetButtonProp(this->State);
86   this->Follower->SetProp3D(this->CurrentProp);
87 
88   this->Picker->InitializePickList();
89   if ( this->CurrentProp )
90   {
91     this->Picker->AddPickList(this->CurrentProp);
92   }
93 }
94 
95 //-------------------------------------------------------------------------
96 void vtkProp3DButtonRepresentation::
SetButtonProp(int i,vtkProp3D * prop)97 SetButtonProp(int i, vtkProp3D *prop)
98 {
99   if ( i < 0 )
100   {
101     i = 0;
102   }
103   if ( i >= this->NumberOfStates )
104   {
105     i = this->NumberOfStates - 1;
106   }
107 
108   vtkScaledProp sprop;
109   sprop.Prop = prop;
110 
111   (*this->PropArray)[i] = sprop;
112 }
113 
114 
115 //-------------------------------------------------------------------------
116 vtkProp3D *vtkProp3DButtonRepresentation::
GetButtonProp(int i)117 GetButtonProp(int i)
118 {
119   if ( i < 0 )
120   {
121     i = 0;
122   }
123   if ( i >= this->NumberOfStates )
124   {
125     i = this->NumberOfStates - 1;
126   }
127 
128   vtkPropArrayIterator iter = this->PropArray->find(i);
129   if ( iter != this->PropArray->end() )
130   {
131     return (*iter).second.Prop;
132   }
133   else
134   {
135     return nullptr;
136   }
137 }
138 
139 //------------------------------------------------------------------------------
RegisterPickers()140 void vtkProp3DButtonRepresentation::RegisterPickers()
141 {
142   vtkPickingManager* pm = this->GetPickingManager();
143   if (!pm)
144   {
145     return;
146   }
147   pm->AddPicker(this->Picker, this);
148 }
149 
150 //-------------------------------------------------------------------------
PlaceWidget(double bds[6])151 void vtkProp3DButtonRepresentation::PlaceWidget(double bds[6])
152 {
153   double bounds[6], center[3], aBds[6], aCenter[3];
154 
155   this->AdjustBounds(bds, bounds, center);
156   for (int i=0; i<6; i++)
157   {
158     this->InitialBounds[i] = bounds[i];
159   }
160   this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
161                              (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
162                              (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
163 
164   this->SetState(this->State);
165 
166   vtkProp3D *prop;
167   vtkPropArrayIterator iter;
168   for ( iter=this->PropArray->begin(); iter != this->PropArray->end(); ++iter )
169   {
170     prop = (*iter).second.Prop;
171 
172     prop->GetBounds(aBds);
173     aCenter[0] = (aBds[0]+aBds[1]) / 2.0;
174     aCenter[1] = (aBds[2]+aBds[3]) / 2.0;
175     aCenter[2] = (aBds[4]+aBds[5]) / 2.0;
176 
177     // Now fit the actor bounds in the place bounds by tampering with its
178     // transform.
179     (*iter).second.Origin[0] = aCenter[0];
180     (*iter).second.Origin[1] = aCenter[1];
181     (*iter).second.Origin[2] = aCenter[2];
182 
183     (*iter).second.Translation[0] = center[0]-aCenter[0];
184     (*iter).second.Translation[1] = center[1]-aCenter[1];
185     (*iter).second.Translation[2] = center[2]-aCenter[2];
186 
187     double s[3], sMin;
188     for (int i=0; i < 3; ++i)
189     {
190       if ( (bounds[2*i+1]-bounds[2*i]) <= 0.0 || (aBds[2*i+1]-aBds[2*i]) <= 0.0 )
191       {
192         s[i] = VTK_FLOAT_MAX;
193       }
194       else
195       {
196         s[i] = (bounds[2*i+1]-bounds[2*i]) / (aBds[2*i+1]-aBds[2*i]);
197       }
198     }
199     sMin = (s[0]<s[1] ? (s[0]<s[2] ? s[0] : s[2]) : (s[1]<s[2] ? s[1] : s[2]) );
200 
201     (*iter).second.Scale = sMin;
202   }
203 }
204 
205 //-------------------------------------------------------------------------
206 int vtkProp3DButtonRepresentation
ComputeInteractionState(int X,int Y,int vtkNotUsed (modify))207 ::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify))
208 {
209   this->InteractionState = vtkButtonRepresentation::Outside;
210   if (!this->Renderer ||
211       !this->Renderer->GetRenderWindow()->GetMapped())
212   {
213     return this->InteractionState;
214   }
215   this->VisibilityOn(); //actor must be on to be picked
216 
217   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->Picker);
218 
219   if ( path != nullptr )
220   {
221     this->InteractionState = vtkButtonRepresentation::Inside;
222   }
223 
224   return this->InteractionState;
225 }
226 
227 //----------------------------------------------------------------------
BuildRepresentation()228 void vtkProp3DButtonRepresentation::BuildRepresentation()
229 {
230   // The net effect is to resize the handle
231   if ( this->GetMTime() > this->BuildTime ||
232        (this->Renderer && this->Renderer->GetVTKWindow() &&
233         this->Renderer->GetVTKWindow()->GetMTime() > this->BuildTime) )
234   {
235     this->SetState(this->State); //side effect sets CurrentProp
236     vtkPropArrayIterator iter = this->PropArray->find(this->State);
237     if ( this->CurrentProp == nullptr || iter == this->PropArray->end() )
238     {
239       return;
240     }
241 
242     // In case follower is being used
243     if ( this->FollowCamera )
244     {
245       this->Follower->SetCamera(this->Renderer->GetActiveCamera());
246       this->Follower->SetProp3D(this->CurrentProp);
247       this->Follower->SetOrigin((*iter).second.Origin);
248       this->Follower->SetPosition((*iter).second.Translation);
249       this->Follower->SetScale((*iter).second.Scale);
250     }
251     else
252     {
253       this->CurrentProp->SetOrigin((*iter).second.Origin);
254       this->CurrentProp->SetPosition((*iter).second.Translation);
255       this->CurrentProp->SetScale((*iter).second.Scale);
256     }
257 
258     this->BuildTime.Modified();
259   }
260 }
261 
262 
263 //----------------------------------------------------------------------
ShallowCopy(vtkProp * prop)264 void vtkProp3DButtonRepresentation::ShallowCopy(vtkProp *prop)
265 {
266   vtkProp3DButtonRepresentation *rep =
267     vtkProp3DButtonRepresentation::SafeDownCast(prop);
268   if ( rep )
269   {
270     vtkPropArrayIterator iter;
271     for ( iter=rep->PropArray->begin();
272           iter != rep->PropArray->end(); ++iter )
273     {
274       (*this->PropArray)[(*iter).first] = (*iter).second;
275     }
276     this->FollowCamera = rep->FollowCamera;
277   }
278 
279   this->Superclass::ShallowCopy(prop);
280 }
281 
282 //----------------------------------------------------------------------
283 void vtkProp3DButtonRepresentation::
ReleaseGraphicsResources(vtkWindow * win)284 ReleaseGraphicsResources(vtkWindow *win)
285 {
286   this->Follower->ReleaseGraphicsResources(win);
287 }
288 
289 //----------------------------------------------------------------------
290 int vtkProp3DButtonRepresentation::
RenderVolumetricGeometry(vtkViewport * viewport)291 RenderVolumetricGeometry(vtkViewport *viewport)
292 {
293   this->BuildRepresentation();
294 
295   if ( !this->CurrentProp )
296   {
297     return 0;
298   }
299 
300   if ( this->FollowCamera )
301   {
302     return this->Follower->RenderVolumetricGeometry(viewport);
303   }
304   else
305   {
306     return this->CurrentProp->RenderVolumetricGeometry(viewport);
307   }
308 }
309 
310 //----------------------------------------------------------------------
311 int vtkProp3DButtonRepresentation::
RenderOpaqueGeometry(vtkViewport * viewport)312 RenderOpaqueGeometry(vtkViewport *viewport)
313 {
314   this->BuildRepresentation();
315 
316   if ( !this->CurrentProp )
317   {
318     return 0;
319   }
320 
321   if ( this->FollowCamera )
322   {
323     return this->Follower->RenderOpaqueGeometry(viewport);
324   }
325   else
326   {
327     return this->CurrentProp->RenderOpaqueGeometry(viewport);
328   }
329 }
330 
331 //-----------------------------------------------------------------------------
332 int vtkProp3DButtonRepresentation::
RenderTranslucentPolygonalGeometry(vtkViewport * viewport)333 RenderTranslucentPolygonalGeometry(vtkViewport *viewport)
334 {
335   this->BuildRepresentation();
336 
337   if ( !this->CurrentProp )
338   {
339     return 0;
340   }
341 
342   if ( this->FollowCamera )
343   {
344     return this->Follower->RenderTranslucentPolygonalGeometry(viewport);
345   }
346   else
347   {
348     return this->CurrentProp->RenderTranslucentPolygonalGeometry(viewport);
349   }
350 }
351 //-----------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()352 vtkTypeBool vtkProp3DButtonRepresentation::HasTranslucentPolygonalGeometry()
353 {
354   this->BuildRepresentation();
355 
356   if ( this->CurrentProp )
357   {
358     return this->CurrentProp->HasTranslucentPolygonalGeometry();
359   }
360   else
361   {
362     return 0;
363   }
364 }
365 
366 
367 //----------------------------------------------------------------------
GetBounds()368 double *vtkProp3DButtonRepresentation::GetBounds()
369 {
370   if ( !this->CurrentProp )
371   {
372     return nullptr;
373   }
374 
375   if ( this->FollowCamera )
376   {
377     return this->Follower->GetBounds();
378   }
379   else
380   {
381     return this->CurrentProp->GetBounds();
382   }
383 }
384 
385 //----------------------------------------------------------------------
GetActors(vtkPropCollection * pc)386 void vtkProp3DButtonRepresentation::GetActors(vtkPropCollection *pc)
387 {
388   if ( this->CurrentProp )
389   {
390     this->CurrentProp->GetActors(pc);
391   }
392 }
393 
394 //----------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)395 void vtkProp3DButtonRepresentation::PrintSelf(ostream& os, vtkIndent indent)
396 {
397   //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h
398   this->Superclass::PrintSelf(os,indent);
399 
400   os << indent << "Follow Camera: " << (this->FollowCamera ? "On\n" : "Off\n");
401 
402   os << indent << "3D Props: \n";
403   vtkPropArrayIterator iter;
404   int i;
405   for ( i=0, iter=this->PropArray->begin();
406         iter != this->PropArray->end(); ++iter, ++i )
407   {
408     os << indent << "  (" << i << "): " << (*iter).second.Prop << "\n";
409   }
410 }
411