1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 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 
14 #include <osgUI/Callbacks>
15 #include <osgUI/Widget>
16 #include <osgUI/Dialog>
17 
18 #include <osg/ValueObject>
19 #include <osg/MatrixTransform>
20 #include <osg/io_utils>
21 
22 using namespace osgUI;
23 
CloseCallback(const std::string & callbackName,osgUI::Widget * closeWidget)24 CloseCallback::CloseCallback(const std::string& callbackName, osgUI::Widget* closeWidget):
25     _closeWidget(closeWidget)
26 {
27     setName(callbackName);
28 }
29 
CloseCallback(const CloseCallback & hc,const osg::CopyOp & copyop)30 CloseCallback::CloseCallback(const CloseCallback& hc, const osg::CopyOp& copyop)
31 {
32 }
33 
run(osg::Object * object,osg::Parameters &,osg::Parameters &) const34 bool CloseCallback::run(osg::Object* object, osg::Parameters&, osg::Parameters&) const
35 {
36     if (_closeWidget.valid())
37     {
38         _closeWidget->setVisible(false);
39     }
40 
41     osg::Node* node = dynamic_cast<osg::Node*>(object);
42     if (node)
43     {
44         osg::NodePathList nodePathList = node->getParentalNodePaths();
45         for(osg::NodePathList::iterator itr = nodePathList.begin();
46             itr != nodePathList.end();
47             ++itr)
48         {
49             osg::NodePath& nodePath = *itr;
50             for(osg::NodePath::reverse_iterator ritr = nodePath.rbegin();
51                 ritr !=  nodePath.rend();
52                 ++ritr)
53             {
54                 osgUI::Dialog* dialog = dynamic_cast<osgUI::Dialog*>(*ritr);
55                 if (dialog)
56                 {
57                     dialog->setVisible(false);
58                     break;
59                 }
60             }
61         }
62         return true;
63     }
64     return false;
65 }
66 
HandleCallback()67 HandleCallback::HandleCallback()
68 {
69     setName("handle");
70 }
71 
HandleCallback(const HandleCallback & hc,const osg::CopyOp & copyop)72 HandleCallback::HandleCallback(const HandleCallback& hc, const osg::CopyOp& copyop):
73     osg::CallbackObject(hc, copyop)
74 {
75 }
76 
run(osg::Object * object,osg::Parameters & inputParameters,osg::Parameters & outputParameters) const77 bool HandleCallback::run(osg::Object* object, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const
78 {
79     if (inputParameters.size()>=2)
80     {
81         osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(inputParameters[0].get());
82         osgGA::Event* event = dynamic_cast<osgGA::Event*>(inputParameters[1].get());
83         if (ev && event)
84         {
85             outputParameters.push_back(new osg::BoolValueObject("return",handle(ev,event)));
86             return true;
87         }
88     }
89     return false;
90 }
91 
handle(osgGA::EventVisitor * ev,osgGA::Event * event) const92 bool HandleCallback::handle(osgGA::EventVisitor* ev, osgGA::Event* event) const
93 {
94     return false;
95 }
96 
97 
DragCallback()98 DragCallback::DragCallback():
99     _dragging(false)
100 {
101 }
102 
DragCallback(const DragCallback & hc,const osg::CopyOp & copyop)103 DragCallback::DragCallback(const DragCallback& hc, const osg::CopyOp& copyop):
104     HandleCallback(hc, copyop)
105 {
106 }
107 
findNearestTransform(const osg::NodePath & nodePath)108 osg::Transform* findNearestTransform(const osg::NodePath& nodePath)
109 {
110     osg::Transform* transform = 0;
111     for(osg::NodePath::const_reverse_iterator itr = nodePath.rbegin();
112         itr != nodePath.rend();
113         ++itr)
114     {
115         if ((*itr)->asTransform())
116         {
117             transform = (*itr)->asTransform();
118             break;
119         }
120     }
121     return transform;
122 }
123 
handle(osgGA::EventVisitor * ev,osgGA::Event * event) const124 bool DragCallback::handle(osgGA::EventVisitor* ev, osgGA::Event* event) const
125 {
126     osgGA::GUIEventAdapter* ea = event ? event->asGUIEventAdapter() : 0;
127     if (!ev || !ea) return false;
128 
129     osgUI::Widget* widget = dynamic_cast<osgUI::Widget*>(ev->getNodePath().empty() ? 0 : ev->getNodePath().back());
130     if (widget && widget->getHasEventFocus())
131     {
132         DragCallback* dc = const_cast<DragCallback*>(this);
133         switch(ea->getEventType())
134         {
135             case(osgGA::GUIEventAdapter::SCROLL):
136             {
137                 osg::Vec3d localPosition;
138                 if (!widget->computeExtentsPositionInLocalCoordinates(ev, ea, localPosition)) break;
139 
140                 OSG_NOTICE<<"Scroll motion: "<<ea->getScrollingMotion()<<", "<<localPosition<<std::endl;
141                 double scale = 1.0;
142 
143                 switch(ea->getScrollingMotion())
144                 {
145                     case(osgGA::GUIEventAdapter::SCROLL_UP): scale = 0.9; break;
146                     case(osgGA::GUIEventAdapter::SCROLL_DOWN): scale = 1.0/0.9; break;
147                     default: break;
148                 }
149 
150                 if (scale!=1.0)
151                 {
152                     osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(findNearestTransform(ev->getNodePath()));
153                     if (transform)
154                     {
155                         transform->setMatrix(
156                             osg::Matrixd::translate(-localPosition)*
157                             osg::Matrixd::scale(osg::Vec3d(scale, scale, scale))*
158                             osg::Matrixd::translate(localPosition)*
159                             transform->getMatrix());
160                     }
161                 }
162 
163                 break;
164             }
165             case(osgGA::GUIEventAdapter::PUSH):
166             {
167                 dc->_dragging = (ea->getButtonMask()==osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON);
168                 if (dc->_dragging)
169                 {
170                     osg::Vec3d localPosition;
171                     if (widget->computeExtentsPositionInLocalCoordinates(ev, ea, localPosition))
172 
173                     {
174                         dc->_previousPosition = localPosition;
175                     }
176                 }
177                 break;
178             }
179             case(osgGA::GUIEventAdapter::DRAG):
180             {
181                 if (dc->_dragging)
182                 {
183                     osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(findNearestTransform(ev->getNodePath()));
184                     if (transform)
185                     {
186                         osg::Vec3d position;
187                         if (widget->computeExtentsPositionInLocalCoordinates(ev, ea, position, false))
188                         {
189                             osg::Vec3d delta = position-_previousPosition;
190                             osg::MatrixTransform* mt = transform->asMatrixTransform();
191                             mt->setMatrix(osg::Matrixd::translate(delta)*mt->getMatrix());
192                             // OSG_NOTICE<<"Move to local "<<position<<", "<<position-_previousPosition<<std::endl;
193                         }
194                     }
195                     else
196                     {
197                         OSG_NOTICE<<"Failed to drag, No Transform to move"<<std::endl;
198                     }
199                 }
200                 break;
201             }
202             case(osgGA::GUIEventAdapter::RELEASE):
203                 dc->_dragging = false;
204             default:
205                 break;
206         }
207     }
208     return false;
209 }
210