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

Revision 13376, 18.0 kB (checked in by robert, 3 days ago)

From Alberto Luaces,"the current code uses the preprocessor for generating the plugin path in
a way that when CMAKE_INSTALL_PREFIX contains something along the lines
of

/usr/x86_64-linux-gnu/

it gets substituted as

/usr/x86_64-1-gnu/

that is, the string is preprocessed again, thereby making changes to
anything that matches any defined symbol, as "linux" in this example
(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=763816).

Quoting that path directly in CMake scripts solves that problem.
"

  • 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    _activationMouseButtonMask(0),
170    _activationKeyEvent(0),
171    _activationPermittedByModKeyMask(false),
172    _activationPermittedByMouseButtonMask(false),
173    _activationPermittedByKeyEvent(false),
174    _intersectionMask(0xffffffff)
175{
176    _parentDragger = this;
177    getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC);
178
179    _selfUpdater = new DraggerTransformCallback(this);
180
181}
182
183Dragger::Dragger(const Dragger& rhs, const osg::CopyOp& copyop):
184    osg::MatrixTransform(rhs, copyop),
185    _handleEvents(rhs._handleEvents),
186    _draggerActive(false),
187    _activationModKeyMask(rhs._activationModKeyMask),
188    _activationMouseButtonMask(rhs._activationMouseButtonMask),
189    _activationKeyEvent(rhs._activationKeyEvent),
190    _activationPermittedByModKeyMask(false),
191    _activationPermittedByMouseButtonMask(false),
192    _activationPermittedByKeyEvent(false),
193    _intersectionMask(0xffffffff)
194{
195}
196
197Dragger::~Dragger()
198{
199}
200
201void Dragger::setHandleEvents(bool flag)
202{
203    if (_handleEvents == flag) return;
204
205    _handleEvents = flag;
206
207    // update the number of children that require an event traversal to make sure this dragger recieves events.
208    if (_handleEvents) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+1);
209    else if (getNumChildrenRequiringEventTraversal()>=1) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
210}
211
212void Dragger::addConstraint(Constraint* constraint)
213{
214    // check to make sure constaint hasn't already been attached.
215    for(Constraints::iterator itr = _constraints.begin();
216        itr != _constraints.end();
217        ++itr)
218    {
219        if (*itr == constraint) return;
220    }
221
222    _constraints.push_back(constraint);
223}
224
225void Dragger::removeConstraint(Constraint* constraint)
226{
227    for(Constraints::iterator itr = _constraints.begin();
228        itr != _constraints.end();
229        )
230    {
231        if (*itr == constraint)
232        {
233            _constraints.erase(itr);
234            return;
235        } else
236        {
237            ++itr;
238        }
239    }
240}
241
242void Dragger::addTransformUpdating(osg::MatrixTransform* transform, int handleCommandMask)
243{
244    addDraggerCallback(new DraggerTransformCallback(transform, handleCommandMask));
245}
246
247void Dragger::removeTransformUpdating(osg::MatrixTransform* transform)
248{
249    for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
250        itr != _draggerCallbacks.end();
251        )
252    {
253        DraggerCallback* dc = itr->get();
254        DraggerTransformCallback* dtc = dynamic_cast<DraggerTransformCallback*>(dc);
255        if (dtc && dtc->getTransform()==transform)
256        {
257            itr = _draggerCallbacks.erase(itr);
258        }
259        else
260        {
261            ++itr;
262        }
263    }
264
265}
266
267void Dragger::addDraggerCallback(DraggerCallback* dc)
268{
269    for(DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
270        itr != _draggerCallbacks.end();
271        ++itr)
272    {
273        if (*itr == dc) return;
274    }
275
276    _draggerCallbacks.push_back(dc);
277}
278
279void Dragger::removeDraggerCallback(DraggerCallback* dc)
280{
281    for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
282        itr != _draggerCallbacks.end();
283        )
284    {
285        if (dc==itr->get())
286        {
287            itr = _draggerCallbacks.erase(itr);
288        }
289        else
290        {
291            ++itr;
292        }
293    }
294}
295
296
297void Dragger::traverse(osg::NodeVisitor& nv)
298{
299    if (_handleEvents && nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
300    {
301        osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
302        if (ev)
303        {
304            for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
305                itr != ev->getEvents().end();
306                ++itr)
307            {
308                osgGA::GUIEventAdapter* ea = itr->get();
309                if (handle(*ea, *(ev->getActionAdapter()))) ea->setHandled(true);
310            }
311        }
312        return;
313    }
314
315    MatrixTransform::traverse(nv);
316}
317
318bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
319{
320    if (ea.getHandled()) return false;
321
322    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
323    if (!view) return false;
324
325    bool handled = false;
326
327    bool activationPermitted = true;
328    if (_activationModKeyMask!=0 || _activationMouseButtonMask!=0 || _activationKeyEvent!=0)
329    {
330        _activationPermittedByModKeyMask = (_activationModKeyMask!=0) ?
331            ((ea.getModKeyMask() & _activationModKeyMask)!=0) :
332            false;
333
334        _activationPermittedByMouseButtonMask = (_activationMouseButtonMask!=0) ?
335            ((ea.getButtonMask() & _activationMouseButtonMask)!=0) :
336            false;
337
338        if (_activationKeyEvent!=0)
339        {
340            switch (ea.getEventType())
341            {
342                case osgGA::GUIEventAdapter::KEYDOWN:
343                {
344                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = true;
345                    break;
346                }
347                case osgGA::GUIEventAdapter::KEYUP:
348                {
349                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = false;
350                    break;
351                }
352                default:
353                    break;
354            }
355        }
356
357        activationPermitted =  _activationPermittedByModKeyMask || _activationPermittedByMouseButtonMask || _activationPermittedByKeyEvent;
358
359    }
360
361    if (activationPermitted || _draggerActive)
362    {
363        switch (ea.getEventType())
364        {
365            case osgGA::GUIEventAdapter::PUSH:
366            {
367                osgUtil::LineSegmentIntersector::Intersections intersections;
368
369                _pointer.reset();
370
371                if (view->computeIntersections(ea ,intersections, _intersectionMask))
372                {
373                    for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
374                        hitr != intersections.end();
375                        ++hitr)
376                    {
377                        _pointer.addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint());
378                    }
379                    for (osg::NodePath::iterator itr = _pointer._hitList.front().first.begin();
380                            itr != _pointer._hitList.front().first.end();
381                            ++itr)
382                    {
383                        osgManipulator::Dragger* dragger = dynamic_cast<osgManipulator::Dragger*>(*itr);
384                        if (dragger)
385                        {
386                            if (dragger==this)
387                            {
388                                osg::Camera *rootCamera = view->getCamera();
389                                osg::NodePath nodePath = _pointer._hitList.front().first;
390                                osg::NodePath::reverse_iterator ritr;
391                                for(ritr = nodePath.rbegin();
392                                    ritr != nodePath.rend();
393                                    ++ritr)
394                                {
395                                    osg::Camera* camera = dynamic_cast<osg::Camera*>(*ritr);
396                                    if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty()))
397                                    {
398                                         rootCamera = camera;
399                                         break;
400                                    }
401                                }
402
403                                _pointer.setCamera(rootCamera);
404                                _pointer.setMousePosition(ea.getX(), ea.getY());
405
406                                dragger->handle(_pointer, ea, aa);
407                                dragger->setDraggerActive(true);
408                                handled = true;
409                            }
410                        }
411                    }
412                }
413                break;
414            }
415            case osgGA::GUIEventAdapter::DRAG:
416            case osgGA::GUIEventAdapter::RELEASE:
417            {
418                if (_draggerActive)
419                {
420                    _pointer._hitIter = _pointer._hitList.begin();
421//                    _pointer.setCamera(view->getCamera());
422                    _pointer.setMousePosition(ea.getX(), ea.getY());
423
424                    handle(_pointer, ea, aa);
425
426                    handled = true;
427                }
428                break;
429            }
430            default:
431                break;
432        }
433
434        if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
435        {
436            setDraggerActive(false);
437            _pointer.reset();
438        }
439    }
440
441    return handled;
442}
443
444bool Dragger::receive(const MotionCommand& command)
445{
446    if (_selfUpdater.valid()) return _selfUpdater->receive(command);
447    else return false;
448}
449
450void Dragger::dispatch(MotionCommand& command)
451{
452    // apply any constraints
453    for(Constraints::iterator itr = _constraints.begin();
454        itr != _constraints.end();
455        ++itr)
456    {
457        command.accept(*(*itr));
458    }
459
460    // apply any constraints of parent dragger.
461    if (getParentDragger()!=this)
462    {
463        for(Constraints::iterator itr = getParentDragger()->getConstraints().begin();
464            itr != getParentDragger()->getConstraints().end();
465            ++itr)
466        {
467            command.accept(*(*itr));
468        }
469    }
470
471    // move self
472    getParentDragger()->receive(command);
473
474    // pass on movement to any dragger callbacks
475    for(DraggerCallbacks::iterator itr = getParentDragger()->getDraggerCallbacks().begin();
476        itr != getParentDragger()->getDraggerCallbacks().end();
477        ++itr)
478    {
479        command.accept(*(*itr));
480    }
481}
482
483
484///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
485//
486// CompositeDragger
487//
488CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop):
489    Dragger(rhs, copyop)
490{
491    OSG_NOTICE<<"CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop) not Implemented yet."<<std::endl;
492}
493
494bool CompositeDragger::handle(const PointerInfo& pi, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
495{
496    // Check if the dragger node is in the nodepath.
497    if (!pi.contains(this))
498        return false;
499
500    for (DraggerList::iterator itr=_draggerList.begin(); itr!=_draggerList.end(); ++itr)
501    {
502        if ((*itr)->handle(pi, ea, aa))
503            return true;
504    }
505    return false;
506}
507bool CompositeDragger::containsDragger( const Dragger* dragger ) const
508{
509    for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
510    {
511        if (itr->get() == dragger) return true;
512    }
513    return false;
514}
515
516CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger )
517{
518    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
519    {
520        if (itr->get() == dragger) return itr;
521    }
522    return _draggerList.end();
523}
524
525bool CompositeDragger::addDragger(Dragger *dragger)
526{
527    if (dragger && !containsDragger(dragger))
528    {
529        _draggerList.push_back(dragger);
530        return true;
531    }
532    else return false;
533
534}
535
536bool CompositeDragger::removeDragger(Dragger *dragger)
537{
538    DraggerList::iterator itr = findDragger(dragger);
539    if (itr != _draggerList.end())
540    {
541        _draggerList.erase(itr);
542        return true;
543    }
544    else return false;
545
546}
547
548void CompositeDragger::setParentDragger(Dragger* dragger)
549{
550    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
551    {
552        (*itr)->setParentDragger(dragger);
553    }
554    Dragger::setParentDragger(dragger);
555}
556
557void CompositeDragger::setIntersectionMask(osg::Node::NodeMask intersectionMask)
558{
559    Dragger::setIntersectionMask(intersectionMask);
560    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
561    {
562        (*itr)->setIntersectionMask(intersectionMask);
563    }
564}
565
566class ForceCullCallback : public osg::Drawable::CullCallback
567{
568    public:
569        virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
570        {
571            return true;
572        }
573};
574
575void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable)
576{
577    ForceCullCallback* cullCB = new ForceCullCallback;
578    drawable.setCullCallback (cullCB);
579}
580
581void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node)
582{
583    osg::Material* mat = dynamic_cast<osg::Material*>(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
584    if (! mat)
585    {
586        mat = new osg::Material;
587        mat->setDataVariance(osg::Object::DYNAMIC);
588        node.getOrCreateStateSet()->setAttribute(mat);
589    }
590    mat->setDiffuse(osg::Material::FRONT_AND_BACK, color);
591}
Note: See TracBrowser for help on using the browser.