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

Revision 13415, 18.2 kB (checked in by robert, 40 seconds ago)

From Paul Martz, fixed placement of OpenGL header so that it gets generated and placed in the build directory as per the Config file

  • 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                                if(dragger->handle(_pointer, ea, aa))
407                                {
408                                    dragger->setDraggerActive(true);
409                                    handled = true;
410                                }
411                            }
412                        }
413                    }
414                }
415                break;
416            }
417            case osgGA::GUIEventAdapter::DRAG:
418            case osgGA::GUIEventAdapter::RELEASE:
419            {
420                if (_draggerActive)
421                {
422                    _pointer._hitIter = _pointer._hitList.begin();
423//                    _pointer.setCamera(view->getCamera());
424                    _pointer.setMousePosition(ea.getX(), ea.getY());
425
426                    if(handle(_pointer, ea, aa))
427                    {
428                        handled = true;
429                    }
430                }
431                break;
432            }
433            default:
434                break;
435        }
436
437        if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
438        {
439            setDraggerActive(false);
440            _pointer.reset();
441        }
442    }
443
444    return handled;
445}
446
447bool Dragger::receive(const MotionCommand& command)
448{
449    if (_selfUpdater.valid()) return _selfUpdater->receive(command);
450    else return false;
451}
452
453void Dragger::dispatch(MotionCommand& command)
454{
455    // apply any constraints
456    for(Constraints::iterator itr = _constraints.begin();
457        itr != _constraints.end();
458        ++itr)
459    {
460        command.accept(*(*itr));
461    }
462
463    // apply any constraints of parent dragger.
464    if (getParentDragger()!=this)
465    {
466        for(Constraints::iterator itr = getParentDragger()->getConstraints().begin();
467            itr != getParentDragger()->getConstraints().end();
468            ++itr)
469        {
470            command.accept(*(*itr));
471        }
472    }
473
474    // move self
475    getParentDragger()->receive(command);
476
477    // pass on movement to any dragger callbacks
478    for(DraggerCallbacks::iterator itr = getParentDragger()->getDraggerCallbacks().begin();
479        itr != getParentDragger()->getDraggerCallbacks().end();
480        ++itr)
481    {
482        command.accept(*(*itr));
483    }
484}
485
486
487///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
488//
489// CompositeDragger
490//
491CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop):
492    Dragger(rhs, copyop)
493{
494    OSG_NOTICE<<"CompositeDragger::CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop) not Implemented yet."<<std::endl;
495}
496
497bool CompositeDragger::handle(const PointerInfo& pi, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
498{
499    // Check if the dragger node is in the nodepath.
500    if (!pi.contains(this))
501        return false;
502
503    for (DraggerList::iterator itr=_draggerList.begin(); itr!=_draggerList.end(); ++itr)
504    {
505        if ((*itr)->handle(pi, ea, aa))
506            return true;
507    }
508    return false;
509}
510bool CompositeDragger::containsDragger( const Dragger* dragger ) const
511{
512    for (DraggerList::const_iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
513    {
514        if (itr->get() == dragger) return true;
515    }
516    return false;
517}
518
519CompositeDragger::DraggerList::iterator CompositeDragger::findDragger( const Dragger* dragger )
520{
521    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
522    {
523        if (itr->get() == dragger) return itr;
524    }
525    return _draggerList.end();
526}
527
528bool CompositeDragger::addDragger(Dragger *dragger)
529{
530    if (dragger && !containsDragger(dragger))
531    {
532        _draggerList.push_back(dragger);
533        return true;
534    }
535    else return false;
536
537}
538
539bool CompositeDragger::removeDragger(Dragger *dragger)
540{
541    DraggerList::iterator itr = findDragger(dragger);
542    if (itr != _draggerList.end())
543    {
544        _draggerList.erase(itr);
545        return true;
546    }
547    else return false;
548
549}
550
551void CompositeDragger::setParentDragger(Dragger* dragger)
552{
553    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
554    {
555        (*itr)->setParentDragger(dragger);
556    }
557    Dragger::setParentDragger(dragger);
558}
559
560void CompositeDragger::setIntersectionMask(osg::Node::NodeMask intersectionMask)
561{
562    Dragger::setIntersectionMask(intersectionMask);
563    for (DraggerList::iterator itr = _draggerList.begin(); itr != _draggerList.end(); ++itr)
564    {
565        (*itr)->setIntersectionMask(intersectionMask);
566    }
567}
568
569class ForceCullCallback : public osg::Drawable::CullCallback
570{
571    public:
572        virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
573        {
574            return true;
575        }
576};
577
578void osgManipulator::setDrawableToAlwaysCull(osg::Drawable& drawable)
579{
580    ForceCullCallback* cullCB = new ForceCullCallback;
581    drawable.setCullCallback (cullCB);
582}
583
584void osgManipulator::setMaterialColor(const osg::Vec4& color, osg::Node& node)
585{
586    osg::Material* mat = dynamic_cast<osg::Material*>(node.getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL));
587    if (! mat)
588    {
589        mat = new osg::Material;
590        mat->setDataVariance(osg::Object::DYNAMIC);
591        node.getOrCreateStateSet()->setAttribute(mat);
592    }
593    mat->setDiffuse(osg::Material::FRONT_AND_BACK, color);
594}
Note: See TracBrowser for help on using the browser.