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

Revision 13890, 18.2 kB (checked in by robert, 23 hours ago)

Centralized the calling of #include <stdint.h> and VS fallback into include/osg/Types header

  • 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)->asGUIEventAdapter();
309                if (ea && 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.