Moved experimental Widget class to osgGA
Add computeIntersections() to the osgGA::GUIActionAdapter base class to enable intersection tests without needing to directly link to osgViewer.
This commit is contained in:
@@ -9,6 +9,7 @@ SET(LIB_NAME osgGA)
|
||||
SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME})
|
||||
SET(TARGET_H
|
||||
${HEADER_PATH}/AnimationPathManipulator
|
||||
${HEADER_PATH}/CameraViewSwitchManipulator
|
||||
${HEADER_PATH}/DriveManipulator
|
||||
${HEADER_PATH}/Device
|
||||
${HEADER_PATH}/Event
|
||||
@@ -32,8 +33,8 @@ SET(TARGET_H
|
||||
${HEADER_PATH}/TerrainManipulator
|
||||
${HEADER_PATH}/TrackballManipulator
|
||||
${HEADER_PATH}/UFOManipulator
|
||||
${HEADER_PATH}/Widget
|
||||
${HEADER_PATH}/Version
|
||||
${HEADER_PATH}/CameraViewSwitchManipulator
|
||||
)
|
||||
|
||||
SET(TARGET_SRC
|
||||
@@ -59,6 +60,7 @@ SET(TARGET_SRC
|
||||
TerrainManipulator.cpp
|
||||
TrackballManipulator.cpp
|
||||
UFOManipulator.cpp
|
||||
Widget.cpp
|
||||
Version.cpp
|
||||
CameraViewSwitchManipulator.cpp
|
||||
${OPENSCENEGRAPH_VERSIONINFO_RC}
|
||||
|
||||
302
src/osgGA/Widget.cpp
Normal file
302
src/osgGA/Widget.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/ScriptEngine>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <osgGA/Widget>
|
||||
#include <osgGA/EventVisitor>
|
||||
#include <osgGA/GUIActionAdapter>
|
||||
|
||||
using namespace osgGA;
|
||||
|
||||
Widget::Widget():
|
||||
_focusBehaviour(FOCUS_FOLLOWS_POINTER),
|
||||
_hasEventFocus(false),
|
||||
_graphicsInitialized(false)
|
||||
|
||||
{
|
||||
setNumChildrenRequiringEventTraversal(1);
|
||||
}
|
||||
|
||||
Widget::Widget(const Widget& widget, const osg::CopyOp& copyop):
|
||||
osg::Group(),
|
||||
_focusBehaviour(widget._focusBehaviour),
|
||||
_hasEventFocus(false),
|
||||
_graphicsInitialized(false)
|
||||
{
|
||||
setNumChildrenRequiringEventTraversal(1);
|
||||
}
|
||||
|
||||
void Widget::setExtents(const osg::BoundingBox& bb)
|
||||
{
|
||||
_extents = bb;
|
||||
}
|
||||
|
||||
void Widget::updateFocus(osg::NodeVisitor& nv)
|
||||
{
|
||||
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
|
||||
osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0;
|
||||
if (ev && aa)
|
||||
{
|
||||
osgGA::EventQueue::Events& events = ev->getEvents();
|
||||
for(osgGA::EventQueue::Events::iterator itr = events.begin();
|
||||
itr != events.end();
|
||||
++itr)
|
||||
{
|
||||
osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
|
||||
if (ea)
|
||||
{
|
||||
bool previousFocus = _hasEventFocus;
|
||||
if (_focusBehaviour==CLICK_TO_FOCUS)
|
||||
{
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::PUSH)
|
||||
{
|
||||
int numButtonsPressed = 0;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
if (ea->getButtonMask()&osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ++numButtonsPressed;
|
||||
|
||||
if (numButtonsPressed==1)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
if (withinWidget) _hasEventFocus = true;
|
||||
else _hasEventFocus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_focusBehaviour==FOCUS_FOLLOWS_POINTER)
|
||||
{
|
||||
bool checkWithinWidget = false;
|
||||
if (!_hasEventFocus)
|
||||
{
|
||||
checkWithinWidget = (ea->getEventType()!=osgGA::GUIEventAdapter::FRAME) && ea->getButtonMask()==0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if mouse move or mouse release check to see if mouse still within widget to retain focus
|
||||
if (ea->getEventType()==osgGA::GUIEventAdapter::MOVE)
|
||||
{
|
||||
checkWithinWidget = true;
|
||||
}
|
||||
else if (ea->getEventType()==osgGA::GUIEventAdapter::RELEASE)
|
||||
{
|
||||
// if no buttons pressed then check
|
||||
if (ea->getButtonMask()==0) checkWithinWidget = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkWithinWidget)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
bool withinWidget = aa->computeIntersections(*ea, nv.getNodePath(), intersections);
|
||||
|
||||
_hasEventFocus = withinWidget;
|
||||
}
|
||||
}
|
||||
|
||||
if (previousFocus != _hasEventFocus)
|
||||
{
|
||||
if (_hasEventFocus)
|
||||
{
|
||||
enter();
|
||||
#if 0
|
||||
if (view->getCameraManipulator())
|
||||
{
|
||||
view->getCameraManipulator()->finishAnimation();
|
||||
view->requestContinuousUpdate( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setHasEventFocus(bool focus)
|
||||
{
|
||||
if (_hasEventFocus == focus) return;
|
||||
|
||||
_hasEventFocus = focus;
|
||||
|
||||
if (_hasEventFocus) enter();
|
||||
else leave();
|
||||
}
|
||||
|
||||
bool Widget::getHasEventFocus() const
|
||||
{
|
||||
return _hasEventFocus;
|
||||
}
|
||||
|
||||
void Widget::enter()
|
||||
{
|
||||
osg::CallbackObject* co = osg::getCallbackObject(this, "enter");
|
||||
if (co)
|
||||
{
|
||||
co->run(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
enterImplementation();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::enterImplementation()
|
||||
{
|
||||
OSG_NOTICE<<"enter()"<<std::endl;
|
||||
}
|
||||
|
||||
void Widget::leave()
|
||||
{
|
||||
osg::CallbackObject* co = osg::getCallbackObject(this, "leave");
|
||||
if (co)
|
||||
{
|
||||
co->run(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
leaveImplementation();
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::leaveImplementation()
|
||||
{
|
||||
OSG_NOTICE<<"leave()"<<std::endl;
|
||||
}
|
||||
|
||||
void Widget::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
osg::CallbackObject* co = osg::getCallbackObject(this, "traverse");
|
||||
if (co)
|
||||
{
|
||||
osg::Parameters inputParameters, outputParameters;
|
||||
inputParameters.push_back(&nv);
|
||||
co->run(this, inputParameters, outputParameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
traverseImplementation(nv);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::traverseImplementation(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (!_graphicsInitialized && nv.getVisitorType()!=osg::NodeVisitor::CULL_VISITOR) createGraphics();
|
||||
|
||||
osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(&nv);
|
||||
if (ev)
|
||||
{
|
||||
updateFocus(nv);
|
||||
|
||||
if (getHasEventFocus())
|
||||
{
|
||||
// signify that event has been taken by widget with focus
|
||||
ev->setEventHandled(true);
|
||||
|
||||
osgGA::EventQueue::Events& events = ev->getEvents();
|
||||
for(osgGA::EventQueue::Events::iterator itr = events.begin();
|
||||
itr != events.end();
|
||||
++itr)
|
||||
{
|
||||
handle(ev, itr->get());
|
||||
|
||||
(*itr)->setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Group::traverse(nv);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::handle(osgGA::EventVisitor* ev, osgGA::Event* event)
|
||||
{
|
||||
osg::CallbackObject* co = osg::getCallbackObject(this, "handle");
|
||||
if (co)
|
||||
{
|
||||
osg::Parameters inputParameters, outputParameters;
|
||||
inputParameters.push_back(ev);
|
||||
inputParameters.push_back(event);
|
||||
if (co->run(this, inputParameters, outputParameters))
|
||||
{
|
||||
if (outputParameters.size()>=1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return handleImplementation(ev, event);
|
||||
}
|
||||
}
|
||||
|
||||
bool Widget::handleImplementation(osgGA::EventVisitor* /*ev*/, osgGA::Event* /*event*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3& localPosition) const
|
||||
{
|
||||
osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0;
|
||||
osgUtil::LineSegmentIntersector::Intersections intersections;
|
||||
if (aa && aa->computeIntersections(*event, ev->getNodePath(), intersections))
|
||||
{
|
||||
localPosition = intersections.begin()->getLocalIntersectPoint();
|
||||
|
||||
return (_extents.contains(localPosition, 1e-6));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Widget::createGraphics()
|
||||
{
|
||||
osg::CallbackObject* co = osg::getCallbackObject(this, "createGraphics");
|
||||
if (co)
|
||||
{
|
||||
co->run(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
createGraphicsImplementation();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Widget::createGraphicsImplementation()
|
||||
{
|
||||
_graphicsInitialized = true;
|
||||
}
|
||||
|
||||
osg::BoundingSphere Widget::computeBound() const
|
||||
{
|
||||
return osg::BoundingSphere(_extents);
|
||||
}
|
||||
Reference in New Issue
Block a user