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 SoDirectionalLightDragger SoDirectionalLightDragger.h Inventor/draggers/SoDirectionalLightDragger.h
41 \brief The SoDirectionalLightDragger class provides interactive geometry for manipulating a directional light source.
42
43 \ingroup draggers
44
45 \DRAGGER_DEFAULT_SCREENSHOT
46
47 <center>
48 \image html directionallight.png "Screen Shot of Default Dragger"
49 </center>
50
51 This dragger is well suited to use for setting up the fields of a
52 SoDirectionalLight node, as it provides geometry for the end-user to
53 interact with a directional vector.
54
55 The image below is an action shot example, with the directional light being red
56 and the camera headlight turned right down.
57
58 <center>
59 \image html directionallightdragger_actionshot.png "DirectionalLight Dragger Action Shot"
60 </center>
61
62 For convenience, this dragger also by default contains interaction
63 geometry for placing the dragger itself. (SoDirectionalLight nodes
64 don't have a position field, so this was strictly not needed.)
65
66 The Coin library also includes a manipulator class,
67 SoDirectionalLightManip, which wraps the functionality provided by
68 this class inside the necessary mechanisms for connecting it to
69 SoDirectionalLight node instances in a scenegraph.
70
71 \sa SoDirectionalLightManip
72 */
73
74 #include <Inventor/draggers/SoDirectionalLightDragger.h>
75
76 #include <cstring>
77
78 #include <Inventor/draggers/SoDragPointDragger.h>
79 #include <Inventor/draggers/SoRotateSphericalDragger.h>
80 #include <Inventor/nodes/SoMaterial.h>
81 #include <Inventor/nodes/SoRotation.h>
82 #include <Inventor/nodes/SoSeparator.h>
83 #include <Inventor/sensors/SoFieldSensor.h>
84
85 #include <data/draggerDefaults/directionalLightDragger.h>
86
87 #include "nodekits/SoSubKitP.h"
88 #include "SbBasicP.h"
89
90 /*!
91 \var SoSFRotation SoDirectionalLightDragger::rotation
92
93 This field is continuously updated to contain the rotation of the
94 current direction vector. The application programmer will typically
95 connect this to the rotation field of a SoDirectionalLight node
96 (unless using the SoDirectionalLightManip class, where this is taken
97 care of automatically).
98
99 It may also of course be connected to any other rotation field
100 controlling the direction of scenegraph geometry, it does not have
101 to part of a SoDirectionalLight node specifically.
102 */
103 /*!
104 \var SoSFVec3f SoDirectionalLightDragger::translation
105
106 Continuously updated to contain the current translation from the
107 dragger's local origo position.
108
109 This field is not used by the SoDirectionalLightManip, but may be of
110 interest for the application programmer wanting to use the
111 SoDirectionalLightDragger outside the context of controlling a
112 directional light node.
113 */
114
115 /*!
116 \var SoFieldSensor * SoDirectionalLightDragger::rotFieldSensor
117 \COININTERNAL
118 */
119 /*!
120 \var SoFieldSensor * SoDirectionalLightDragger::translFieldSensor
121 \COININTERNAL
122 */
123
124 class SoDirectionalLightDraggerP {
125 public:
126 };
127
128 SO_KIT_SOURCE(SoDirectionalLightDragger);
129
130
131 // Doc in superclass.
132 void
initClass(void)133 SoDirectionalLightDragger::initClass(void)
134 {
135 SO_KIT_INTERNAL_INIT_CLASS(SoDirectionalLightDragger, SO_FROM_INVENTOR_1);
136 }
137
138 // FIXME: document which parts need to be present in the geometry
139 // scenegraph, and what role they play in the dragger. 20010913 mortene.
140 /*!
141 \DRAGGER_CONSTRUCTOR
142
143 \NODEKIT_PRE_DIAGRAM
144
145 \verbatim
146 CLASS SoDirectionalLightDragger
147 -->"this"
148 "callbackList"
149 "topSeparator"
150 "motionMatrix"
151 --> "material"
152 --> "translatorSep"
153 --> "translatorRotInv"
154 --> "translator"
155 --> "rotator"
156 "geomSeparator"
157 \endverbatim
158
159 \NODEKIT_POST_DIAGRAM
160
161
162 \NODEKIT_PRE_TABLE
163
164 \verbatim
165 CLASS SoDirectionalLightDragger
166 PVT "this", SoDirectionalLightDragger ---
167 "callbackList", SoNodeKitListPart [ SoCallback, SoEventCallback ]
168 PVT "topSeparator", SoSeparator ---
169 PVT "motionMatrix", SoMatrixTransform ---
170 "material", SoMaterial ---
171 PVT "translatorSep", SoSeparator ---
172 "translatorRotInv", SoRotation ---
173 "translator", SoDragPointDragger ---
174 "rotator", SoRotateSphericalDragger ---
175 PVT "geomSeparator", SoSeparator ---
176 \endverbatim
177
178 \NODEKIT_POST_TABLE
179 */
SoDirectionalLightDragger(void)180 SoDirectionalLightDragger::SoDirectionalLightDragger(void)
181 {
182 SO_KIT_INTERNAL_CONSTRUCTOR(SoDirectionalLightDragger);
183
184 SO_KIT_ADD_CATALOG_ENTRY(material, SoMaterial, TRUE, topSeparator, translatorSep, TRUE);
185 SO_KIT_ADD_CATALOG_ENTRY(rotator, SoRotateSphericalDragger, TRUE, topSeparator, geomSeparator, TRUE);
186 SO_KIT_ADD_CATALOG_ENTRY(translator, SoDragPointDragger, TRUE, translatorSep, "", TRUE);
187 SO_KIT_ADD_CATALOG_ENTRY(translatorRotInv, SoRotation, TRUE, translatorSep, translator, TRUE);
188 SO_KIT_ADD_CATALOG_ENTRY(translatorSep, SoSeparator, TRUE, topSeparator, rotator, FALSE);
189
190 if (SO_KIT_IS_FIRST_INSTANCE()) {
191 SoInteractionKit::readDefaultParts("directionalLightDragger.iv",
192 DIRECTIONALLIGHTDRAGGER_draggergeometry,
193 static_cast<int>(strlen(DIRECTIONALLIGHTDRAGGER_draggergeometry)));
194 }
195
196 SO_KIT_ADD_FIELD(rotation, (SbRotation(SbVec3f(0.0f, 0.0f, 1.0f), 0.0f)));
197 SO_KIT_ADD_FIELD(translation, (0.0f, 0.0f, 0.0f));
198 SO_KIT_INIT_INSTANCE();
199
200 SoDragger *pdragger = SO_GET_ANY_PART(this, "translator", SoDragPointDragger);
201 assert(pdragger);
202 SoDragger *sdragger = SO_GET_ANY_PART(this, "rotator", SoDragPointDragger);
203 assert(sdragger);
204
205 this->setPartAsDefault("material", "directionalLightOverallMaterial");
206
207 this->addValueChangedCallback(SoDirectionalLightDragger::valueChangedCB);
208
209 this->rotFieldSensor = new SoFieldSensor(SoDirectionalLightDragger::fieldSensorCB, this);
210 this->rotFieldSensor->setPriority(0);
211 this->translFieldSensor = new SoFieldSensor(SoDirectionalLightDragger::fieldSensorCB, this);
212 this->translFieldSensor->setPriority(0);
213
214 this->setUpConnections(TRUE, TRUE);
215
216 // create this part to avoid changes in the scene graph while traversing it
217 (void) SO_GET_ANY_PART(this, "translatorRotInv", SoRotation);
218
219 this->translatorSep.setDefault(TRUE);
220 }
221
222 /*!
223 Protected destructor.
224
225 (Dragger classes are derived from SoBase, so they are reference
226 counted and automatically destroyed when their reference count goes
227 to 0.)
228 */
~SoDirectionalLightDragger()229 SoDirectionalLightDragger::~SoDirectionalLightDragger()
230 {
231 delete this->translFieldSensor;
232 delete this->rotFieldSensor;
233 }
234
235 // doc in superclass
236 SbBool
setUpConnections(SbBool onoff,SbBool doitalways)237 SoDirectionalLightDragger::setUpConnections(SbBool onoff, SbBool doitalways)
238 {
239 if (!doitalways && this->connectionsSetUp == onoff) return onoff;
240
241 if (onoff) {
242 inherited::setUpConnections(onoff, doitalways);
243 SoDragger * therotator = coin_assert_cast<SoDragger *>(this->getAnyPart("rotator", FALSE));
244 therotator->setPartAsDefault("rotator", "directionalLightRotatorRotator");
245 therotator->setPartAsDefault("rotatorActive",
246 "directionalLightRotatorRotatorActive");
247 therotator->setPartAsDefault("feedback",
248 "directionalLightRotatorFeedback");
249 therotator->setPartAsDefault("feedbackActive",
250 "directionalLightRotatorFeedbackActive");
251
252 SoDragger *thetranslator = coin_assert_cast<SoDragger *>(this->getAnyPart("translator", FALSE));
253 thetranslator->setPartAsDefault("yzTranslator.translator",
254 "directionalLightTranslatorPlaneTranslator");
255 thetranslator->setPartAsDefault("xzTranslator.translator",
256 "directionalLightTranslatorPlaneTranslator");
257 thetranslator->setPartAsDefault("xyTranslator.translator",
258 "directionalLightTranslatorPlaneTranslator");
259 thetranslator->setPartAsDefault("yzTranslator.translatorActive",
260 "directionalLightTranslatorPlaneTranslatorActive");
261 thetranslator->setPartAsDefault("xzTranslator.translatorActive",
262 "directionalLightTranslatorPlaneTranslatorActive");
263 thetranslator->setPartAsDefault("xyTranslator.translatorActive",
264 "directionalLightTranslatorPlaneTranslatorActive");
265 thetranslator->setPartAsDefault("xTranslator.translator",
266 "directionalLightTranslatorLineTranslator");
267 thetranslator->setPartAsDefault("yTranslator.translator",
268 "directionalLightTranslatorLineTranslator");
269 thetranslator->setPartAsDefault("zTranslator.translator",
270 "directionalLightTranslatorLineTranslator");
271 thetranslator->setPartAsDefault("xTranslator.translatorActive",
272 "directionalLightTranslatorLineTranslatorActive");
273 thetranslator->setPartAsDefault("yTranslator.translatorActive",
274 "directionalLightTranslatorLineTranslatorActive");
275 thetranslator->setPartAsDefault("zTranslator.translatorActive",
276 "directionalLightTranslatorLineTranslatorActive");
277
278 this->registerChildDragger(therotator);
279 this->registerChildDragger(thetranslator);
280
281 if (this->translFieldSensor->getAttachedField() != &this->translation)
282 this->translFieldSensor->attach(&this->translation);
283 if (this->rotFieldSensor->getAttachedField() != &this->rotation)
284 this->rotFieldSensor->attach(&this->rotation);
285 }
286 else {
287 SoDragger * thetranslator = coin_assert_cast<SoDragger *>(this->getAnyPart("translator", FALSE));
288 this->unregisterChildDragger(thetranslator);
289 SoDragger * therotator = coin_assert_cast<SoDragger *>(this->getAnyPart("rotator", FALSE));
290 this->unregisterChildDragger(therotator);
291
292 if (this->rotFieldSensor->getAttachedField() != NULL)
293 this->rotFieldSensor->detach();
294 if (this->translFieldSensor->getAttachedField() != NULL)
295 this->translFieldSensor->detach();
296
297 inherited::setUpConnections(onoff, doitalways);
298 }
299 return !(this->connectionsSetUp = onoff);
300 }
301
302 // doc in superclass
303 void
setDefaultOnNonWritingFields(void)304 SoDirectionalLightDragger::setDefaultOnNonWritingFields(void)
305 {
306 this->translator.setDefault(TRUE);
307 this->rotator.setDefault(TRUE);
308 this->translatorRotInv.setDefault(TRUE);
309
310 inherited::setDefaultOnNonWritingFields();
311 }
312
313 /*! \COININTERNAL */
314 void
fieldSensorCB(void * d,SoSensor *)315 SoDirectionalLightDragger::fieldSensorCB(void * d, SoSensor *)
316 {
317 SoDirectionalLightDragger * thisp = static_cast<SoDirectionalLightDragger *>(d);
318 SbMatrix matrix = thisp->getMotionMatrix();
319 thisp->workFieldsIntoTransform(matrix);
320 thisp->setMotionMatrix(matrix);
321 }
322
323 /*! \COININTERNAL */
324 void
valueChangedCB(void *,SoDragger * d)325 SoDirectionalLightDragger::valueChangedCB(void *, SoDragger * d)
326 {
327 SoDirectionalLightDragger *thisp = static_cast<SoDirectionalLightDragger *>(d);
328 SbMatrix matrix = thisp->getMotionMatrix();
329 SbVec3f trans, scale;
330 SbRotation rot, scaleOrient;
331 matrix.getTransform(trans, rot, scale, scaleOrient);
332
333 thisp->translFieldSensor->detach();
334 if (thisp->translation.getValue() != trans)
335 thisp->translation = trans;
336 thisp->translFieldSensor->attach(&thisp->translation);
337
338 thisp->rotFieldSensor->detach();
339 if (thisp->rotation.getValue() != rot)
340 thisp->rotation = rot;
341 thisp->rotFieldSensor->attach(&thisp->rotation);
342
343 SoRotation *invRot = SO_GET_ANY_PART(thisp, "translatorRotInv", SoRotation);
344 invRot->rotation = rot.inverse();
345 }
346
347 #endif // HAVE_DRAGGERS
348