1 #if defined(_MSC_VER) /* MSVC Compiler */
2 #pragma warning ( disable : 4305 )
3 #pragma warning ( disable : 4786 )
4 #endif
5 
6 #include "qwt3d_extglwidget.h"
7 
8 using namespace std;
9 using namespace Qwt3D;
10 
11 
12 /**
13 	Standard mouse button Function. Prepares the call to mouseMoveEvent
14 	\see mouseMoveEvent()
15 */
16 void ExtGLWidget::mousePressEvent( QMouseEvent *e )
17 {
18 	lastMouseMovePosition_ = e->pos();
19 	mpressed_ = true;
20 }
21 
22 /**
23 	Standard mouse button Function. Completes the call to mouseMoveEvent
24 	\see mouseMoveEvent()
25 */
26 void ExtGLWidget::mouseReleaseEvent( QMouseEvent* )
27 {
28 	mpressed_ = false;
29 }
30 
31 /**
32 	Standard mouse button Function
33 	\see assignMouse()
34 */
35 void ExtGLWidget::mouseMoveEvent( QMouseEvent *e )
36 {
37 	if (!mpressed_ || !mouseEnabled()) {
38 		e->ignore();
39 		return;
40 	}
41 
42 #if QT_VERSION < 0x040000
43 	MouseState bstate = e->state();
44 #else
45 	MouseState bstate(e->buttons(),e->modifiers());
46 #endif
47 
48 	QPoint diff = e->pos() - lastMouseMovePosition_;
49 
50 	setRotationMouse(bstate, 3, diff);
51 	setScaleMouse(bstate, 5, diff);
52 	setShiftMouse(bstate, 2, diff);
53 
54 	lastMouseMovePosition_ = e->pos();
55 }
56 
57 void ExtGLWidget::setRotationMouse(MouseState bstate, double accel, QPoint diff)
58 {
59 	// Rotation
60 	double w = max(1,width());
61 	double h = max(1,height());
62 
63 	double relx = accel*360 * diff.x() / w;
64 	double relyz = accel*360 * diff.y() / h;
65 
66 	double new_xrot = xRotation();
67 	double new_yrot = yRotation();
68 	double new_zrot = zRotation();
69 
70 	if ( bstate == xrot_mstate_ )
71 		new_xrot = round(xRotation() + relyz) % 360;
72 	if ( bstate == yrot_mstate_ )
73 		new_yrot = round(yRotation() + relx) % 360;
74 	if ( bstate == zrot_mstate_ )
75 		new_zrot = round(zRotation() + relx) % 360;
76 
77 	setRotation(new_xrot, new_yrot, new_zrot);
78 }
79 
80 void ExtGLWidget::setScaleMouse(MouseState bstate, double accel, QPoint diff)
81 {
82 	// Scale
83 	double w = max(1,width());
84 	double h = max(1,height());
85 
86 	double relx = diff.x() * accel / w; relx = exp(relx) - 1;
87 	double relyz = diff.y() * accel / h; relyz = exp(relyz) - 1;
88 
89 	double new_xscale = xScale();
90 	double new_yscale = yScale();
91 	double new_zscale = zScale();
92 
93 	if ( bstate == xscale_mstate_)
94 		new_xscale = max(0.0,xScale() + relx);
95 	if ( bstate == yscale_mstate_)
96 		new_yscale = max(0.0,yScale() - relyz);
97 	if ( bstate == zscale_mstate_)
98 		new_zscale = max(0.0,zScale() - relyz);
99 
100 	setScale(new_xscale, new_yscale, new_zscale);
101 
102 	if ( bstate == zoom_mstate_)
103 		setZoom(max(0.0,zoom() - relyz));
104 }
105 
106 void ExtGLWidget::setShiftMouse(MouseState bstate, double accel, QPoint diff)
107 {
108 	// Shift
109 	double w = max(1,width());
110 	double h = max(1,height());
111 
112 	double relx = diff.x() * accel / w;
113 	double relyz = diff.y() * accel / h;
114 
115 	double new_xshift = xViewportShift();
116 	double new_yshift = yViewportShift();
117 
118 	if ( bstate == xshift_mstate_)
119 		new_xshift = xViewportShift() + relx;
120 	if ( bstate == yshift_mstate_)
121 		new_yshift = yViewportShift() - relyz;
122 
123 	setViewportShift(new_xshift, new_yshift);
124 }
125 
126 /**
127 	Standard wheel Function - zoom (wheel only) or z-scale (shift+wheel)
128 */
129 void ExtGLWidget::wheelEvent( QWheelEvent *e )
130 {
131 	if (!mouseEnabled())	return;
132 
133 	double accel = 0.05;
134 	double step =  accel * e->delta() / WHEEL_DELTA ;
135 	step = exp(step)-1;
136 
137 #if QT_VERSION < 0x040000
138 	if ( e->state() & Qt::ShiftButton )
139 #else
140 	if ( e->modifiers() & Qt::ShiftModifier )
141 #endif
142 		setScale(xScale(),yScale(), max(0.0,zScale() + step));
143 	else
144 		setZoom(max(0.0,zoom() + step ));
145 }
146 
147 /**
148 	Sets the key/mousebutton combination for data/coordinatesystem moves inside the widget\n\n
149 	default behaviour:\n
150 
151 	\verbatim
152 	rotate around x axis: Qt::LeftButton
153 	rotate around y axis: Qt::LeftButton | Qt::ShiftButton
154 	rotate around z axis: Qt::LeftButton
155 	scale x:              Qt::LeftButton | Qt::AltButton
156 	scale y:              Qt::LeftButton | Qt::AltButton
157 	scale z:              Qt::LeftButton | Qt::AltButton | Qt::ShiftButton
158 	zoom:                 Qt::LeftButton | Qt::AltButton | Qt::ControlButton
159 	shifting along x:     Qt::LeftButton | Qt::ControlButton
160 	shifting along y:     Qt::LeftButton | Qt::ControlButton
161 	\endverbatim
162 
163 	mouseMoveEvent() evaluates this function - if overridden, their usefulness becomes somehow limited
164 */
165 void ExtGLWidget::assignMouse(MouseState xrot, MouseState yrot, MouseState zrot,
166 											 MouseState xscale, MouseState yscale, MouseState zscale,
167 											 MouseState zoom, MouseState xshift, MouseState yshift)
168 {
169 	xrot_mstate_   = 	xrot;
170 	yrot_mstate_   =  yrot;
171 	zrot_mstate_   =  zrot;
172 	xscale_mstate_ =  xscale;
173 	yscale_mstate_ =  yscale;
174 	zscale_mstate_ =  zscale;
175 	zoom_mstate_   =  zoom;
176 	xshift_mstate_ =  xshift;
177 	yshift_mstate_ =  yshift;
178 }
179 
180 /**
181 The function has no effect if you derive from ExtGLWidget and overrides the mouse Function too careless.
182 In this case check first against mouseEnabled() in your version of mouseMoveEvent() and wheelEvent().
183 A more fine grained input control can be achieved by combining assignMouse() with enableMouse().
184 */
185 void ExtGLWidget::enableMouse(bool val) {mouse_input_enabled_ = val;}
186 
187 /**
188 \see enableMouse()
189 */
190 void ExtGLWidget::disableMouse(bool val) {mouse_input_enabled_ = !val;}
191 bool ExtGLWidget::mouseEnabled() const {return mouse_input_enabled_;}
192 
193 
194 void ExtGLWidget::keyPressEvent( QKeyEvent *e )
195 {
196 	if (!keyboardEnabled()) {
197 		e->ignore();
198 		return;
199 	}
200 
201 #if QT_VERSION < 0x040000
202 	int bstate = e->state() & Qt::KeyButtonMask; // filter kbd modifier only
203 	KeyboardState keyseq = bstate + e->key();
204 #else
205 	KeyboardState keyseq(e->key(), e->modifiers());
206 #endif
207 
208 	setRotationKeyboard(keyseq, kbd_rot_speed_);
209 	setScaleKeyboard(keyseq, kbd_scale_speed_);
210 	setShiftKeyboard(keyseq, kbd_shift_speed_);
211 }
212 
213 void ExtGLWidget::setRotationKeyboard(KeyboardState kseq, double speed)
214 {
215 	// Rotation
216 	double w = max(1,width());
217 	double h = max(1,height());
218 
219 	double relx = speed*360 / w;
220 	double relyz = speed*360 / h;
221 
222 	double new_xrot = xRotation();
223 	double new_yrot = yRotation();
224 	double new_zrot = zRotation();
225 
226 	if ( kseq == xrot_kstate_[0] )
227 		new_xrot = round(xRotation() + relyz) % 360;
228 	if ( kseq == xrot_kstate_[1] )
229 		new_xrot = round(xRotation() - relyz) % 360;
230 	if ( kseq == yrot_kstate_[0] )
231 		new_yrot = round(yRotation() + relx) % 360;
232 	if ( kseq == yrot_kstate_[1] )
233 		new_yrot = round(yRotation() - relx) % 360;
234 	if ( kseq == zrot_kstate_[0] )
235 		new_zrot = round(zRotation() + relx) % 360;
236 	if ( kseq == zrot_kstate_[1] )
237 		new_zrot = round(zRotation() - relx) % 360;
238 
239 	setRotation(new_xrot, new_yrot, new_zrot);
240 }
241 
242 void ExtGLWidget::setScaleKeyboard(KeyboardState kseq, double speed)
243 {
244 	// Scale
245 	double w = max(1,width());
246 	double h = max(1,height());
247 
248 	double relx = speed / w; relx = exp(relx) - 1;
249 	double relyz = speed / h; relyz = exp(relyz) - 1;
250 
251 	double new_xscale = xScale();
252 	double new_yscale = yScale();
253 	double new_zscale = zScale();
254 
255 	if ( kseq == xscale_kstate_[0])
256 		new_xscale = max(0.0,xScale() + relx);
257 	if ( kseq == xscale_kstate_[1])
258 		new_xscale = max(0.0,xScale() - relx);
259 	if ( kseq == yscale_kstate_[0])
260 		new_yscale = max(0.0,yScale() - relyz);
261 	if ( kseq == yscale_kstate_[1])
262 		new_yscale = max(0.0,yScale() + relyz);
263 	if ( kseq == zscale_kstate_[0])
264 		new_zscale = max(0.0,zScale() - relyz);
265 	if ( kseq == zscale_kstate_[1])
266 		new_zscale = max(0.0,zScale() + relyz);
267 
268 	setScale(new_xscale, new_yscale, new_zscale);
269 
270 	if ( kseq == zoom_kstate_[0])
271 		setZoom(max(0.0,zoom() - relyz));
272 	if ( kseq == zoom_kstate_[1])
273 		setZoom(max(0.0,zoom() + relyz));
274 }
275 
276 void ExtGLWidget::setShiftKeyboard(KeyboardState kseq, double speed)
277 {
278 	// Shift
279 	double w = max(1,width());
280 	double h = max(1,height());
281 
282 	double relx = speed / w;
283 	double relyz = speed / h;
284 
285 	double new_xshift = xViewportShift();
286 	double new_yshift = yViewportShift();
287 
288 	if ( kseq == xshift_kstate_[0])
289 		new_xshift = xViewportShift() + relx;
290 	if ( kseq == xshift_kstate_[1])
291 		new_xshift = xViewportShift() - relx;
292 	if ( kseq == yshift_kstate_[0])
293 		new_yshift = yViewportShift() - relyz;
294 	if ( kseq == yshift_kstate_[1])
295 		new_yshift = yViewportShift() + relyz;
296 
297 	setViewportShift(new_xshift, new_yshift);
298 }
299 
300 /**
301 	Sets the keybutton combination for data/coordinatesystem moves inside the widget\n\n
302 	default behaviour:\n
303 
304 	\verbatim
305 	rotate around x axis: [Key_Down, Key_Up]
306 	rotate around y axis: SHIFT+[Key_Right, Key_Left]
307 	rotate around z axis: [Key_Right, Key_Left]
308 	scale x:              ALT+[Key_Right, Key_Left]
309 	scale y:              ALT+[Key_Up, Key_Down]
310 	scale z:              ALT+SHIFT[Key_Down, Key_Up]
311 	zoom:                 ALT+CTRL+[Key_Down, Key_Up]
312 	shifting along x:     CTRL+[Key_Right, Key_Left]
313 	shifting along z:     CTRL+[Key_Down, Key_Up]
314 	\endverbatim
315 */
316 void ExtGLWidget::assignKeyboard(KeyboardState xrot_n, KeyboardState xrot_p
317 								,KeyboardState yrot_n, KeyboardState yrot_p
318 								,KeyboardState zrot_n, KeyboardState zrot_p
319 								,KeyboardState xscale_n, KeyboardState xscale_p
320 								,KeyboardState yscale_n, KeyboardState yscale_p
321 								,KeyboardState zscale_n, KeyboardState zscale_p
322 								,KeyboardState zoom_n, KeyboardState zoom_p
323 								,KeyboardState xshift_n, KeyboardState xshift_p
324 								,KeyboardState yshift_n, KeyboardState yshift_p)
325 {
326 	xrot_kstate_[0]   =  xrot_n;
327 	yrot_kstate_[0]   =  yrot_n;
328 	zrot_kstate_[0]   =  zrot_n;
329 	xrot_kstate_[1]   =  xrot_p;
330 	yrot_kstate_[1]   =  yrot_p;
331 	zrot_kstate_[1]   =  zrot_p;
332 
333 	xscale_kstate_[0] =  xscale_n;
334 	yscale_kstate_[0] =  yscale_n;
335 	zscale_kstate_[0] =  zscale_n;
336 	xscale_kstate_[1] =  xscale_p;
337 	yscale_kstate_[1] =  yscale_p;
338 	zscale_kstate_[1] =  zscale_p;
339 
340 	zoom_kstate_[0]   =  zoom_n;
341 	xshift_kstate_[0] =  xshift_n;
342 	yshift_kstate_[0] =  yshift_n;
343 	zoom_kstate_[1]   =  zoom_p;
344 	xshift_kstate_[1] =  xshift_p;
345 	yshift_kstate_[1] =  yshift_p;
346 }
347 
348 /**
349 The function has no effect if you derive from ExtGLWidget and overrides the keyboard Functions too careless.
350 In this case check first against keyboardEnabled() in your version of keyPressEvent()
351 A more fine grained input control can be achieved by combining assignKeyboard() with enableKeyboard().
352 */
353 void ExtGLWidget::enableKeyboard(bool val) {kbd_input_enabled_ = val;}
354 
355 /**
356 \see enableKeyboard()
357 */
358 void ExtGLWidget::disableKeyboard(bool val) {kbd_input_enabled_ = !val;}
359 bool ExtGLWidget::keyboardEnabled() const {return kbd_input_enabled_;}
360 
361 /**
362 Values < 0 are ignored. Default is (3,5,5)
363 */
364 void ExtGLWidget::setKeySpeed(double rot, double scale, double shift)
365 {
366 	if (rot > 0)	kbd_rot_speed_ = rot;
367 	if (scale > 0)	kbd_scale_speed_ = scale;
368 	if (shift > 0)	kbd_shift_speed_ = shift;
369 }
370 
371 void ExtGLWidget::keySpeed(double& rot, double& scale, double& shift) const
372 {
373 	rot = kbd_rot_speed_;
374 	scale = kbd_scale_speed_;
375 	shift = kbd_shift_speed_;
376 }
377