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