1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
13//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.
15#ifndef OSGMANIPULATOR_DRAGGER
16#define OSGMANIPULATOR_DRAGGER 1
18#include <osgManipulator/Constraint>
19#include <osgManipulator/Command>
21#include <osg/BoundingSphere>
22#include <osg/MatrixTransform>
23#include <osgUtil/SceneView>
24#include <osgGA/GUIEventAdapter>
25#include <osgGA/GUIActionAdapter>
27namespace osgManipulator
30class CompositeDragger;
32class TranslateInLineCommand;
33class TranslateInPlaneCommand;
36class ScaleUniformCommand;
39/** Computes the nodepath from the given node all the way up to the root. */
40extern OSGMANIPULATOR_EXPORT void computeNodePathToRoot(osg::Node& node, osg::NodePath& np);
43class OSGMANIPULATOR_EXPORT DraggerTransformCallback : public DraggerCallback
47 enum HandleCommandMask
49 HANDLE_TRANSLATE_IN_LINE = 1<<0,
50 HANDLE_TRANSLATE_IN_PLANE = 1<<1,
51 HANDLE_SCALED_1D = 1<<2,
52 HANDLE_SCALED_2D = 1<<3,
53 HANDLE_SCALED_UNIFORM = 1<<4,
54 HANDLE_ROTATE_3D = 1<<5,
55 HANDLE_ALL = 0x8ffffff
58 DraggerTransformCallback(osg::MatrixTransform* transform, int handleCommandMask = HANDLE_ALL);
60 virtual bool receive(const MotionCommand&);
61 virtual bool receive(const TranslateInLineCommand& command);
62 virtual bool receive(const TranslateInPlaneCommand& command);
63 virtual bool receive(const Scale1DCommand& command);
64 virtual bool receive(const Scale2DCommand& command);
65 virtual bool receive(const ScaleUniformCommand& command);
66 virtual bool receive(const Rotate3DCommand& command);
68 osg::MatrixTransform* getTransform() { return _transform.get(); }
69 const osg::MatrixTransform* getTransform() const { return _transform.get(); }
73 unsigned int _handleCommandMask;
75 osg::observer_ptr<osg::MatrixTransform> _transform;
76 osg::Matrix _startMotionMatrix;
78 osg::Matrix _localToWorld;
79 osg::Matrix _worldToLocal;
83class OSGMANIPULATOR_EXPORT PointerInfo
89 PointerInfo(const PointerInfo& rhs):
90 _hitList(rhs._hitList),
91 _nearPoint(rhs._nearPoint),
92 _farPoint(rhs._farPoint),
95 _hitIter = _hitList.begin();
101 _hitIter = _hitList.begin();
106 bool completed() const { return _hitIter==_hitList.end(); }
110 if (!completed()) ++_hitIter;
113 typedef std::pair<osg::NodePath, osg::Vec3d> NodePathIntersectionPair;
114 typedef std::list< NodePathIntersectionPair> IntersectionList;
117 osg::Vec3d getLocalIntersectPoint() const { return _hitIter->second; }
121 void setNearFarPoints (osg::Vec3d nearPoint, osg::Vec3d farPoint) {
122 _nearPoint = nearPoint;
124 _eyeDir = farPoint - nearPoint;
127 const osg::Vec3d& getEyeDir() const {return _eyeDir;}
129 void getNearFarPoints( osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const {
130 nearPoint = _nearPoint;
131 farPoint = _farPoint;
134 bool contains(const osg::Node* node) const;
136 void setCamera(osg::Camera* camera)
141 _MVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
142 if (camera->getViewport()) _MVPW.postMult(camera->getViewport()->computeWindowMatrix());
143 _inverseMVPW.invert(_MVPW);
144 osg::Vec3d eye, center, up;
145 camera->getViewMatrix().getLookAt(eye, center, up);
146 _eyeDir = eye - center;
151 _MVPW.makeIdentity();
152 _inverseMVPW.makeIdentity();
153 _eyeDir = osg::Vec3d(0,0,1);
158 void addIntersection(const osg::NodePath& nodePath, const osg::Vec3d& intersectionPoint)
160 bool needToResetHitIter = _hitList.empty();
161 _hitList.push_back(NodePathIntersectionPair(nodePath, intersectionPoint));
162 if (needToResetHitIter) _hitIter = _hitList.begin();
165 void setMousePosition(float pixel_x, float pixel_y)
167 projectWindowXYIntoObject(osg::Vec2d(pixel_x, pixel_y), _nearPoint, _farPoint);
171 bool projectWindowXYIntoObject(const osg::Vec2d& windowCoord, osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const;
174 IntersectionList _hitList;
175 IntersectionList::const_iterator _hitIter;
179 osg::Vec3d _nearPoint,_farPoint;
183 osg::Matrix _inverseMVPW;
188 * Base class for draggers. Concrete draggers implement the pick event handler
189 * and generate motion commands (translate, rotate, ...) and sends these
190 * command to all the DraggerCallbacks & Transforms that are connected to the Dragger that generates the
193class OSGMANIPULATOR_EXPORT Dragger : public osg::MatrixTransform
198 META_Node(osgManipulator,Dragger);
201 * Set/Get parent dragger. For simple draggers parent points to itself.
202 * For composite draggers parent points to the parent dragger that uses
205 virtual void setParentDragger(Dragger* parent) { _parentDragger = parent; }
207 Dragger* getParentDragger() { return _parentDragger; }
208 const Dragger* getParentDragger() const { return _parentDragger; }
210 /** Returns 0 if this Dragger is not a CompositeDragger. */
211 virtual const CompositeDragger* getComposite() const { return 0; }
213 /** Returns 0 if this Dragger is not a CompositeDragger. */
214 virtual CompositeDragger* getComposite() { return 0; }
217 void setHandleEvents(bool flag);
218 bool getHandleEvents() const { return _handleEvents; }
220 void setActivationModKeyMask(unsigned int mask) { _activationModKeyMask = mask; }
221 unsigned int getActivationModKeyMask() const { return _activationModKeyMask; }
223 void setActivationMouseButtonMask(unsigned int mask) { _activationMouseButtonMask = mask; }
224 unsigned int getActivationMouseButtonMask() const { return _activationMouseButtonMask; }
226 void setActivationKeyEvent(int key) { _activationKeyEvent = key; }
227 int getActivationKeyEvent() const { return _activationKeyEvent; }
230 virtual void traverse(osg::NodeVisitor& nv);
232 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
233 virtual bool handle(const PointerInfo&, const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) { return false; }
236 typedef std::vector< osg::ref_ptr<Constraint> > Constraints;
238 void addConstraint(Constraint* constraint);
239 template<class T> void addConstraint(const osg::ref_ptr<T>& c) { addConstraint(c.get()); }
241 void removeConstraint(Constraint* constraint);
242 template<class T> void removeConstraint(const osg::ref_ptr<T>& c) { removeConstraint(c.get()); }
244 Constraints& getConstraints() { return _constraints; }
245 const Constraints& getConstraints() const { return _constraints; }
248 typedef std::vector< osg::ref_ptr<DraggerCallback> > DraggerCallbacks;
250 void addDraggerCallback(DraggerCallback* dc);
251 template<class T> void addDraggerCallback(const osg::ref_ptr<T>& dc) { addDraggerCallback(dc.get()); }
253 void removeDraggerCallback(DraggerCallback* dc);
254 template<class T> void removeDraggerCallback(const osg::ref_ptr<T>& dc) { removeDraggerCallback(dc.get()); }
256 DraggerCallbacks& getDraggerCallbacks() { return _draggerCallbacks; }
257 const DraggerCallbacks& getDraggerCallbacks() const { return _draggerCallbacks; }
259 void addTransformUpdating(MatrixTransform* transform, int handleCommandMask = DraggerTransformCallback::HANDLE_ALL);
260 void removeTransformUpdating(MatrixTransform* transform);
262 /** Setup default geometry for dragger. */
263 virtual void setupDefaultGeometry() {}
265 virtual bool receive(const MotionCommand& command);
266 virtual void dispatch(MotionCommand& command);
268 void setDraggerActive(bool active) { _draggerActive = active; }
269 bool getDraggerActive() const { return _draggerActive; }
272 * Set/Get the traversal mask used by this dragger when looking for intersections during event handling.
273 * This is useful to "hide" some geometry during event handling.
275 virtual void setIntersectionMask(osg::Node::NodeMask intersectionMask) { _intersectionMask = intersectionMask; }
276 osg::Node::NodeMask getIntersectionMask() const { return _intersectionMask; }
278 /** Return true if the axis of the Locator are inverted requiring the faces of any cubes used from rendering to be flipped to ensure the correct front/back face is used.*/
279 bool inverted() const;
281 /** apply the appropriate FrontFace setting to provided StateSet to ensure that the rendering of hull of the volume is the correct orientation.*/
282 void applyAppropriateFrontFace(osg::StateSet* ss) const;
287 Dragger(const Dragger& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
295 unsigned int _activationModKeyMask;
296 unsigned int _activationMouseButtonMask;
297 int _activationKeyEvent;
298 bool _activationPermittedByModKeyMask;
299 bool _activationPermittedByMouseButtonMask;
300 bool _activationPermittedByKeyEvent;
302 osgManipulator::PointerInfo _pointer;
304 Dragger* _parentDragger;
306 osg::ref_ptr<DraggerCallback> _selfUpdater;
307 Constraints _constraints;
308 DraggerCallbacks _draggerCallbacks;
309 osg::Node::NodeMask _intersectionMask;
315 * CompositeDragger allows to create complex draggers that are composed of a
316 * hierarchy of Draggers.
318class OSGMANIPULATOR_EXPORT CompositeDragger : public Dragger
322 META_Node(osgManipulator,CompositeDragger);
324 typedef std::vector< osg::ref_ptr<Dragger> > DraggerList;
326 virtual const CompositeDragger* getComposite() const { return this; }
327 virtual CompositeDragger* getComposite() { return this; }
329 virtual void setParentDragger(Dragger* parent);
331 virtual bool handle(const PointerInfo& pi, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
333 // Composite-specific methods below
334 virtual bool addDragger(Dragger* dragger);
335 template<class T> bool addDragger(const osg::ref_ptr<T>& dc) { return addDragger(dc.get()); }
337 virtual bool removeDragger(Dragger* dragger);
338 template<class T> bool removeDragger(const osg::ref_ptr<T>& dc) { return removeDragger(dc.get()); }
340 unsigned int getNumDraggers() const { return _draggerList.size(); }
342 Dragger* getDragger(unsigned int i) { return _draggerList[i].get(); }
343 const Dragger* getDragger(unsigned int i) const { return _draggerList[i].get(); }
345 bool containsDragger(const Dragger* dragger) const;
346 template<class T> bool containsDragger(const osg::ref_ptr<T>& dc) const { return containsDragger(dc.get()); }
348 DraggerList::iterator findDragger(const Dragger* dragger);
350 virtual void setIntersectionMask(osg::Node::NodeMask intersectionMask);
354 CompositeDragger() {}
355 CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
357 virtual ~CompositeDragger() {}
359 DraggerList _draggerList;
363 * Culls the drawable all the time. Used by draggers to have invisible geometry
364 * around lines and points so that they can be picked. For example, a dragger
365 * could have a line with an invisible cylinder around it to enable picking on
368void OSGMANIPULATOR_EXPORT setDrawableToAlwaysCull(osg::Drawable& drawable);
371 * Convenience function for setting the material color on a node.
373void OSGMANIPULATOR_EXPORT setMaterialColor(const osg::Vec4& color, osg::Node& node);