root/OpenSceneGraph/trunk/src/osgManipulator/Dragger.cpp @ 13041

Revision 13041, 17.5 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
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.
7 *
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.
12*/
13//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.
14
15#include <osgManipulator/Dragger>
16#include <osgManipulator/Command>
17#include <osg/Material>
18#include <osgGA/EventVisitor>
19#include <osgViewer/View>
20#include <osg/io_utils>
21using namespace osgManipulator;
22
23///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
24//
25// computeNodePathToRoot
26//
27void osgManipulator::computeNodePathToRoot(osg::Node& node, osg::NodePath& np)
28{
29    np.clear();
30
31    osg::NodePathList nodePaths = node.getParentalNodePaths();
32
33    if (!nodePaths.empty())
34    {
35        np = nodePaths.front();
36        if (nodePaths.size()>1)
37        {
38            OSG_NOTICE<<"osgManipulator::computeNodePathToRoot(,) taking first parent path, ignoring others."<<std::endl;
39        }
40    }
41}
42
43
44///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45//
46// DraggerTransformCallback
47//
48DraggerTransformCallback::DraggerTransformCallback(osg::MatrixTransform* transform,int handleCommandMask):
49    _handleCommandMask(handleCommandMask),
50    _transform(transform)
51{
52}
53
54bool DraggerTransformCallback::receive(const MotionCommand& command)
55{
56    if (!_transform) return false;
57
58    switch (command.getStage())
59    {
60        case MotionCommand::START:
61        {
62            // Save the current matrix
63            _startMotionMatrix = _transform->getMatrix();
64
65            // Get the LocalToWorld and WorldToLocal matrix for this node.
66            osg::NodePath nodePathToRoot;
67            computeNodePathToRoot(*_transform,nodePathToRoot);
68            _localToWorld = osg::computeLocalToWorld(nodePathToRoot);
69            _worldToLocal = osg::Matrix::inverse(_localToWorld);
70
71            return true;
72        }
73        case MotionCommand::MOVE:
74        {
75            //OSG_NOTICE<<"MotionCommand::MOVE "<<command.getMotionMatrix()<<std::endl;
76
77            // Transform the command's motion matrix into local motion matrix.
78            osg::Matrix localMotionMatrix = _localToWorld * command.getWorldToLocal()
79                                            * command.getMotionMatrix()
80                                            * command.getLocalToWorld() * _worldToLocal;
81
82            // Transform by the localMotionMatrix
83            _transform->setMatrix(localMotionMatrix * _startMotionMatrix);
84
85            return true;
86        }
87        case MotionCommand::FINISH:
88        {
89            return true;
90        }
91        case MotionCommand::NONE:
92        default:
93            return false;
94    }
95}
96
97bool DraggerTransformCallback::receive(const TranslateInLineCommand& command)
98{
99    if ((_handleCommandMask&HANDLE_TRANSLATE_IN_LINE)!=0) return receive(static_cast<const MotionCommand&>(command));
100    return false;
101}
102
103bool DraggerTransformCallback::receive(const TranslateInPlaneCommand& command)
104{
105    if ((_handleCommandMask&HANDLE_TRANSLATE_IN_PLANE)!=0) return receive(static_cast<const MotionCommand&>(command));
106    return false;
107}
108
109bool DraggerTransformCallback::receive(const Scale1DCommand& command)
110{
111    if ((_handleCommandMask&HANDLE_SCALED_1D)!=0) return receive(static_cast<const MotionCommand&>(command));
112    return false;
113}
114
115bool DraggerTransformCallback::receive(const Scale2DCommand& command)
116{
117    if ((_handleCommandMask&HANDLE_SCALED_2D)!=0) return receive(static_cast<const MotionCommand&>(command));
118    return false;
119}
120
121bool DraggerTransformCallback::receive(const ScaleUniformCommand& command)
122{
123    if ((_handleCommandMask&HANDLE_SCALED_UNIFORM)!=0) return receive(static_cast<const MotionCommand&>(command));
124    return false;
125}
126
127bool DraggerTransformCallback::receive(const Rotate3DCommand& command)
128{
129    if ((_handleCommandMask&HANDLE_ROTATE_3D)!=0) return receive(static_cast<const MotionCommand&>(command));
130    return false;
131}
132
133
134///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
135//
136// PointerInfo
137//
138PointerInfo::PointerInfo():
139    _nearPoint(osg::Vec3d()),
140    _farPoint(osg::Vec3d()),
141    _eyeDir(osg::Vec3d(0,0,1))
142{
143    _hitIter = _hitList.begin();
144}
145
146bool PointerInfo::contains(const osg::Node* node) const
147{
148    if (node && _hitIter!=_hitList.end()) return std::find((*_hitIter).first.begin(), (*_hitIter).first.end(), node) != (*_hitIter).first.end();
149    else return false;
150}
151
152bool PointerInfo::projectWindowXYIntoObject(const osg::Vec2d& windowCoord, osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const
153{
154    nearPoint = osg::Vec3d(windowCoord.x(),windowCoord.y(),0.0)*_inverseMVPW;
155    farPoint = osg::Vec3d(windowCoord.x(),windowCoord.y(),1.0)*_inverseMVPW;
156
157    return true;
158}
159
160
161///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162//
163// Dragger
164//
165Dragger::Dragger() :
166    _handleEvents(false),
167    _draggerActive(false),
168    _activationModKeyMask(0),
169    _activationKeyEvent(0),
170    _activationPermittedByModKeyMask(false),
171    _activationPermittedByKeyEvent(false),
172    _intersectionMask(0xffffffff)
173{
174    _parentDragger = this;
175    getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC);
176
177    _selfUpdater = new DraggerTransformCallback(this);
178
179}
180
181Dragger::Dragger(const Dragger& rhs, const osg::CopyOp& copyop):
182    osg::MatrixTransform(rhs, copyop),
183    _handleEvents(rhs._handleEvents),
184    _draggerActive(false),
185    _activationModKeyMask(rhs._activationModKeyMask),
186    _activationKeyEvent(rhs._activationKeyEvent),
187    _activationPermittedByModKeyMask(false),
188    _activationPermittedByKeyEvent(false),
189    _intersectionMask(0xffffffff)
190{
191    OSG_NOTICE<<"CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop) not Implemented yet."<<std::endl;
192}
193
194Dragger::~Dragger()
195{
196}
197
198void Dragger::setHandleEvents(bool flag)
199{
200    if (_handleEvents == flag) return;
201
202    _handleEvents = flag;
203
204    // update the number of children that require an event traversal to make sure this dragger recieves events.
205    if (_handleEvents) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+1);
206    else if (getNumChildrenRequiringEventTraversal()>=1) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
207}
208
209void Dragger::addConstraint(Constraint* constraint)
210{
211    // check to make sure constaint hasn't already been attached.
212    for(Constraints::iterator itr = _constraints.begin();
213        itr != _constraints.end();
214        ++itr)
215    {
216        if (*itr == constraint) return;
217    }
218
219    _constraints.push_back(constraint);
220}
221
222void Dragger::removeConstraint(Constraint* constraint)
223{
224    for(Constraints::iterator itr = _constraints.begin();
225        itr != _constraints.end();
226        )
227    {
228        if (*itr == constraint)
229        {
230            _constraints.erase(itr);
231            return;
232        } else
233        {
234            ++itr;
235        }
236    }
237}
238
239void Dragger::addTransformUpdating(osg::MatrixTransform* transform, int handleCommandMask)
240{
241    addDraggerCallback(new DraggerTransformCallback(transform, handleCommandMask));
242}
243
244void Dragger::removeTransformUpdating(osg::MatrixTransform* transform)
245{
246    for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
247        itr != _draggerCallbacks.end();
248        )
249    {
250        DraggerCallback* dc = itr->get();
251        DraggerTransformCallback* dtc = dynamic_cast<DraggerTransformCallback*>(dc);
252        if (dtc && dtc->getTransform()==transform)
253        {
254            itr = _draggerCallbacks.erase(itr);
255        }
256        else
257        {
258            ++itr;
259        }
260    }
261
262}
263
264void Dragger::addDraggerCallback(DraggerCallback* dc)
265{
266    for(DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
267        itr != _draggerCallbacks.end();
268        ++itr)
269    {
270        if (*itr == dc) return;
271    }
272
273    _draggerCallbacks.push_back(dc);
274}
275
276void Dragger::removeDraggerCallback(DraggerCallback* dc)
277{
278}
279
280
281void Dragger::traverse(osg::NodeVisitor& nv)
282{
283    if (_handleEvents && nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
284    {
285        osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
286        if (ev)
287        {
288            for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
289                itr != ev->getEvents().end();
290                ++itr)
291            {
292                osgGA::GUIEventAdapter* ea = itr->get();
293                if (handle(*ea, *(ev->getActionAdapter()))) ea->setHandled(true);
294            }
295        }
296        return;
297    }
298
299    MatrixTransform::traverse(nv);
300}
301
302bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
303{
304    if (ea.getHandled()) return false;
305
306    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
307    if (!view) return false;
308
309    bool handled = false;
310
311    bool activationPermitted = true;
312    if (_activationModKeyMask!=0 || _activationKeyEvent!=0)
313    {
314        _activationPermittedByModKeyMask = (_activationModKeyMask!=0) ?
315            ((ea.getModKeyMask() & _activationModKeyMask)!=0) :
316            false;
317
318        if (_activationKeyEvent!=0)
319        {
320            switch (ea.getEventType())
321            {
322                case osgGA::GUIEventAdapter::KEYDOWN:
323                {
324                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = true;
325                    break;
326                }
327                case osgGA::GUIEventAdapter::KEYUP:
328                {
329                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = false;
330                    break;
331                }
332                default:
333                    break;
334            }
335        }
336
337        activationPermitted =  _activationPermittedByModKeyMask || _activationPermittedByKeyEvent;
338
339    }
340
341    if (activationPermitted || _draggerActive)
342    {
343        switch (ea.getEventType())
344        {
345            case osgGA::GUIEventAdapter::PUSH:
346            {
347                osgUtil::LineSegmentIntersector::Intersections intersections;
348
349                _pointer.reset();
350
351                if (view->computeIntersections(ea.getX(),ea.getY(),intersections, _intersectionMask))
352                {
353                    for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
354                        hitr != intersections.end();
355                        ++hitr)
356                    {
357                        _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint());
358                    }
359                    for (osg::NodePath::iterator itr = _pointer._hitList.front().first.begin();
360                            itr != _pointer._hitList.front().first.end();
361                            ++itr)
362                    {
363                        osgManipulator::Dragger* dragger = dynamic_cast<osgManipulator::Dragger*>(*itr);
364                        if (dragger)
365                        {
366                            if (dragger==this)
367                            {
368                                osg::Camera *rootCamera = view->getCamera();
369                                osg::NodePath nodePath = _pointer._hitList.front().first;
370                                osg::NodePath::reverse_iterator ritr;
371                                for(ritr = nodePath.rbegin();
372                                    ritr != nodePath.rend();
373                                    ++ritr)
374                                {
375                                    osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr);
376                                    if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty()))
377                                    {
378                                         rootCamera = camera;
379                                         break;
380                                    }
381                                }
382
383                                _pointer.setCamera(rootCamera);
384                                _pointer.setMousePosition(ea.getX(), ea.getY());
385
386                                dragger->handle(_pointer, ea, aa);
387                                dragger->setDraggerActive(true);
388                                handled = true;
389                            }
390                        }
391                    }
392                }
393            }
394            case osgGA::GUIEventAdapter::DRAG:
395            case osgGA::GUIEventAdapter::RELEASE:
396            {
397                if (_draggerActive)
398                {
399                    _pointer._hitIter = _pointer._hitList.begin();
400//                    _pointer.setCamera(view->getCamera());
401                    _pointer.setMousePosition(ea.getX(), ea.getY());
402
403                    handle(_pointer, ea, aa);
404
405                    handled = true;
406                }
407                break;
408            }
409            default:
410                break;
411        }
412
413        if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
414        {
415            setDraggerActive(false);
416            _pointer.reset();
417        }
418    }
419
420    return handled;
421}
422
423bool Dragger::receive(const MotionCommand& command)
424{
425    if (_selfUpdater.valid()) return _selfUpdater->receive(command);
426    else return false;
427}
428
429void Dragger::dispatch(MotionCommand& command)
430{
431    // apply any constraints
432    for(Constraints::iterator itr = _constraints.begin();
433        itr != _constraints.end();
434        ++itr)
435    {
436        command.accept(*(*itr));
437    }
438
439    // apply any constraints of parent dragger.
440    if (getParentDragger()!=this)
441    {
442        for(Constraints::iterator itr = getParentDragger()->getConstraints().begin();
443            itr != getParentDragger()->getConstraints().end();
444            ++itr)
445        {
446            command.accept(*(*itr));
447        }
448    }
449
450    // move self
451    getParentDragger()->receive(command);
452
453    // pass on movement to any dragger callbacks
454    for(DraggerCallbacks::iterator itr = getParentDragger()->getDraggerCallbacks().begin();
455        itr != getParentDragger()->getDraggerCallbacks().end();
456        ++itr)
457    {
458        command.accept(*(*itr));
459    }
460}
461
462
463///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
464//
465// CompositeDragger
466//
467CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop):
468    Dragger(rhs, copyop)
469{
470    OSG_NOTICE<<"CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop) not Implemented yet."<<std::endl;
471}
472
473bool CompositeDragger::handle(const PointerInfo& pi, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
474{
475    // Check if the dragger node is in the nodepath.
476    if (!pi.contains(this))
477        return false;
478
479    for (DraggerList::iterator itr=_draggerList.begin(); itr!=_draggerList.end(); ++itr)
480    {
481        if ((*itr)->handle(pi, ea, aa))
482            return true;
483    }
484    return false;
485}
486bool CompositeDragger::containsDragger( const Dragger* dragger ) const
487{
488    for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
489    {
490        if (itr->get() == dragger) return true;
491    }
492    return false;
493}
494
495CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger )
496{
497    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
498    {
499        if (itr->get() == dragger) return itr;
500    }
501    return _draggerList.end();
502}
503
504bool CompositeDragger::addDragger(Dragger *dragger)
505{
506    if (dragger && !containsDragger(dragger))
507    {
508        _draggerList.push_back(dragger);
509        return true;
510    }
511    else return false;
512
513}
514
515bool CompositeDragger::removeDragger(Dragger *dragger)
516{
517    DraggerList::iterator itr = findDragger(dragger);
518    if (itr != _draggerList.end())
519    {
520        _draggerList.erase(itr);
521        return true;
522    }
523    else return false;
524
525}
526
527void CompositeDragger::setParentDragger(Dragger* dragger)
528{
529    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
530    {
531        (*itr)->setParentDragger(dragger);
532    }
533    Dragger::setParentDragger(dragger);
534}
535
536void CompositeDragger::setIntersectionMask(osg::Node::NodeMask intersectionMask)
537{
538    Dragger::setIntersectionMask(intersectionMask);
539    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
540    {
541        (*itr)->setIntersectionMask(intersectionMask);
542    }
543}
544
545class ForceCullCallback : public osg::Drawable::CullCallback
546{
547    public:
548        virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
549        {
550            return true;
551        }
552};
553
554void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable)
555{
556    ForceCullCallback* cullCB = new ForceCullCallback;
557    drawable.setCullCallback (cullCB);
558}
559
560void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node)
561{
562    osg::Material* mat = dynamic_cast<osg::Material*>(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
563    if (! mat)
564    {
565        mat = new osg::Material;
566        mat->setDataVariance(osg::Object::DYNAMIC);
567        node.getOrCreateStateSet()->setAttribute(mat);
568    }
569    mat->setDiffuse(osg::Material::FRONT_AND_BACK, color);
570}
Note: See TracBrowser for help on using the browser.