1 /**************************************************************************\
2 * Copyright (c) Kongsberg Oil & Gas Technologies AS
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of the copyright holder nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif // HAVE_CONFIG_H
36
37 #ifdef HAVE_DRAGGERS
38
39 /*!
40 \class SoHandleBoxDragger SoHandleBoxDragger.h Inventor/draggers/SoHandleBoxDragger.h
41 \brief The SoHandleBoxDragger class provides support for interactive scaling and translation.
42
43 \ingroup draggers
44
45 \DRAGGER_DEFAULT_SCREENSHOT
46
47 <center>
48 \image html handlebox.png "Screen Shot of Default Dragger"
49 </center>
50
51 A handlebox dragger is convenient to use for letting the user
52 interact with geometry that can be scaled (uniformly or in a
53 non-uniform way) and translated in 3D.
54
55 The dragger consists of a "cube" of interaction geometry. The
56 end-user can click and drag any side of the cube to translate the
57 dragger and click and drag any of the corner or edge markers for
58 scaling operations.
59 */
60 // FIXME: Should include an URL-link to the default geometry-file?
61 // Plus a small usage example. 20011113 mortene.
62
63 #include <Inventor/draggers/SoHandleBoxDragger.h>
64
65 #include <cstring>
66
67 #include <Inventor/nodes/SoDrawStyle.h>
68 #include <Inventor/nodes/SoSeparator.h>
69 #include <Inventor/nodes/SoSurroundScale.h>
70 #include <Inventor/nodes/SoSwitch.h>
71 #include <Inventor/nodes/SoTranslation.h>
72 #include <Inventor/sensors/SoFieldSensor.h>
73 #include <Inventor/projectors/SbPlaneProjector.h>
74 #include <Inventor/projectors/SbLineProjector.h>
75 #include <Inventor/events/SoKeyboardEvent.h>
76 #include <Inventor/actions/SoGetMatrixAction.h>
77
78 #include <data/draggerDefaults/handleBoxDragger.h>
79
80 #include "nodekits/SoSubKitP.h"
81 #include "coindefs.h"
82 #include "SbBasicP.h"
83
84 /*!
85 \var SoSFVec3f SoHandleBoxDragger::scaleFactor
86
87 Continuously updated to contain the current vector of scaling along
88 the X, Y and Z axes.
89 */
90
91 /*!
92 \var SoSFVec3f SoHandleBoxDragger::translation
93
94 Continuously updated to contain the current translation from the
95 dragger's local origo position.
96
97 The application programmer applying this dragger in his code should
98 connect the relevant node fields in the scene to this field to make
99 it follow the dragger.
100 */
101
102
103 /*!
104 \var SoFieldSensor * SoHandleBoxDragger::translFieldSensor
105 \COININTERNAL
106 */
107 /*!
108 \var SoFieldSensor * SoHandleBoxDragger::scaleFieldSensor
109 \COININTERNAL
110 */
111
112 #define WHATKIND_NONE 0
113 #define WHATKIND_TRANSLATOR 1
114 #define WHATKIND_EXTRUDER 2
115 #define WHATKIND_UNIFORM 3
116
117 #define CONSTRAINT_OFF 0
118 #define CONSTRAINT_WAIT 1
119 #define CONSTRAINT_X 2
120 #define CONSTRAINT_Y 3
121 #define CONSTRAINT_Z 4
122
123 static int uniform_ctrl_lookup[8][6] = {
124 { 1,4,5,2,3,6 },
125 { 1,4,6,2,3,5 },
126 { 2,4,5,1,3,6 },
127 { 2,4,6,1,3,5 },
128 { 1,3,5,2,4,6 },
129 { 1,3,6,2,4,5 },
130 { 2,3,5,1,4,6 },
131 { 2,3,6,1,4,5 }
132 };
133
134 class SoHandleBoxDraggerP {
135 public:
136 };
137
138 SO_KIT_SOURCE(SoHandleBoxDragger);
139
140
141 // doc in superclass
142 void
initClass(void)143 SoHandleBoxDragger::initClass(void)
144 {
145 SO_KIT_INTERNAL_INIT_CLASS(SoHandleBoxDragger, SO_FROM_INVENTOR_1);
146 }
147
148 // FIXME: document which parts need to be present in the geometry
149 // scenegraph, and what role they play in the dragger. 20010913 mortene.
150 /*!
151 \DRAGGER_CONSTRUCTOR
152
153 \NODEKIT_PRE_DIAGRAM
154
155 \verbatim
156 CLASS SoHandleBoxDragger
157 -->"this"
158 "callbackList"
159 "topSeparator"
160 "motionMatrix"
161 --> "surroundScale"
162 "geomSeparator"
163 --> "drawStyle"
164 --> "translator1Switch"
165 --> "translator1"
166 --> "translator1Active"
167 --> "translator2Switch"
168 --> "translator2"
169 --> "translator2Active"
170 --> "translator3Switch"
171 --> "translator3"
172 --> "translator3Active"
173 --> "translator4Switch"
174 --> "translator4"
175 --> "translator4Active"
176 --> "translator5Switch"
177 --> "translator5"
178 --> "translator5Active"
179 --> "translator6Switch"
180 --> "translator6"
181 --> "translator6Active"
182 --> "extruder1Switch"
183 --> "extruder1"
184 --> "extruder1Active"
185 --> "extruder2Switch"
186 --> "extruder2"
187 --> "extruder2Active"
188 --> "extruder3Switch"
189 --> "extruder3"
190 --> "extruder3Active"
191 --> "extruder4Switch"
192 --> "extruder4"
193 --> "extruder4Active"
194 --> "extruder5Switch"
195 --> "extruder5"
196 --> "extruder5Active"
197 --> "extruder6Switch"
198 --> "extruder6"
199 --> "extruder6Active"
200 --> "uniform1Switch"
201 --> "uniform1"
202 --> "uniform1Active"
203 --> "uniform2Switch"
204 --> "uniform2"
205 --> "uniform2Active"
206 --> "uniform3Switch"
207 --> "uniform3"
208 --> "uniform3Active"
209 --> "uniform4Switch"
210 --> "uniform4"
211 --> "uniform4Active"
212 --> "uniform5Switch"
213 --> "uniform5"
214 --> "uniform5Active"
215 --> "uniform6Switch"
216 --> "uniform6"
217 --> "uniform6Active"
218 --> "uniform7Switch"
219 --> "uniform7"
220 --> "uniform7Active"
221 --> "uniform8Switch"
222 --> "uniform8"
223 --> "uniform8Active"
224 --> "arrowTranslation"
225 --> "arrow1Switch"
226 --> "arrow1"
227 --> "arrow2Switch"
228 --> "arrow2"
229 --> "arrow3Switch"
230 --> "arrow3"
231 --> "arrow4Switch"
232 --> "arrow4"
233 --> "arrow5Switch"
234 --> "arrow5"
235 --> "arrow6Switch"
236 --> "arrow6"
237 \endverbatim
238
239 \NODEKIT_POST_DIAGRAM
240
241
242 \NODEKIT_PRE_TABLE
243
244 \verbatim
245 CLASS SoHandleBoxDragger
246 PVT "this", SoHandleBoxDragger ---
247 "callbackList", SoNodeKitListPart [ SoCallback, SoEventCallback ]
248 PVT "topSeparator", SoSeparator ---
249 PVT "motionMatrix", SoMatrixTransform ---
250 "surroundScale", SoSurroundScale ---
251 PVT "geomSeparator", SoSeparator ---
252 PVT "drawStyle", SoDrawStyle ---
253 PVT "translator1Switch", SoSwitch ---
254 "translator1", SoSeparator ---
255 "translator1Active", SoSeparator ---
256 PVT "translator2Switch", SoSwitch ---
257 "translator2", SoSeparator ---
258 "translator2Active", SoSeparator ---
259 PVT "translator3Switch", SoSwitch ---
260 "translator3", SoSeparator ---
261 "translator3Active", SoSeparator ---
262 PVT "translator4Switch", SoSwitch ---
263 "translator4", SoSeparator ---
264 "translator4Active", SoSeparator ---
265 PVT "translator5Switch", SoSwitch ---
266 "translator5", SoSeparator ---
267 "translator5Active", SoSeparator ---
268 PVT "translator6Switch", SoSwitch ---
269 "translator6", SoSeparator ---
270 "translator6Active", SoSeparator ---
271 PVT "extruder1Switch", SoSwitch ---
272 "extruder1", SoSeparator ---
273 "extruder1Active", SoSeparator ---
274 PVT "extruder2Switch", SoSwitch ---
275 "extruder2", SoSeparator ---
276 "extruder2Active", SoSeparator ---
277 PVT "extruder3Switch", SoSwitch ---
278 "extruder3", SoSeparator ---
279 "extruder3Active", SoSeparator ---
280 PVT "extruder4Switch", SoSwitch ---
281 "extruder4", SoSeparator ---
282 "extruder4Active", SoSeparator ---
283 PVT "extruder5Switch", SoSwitch ---
284 "extruder5", SoSeparator ---
285 "extruder5Active", SoSeparator ---
286 PVT "extruder6Switch", SoSwitch ---
287 "extruder6", SoSeparator ---
288 "extruder6Active", SoSeparator ---
289 PVT "uniform1Switch", SoSwitch ---
290 "uniform1", SoSeparator ---
291 "uniform1Active", SoSeparator ---
292 PVT "uniform2Switch", SoSwitch ---
293 "uniform2", SoSeparator ---
294 "uniform2Active", SoSeparator ---
295 PVT "uniform3Switch", SoSwitch ---
296 "uniform3", SoSeparator ---
297 "uniform3Active", SoSeparator ---
298 PVT "uniform4Switch", SoSwitch ---
299 "uniform4", SoSeparator ---
300 "uniform4Active", SoSeparator ---
301 PVT "uniform5Switch", SoSwitch ---
302 "uniform5", SoSeparator ---
303 "uniform5Active", SoSeparator ---
304 PVT "uniform6Switch", SoSwitch ---
305 "uniform6", SoSeparator ---
306 "uniform6Active", SoSeparator ---
307 PVT "uniform7Switch", SoSwitch ---
308 "uniform7", SoSeparator ---
309 "uniform7Active", SoSeparator ---
310 PVT "uniform8Switch", SoSwitch ---
311 "uniform8", SoSeparator ---
312 "uniform8Active", SoSeparator ---
313 PVT "arrowTranslation", SoTranslation ---
314 PVT "arrow1Switch", SoSwitch ---
315 "arrow1", SoSeparator ---
316 PVT "arrow2Switch", SoSwitch ---
317 "arrow2", SoSeparator ---
318 PVT "arrow3Switch", SoSwitch ---
319 "arrow3", SoSeparator ---
320 PVT "arrow4Switch", SoSwitch ---
321 "arrow4", SoSeparator ---
322 PVT "arrow5Switch", SoSwitch ---
323 "arrow5", SoSeparator ---
324 PVT "arrow6Switch", SoSwitch ---
325 "arrow6", SoSeparator ---
326 \endverbatim
327
328 \NODEKIT_POST_TABLE
329 */
SoHandleBoxDragger(void)330 SoHandleBoxDragger::SoHandleBoxDragger(void)
331 {
332 SO_KIT_INTERNAL_CONSTRUCTOR(SoHandleBoxDragger);
333
334 SO_KIT_ADD_CATALOG_ENTRY(surroundScale, SoSurroundScale, TRUE, topSeparator, geomSeparator, TRUE);
335 SO_KIT_ADD_CATALOG_ENTRY(drawStyle, SoDrawStyle, TRUE, geomSeparator, translator1Switch, FALSE);
336 SO_KIT_ADD_CATALOG_ENTRY(translator1Switch, SoSwitch, TRUE, geomSeparator, translator2Switch, FALSE);
337 SO_KIT_ADD_CATALOG_ENTRY(translator1, SoSeparator, TRUE, translator1Switch, translator1Active, TRUE);
338 SO_KIT_ADD_CATALOG_ENTRY(translator1Active, SoSeparator, TRUE, translator1Switch, "", TRUE);
339 SO_KIT_ADD_CATALOG_ENTRY(translator2Switch, SoSwitch, TRUE, geomSeparator, translator3Switch, FALSE);
340 SO_KIT_ADD_CATALOG_ENTRY(translator2, SoSeparator, TRUE, translator2Switch, translator2Active, TRUE);
341 SO_KIT_ADD_CATALOG_ENTRY(translator2Active, SoSeparator, TRUE, translator2Switch, "", TRUE);
342 SO_KIT_ADD_CATALOG_ENTRY(translator3Switch, SoSwitch, TRUE, geomSeparator, translator4Switch, FALSE);
343 SO_KIT_ADD_CATALOG_ENTRY(translator3, SoSeparator, TRUE, translator3Switch, translator3Active, TRUE);
344 SO_KIT_ADD_CATALOG_ENTRY(translator3Active, SoSeparator, TRUE, translator3Switch, "", TRUE);
345 SO_KIT_ADD_CATALOG_ENTRY(translator4Switch, SoSwitch, TRUE, geomSeparator, translator5Switch, FALSE);
346 SO_KIT_ADD_CATALOG_ENTRY(translator4, SoSeparator, TRUE, translator4Switch, translator4Active, TRUE);
347 SO_KIT_ADD_CATALOG_ENTRY(translator4Active, SoSeparator, TRUE, translator4Switch, "", TRUE);
348 SO_KIT_ADD_CATALOG_ENTRY(translator5Switch, SoSwitch, TRUE, geomSeparator, translator6Switch, FALSE);
349 SO_KIT_ADD_CATALOG_ENTRY(translator5, SoSeparator, TRUE, translator5Switch, translator5Active, TRUE);
350 SO_KIT_ADD_CATALOG_ENTRY(translator5Active, SoSeparator, TRUE, translator5Switch, "", TRUE);
351 SO_KIT_ADD_CATALOG_ENTRY(translator6Switch, SoSwitch, TRUE, geomSeparator, extruder1Switch, FALSE);
352 SO_KIT_ADD_CATALOG_ENTRY(translator6, SoSeparator, TRUE, translator6Switch, translator6Active, TRUE);
353 SO_KIT_ADD_CATALOG_ENTRY(translator6Active, SoSeparator, TRUE, translator6Switch, "", TRUE);
354 SO_KIT_ADD_CATALOG_ENTRY(extruder1Switch, SoSwitch, TRUE, geomSeparator, extruder2Switch, FALSE);
355 SO_KIT_ADD_CATALOG_ENTRY(extruder1, SoSeparator, TRUE, extruder1Switch, extruder1Active, TRUE);
356 SO_KIT_ADD_CATALOG_ENTRY(extruder1Active, SoSeparator, TRUE, extruder1Switch, "", TRUE);
357 SO_KIT_ADD_CATALOG_ENTRY(extruder2Switch, SoSwitch, TRUE, geomSeparator, extruder3Switch, FALSE);
358 SO_KIT_ADD_CATALOG_ENTRY(extruder2, SoSeparator, TRUE, extruder2Switch, extruder2Active, TRUE);
359 SO_KIT_ADD_CATALOG_ENTRY(extruder2Active, SoSeparator, TRUE, extruder2Switch, "", TRUE);
360 SO_KIT_ADD_CATALOG_ENTRY(extruder3Switch, SoSwitch, TRUE, geomSeparator, extruder4Switch, FALSE);
361 SO_KIT_ADD_CATALOG_ENTRY(extruder3, SoSeparator, TRUE, extruder3Switch, extruder3Active, TRUE);
362 SO_KIT_ADD_CATALOG_ENTRY(extruder3Active, SoSeparator, TRUE, extruder3Switch, "", TRUE);
363 SO_KIT_ADD_CATALOG_ENTRY(extruder4Switch, SoSwitch, TRUE, geomSeparator, extruder5Switch, FALSE);
364 SO_KIT_ADD_CATALOG_ENTRY(extruder4, SoSeparator, TRUE, extruder4Switch, extruder4Active, TRUE);
365 SO_KIT_ADD_CATALOG_ENTRY(extruder4Active, SoSeparator, TRUE, extruder4Switch, "", TRUE);
366 SO_KIT_ADD_CATALOG_ENTRY(extruder5Switch, SoSwitch, TRUE, geomSeparator, extruder6Switch, FALSE);
367 SO_KIT_ADD_CATALOG_ENTRY(extruder5, SoSeparator, TRUE, extruder5Switch, extruder5Active, TRUE);
368 SO_KIT_ADD_CATALOG_ENTRY(extruder5Active, SoSeparator, TRUE, extruder5Switch, "", TRUE);
369 SO_KIT_ADD_CATALOG_ENTRY(extruder6Switch, SoSwitch, TRUE, geomSeparator, uniform1Switch, FALSE);
370 SO_KIT_ADD_CATALOG_ENTRY(extruder6, SoSeparator, TRUE, extruder6Switch, extruder6Active, TRUE);
371 SO_KIT_ADD_CATALOG_ENTRY(extruder6Active, SoSeparator, TRUE, extruder6Switch, "", TRUE);
372 SO_KIT_ADD_CATALOG_ENTRY(uniform1Switch, SoSwitch, TRUE, geomSeparator, uniform2Switch, FALSE);
373 SO_KIT_ADD_CATALOG_ENTRY(uniform1, SoSeparator, TRUE, uniform1Switch, uniform1Active, TRUE);
374 SO_KIT_ADD_CATALOG_ENTRY(uniform1Active, SoSeparator, TRUE, uniform1Switch, "", TRUE);
375 SO_KIT_ADD_CATALOG_ENTRY(uniform2Switch, SoSwitch, TRUE, geomSeparator, uniform3Switch, FALSE);
376 SO_KIT_ADD_CATALOG_ENTRY(uniform2, SoSeparator, TRUE, uniform2Switch, uniform2Active, TRUE);
377 SO_KIT_ADD_CATALOG_ENTRY(uniform2Active, SoSeparator, TRUE, uniform2Switch, "", TRUE);
378 SO_KIT_ADD_CATALOG_ENTRY(uniform3Switch, SoSwitch, TRUE, geomSeparator, uniform4Switch, FALSE);
379 SO_KIT_ADD_CATALOG_ENTRY(uniform3, SoSeparator, TRUE, uniform3Switch, uniform3Active, TRUE);
380 SO_KIT_ADD_CATALOG_ENTRY(uniform3Active, SoSeparator, TRUE, uniform3Switch, "", TRUE);
381 SO_KIT_ADD_CATALOG_ENTRY(uniform4Switch, SoSwitch, TRUE, geomSeparator, uniform5Switch, FALSE);
382 SO_KIT_ADD_CATALOG_ENTRY(uniform4, SoSeparator, TRUE, uniform4Switch, uniform4Active, TRUE);
383 SO_KIT_ADD_CATALOG_ENTRY(uniform4Active, SoSeparator, TRUE, uniform4Switch, "", TRUE);
384 SO_KIT_ADD_CATALOG_ENTRY(uniform5Switch, SoSwitch, TRUE, geomSeparator, uniform6Switch, FALSE);
385 SO_KIT_ADD_CATALOG_ENTRY(uniform5, SoSeparator, TRUE, uniform5Switch, uniform5Active, TRUE);
386 SO_KIT_ADD_CATALOG_ENTRY(uniform5Active, SoSeparator, TRUE, uniform5Switch, "", TRUE);
387 SO_KIT_ADD_CATALOG_ENTRY(uniform6Switch, SoSwitch, TRUE, geomSeparator, uniform7Switch, FALSE);
388 SO_KIT_ADD_CATALOG_ENTRY(uniform6, SoSeparator, TRUE, uniform6Switch, uniform6Active, TRUE);
389 SO_KIT_ADD_CATALOG_ENTRY(uniform6Active, SoSeparator, TRUE, uniform6Switch, "", TRUE);
390 SO_KIT_ADD_CATALOG_ENTRY(uniform7Switch, SoSwitch, TRUE, geomSeparator, uniform8Switch, FALSE);
391 SO_KIT_ADD_CATALOG_ENTRY(uniform7, SoSeparator, TRUE, uniform7Switch, uniform7Active, TRUE);
392 SO_KIT_ADD_CATALOG_ENTRY(uniform7Active, SoSeparator, TRUE, uniform7Switch, "", TRUE);
393 SO_KIT_ADD_CATALOG_ENTRY(uniform8Switch, SoSwitch, TRUE, geomSeparator, arrowTranslation, FALSE);
394 SO_KIT_ADD_CATALOG_ENTRY(uniform8, SoSeparator, TRUE, uniform8Switch, uniform8Active, TRUE);
395 SO_KIT_ADD_CATALOG_ENTRY(uniform8Active, SoSeparator, TRUE, uniform8Switch, "", TRUE);
396 SO_KIT_ADD_CATALOG_ENTRY(arrowTranslation, SoTranslation, TRUE, geomSeparator, arrow1Switch, FALSE);
397 SO_KIT_ADD_CATALOG_ENTRY(arrow1Switch, SoSwitch, TRUE, geomSeparator, arrow2Switch, FALSE);
398 SO_KIT_ADD_CATALOG_ENTRY(arrow1, SoSeparator, TRUE, arrow1Switch, "", TRUE);
399 SO_KIT_ADD_CATALOG_ENTRY(arrow2Switch, SoSwitch, TRUE, geomSeparator, arrow3Switch, FALSE);
400 SO_KIT_ADD_CATALOG_ENTRY(arrow2, SoSeparator, TRUE, arrow2Switch, "", TRUE);
401 SO_KIT_ADD_CATALOG_ENTRY(arrow3Switch, SoSwitch, TRUE, geomSeparator, arrow4Switch, FALSE);
402 SO_KIT_ADD_CATALOG_ENTRY(arrow3, SoSeparator, TRUE, arrow3Switch, "", TRUE);
403 SO_KIT_ADD_CATALOG_ENTRY(arrow4Switch, SoSwitch, TRUE, geomSeparator, arrow5Switch, FALSE);
404 SO_KIT_ADD_CATALOG_ENTRY(arrow4, SoSeparator, TRUE, arrow4Switch, "", TRUE);
405 SO_KIT_ADD_CATALOG_ENTRY(arrow5Switch, SoSwitch, TRUE, geomSeparator, arrow6Switch, FALSE);
406 SO_KIT_ADD_CATALOG_ENTRY(arrow5, SoSeparator, TRUE, arrow5Switch, "", TRUE);
407 SO_KIT_ADD_CATALOG_ENTRY(arrow6Switch, SoSwitch, TRUE, geomSeparator, "", FALSE);
408 SO_KIT_ADD_CATALOG_ENTRY(arrow6, SoSeparator, TRUE, arrow6Switch, "", TRUE);
409
410 if (SO_KIT_IS_FIRST_INSTANCE()) {
411 SoInteractionKit::readDefaultParts("handleBoxDragger.iv",
412 HANDLEBOXDRAGGER_draggergeometry,
413 static_cast<int>(strlen(HANDLEBOXDRAGGER_draggergeometry)));
414 }
415
416 SO_KIT_ADD_FIELD(translation, (0.0f, 0.0f, 0.0f));
417 SO_KIT_ADD_FIELD(scaleFactor, (1.0f, 1.0f, 1.0f));
418
419 SO_KIT_INIT_INSTANCE();
420
421 this->setPartAsDefault("translator1", "handleBoxTranslator1");
422 this->setPartAsDefault("translator2", "handleBoxTranslator2");
423 this->setPartAsDefault("translator3", "handleBoxTranslator3");
424 this->setPartAsDefault("translator4", "handleBoxTranslator4");
425 this->setPartAsDefault("translator5", "handleBoxTranslator5");
426 this->setPartAsDefault("translator6", "handleBoxTranslator6");
427
428 this->setPartAsDefault("translator1Active", "handleBoxTranslator1Active");
429 this->setPartAsDefault("translator2Active", "handleBoxTranslator2Active");
430 this->setPartAsDefault("translator3Active", "handleBoxTranslator3Active");
431 this->setPartAsDefault("translator4Active", "handleBoxTranslator4Active");
432 this->setPartAsDefault("translator5Active", "handleBoxTranslator5Active");
433 this->setPartAsDefault("translator6Active", "handleBoxTranslator6Active");
434
435 this->setPartAsDefault("extruder1", "handleBoxExtruder1");
436 this->setPartAsDefault("extruder2", "handleBoxExtruder2");
437 this->setPartAsDefault("extruder3", "handleBoxExtruder3");
438 this->setPartAsDefault("extruder4", "handleBoxExtruder4");
439 this->setPartAsDefault("extruder5", "handleBoxExtruder5");
440 this->setPartAsDefault("extruder6", "handleBoxExtruder6");
441
442 this->setPartAsDefault("extruder1Active", "handleBoxExtruder1Active");
443 this->setPartAsDefault("extruder2Active", "handleBoxExtruder2Active");
444 this->setPartAsDefault("extruder3Active", "handleBoxExtruder3Active");
445 this->setPartAsDefault("extruder4Active", "handleBoxExtruder4Active");
446 this->setPartAsDefault("extruder5Active", "handleBoxExtruder5Active");
447 this->setPartAsDefault("extruder6Active", "handleBoxExtruder6Active");
448
449 this->setPartAsDefault("uniform1", "handleBoxUniform1");
450 this->setPartAsDefault("uniform2", "handleBoxUniform2");
451 this->setPartAsDefault("uniform3", "handleBoxUniform3");
452 this->setPartAsDefault("uniform4", "handleBoxUniform4");
453 this->setPartAsDefault("uniform5", "handleBoxUniform5");
454 this->setPartAsDefault("uniform6", "handleBoxUniform6");
455 this->setPartAsDefault("uniform7", "handleBoxUniform7");
456 this->setPartAsDefault("uniform8", "handleBoxUniform8");
457
458 this->setPartAsDefault("uniform1Active", "handleBoxUniform1Active");
459 this->setPartAsDefault("uniform2Active", "handleBoxUniform2Active");
460 this->setPartAsDefault("uniform3Active", "handleBoxUniform3Active");
461 this->setPartAsDefault("uniform4Active", "handleBoxUniform4Active");
462 this->setPartAsDefault("uniform5Active", "handleBoxUniform5Active");
463 this->setPartAsDefault("uniform6Active", "handleBoxUniform6Active");
464 this->setPartAsDefault("uniform7Active", "handleBoxUniform7Active");
465 this->setPartAsDefault("uniform8Active", "handleBoxUniform8Active");
466
467 this->setPartAsDefault("arrow1", "handleBoxArrow1");
468 this->setPartAsDefault("arrow2", "handleBoxArrow2");
469 this->setPartAsDefault("arrow3", "handleBoxArrow3");
470 this->setPartAsDefault("arrow4", "handleBoxArrow4");
471 this->setPartAsDefault("arrow5", "handleBoxArrow5");
472 this->setPartAsDefault("arrow6", "handleBoxArrow6");
473
474 this->constraintState = CONSTRAINT_OFF;
475 this->whatkind = WHATKIND_NONE;
476
477 this->setAllPartsActive(FALSE);
478
479 this->planeProj = new SbPlaneProjector;
480 this->lineProj = new SbLineProjector;
481
482 this->addStartCallback(SoHandleBoxDragger::startCB);
483 this->addMotionCallback(SoHandleBoxDragger::motionCB);
484 this->addFinishCallback(SoHandleBoxDragger::finishCB);
485 this->addValueChangedCallback(SoHandleBoxDragger::valueChangedCB);
486 this->addOtherEventCallback(SoHandleBoxDragger::metaKeyChangeCB);
487
488 this->translFieldSensor = new SoFieldSensor(SoHandleBoxDragger::fieldSensorCB, this);
489 this->translFieldSensor->setPriority(0);
490 this->scaleFieldSensor = new SoFieldSensor(SoHandleBoxDragger::fieldSensorCB, this);
491 this->scaleFieldSensor->setPriority(0);
492
493 this->setUpConnections(TRUE, TRUE);
494 }
495
496 /*!
497 Protected destructor.
498
499 (Dragger classes are derived from SoBase, so they are reference
500 counted and automatically destroyed when their reference count goes
501 to 0.)
502 */
~SoHandleBoxDragger()503 SoHandleBoxDragger::~SoHandleBoxDragger()
504 {
505 delete this->lineProj;
506 delete this->planeProj;
507 delete this->translFieldSensor;
508 delete this->scaleFieldSensor;
509 }
510
511 // Doc in superclass.
512 SbBool
setUpConnections(SbBool onoff,SbBool doitalways)513 SoHandleBoxDragger::setUpConnections(SbBool onoff, SbBool doitalways)
514 {
515 if (!doitalways && this->connectionsSetUp == onoff) return onoff;
516
517 if (onoff) {
518 inherited::setUpConnections(onoff, doitalways);
519
520 SoHandleBoxDragger::fieldSensorCB(this, NULL);
521
522 if (this->translFieldSensor->getAttachedField() != &this->translation) {
523 this->translFieldSensor->attach(&this->translation);
524 }
525 if (this->scaleFieldSensor->getAttachedField() != &this->scaleFactor) {
526 this->scaleFieldSensor->attach(&this->scaleFactor);
527 }
528
529 }
530 else {
531 if (this->translFieldSensor->getAttachedField() != NULL) {
532 this->translFieldSensor->detach();
533 }
534 if (this->scaleFieldSensor->getAttachedField() != NULL) {
535 this->scaleFieldSensor->detach();
536 }
537 inherited::setUpConnections(onoff, doitalways);
538 }
539 return !(this->connectionsSetUp = onoff);
540 }
541
542 // Doc in superclass.
543 void
setDefaultOnNonWritingFields(void)544 SoHandleBoxDragger::setDefaultOnNonWritingFields(void)
545 {
546 this->surroundScale.setDefault(TRUE);
547 this->arrowTranslation.setDefault(TRUE);
548 this->drawStyle.setDefault(TRUE);
549
550 inherited::setDefaultOnNonWritingFields();
551 }
552
553 /*! \COININTERNAL */
554 void
fieldSensorCB(void * d,SoSensor *)555 SoHandleBoxDragger::fieldSensorCB(void * d, SoSensor *)
556 {
557 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
558 SbMatrix matrix = thisp->getMotionMatrix();
559 thisp->workFieldsIntoTransform(matrix);
560 thisp->setMotionMatrix(matrix);
561 }
562
563 /*! \COININTERNAL */
564 void
valueChangedCB(void * COIN_UNUSED_ARG (f),SoDragger * d)565 SoHandleBoxDragger::valueChangedCB(void * COIN_UNUSED_ARG(f), SoDragger * d)
566 {
567 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
568 SbMatrix matrix = thisp->getMotionMatrix();
569 SbVec3f trans, scale;
570 SbRotation rot, scaleOrient;
571 matrix.getTransform(trans, rot, scale, scaleOrient);
572
573 thisp->translFieldSensor->detach();
574 if (thisp->translation.getValue() != trans)
575 thisp->translation = trans;
576 thisp->translFieldSensor->attach(&thisp->translation);
577
578 thisp->scaleFieldSensor->detach();
579 if (thisp->scaleFactor.getValue() != scale)
580 thisp->scaleFactor = scale;
581 thisp->scaleFieldSensor->attach(&thisp->scaleFactor);
582 }
583
584 /*! \COININTERNAL */
585 void
startCB(void *,SoDragger * d)586 SoHandleBoxDragger::startCB(void *, SoDragger * d)
587 {
588 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
589 thisp->dragStart();
590 }
591
592 /*! \COININTERNAL */
593 void
motionCB(void *,SoDragger * d)594 SoHandleBoxDragger::motionCB(void *, SoDragger * d)
595 {
596 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
597 thisp->drag();
598 }
599
600 /*! \COININTERNAL */
601 void
finishCB(void *,SoDragger * d)602 SoHandleBoxDragger::finishCB(void *, SoDragger * d)
603 {
604 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
605 thisp->dragFinish();
606 }
607
608 /*! \COININTERNAL */
609 void
metaKeyChangeCB(void *,SoDragger * d)610 SoHandleBoxDragger::metaKeyChangeCB(void *, SoDragger * d)
611 {
612 SoHandleBoxDragger * thisp = static_cast<SoHandleBoxDragger *>(d);
613 if (!thisp->isActive.getValue()) return;
614
615 const SoEvent *event = thisp->getEvent();
616 if (SO_KEY_RELEASE_EVENT(event, LEFT_SHIFT) ||
617 SO_KEY_RELEASE_EVENT(event, RIGHT_SHIFT)) {
618 if (thisp->constraintState != CONSTRAINT_OFF) thisp->drag();
619 }
620 else if (thisp->ctrlDown != event->wasCtrlDown()) {
621 thisp->ctrlDown = !thisp->ctrlDown;
622 thisp->updateSwitches();
623 }
624 }
625
626 // Invalidate surround scale node, if it exists.
627 //
628 // Note: keep the function name prefix to avoid name clashes with
629 // other dragger .cpp files for "--enable-compact" builds.
630 //
631 // FIXME: should collect these methods in a common method visible to
632 // all draggers implementing the exact same functionality. 20010826 mortene.
633 static void
SoHandleBoxDragger_invalidate_surroundscale(SoBaseKit * kit)634 SoHandleBoxDragger_invalidate_surroundscale(SoBaseKit * kit)
635 {
636 SoSurroundScale * ss = coin_safe_cast<SoSurroundScale *>(
637 kit->getPart("surroundScale", FALSE)
638 );
639 if (ss) ss->invalidate();
640 }
641
642 /*! \COININTERNAL
643 Called when dragger is selected (picked) by the user.
644 */
645 void
dragStart(void)646 SoHandleBoxDragger::dragStart(void)
647 {
648 SoHandleBoxDragger_invalidate_surroundscale(this);
649
650 static const char translatorname[] = "translator";
651 static const char extrudername[] = "extruder";
652 static const char uniformname[] = "uniform";
653
654 const SoPath *pickpath = this->getPickPath();
655
656 SbBool found = FALSE;
657 this->whatkind = WHATKIND_NONE;
658 this->whatnum = 0;
659
660 int i;
661 SbString str;
662 if (!found) {
663 for (i = 1; i <= 6; i++) {
664 str.sprintf("%s%d", translatorname, i);
665 if (pickpath->findNode(this->getNodeFieldNode(str.getString())) >= 0||
666 this->getSurrogatePartPickedName() == str.getString()) break;
667 }
668 if (i <= 6) {
669 found = TRUE;
670 this->whatkind = WHATKIND_TRANSLATOR;
671 this->whatnum = i;
672 }
673 }
674
675 if (!found) {
676 for (i = 1; i <= 6; i++) {
677 str.sprintf("%s%d", extrudername, i);
678 if (pickpath->findNode(this->getNodeFieldNode(str.getString()))>= 0 ||
679 this->getSurrogatePartPickedName() == str.getString()) break;
680 }
681 if (i <= 6) {
682 found = TRUE;
683 this->whatkind = WHATKIND_EXTRUDER;
684 this->whatnum = i;
685 }
686 }
687 if (!found) {
688 for (i = 1; i <= 8; i++) {
689 str.sprintf("%s%d", uniformname, i);
690 if (pickpath->findNode(this->getNodeFieldNode(str.getString()))>= 0 ||
691 this->getSurrogatePartPickedName() == str.getString()) break;
692 }
693 if (i <= 8) {
694 found = TRUE;
695 this->whatkind = WHATKIND_UNIFORM;
696 this->whatnum = i;
697 }
698 }
699 assert(found);
700 if (!found) return;
701
702 SbVec3f startPt = this->getLocalStartingPoint();
703
704 switch(this->whatkind) {
705 case WHATKIND_TRANSLATOR:
706 {
707 SbVec3f n;
708 if (this->whatnum <= 2) {
709 n = SbVec3f(0.0f, 1.0f, 0.0f);
710 }
711 else if (this->whatnum <= 4) {
712 n = SbVec3f(1.0f, 0.0f, 0.0f);
713 }
714 else {
715 n = SbVec3f(0.0f, 0.0f, 1.0f);
716 }
717 SbVec3f localPt;
718 {
719 SbMatrix mat, inv;
720 this->getSurroundScaleMatrices(mat, inv);
721 inv.multVecMatrix(startPt, localPt);
722 }
723 this->planeProj->setPlane(SbPlane(n, startPt));
724 SbLine myline(SbVec3f(0.0f, 0.0f, 0.0f), n);
725 SoTranslation *t = SO_GET_ANY_PART(this, "arrowTranslation", SoTranslation);
726 t->translation = myline.getClosestPoint(localPt);
727 if (this->getEvent()->wasShiftDown()) {
728 this->getLocalToWorldMatrix().multVecMatrix(startPt, this->worldRestartPt);
729 this->constraintState = CONSTRAINT_WAIT;
730 }
731 }
732 break;
733 case WHATKIND_EXTRUDER:
734 this->lineProj->setLine(SbLine(this->getDraggerCenter(), startPt));
735 this->ctrlOffset = this->calcCtrlOffset(startPt);
736 break;
737 case WHATKIND_UNIFORM:
738 this->lineProj->setLine(SbLine(this->getDraggerCenter(), startPt));
739 this->ctrlOffset = this->calcCtrlOffset(startPt);
740 break;
741 }
742 this->ctrlDown = this->getEvent()->wasCtrlDown();
743 this->updateSwitches();
744 }
745
746 /*! \COININTERNAL
747 Called when user drags the mouse after picking the dragger.
748 */
749 void
drag(void)750 SoHandleBoxDragger::drag(void)
751 {
752 SbVec3f startPt = this->getLocalStartingPoint();
753
754 if (this->whatkind == WHATKIND_TRANSLATOR) {
755 this->planeProj->setViewVolume(this->getViewVolume());
756 this->planeProj->setWorkingSpace(this->getLocalToWorldMatrix());
757 SbVec3f projPt = this->planeProj->project(this->getNormalizedLocaterPosition());
758
759 const SoEvent *event = this->getEvent();
760 if (event->wasShiftDown() && this->constraintState == CONSTRAINT_OFF) {
761 this->constraintState = CONSTRAINT_WAIT;
762 this->setStartLocaterPosition(event->getPosition());
763 this->getLocalToWorldMatrix().multVecMatrix(projPt, this->worldRestartPt);
764 }
765 else if (!event->wasShiftDown() && this->constraintState != CONSTRAINT_OFF) {
766 this->constraintState = CONSTRAINT_OFF;
767 this->updateArrows();
768 }
769
770 SbVec3f motion, localrestartpt;
771 if (this->constraintState != CONSTRAINT_OFF) {
772 this->getWorldToLocalMatrix().multVecMatrix(this->worldRestartPt,
773 localrestartpt);
774 motion = localrestartpt - startPt;
775 }
776 else motion = projPt - startPt;
777 switch(this->constraintState) {
778 case CONSTRAINT_OFF:
779 break;
780 case CONSTRAINT_WAIT:
781 if (this->isAdequateConstraintMotion()) {
782 SbVec3f newmotion = projPt - localrestartpt;
783 int biggest = 0;
784 double bigval = fabs(newmotion[0]);
785 if (fabs(newmotion[1]) > bigval) {
786 biggest = 1;
787 bigval = fabs(newmotion[1]);
788 }
789 if (fabs(newmotion[2]) > bigval) {
790 biggest = 2;
791 }
792 motion[biggest] += newmotion[biggest];
793 this->constraintState = CONSTRAINT_X + biggest;
794 this->updateArrows();
795 }
796 else {
797 return;
798 }
799 break;
800 case CONSTRAINT_X:
801 motion[0] += projPt[0] - localrestartpt[0];
802 break;
803 case CONSTRAINT_Y:
804 motion[1] += projPt[1] - localrestartpt[1];
805 break;
806 case CONSTRAINT_Z:
807 motion[2] += projPt[2] - localrestartpt[2];
808 }
809 this->setMotionMatrix(this->appendTranslation(this->getStartMotionMatrix(), motion));
810 }
811 else {
812 this->lineProj->setViewVolume(this->getViewVolume());
813 this->lineProj->setWorkingSpace(this->getLocalToWorldMatrix());
814 SbVec3f projPt = this->lineProj->project(this->getNormalizedLocaterPosition());
815 SbVec3f center = this->getDraggerCenter();
816 if (this->getEvent()->wasCtrlDown()) {
817 center += this->ctrlOffset;
818 }
819
820 float orglen = (startPt-center).length();
821 float currlen = (projPt-center).length();
822 float scale = 0.0f;
823
824 if (orglen > 0.0f) scale = currlen / orglen;
825 if (scale > 0.0f && (startPt-center).dot(projPt-center) <= 0.0f) scale = 0.0f;
826
827 SbVec3f scalevec(scale, scale, scale);
828 if (this->whatkind == WHATKIND_EXTRUDER) {
829 if (this->whatnum <= 2) scalevec[0] = scalevec[2] = 1.0f;
830 else if (this->whatnum <= 4) scalevec[1] = scalevec[2] = 1.0f;
831 else scalevec[0] = scalevec[1] = 1.0f;
832 }
833
834 this->setMotionMatrix(this->appendScale(this->getStartMotionMatrix(),
835 scalevec,
836 center));
837 }
838 }
839
840 /*! \COININTERNAL
841 Called when mouse button is released after picking and interacting
842 with the dragger.
843 */
844 void
dragFinish(void)845 SoHandleBoxDragger::dragFinish(void)
846 {
847 this->constraintState = CONSTRAINT_OFF;
848 this->whatkind = WHATKIND_NONE;
849 this->setAllPartsActive(FALSE);
850
851 SoHandleBoxDragger_invalidate_surroundscale(this);
852 }
853
854 /*!
855 Activate or deactive all dragger geometry parts.
856 */
857 void
setAllPartsActive(SbBool onoroff)858 SoHandleBoxDragger::setAllPartsActive(SbBool onoroff)
859 {
860 int i;
861 int val = onoroff ? 1 : 0;
862 SoSwitch *sw;
863 SbString str;
864 for (i = 1; i <= 6; i++) {
865 str.sprintf("translator%dSwitch", i);
866 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
867 SoInteractionKit::setSwitchValue(sw, val);
868 }
869 for (i = 1; i <= 6; i++) {
870 str.sprintf("extruder%dSwitch", i);
871 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
872 SoInteractionKit::setSwitchValue(sw, val);
873 }
874 for (i = 1; i <= 8; i++) {
875 str.sprintf("uniform%dSwitch", i);
876 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
877 SoInteractionKit::setSwitchValue(sw, val);
878 }
879 this->updateArrows();
880 }
881
882 // Return node pointer from a SoSFNode field. Does misc sanity
883 // checking for robustness.
884 SoNode *
getNodeFieldNode(const char * fieldname)885 SoHandleBoxDragger::getNodeFieldNode(const char * fieldname)
886 {
887 SoField * field = this->getField(fieldname);
888 assert(field != NULL);
889 assert(coin_assert_cast<SoSFNode *>(field)->getValue() != NULL);
890 return coin_assert_cast<SoSFNode *>(field)->getValue();
891 }
892
893 void
updateSwitches(void)894 SoHandleBoxDragger::updateSwitches(void)
895 {
896 int i;
897 SbString str;
898 SoSwitch *sw;
899
900 if (this->whatkind == WHATKIND_UNIFORM) {
901 if (this->ctrlDown) {
902 const int *ptr = uniform_ctrl_lookup[this->whatnum-1];
903 for (i = 0; i < 6; i++) {
904 str.sprintf("extruder%dSwitch", ptr[i]);
905 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
906 SoInteractionKit::setSwitchValue(sw, i < 3 ? 1 : 0);
907 }
908 }
909 else {
910 for (i = 1; i <= 6; i++) {
911 str.sprintf("extruder%dSwitch", i);
912 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
913 SoInteractionKit::setSwitchValue(sw, 1);
914 }
915 }
916 str.sprintf("uniform%dSwitch", this->whatnum);
917 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
918 SoInteractionKit::setSwitchValue(sw, 1);
919 }
920 else if (this->whatkind == WHATKIND_EXTRUDER) {
921 int othernum = ((this->whatnum-1) & ~1) + 1;
922 if (othernum == this->whatnum) othernum++;
923
924 str.sprintf("extruder%dSwitch", this->whatnum);
925 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
926 SoInteractionKit::setSwitchValue(sw, 1);
927 str.sprintf("extruder%dSwitch", othernum);
928 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
929 SoInteractionKit::setSwitchValue(sw, this->ctrlDown ? 0 : 1);
930 }
931 else {
932 this->setAllPartsActive(TRUE);
933 this->updateArrows();
934 }
935 }
936
937 void
updateArrows(void)938 SoHandleBoxDragger::updateArrows(void)
939 {
940 int i;
941 SbString str;
942 SoSwitch *sw;
943
944 if (this->constraintState >= CONSTRAINT_X) {
945 int onval = -1;
946 switch (this->constraintState) {
947 case CONSTRAINT_X:
948 onval = 3;
949 break;
950 case CONSTRAINT_Y:
951 onval = 1;
952 break;
953 case CONSTRAINT_Z:
954 onval = 5;
955 break;
956 }
957 for (i = 1; i <= 6; i++) {
958 str.sprintf("arrow%dSwitch", i);
959 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
960 if (i == onval || i == onval + 1) {
961 SoInteractionKit::setSwitchValue(sw, 0);
962 }
963 else {
964 SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
965 }
966 }
967 }
968 else if (this->whatkind == WHATKIND_TRANSLATOR) {
969 int num = (this->whatnum-1) & ~1;
970 for (i = 0; i < 6; i++) {
971 str.sprintf("arrow%dSwitch", i+1);
972 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
973 if (i == num || i == num+1) {
974 SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
975 }
976 else {
977 SoInteractionKit::setSwitchValue(sw, 0);
978 }
979 }
980 }
981 else {
982 for (i = 1; i <= 6; i++) {
983 str.sprintf("arrow%dSwitch", i);
984 sw = SO_GET_ANY_PART(this, str.getString(), SoSwitch);
985 SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
986 }
987 }
988 }
989
990 void
getSurroundScaleMatrices(SbMatrix & mat,SbMatrix & inv)991 SoHandleBoxDragger::getSurroundScaleMatrices(SbMatrix &mat, SbMatrix &inv)
992 {
993 if (this->surroundScale.getValue()) {
994 this->getPartToLocalMatrix("surroundScale", mat, inv);
995 }
996 else {
997 mat = inv = SbMatrix::identity();
998 }
999 }
1000
1001 SbVec3f
getDraggerCenter(void)1002 SoHandleBoxDragger::getDraggerCenter(void)
1003 {
1004 SbMatrix mat, inv;
1005 this->getSurroundScaleMatrices(mat, inv);
1006 return SbVec3f(mat[3][0], mat[3][1], mat[3][2]);
1007 }
1008
1009 SbVec3f
calcCtrlOffset(const SbVec3f startpt)1010 SoHandleBoxDragger::calcCtrlOffset(const SbVec3f startpt)
1011 {
1012 SbMatrix m, inv;
1013 this->getSurroundScaleMatrices(m, inv);
1014 SbVec3f v = SbVec3f(m[3][0], m[3][1], m[3][2]) - startpt;
1015
1016 for (int i = 0; i < 3; i++) {
1017 v[i] *= inv[i][i];
1018 if (v[i] < -0.95) v[i] = -1.0f;
1019 else if (v[i] > 0.95) v[i] = 1.0f;
1020 else v[i] = 0.0f;
1021 v[i] *= m[i][i];
1022 }
1023 return v;
1024 }
1025
1026 #undef WHATKIND_NONE
1027 #undef WHATKIND_TRANSLATOR
1028 #undef WHATKIND_EXTRUDER
1029 #undef WHATKIND_UNIFORM
1030 #undef CONSTRAINT_OFF
1031 #undef CONSTRAINT_WAIT
1032 #undef CONSTRAINT_X
1033 #undef CONSTRAINT_Y
1034 #undef CONSTRAINT_Z
1035
1036 #endif // HAVE_DRAGGERS
1037