1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkQWidgetRepresentation.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 "vtkQWidgetRepresentation.h"
16
17 #include "vtkActor.h"
18 #include "vtkCellPicker.h"
19 #include "vtkEventData.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkOpenGLRenderWindow.h"
22 #include "vtkOpenGLState.h"
23 #include "vtkOpenGLTexture.h"
24 #include "vtkPickingManager.h"
25 #include "vtkPlaneSource.h"
26 #include "vtkPolyDataMapper.h"
27 #include "vtkProperty.h"
28 #include "vtkQWidgetTexture.h"
29 #include "vtkRenderer.h"
30 #include "vtkVectorOperators.h"
31 #include <QtWidgets/QWidget>
32
33 #include "vtk_glew.h"
34
35 vtkStandardNewMacro(vtkQWidgetRepresentation);
36
37 //------------------------------------------------------------------------------
vtkQWidgetRepresentation()38 vtkQWidgetRepresentation::vtkQWidgetRepresentation()
39 {
40 this->PlaneSource = vtkPlaneSource::New();
41 this->PlaneSource->SetOutputPointsPrecision(vtkAlgorithm::DOUBLE_PRECISION);
42
43 this->PlaneMapper = vtkPolyDataMapper::New();
44 this->PlaneMapper->SetInputConnection(this->PlaneSource->GetOutputPort());
45
46 this->QWidgetTexture = vtkQWidgetTexture::New();
47 this->PlaneTexture = vtkOpenGLTexture::New();
48 this->PlaneTexture->SetTextureObject(this->QWidgetTexture);
49
50 this->PlaneActor = vtkActor::New();
51 this->PlaneActor->SetMapper(this->PlaneMapper);
52 this->PlaneActor->SetTexture(this->PlaneTexture);
53 this->PlaneActor->GetProperty()->SetAmbient(1.0);
54 this->PlaneActor->GetProperty()->SetDiffuse(0.0);
55 this->PlaneActor->ForceOpaqueOn();
56
57 // Define the point coordinates
58 double bounds[6];
59 bounds[0] = -0.5;
60 bounds[1] = 0.5;
61 bounds[2] = -0.5;
62 bounds[3] = 0.5;
63 bounds[4] = -0.5;
64 bounds[5] = 0.5;
65
66 // Initial creation of the widget, serves to initialize it
67 this->PlaceWidget(bounds);
68
69 this->Picker = vtkCellPicker::New();
70 this->Picker->SetTolerance(0.005);
71 this->Picker->AddPickList(this->PlaneActor);
72 this->Picker->PickFromListOn();
73 }
74
75 //------------------------------------------------------------------------------
~vtkQWidgetRepresentation()76 vtkQWidgetRepresentation::~vtkQWidgetRepresentation()
77 {
78 this->PlaneSource->Delete();
79 this->PlaneMapper->Delete();
80 this->PlaneActor->Delete();
81 this->PlaneTexture->Delete();
82 this->QWidgetTexture->Delete();
83
84 this->Picker->Delete();
85 }
86
SetWidget(QWidget * w)87 void vtkQWidgetRepresentation::SetWidget(QWidget* w)
88 {
89 // just pass down to the QWidgetTexture
90 this->QWidgetTexture->SetWidget(w);
91 this->Modified();
92 }
93
94 // see if the event hits the widget rep, if so set the WidgetCoordinates
95 // and move to Inside state
ComputeComplexInteractionState(vtkRenderWindowInteractor *,vtkAbstractWidget *,unsigned long,void * calldata,int)96 int vtkQWidgetRepresentation::ComputeComplexInteractionState(
97 vtkRenderWindowInteractor*, vtkAbstractWidget*, unsigned long, void* calldata, int)
98 {
99 vtkEventData* edata = static_cast<vtkEventData*>(calldata);
100 vtkEventDataDevice3D* edd = edata->GetAsEventDataDevice3D();
101 if (edd)
102 {
103 // compute intersection point using math, faster better
104 vtkVector3d origin;
105 this->PlaneSource->GetOrigin(origin.GetData());
106 vtkVector3d axis0;
107 this->PlaneSource->GetPoint1(axis0.GetData());
108 vtkVector3d axis1;
109 this->PlaneSource->GetPoint2(axis1.GetData());
110
111 axis0 = axis0 - origin;
112 axis1 = axis1 - origin;
113
114 vtkVector3d rpos;
115 edd->GetWorldPosition(rpos.GetData());
116 rpos = rpos - origin;
117
118 vtkVector3d rdir;
119 edd->GetWorldDirection(rdir.GetData());
120
121 double lengtha0 = vtkMath::Normalize(axis0.GetData());
122 double lengtha1 = vtkMath::Normalize(axis1.GetData());
123
124 vtkVector3d pnorm;
125 pnorm = axis0.Cross(axis1);
126 pnorm.Normalize();
127 double dist = rpos.Dot(pnorm) / rdir.Dot(pnorm);
128 rpos = rpos - rdir * dist;
129 double wCoords[2] = { 0.0, 0.0 };
130 wCoords[0] = rpos.Dot(axis0) / lengtha0;
131 wCoords[1] = rpos.Dot(axis1) / lengtha1;
132
133 if (wCoords[0] < 0.0 || wCoords[0] > 1.0 || wCoords[1] < 0.0 || wCoords[1] > 1.0)
134 {
135 this->InteractionState = vtkQWidgetRepresentation::Outside;
136 return this->InteractionState;
137 }
138
139 // the ray hit the widget
140 this->ValidPick = 1;
141 this->InteractionState = vtkQWidgetRepresentation::Inside;
142
143 QWidget* widget = this->QWidgetTexture->GetWidget();
144 this->WidgetCoordinates[0] = wCoords[0] * widget->width();
145 this->WidgetCoordinates[1] = wCoords[1] * widget->height();
146 this->WidgetCoordinates[1] = widget->height() - this->WidgetCoordinates[1];
147 }
148
149 return this->InteractionState;
150 }
151
152 //------------------------------------------------------------------------------
GetBounds()153 double* vtkQWidgetRepresentation::GetBounds()
154 {
155 this->BuildRepresentation();
156 return this->PlaneActor->GetBounds();
157 }
158
159 //------------------------------------------------------------------------------
GetActors(vtkPropCollection * pc)160 void vtkQWidgetRepresentation::GetActors(vtkPropCollection* pc)
161 {
162 this->PlaneActor->GetActors(pc);
163 }
164
165 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * w)166 void vtkQWidgetRepresentation::ReleaseGraphicsResources(vtkWindow* w)
167 {
168 this->PlaneActor->ReleaseGraphicsResources(w);
169 this->PlaneMapper->ReleaseGraphicsResources(w);
170 this->PlaneTexture->ReleaseGraphicsResources(w);
171 }
172
173 //------------------------------------------------------------------------------
RenderOpaqueGeometry(vtkViewport * v)174 int vtkQWidgetRepresentation::RenderOpaqueGeometry(vtkViewport* v)
175 {
176 vtkInformation* info = this->GetPropertyKeys();
177 this->PlaneActor->SetPropertyKeys(info);
178
179 vtkOpenGLRenderWindow* renWin = static_cast<vtkOpenGLRenderWindow*>(v->GetVTKWindow());
180 vtkOpenGLState* ostate = renWin->GetState();
181
182 // always draw over the rest
183 ostate->vtkglDepthFunc(GL_ALWAYS);
184 int result = this->PlaneActor->RenderOpaqueGeometry(v);
185 ostate->vtkglDepthFunc(GL_LEQUAL);
186
187 return result;
188 }
189
190 //------------------------------------------------------------------------------
RenderTranslucentPolygonalGeometry(vtkViewport *)191 int vtkQWidgetRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport*)
192 {
193 return 0;
194 }
195
196 //------------------------------------------------------------------------------
HasTranslucentPolygonalGeometry()197 vtkTypeBool vtkQWidgetRepresentation::HasTranslucentPolygonalGeometry()
198 {
199 return false;
200 }
201
202 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)203 void vtkQWidgetRepresentation::PrintSelf(ostream& os, vtkIndent indent)
204 {
205 this->Superclass::PrintSelf(os, indent);
206
207 // this->InteractionState is printed in superclass
208 // this is commented to avoid PrintSelf errors
209 }
210
211 //------------------------------------------------------------------------------
PlaceWidget(double bds[6])212 void vtkQWidgetRepresentation::PlaceWidget(double bds[6])
213 {
214 this->PlaneSource->SetOrigin(bds[0], bds[2], bds[4]);
215 this->PlaneSource->SetPoint1(bds[1], bds[2], bds[4]);
216 this->PlaneSource->SetPoint2(bds[0], bds[2], bds[5]);
217
218 this->ValidPick = 1; // since we have positioned the widget successfully
219 }
220
221 //------------------------------------------------------------------------------
GetPolyDataAlgorithm()222 vtkPolyDataAlgorithm* vtkQWidgetRepresentation::GetPolyDataAlgorithm()
223 {
224 return this->PlaneSource;
225 }
226
227 //------------------------------------------------------------------------------
UpdatePlacement()228 void vtkQWidgetRepresentation::UpdatePlacement() {}
229
230 //------------------------------------------------------------------------------
BuildRepresentation()231 void vtkQWidgetRepresentation::BuildRepresentation()
232 {
233 // rep is always built via plane source and doesn't change
234 }
235
236 //------------------------------------------------------------------------------
RegisterPickers()237 void vtkQWidgetRepresentation::RegisterPickers()
238 {
239 vtkPickingManager* pm = this->GetPickingManager();
240 if (!pm)
241 {
242 return;
243 }
244 pm->AddPicker(this->Picker, this);
245 }
246