diff --git a/include/osgUI/Widget b/include/osgUI/Widget index 3ccd6a815..1e0e04e56 100644 --- a/include/osgUI/Widget +++ b/include/osgUI/Widget @@ -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 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(); diff --git a/src/osgUI/ComboBox.cpp b/src/osgUI/ComboBox.cpp index 2a0fbdfd6..0dbb859e7 100644 --- a/src/osgUI/ComboBox.cpp +++ b/src/osgUI/ComboBox.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include 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 "<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 { "<getName()<setVisible(!_popup->getVisible()); + } + + if (_popup->getVisible() && _popup->getExtents().contains(localPosition, 1e-6)) + { + OSG_NOTICE<<"In pop up"<getUserValue("index",index)) break; + } + + if (index<_items.size()) + { + OSG_NOTICE<<" index selected "<setVisible(false); + } + } break; + } case(osgGA::GUIEventAdapter::RELEASE): OSG_NOTICE<<"Button release "<get(); OSG_NOTICE<<"Creating item "<getText()<<", "<getColor()< 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()); diff --git a/src/osgUI/Popup.cpp b/src/osgUI/Popup.cpp index 3c3d639d2..0037fae46 100644 --- a/src/osgUI/Popup.cpp +++ b/src/osgUI/Popup.cpp @@ -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"<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) ); diff --git a/src/osgUI/Style.cpp b/src/osgUI/Style.cpp index 25d22c2d4..d12767da3 100644 --- a/src/osgUI/Style.cpp +++ b/src/osgUI/Style.cpp @@ -61,6 +61,7 @@ osg::Node* Style::createPanel(const osg::BoundingBox& extents, const osg::Vec4& { OSG_NOTICE<<"Creating Panel"< geometry = new osg::Geometry; + geometry->setName("Panel"); osg::ref_ptr 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 geometry = new osg::Geometry; + geometry->setName("DepthSetPanel"); osg::ref_ptr 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 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 textDrawable = new osgText::Text; + textDrawable->setName("Text"); textDrawable->setText(text); textDrawable->setPosition( osg::Vec3(extents.xMin(), extents.yMin(), extents.zMin()) ); diff --git a/src/osgUI/Widget.cpp b/src/osgUI/Widget.cpp index af37e0540..9f38bf457 100644 --- a/src/osgUI/Widget.cpp +++ b/src/osgUI/Widget.cpp @@ -23,6 +23,8 @@ #include #include +#include + 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"<(parent); + + unsigned int lhs_index = parent->getChildIndex(*itr_lhs); + double lhs_sort_value = static_cast(lhs_index)/static_cast(parent->getNumChildren()); + + unsigned int rhs_index = parent->getChildIndex(*itr_rhs); + double rhs_sort_value = (static_cast(rhs_index)+epsilon)/static_cast(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_valuegetActionAdapter() : 0; + osgUtil::LineSegmentIntersector::Intersections source_intersections; + if (aa && aa->computeIntersections(*event, ev->getNodePath(), source_intersections, traversalMask)) + { + typedef std::vector 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; }