Implemented more robust intersection handling for mouse interactions. Wired up even handling of ComboBox popup.
git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14250 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
parent
89ca694684
commit
86a9a45525
@ -38,6 +38,8 @@ public:
|
||||
virtual bool handle(osgGA::EventVisitor* ev, osgGA::Event* event);
|
||||
virtual bool handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event);
|
||||
|
||||
typedef std::vector<osgUtil::LineSegmentIntersector::Intersection> Intersections;
|
||||
virtual bool computeIntersections(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, Intersections& intersections, osg::Node::NodeMask traversalMask = 0xffffffff) const;
|
||||
virtual bool computePositionInLocalCoordinates(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, osg::Vec3& localPosition) const;
|
||||
|
||||
virtual void dirty();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <osgText/Font>
|
||||
#include <osgText/Text>
|
||||
#include <osg/Notify>
|
||||
#include <osg/ValueObject>
|
||||
#include <osg/io_utils>
|
||||
|
||||
using namespace osgUI;
|
||||
@ -53,6 +54,7 @@ bool ComboBox::handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||
if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Down)
|
||||
{
|
||||
@ -66,14 +68,70 @@ bool ComboBox::handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case(osgGA::GUIEventAdapter::PUSH):
|
||||
{
|
||||
OSG_NOTICE<<"Button pressed "<<std::endl;
|
||||
// toggle visibility of popup.
|
||||
if (_popup) _popup->setVisible(!_popup->getVisible());
|
||||
osgUI::Widget::Intersections intersections;
|
||||
osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0;
|
||||
osgGA::GUIEventAdapter* ea = event ? event->asGUIEventAdapter() : 0;
|
||||
// if ((aa && ea) && aa->computeIntersections(*ea, ev->getNodePath(), intersections))
|
||||
if ((aa && ea) && computeIntersections(ev, ea, intersections))
|
||||
{
|
||||
OSG_NOTICE<<"ComboBox intersections { "<<std::endl;
|
||||
for(osgUI::Widget::Intersections::const_iterator itr =intersections.begin();
|
||||
itr!=intersections.end();
|
||||
++itr)
|
||||
{
|
||||
const osgUtil::LineSegmentIntersector::Intersection& hit = *itr;
|
||||
OSG_NOTICE<<" hit:drawable "<<hit.drawable.get()<<", "<<hit.drawable->getName()<<std::endl;
|
||||
OSG_NOTICE<<" NodePath::size() "<<hit.nodePath.size()<<std::endl;
|
||||
}
|
||||
OSG_NOTICE<<"}"<<std::endl;
|
||||
|
||||
const osgUtil::LineSegmentIntersector::Intersection& hit = *intersections.begin();
|
||||
osg::Vec3d localPosition = hit.getLocalIntersectPoint();
|
||||
if (_extents.contains(localPosition, 1e-6))
|
||||
{
|
||||
OSG_NOTICE<<"ComboBox button"<<std::endl;
|
||||
_popup->setVisible(!_popup->getVisible());
|
||||
}
|
||||
|
||||
if (_popup->getVisible() && _popup->getExtents().contains(localPosition, 1e-6))
|
||||
{
|
||||
OSG_NOTICE<<"In pop up"<<std::endl;
|
||||
OSG_NOTICE<<" hit:drawable "<<hit.drawable.get()<<std::endl;
|
||||
OSG_NOTICE<<" NodePath::size() "<<hit.nodePath.size()<<std::endl;
|
||||
|
||||
unsigned int index=_items.size();
|
||||
for(osg::NodePath::const_reverse_iterator itr = hit.nodePath.rbegin();
|
||||
itr != hit.nodePath.rend();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)==this) break;
|
||||
if ((*itr)->getUserValue("index",index)) break;
|
||||
}
|
||||
|
||||
if (index<_items.size())
|
||||
{
|
||||
OSG_NOTICE<<" index selected "<<index<<std::endl;
|
||||
setCurrentItem(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
OSG_NOTICE<<" No index selected "<<std::endl;
|
||||
}
|
||||
|
||||
_popup->setVisible(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(osgGA::GUIEventAdapter::RELEASE):
|
||||
OSG_NOTICE<<"Button release "<<std::endl;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -121,9 +179,10 @@ void ComboBox::createGraphicsImplementation()
|
||||
|
||||
osg::BoundingBox popupItemExtents(_extents.xMin()+margin, popupTop-margin-itemHeight, _extents.zMin(), _extents.xMin()+itemWidth, popupTop-margin, _extents.zMax());
|
||||
|
||||
unsigned int index = 0;
|
||||
for(Items::iterator itr = _items.begin();
|
||||
itr != _items.end();
|
||||
++itr)
|
||||
++itr, ++index)
|
||||
{
|
||||
Item* item = itr->get();
|
||||
OSG_NOTICE<<"Creating item "<<item->getText()<<", "<<item->getColor()<<std::endl;
|
||||
@ -139,6 +198,8 @@ void ComboBox::createGraphicsImplementation()
|
||||
// setup graphics for popup
|
||||
{
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
group->setUserValue("index",index);
|
||||
|
||||
if (item->getColor().a()!=0.0f) group->addChild( style->createPanel(popupItemExtents, item->getColor()) );
|
||||
if (!item->getText().empty()) group->addChild( style->createText(popupItemExtents, getAlignmentSettings(), getTextSettings(), item->getText()) );
|
||||
_popup->addChild(group.get());
|
||||
|
@ -32,7 +32,7 @@ Popup::Popup(const osgUI::Popup& dialog, const osg::CopyOp& copyop):
|
||||
|
||||
bool Popup::handleImplementation(osgGA::EventVisitor* ev, osgGA::Event* event)
|
||||
{
|
||||
OSG_NOTICE<<"Popup::handleImplementation"<<std::endl;
|
||||
// OSG_NOTICE<<"Popup::handleImplementation"<<std::endl;
|
||||
|
||||
osgGA::GUIEventAdapter* ea = event->asGUIEventAdapter();
|
||||
if (!ea) return false;
|
||||
@ -70,7 +70,7 @@ void Popup::createGraphicsImplementation()
|
||||
|
||||
Style* style = (getStyle()!=0) ? getStyle() : Style::instance().get();
|
||||
|
||||
osg::Vec4 dialogBackgroundColor(0.8,0.8,0.8,1.0);
|
||||
osg::Vec4 dialogBackgroundColor(0.9,0.9,0.9,1.0);
|
||||
|
||||
_transform->addChild( style->createPanel(_extents, dialogBackgroundColor) );
|
||||
|
||||
|
@ -61,6 +61,7 @@ osg::Node* Style::createPanel(const osg::BoundingBox& extents, const osg::Vec4&
|
||||
{
|
||||
OSG_NOTICE<<"Creating Panel"<<std::endl;
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
geometry->setName("Panel");
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
geometry->setVertexArray(vertices.get());
|
||||
@ -83,6 +84,7 @@ osg::Node* Style::createPanel(const osg::BoundingBox& extents, const osg::Vec4&
|
||||
osg::Node* Style::createDepthSetPanel(const osg::BoundingBox& extents)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
geometry->setName("DepthSetPanel");
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
geometry->setVertexArray(vertices.get());
|
||||
@ -104,6 +106,7 @@ osg::Node* Style::createDepthSetPanel(const osg::BoundingBox& extents)
|
||||
osg::Node* Style::createFrame(const osg::BoundingBox& extents, const FrameSettings* frameSettings, const osg::Vec4& color)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
geometry->setName("Frame");
|
||||
|
||||
float topScale = 1.0f;
|
||||
float bottomScale = 1.0f;
|
||||
@ -219,6 +222,7 @@ osg::Node* Style::createFrame(const osg::BoundingBox& extents, const FrameSettin
|
||||
osg::Node* Style::createText(const osg::BoundingBox& extents, const AlignmentSettings* as, const TextSettings* ts, const std::string& text)
|
||||
{
|
||||
osg::ref_ptr<osgText::Text> textDrawable = new osgText::Text;
|
||||
textDrawable->setName("Text");
|
||||
|
||||
textDrawable->setText(text);
|
||||
textDrawable->setPosition( osg::Vec3(extents.xMin(), extents.yMin(), extents.zMin()) );
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <osgGA/EventVisitor>
|
||||
#include <osgGA/GUIActionAdapter>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace osgUI;
|
||||
|
||||
Widget::Widget():
|
||||
@ -271,22 +273,6 @@ 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::dirty()
|
||||
{
|
||||
_graphicsInitialized = false;
|
||||
@ -304,8 +290,10 @@ void Widget::createGraphicsImplementation()
|
||||
|
||||
osg::BoundingSphere Widget::computeBound() const
|
||||
{
|
||||
if (_extents.valid()) return osg::BoundingSphere(_extents);
|
||||
else return osg::Group::computeBound();
|
||||
osg::BoundingSphere bs;
|
||||
if (_extents.valid()) bs.expandBy(_extents);
|
||||
bs.expandBy(Group::computeBound());
|
||||
return bs;
|
||||
}
|
||||
|
||||
void Widget::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
@ -331,4 +319,119 @@ void Widget::releaseGLObjects(osg::State* state) const
|
||||
}
|
||||
|
||||
Group::releaseGLObjects(state);
|
||||
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
struct SortTraversalOrder
|
||||
{
|
||||
bool operator() (const osgUtil::LineSegmentIntersector::Intersection* lhs, const osgUtil::LineSegmentIntersector::Intersection* rhs) const
|
||||
{
|
||||
double epsilon = 1e-6;
|
||||
if (lhs->ratio > (rhs->ratio+epsilon)) return true;
|
||||
if (lhs->ratio < (rhs->ratio-epsilon)) return false;
|
||||
|
||||
const osg::NodePath& np_lhs = lhs->nodePath;
|
||||
const osg::NodePath& np_rhs = rhs->nodePath;
|
||||
|
||||
osg::NodePath::const_iterator itr_lhs = np_lhs.begin();
|
||||
osg::NodePath::const_iterator end_lhs = np_lhs.end();
|
||||
osg::NodePath::const_iterator itr_rhs = np_rhs.begin();
|
||||
osg::NodePath::const_iterator end_rhs = np_rhs.end();
|
||||
const osg::Group* parent = 0;
|
||||
|
||||
while(itr_lhs!=end_lhs && itr_rhs!=end_rhs)
|
||||
{
|
||||
if (*itr_lhs == *itr_rhs)
|
||||
{
|
||||
parent = (*itr_lhs)->asGroup();
|
||||
++itr_lhs;
|
||||
++itr_rhs;
|
||||
}
|
||||
else if (parent==0)
|
||||
{
|
||||
OSG_NOTICE<<"SortTraversalOrder::operator() NodePath has no parent, just have to use default less than operator for Intersection"<<std::endl;
|
||||
return (*lhs)<(*rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
const osgUI::Widget* widget = dynamic_cast<const osgUI::Widget*>(parent);
|
||||
|
||||
unsigned int lhs_index = parent->getChildIndex(*itr_lhs);
|
||||
double lhs_sort_value = static_cast<double>(lhs_index)/static_cast<double>(parent->getNumChildren());
|
||||
|
||||
unsigned int rhs_index = parent->getChildIndex(*itr_rhs);
|
||||
double rhs_sort_value = (static_cast<double>(rhs_index)+epsilon)/static_cast<double>(parent->getNumChildren());
|
||||
|
||||
if (widget)
|
||||
{
|
||||
const osgUI::Widget::GraphicsSubgraphMap& gsm = widget->getGraphicsSubgraphMap();
|
||||
for(osgUI::Widget::GraphicsSubgraphMap::const_iterator itr=gsm.begin();
|
||||
itr!=gsm.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->second==(*itr_lhs)) lhs_sort_value = itr->first;
|
||||
if (itr->second==(*itr_rhs)) rhs_sort_value = itr->first;
|
||||
}
|
||||
}
|
||||
|
||||
if (lhs_sort_value>rhs_sort_value) return true;
|
||||
if (lhs_sort_value<rhs_sort_value) return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
bool Widget::computeIntersections(osgGA::EventVisitor* ev, osgGA::GUIEventAdapter* event, Intersections& intersections, osg::Node::NodeMask traversalMask) const
|
||||
{
|
||||
osgGA::GUIActionAdapter* aa = ev ? ev->getActionAdapter() : 0;
|
||||
osgUtil::LineSegmentIntersector::Intersections source_intersections;
|
||||
if (aa && aa->computeIntersections(*event, ev->getNodePath(), source_intersections, traversalMask))
|
||||
{
|
||||
typedef std::vector<const osgUtil::LineSegmentIntersector::Intersection*> IntersectionPointerList;
|
||||
IntersectionPointerList intersectionsToSort;
|
||||
|
||||
// populate the temporay vector of poiners to the original intersection pointers.
|
||||
for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = source_intersections.begin();
|
||||
itr != source_intersections.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->drawable->getName()!="DepthSetPanel")
|
||||
{
|
||||
intersectionsToSort.push_back(&(*itr));
|
||||
}
|
||||
}
|
||||
|
||||
// sort the pointer list into order based on child traversal order, to be consistent with osgUI rendering order.
|
||||
std::sort(intersectionsToSort.begin(), intersectionsToSort.end(), SortTraversalOrder());
|
||||
|
||||
// copy the pointers to final Intersection container
|
||||
for(IntersectionPointerList::iterator itr = intersectionsToSort.begin();
|
||||
itr != intersectionsToSort.end();
|
||||
++itr)
|
||||
{
|
||||
intersections.push_back(*(*itr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user