1
/***************************************************************************
2
* Copyright (c) 2005 JĆ¼rgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
25
#include <Inventor/nodes/SoAntiSquish.h>
26
#include <Inventor/nodes/SoRotation.h>
27
#include <Inventor/nodes/SoSeparator.h>
28
#include <Inventor/nodes/SoSurroundScale.h>
29
#include <Inventor/nodes/SoTransform.h>
30
#include <Inventor/sensors/SoFieldSensor.h>
32
// Include files for child dragger classes.
33
#include <Inventor/draggers/SoRotateCylindricalDragger.h>
34
//#include "TranslateRadialDragger.h"
35
#include <Inventor/draggers/SoTranslate1Dragger.h>
37
// Include file for our new class.
38
#include "SoNavigationDragger.h"
40
// This file contains RotTransDragger::geomBuffer, which
41
// describes the default geometry resources for this class.
42
//#include "RotTransDraggerGeom.h"
44
SO_KIT_SOURCE(RotTransDragger);
47
// Initializes the type ID for this dragger node. This
48
// should be called once after SoInteraction::init().
50
RotTransDragger::initClass()
52
SO_KIT_INIT_CLASS(RotTransDragger, SoDragger, "Dragger");
55
RotTransDragger::RotTransDragger()
57
SO_KIT_CONSTRUCTOR(RotTransDragger);
59
// Don't create "surroundScale" by default. It's only put
60
// to use if this dragger is used within a manipulator.
61
SO_KIT_ADD_CATALOG_ENTRY(surroundScale, SoSurroundScale, TRUE,
62
topSeparator, geomSeparator, TRUE);
63
// Create an anti-squish node by default.
64
SO_KIT_ADD_CATALOG_ENTRY(antiSquish, SoAntiSquish, FALSE,
65
topSeparator, geomSeparator, TRUE);
66
SO_KIT_ADD_CATALOG_ENTRY(translator, SoTranslate1Dragger,
67
TRUE, topSeparator, geomSeparator,
69
SO_KIT_ADD_CATALOG_ENTRY(XRotatorSep, SoSeparator, FALSE,
70
topSeparator, geomSeparator, FALSE);
71
SO_KIT_ADD_CATALOG_ENTRY(XRotatorRot, SoRotation, TRUE,
72
XRotatorSep,0 , FALSE);
73
SO_KIT_ADD_CATALOG_ENTRY(XRotator,SoRotateCylindricalDragger,
74
TRUE, XRotatorSep, 0,TRUE);
76
SO_KIT_ADD_CATALOG_ENTRY(YRotator, SoRotateCylindricalDragger,
77
TRUE, topSeparator, geomSeparator, TRUE);
79
SO_KIT_ADD_CATALOG_ENTRY(ZRotatorSep, SoSeparator, FALSE,
80
topSeparator, geomSeparator, FALSE);
81
SO_KIT_ADD_CATALOG_ENTRY(ZRotatorRot, SoRotation, TRUE,
82
ZRotatorSep,0 ,FALSE);
83
SO_KIT_ADD_CATALOG_ENTRY(ZRotator, SoRotateCylindricalDragger,
84
TRUE, ZRotatorSep, 0,TRUE);
86
// Read geometry resources. Only do this the first time we
87
// construct one. 'geomBuffer' contains our compiled in
88
// defaults. The user can override these by specifying new
89
// scene graphs in the file:
90
// $(SO_DRAGGER_DIR)/rotTransDragger.iv"
91
//if (SO_KIT_IS_FIRST_INSTANCE())
92
// readDefaultParts("rotTransDragger.iv", geomBuffer,
93
// sizeof(geomBuffer));
95
// Fields that always show current state of the dragger.
96
SO_KIT_ADD_FIELD(rotation, (0.0, 0.0, 0.0, 1.0));
97
SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0));
99
// Creates parts list and default parts for this nodekit.
100
SO_KIT_INIT_INSTANCE();
102
// Make the anti-squish node surround the biggest dimension
103
SoAntiSquish *myAntiSquish =
104
SO_GET_ANY_PART(this, "antiSquish", SoAntiSquish);
105
myAntiSquish->sizing = SoAntiSquish::BIGGEST_DIMENSION;
107
// Create the simple draggers that comprise this dragger.
108
// This dragger has four simple pieces:
109
// 1 TranslateRadialDragger
110
// 3 RotateCylindricalDraggers
111
// In the constructor, we just call SO_GET_ANY_PART to
112
// build each dragger.
113
// Within the setUpConnections() method, we will
114
// take care of giving these draggers new geometry and
115
// establishing their callbacks.
117
// Create the translator dragger.
118
//SoDragger *tDragger = SO_GET_ANY_PART(this, "translator",
119
// SoTranslate1Dragger);
121
// Create the XRotator dragger.
122
//SoDragger *XDragger = SO_GET_ANY_PART(this, "XRotator",
123
// SoRotateCylindricalDragger);
125
// Create the YRotator dragger.
126
//SoDragger *YDragger = SO_GET_ANY_PART(this, "YRotator",
127
// SoRotateCylindricalDragger);
129
// Create the ZRotator dragger.
130
//SoDragger *ZDragger = SO_GET_ANY_PART(this, "ZRotator",
131
// SoRotateCylindricalDragger);
133
// Set rotations in "XRotatorRot" and "ZRotatorRot" parts.
134
// These parts will orient the draggers from their default
135
// (rotating about Y) to the desired configurations.
136
// By calling 'setAnyPartAsDefault' instead of 'setAnyPart'
137
// we ensure that they will not be written out, unless
138
// they are changed later on.
139
SoRotation *XRot = new SoRotation;
140
XRot->rotation.setValue(
141
SbRotation(SbVec3f(0,1,0), SbVec3f(1,0,0)));
142
setAnyPartAsDefault("XRotatorRot", XRot);
144
SoRotation *ZRot = new SoRotation;
145
ZRot->rotation.setValue(
146
SbRotation(SbVec3f(0,1,0), SbVec3f(0,0,1)));
147
setAnyPartAsDefault("ZRotatorRot", ZRot);
149
// Updates the fields when motionMatrix changes
150
addValueChangedCallback(&RotTransDragger::valueChangedCB);
152
// Updates motionMatrix when either field changes.
153
rotFieldSensor = new SoFieldSensor(
154
&RotTransDragger::fieldSensorCB, this);
155
rotFieldSensor->setPriority(0);
156
translFieldSensor = new SoFieldSensor(
157
&RotTransDragger::fieldSensorCB,this);
158
translFieldSensor->setPriority(0);
160
setUpConnections(TRUE, TRUE);
163
RotTransDragger::~RotTransDragger()
165
if (rotFieldSensor!=NULL)
166
delete rotFieldSensor;
167
if (translFieldSensor!=NULL)
168
delete translFieldSensor;
172
RotTransDragger::setUpConnections(SbBool onOff, SbBool doItAlways)
174
if (!doItAlways && connectionsSetUp == onOff)
178
// We connect AFTER base class.
179
SoDragger::setUpConnections(onOff, doItAlways);
181
// For each of the simple draggers that compries this:
182
// [a]Call setPart after looking up our replacement parts
183
// in the global dictionary.
184
// [b]Add the invalidateSurroundScaleCB as a start and end
185
// callback. When using a surroundScale node, these
186
// trigger it to recalculate a bounding box at the
187
// beginning and end of dragging.
188
// [c]Register the dragger as a 'childDragger' of this
189
// one. This has the following effects:
190
// [1] This dragger's callbacks will be invoked
191
// following the child manip's callbacks.
192
// [2] When the child is dragged, the child's motion
193
// will be transferred into motion of the entire
196
(SoDragger *) getAnyPart("translator", FALSE);
197
// [a] Set up the parts in the child dragger...
198
tD->setPartAsDefault("translator",
199
"rotTransTranslatorTranslator");
200
tD->setPartAsDefault("translatorActive",
201
"rotTransTranslatorTranslatorActive");
202
tD->setPartAsDefault("feedback",
203
"rotTransTranslatorFeedback");
204
tD->setPartAsDefault("feedbackActive",
205
"rotTransTranslatorFeedbackActive");
206
// [b] and [c] Add the callbacks and register the child
207
tD->addStartCallback(
208
&RotTransDragger::invalidateSurroundScaleCB, this);
209
tD->addFinishCallback(
210
&RotTransDragger::invalidateSurroundScaleCB, this);
211
registerChildDragger(tD);
214
(SoDragger *) getAnyPart("XRotator", FALSE);
215
// [a] Set up the parts in the child dragger...
216
XD->setPartAsDefault("rotator",
217
"rotTransRotatorRotator");
218
XD->setPartAsDefault("rotatorActive",
219
"rotTransRotatorRotatorActive");
220
XD->setPartAsDefault("feedback",
221
"rotTransRotatorFeedback");
222
XD->setPartAsDefault("feedbackActive",
223
"rotTransRotatorFeedbackActive");
224
// [b] and [c] Add the callbacks and register the child
225
XD->addStartCallback(
226
&RotTransDragger::invalidateSurroundScaleCB, this);
227
XD->addFinishCallback(
228
&RotTransDragger::invalidateSurroundScaleCB, this);
229
registerChildDragger(XD);
232
(SoDragger *) getAnyPart("YRotator", FALSE);
233
// [a] Set up the parts in the child dragger...
234
YD->setPartAsDefault("rotator",
235
"rotTransRotatorRotator");
236
YD->setPartAsDefault("rotatorActive",
237
"rotTransRotatorRotatorActive");
238
YD->setPartAsDefault("feedback",
239
"rotTransRotatorFeedback");
240
YD->setPartAsDefault("feedbackActive",
241
"rotTransRotatorFeedbackActive");
242
// [b] and [c] Add the callbacks and register the child
243
YD->addStartCallback(
244
&RotTransDragger::invalidateSurroundScaleCB, this);
245
YD->addFinishCallback(
246
&RotTransDragger::invalidateSurroundScaleCB, this);
247
registerChildDragger(YD);
250
(SoDragger *) getAnyPart("ZRotator", FALSE);
251
// [a] Set up the parts in the child dragger...
252
ZD->setPartAsDefault("rotator",
253
"rotTransRotatorRotator");
254
ZD->setPartAsDefault("rotatorActive",
255
"rotTransRotatorRotatorActive");
256
ZD->setPartAsDefault("feedback",
257
"rotTransRotatorFeedback");
258
ZD->setPartAsDefault("feedbackActive",
259
"rotTransRotatorFeedbackActive");
260
// [b] and [c] Add the callbacks and register the child
261
ZD->addStartCallback(
262
&RotTransDragger::invalidateSurroundScaleCB, this);
263
ZD->addFinishCallback(
264
&RotTransDragger::invalidateSurroundScaleCB, this);
265
registerChildDragger(ZD);
268
// Call the sensor CB to make things up-to-date.
269
fieldSensorCB(this, NULL);
271
// Connect the field sensors
272
if (translFieldSensor->getAttachedField() != &translation)
273
translFieldSensor->attach(&translation);
274
if (rotFieldSensor->getAttachedField() != &rotation)
275
rotFieldSensor->attach(&rotation);
278
// We disconnect BEFORE base class.
280
// Remove the callbacks from the child draggers,
281
// and unregister them as children.
283
(SoDragger *) getAnyPart("translator", FALSE);
284
tD->removeStartCallback(
285
&RotTransDragger::invalidateSurroundScaleCB, this);
286
tD->removeFinishCallback(
287
&RotTransDragger::invalidateSurroundScaleCB, this);
288
unregisterChildDragger(tD);
291
(SoDragger *) getAnyPart("XRotator", FALSE);
292
XD->removeStartCallback(
293
&RotTransDragger::invalidateSurroundScaleCB, this);
294
XD->removeFinishCallback(
295
&RotTransDragger::invalidateSurroundScaleCB, this);
296
unregisterChildDragger(XD);
299
(SoDragger *) getAnyPart("YRotator", FALSE);
300
YD->removeStartCallback(
301
&RotTransDragger::invalidateSurroundScaleCB, this);
302
YD->removeFinishCallback(
303
&RotTransDragger::invalidateSurroundScaleCB, this);
304
unregisterChildDragger(YD);
307
(SoDragger *) getAnyPart("ZRotator", FALSE);
308
ZD->removeStartCallback(
309
&RotTransDragger::invalidateSurroundScaleCB, this);
310
ZD->removeFinishCallback(
311
&RotTransDragger::invalidateSurroundScaleCB, this);
312
unregisterChildDragger(ZD);
314
// Disconnect the field sensors.
315
if (translFieldSensor->getAttachedField()!=NULL)
316
translFieldSensor->detach();
317
if (rotFieldSensor->getAttachedField()!=NULL)
318
rotFieldSensor->detach();
320
SoDragger::setUpConnections(onOff, doItAlways);
323
return !(connectionsSetUp = onOff);
326
// Called when the motionMatrix changes. Sets the "translation"
327
// and "rotation" fields based on the new motionMatrix
329
RotTransDragger::valueChangedCB(void *, SoDragger *inDragger)
331
RotTransDragger *myself = (RotTransDragger *) inDragger;
333
// Factor the motionMatrix into its parts
334
SbMatrix motMat = myself->getMotionMatrix();
335
SbVec3f trans, scale;
336
SbRotation rot, scaleOrient;
337
motMat.getTransform(trans, rot, scale, scaleOrient);
339
// Set the fields. Disconnect the sensors while doing so.
340
myself->rotFieldSensor->detach();
341
myself->translFieldSensor->detach();
342
if (myself->rotation.getValue() != rot)
343
myself->rotation = rot;
344
if (myself->translation.getValue() != trans)
345
myself->translation = trans;
346
myself->rotFieldSensor->attach(&myself->rotation);
347
myself->translFieldSensor->attach(&myself->translation);
350
// If the "translation" or "rotation" field changes, changes
351
// the motionMatrix accordingly.
353
RotTransDragger::fieldSensorCB(void *inDragger, SoSensor *)
355
RotTransDragger *myself = (RotTransDragger *) inDragger;
357
SbMatrix motMat = myself->getMotionMatrix();
358
myself->workFieldsIntoTransform(motMat);
360
myself->setMotionMatrix(motMat);
363
// When any child dragger starts or ends a drag, tell the
364
// "surroundScale" part (if it exists) to invalidate its
365
// current bounding box value.
367
RotTransDragger::invalidateSurroundScaleCB(void *parent, SoDragger *)
369
RotTransDragger *myParentDragger = (RotTransDragger *) parent;
371
// Invalidate the surroundScale, if it exists.
372
SoSurroundScale *mySS = SO_CHECK_PART(
373
myParentDragger, "surroundScale", SoSurroundScale);
379
RotTransDragger::setDefaultOnNonWritingFields()
381
// The nodes pointed to by these part-fields may
382
// change after construction, but we
383
// don't want to write them out.
384
surroundScale.setDefault(TRUE);
385
antiSquish.setDefault(TRUE);
387
SoDragger::setDefaultOnNonWritingFields();