- Prevent writing to property tree in wrong thread.
- Add Element::getBoundingBox and
Element::getTightBoundingBox as uniform way to
retrieve bounding boxes of all canvas elements.
- Update path bounding boxe in update traversal.
//----------------------------------------------------------------------------
void Canvas::valueChanged(SGPropertyNode* node)
{
- if( boost::starts_with(node->getNameString(), "status")
- || node->getParent()->getNameString() == "bounding-box" )
+ if( boost::starts_with(node->getNameString(), "status") )
return;
_render_dirty = true;
// Trigger matrix update
getMatrix();
+ // TODO limit bounding box to scissor
if( _attributes_dirty & SCISSOR_COORDS )
{
if( _scissor && _scissor->_coord_reference != GLOBAL )
// Drawables have a bounding box...
if( _drawable )
return _drawable->getBound().contains(osg::Vec3f(local_pos, 0));
- else
+ else if( _transform.valid() )
// ... for other elements, i.e. groups only a bounding sphere is available
return _transform->getBound().contains(osg::Vec3f(parent_pos, 0));
+ else
+ return false;
}
}
//----------------------------------------------------------------------------
- void Element::setBoundingBox(const osg::BoundingBox& bb)
+ osg::BoundingBox Element::getBoundingBox() const
{
- if( _bounding_box.empty() )
- {
- SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
- _bounding_box.resize(4);
- _bounding_box[0] = bb_node->getChild("min-x", 0, true);
- _bounding_box[1] = bb_node->getChild("min-y", 0, true);
- _bounding_box[2] = bb_node->getChild("max-x", 0, true);
- _bounding_box[3] = bb_node->getChild("max-y", 0, true);
- }
+ if( _drawable )
+ return _drawable->getBound();
+
+ osg::BoundingBox bb;
- _bounding_box[0]->setFloatValue(bb._min.x());
- _bounding_box[1]->setFloatValue(bb._min.y());
- _bounding_box[2]->setFloatValue(bb._max.x());
- _bounding_box[3]->setFloatValue(bb._max.y());
+ if( _transform.valid() )
+ bb.expandBy(_transform->getBound());
+
+ return bb;
+ }
+
+ //----------------------------------------------------------------------------
+ osg::BoundingBox Element::getTightBoundingBox() const
+ {
+ return getTransformedBounds(getMatrix());
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
osg::Matrix Element::getMatrix() const
{
+ if( !_transform )
+ return osg::Matrix::identity();
+
if( !(_attributes_dirty & TRANSFORM) )
return _transform->getMatrix();
void setClipFrame(ReferenceFrame rf);
/**
- * Write the given bounding box to the property tree
+ * Get bounding box (may not be as tight as bounding box returned by
+ * #getTightBounds)
*/
- void setBoundingBox(const osg::BoundingBox& bb);
+ osg::BoundingBox getBoundingBox() const;
+
+ /**
+ * Get tight bounding box (child points are transformed to elements
+ * coordinate space before calculating the bounding box).
+ */
+ osg::BoundingBox getTightBoundingBox() const;
/**
* Get bounding box with children/drawables transformed by passed matrix
osg::observer_ptr<osg::MatrixTransform> _transform;
std::vector<TransformType> _transform_types;
- Style _style;
- std::vector<SGPropertyNode_ptr> _bounding_box;
- RelativeScissor *_scissor;
+ Style _style;
+ RelativeScissor *_scissor;
typedef std::vector<EventListener> Listener;
typedef std::map<Event::Type, Listener> ListenerMap;
ListenerMap _listener;
typedef std::map<std::string, StyleInfo> StyleSetters;
- static StyleSetters _style_setters;
+ static StyleSetters _style_setters;
static void staticInit();
_vertices->dirty();
_attributes_dirty &= ~DEST_SIZE;
_geom->dirtyBound();
- setBoundingBox(_geom->getBound());
}
if( _attributes_dirty & SRC_RECT )
// vgPathBounds doesn't take stroke width into account
float ext = 0.5 * _stroke_width;
- osg::BoundingBox bb
+ return osg::BoundingBox
(
min[0] - ext, min[1] - ext, -0.1,
min[0] + size[0] + ext, min[1] + size[1] + ext, 0.1
);
- _path_element->setBoundingBox(bb);
-
- return bb;
}
private:
}
if( _attributes_dirty & BOUNDING_BOX )
+ {
dirtyBound();
+
+ // Recalculate bounding box now (prevent race condition)
+ getBound();
+ }
}
struct PathUpdateCallback:
osg::BoundingBox Text::TextOSG::computeBound() const
{
osg::BoundingBox bb = osgText::Text::computeBound();
- if( !bb.valid() )
- return bb;
#if OSG_VERSION_LESS_THAN(3,1,0)
- // TODO bounding box still doesn't seem always right (eg. with center
- // horizontal alignment not completely accurate)
- bb._min.y() += _offset.y();
- bb._max.y() += _offset.y();
+ if( bb.valid() )
+ {
+ // TODO bounding box still doesn't seem always right (eg. with center
+ // horizontal alignment not completely accurate)
+ bb._min.y() += _offset.y();
+ bb._max.y() += _offset.y();
+ }
#endif
- _text_element->setBoundingBox(bb);
-
return bb;
}