canvas: Refactor and protect against expired pointers
This commit is contained in:
@@ -226,6 +226,10 @@ namespace canvas
|
||||
|
||||
if( _status & STATUS_DIRTY )
|
||||
{
|
||||
// Retrieve reference here, to ensure the scene group is not deleted while
|
||||
// creating the new texture and camera
|
||||
osg::ref_ptr<osg::Group> root_scene_group = _root_group->getSceneGroup();
|
||||
|
||||
_texture.setSize(_size_x, _size_y);
|
||||
|
||||
if( !_texture.serviceable() )
|
||||
@@ -251,7 +255,7 @@ namespace canvas
|
||||
parseColor(_node->getStringValue("background"), clear_color);
|
||||
camera->setClearColor(clear_color);
|
||||
|
||||
camera->addChild(_root_group->getMatrixTransform());
|
||||
camera->addChild(root_scene_group);
|
||||
|
||||
if( _texture.serviceable() )
|
||||
{
|
||||
|
||||
@@ -98,16 +98,10 @@ namespace canvas
|
||||
Image::valueChanged(node);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::Group* Window::getGroup()
|
||||
{
|
||||
return getMatrixTransform();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const SGVec2<float> Window::getPosition() const
|
||||
{
|
||||
const osg::Matrix& m = getMatrixTransform()->getMatrix();
|
||||
auto const& m = getMatrix();
|
||||
return SGVec2<float>( m(3, 0), m(3, 1) );
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,6 @@ namespace canvas
|
||||
virtual void update(double delta_time_sec);
|
||||
virtual void valueChanged(SGPropertyNode* node);
|
||||
|
||||
osg::Group* getGroup();
|
||||
const SGVec2<float> getPosition() const;
|
||||
const SGRect<float> getScreenRegion() const;
|
||||
|
||||
|
||||
@@ -210,14 +210,14 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::onDestroy()
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
return;
|
||||
|
||||
// The transform node keeps a reference on this element, so ensure it is
|
||||
// deleted.
|
||||
for(osg::Group* parent: group->getParents())
|
||||
for(osg::Group* parent: _scene_group->getParents())
|
||||
{
|
||||
parent->removeChild(_transform.get());
|
||||
parent->removeChild(_scene_group.get());
|
||||
}
|
||||
|
||||
// Hide in case someone still holds a reference
|
||||
@@ -225,7 +225,7 @@ namespace canvas
|
||||
removeListener();
|
||||
|
||||
_parent = nullptr;
|
||||
_transform = nullptr;
|
||||
_scene_group = nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -243,29 +243,8 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::update(double dt)
|
||||
{
|
||||
if( !isVisible() )
|
||||
return;
|
||||
|
||||
// Trigger matrix update
|
||||
getMatrix();
|
||||
|
||||
// Update bounding box on manual update (manual updates pass zero dt)
|
||||
if( dt == 0 && _drawable )
|
||||
_drawable->getBound();
|
||||
|
||||
if( (_attributes_dirty & BLEND_FUNC) && _transform.valid() )
|
||||
{
|
||||
parseBlendFunc(
|
||||
_transform->getOrCreateStateSet(),
|
||||
_node->getChild("blend-source"),
|
||||
_node->getChild("blend-destination"),
|
||||
_node->getChild("blend-source-rgb"),
|
||||
_node->getChild("blend-destination-rgb"),
|
||||
_node->getChild("blend-source-alpha"),
|
||||
_node->getChild("blend-destination-alpha")
|
||||
);
|
||||
_attributes_dirty &= ~BLEND_FUNC;
|
||||
}
|
||||
if( isVisible() )
|
||||
updateImpl(dt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -393,9 +372,9 @@ namespace canvas
|
||||
getBoundingBox()
|
||||
#endif
|
||||
.contains(osg::Vec3f(local_pos, 0));
|
||||
else if( _transform.valid() )
|
||||
else if( _scene_group.valid() )
|
||||
// ... for other elements, i.e. groups only a bounding sphere is available
|
||||
return _transform->getBound().contains(osg::Vec3f(parent_pos, 0));
|
||||
return _scene_group->getBound().contains(osg::Vec3f(parent_pos, 0));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -404,35 +383,32 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setVisible(bool visible)
|
||||
{
|
||||
if( _transform.valid() )
|
||||
if( _scene_group.valid() )
|
||||
// TODO check if we need another nodemask
|
||||
_transform->setNodeMask(visible ? 0xffffffff : 0);
|
||||
_scene_group->setNodeMask(visible ? 0xffffffff : 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::isVisible() const
|
||||
{
|
||||
return _transform.valid() && _transform->getNodeMask() != 0;
|
||||
return _scene_group.valid() && _scene_group->getNodeMask() != 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::MatrixTransform* Element::getMatrixTransform()
|
||||
osg::MatrixTransform* Element::getSceneGroup() const
|
||||
{
|
||||
return _transform.get();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::MatrixTransform const* Element::getMatrixTransform() const
|
||||
{
|
||||
return _transform.get();
|
||||
return _scene_group.get();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::Vec2f Element::posToLocal(const osg::Vec2f& pos) const
|
||||
{
|
||||
getMatrix();
|
||||
if (! _transform) return osg::Vec2f(pos[0], pos[1]);
|
||||
const osg::Matrix& m = _transform->getInverseMatrix();
|
||||
if( !_scene_group )
|
||||
// TODO log warning?
|
||||
return pos;
|
||||
|
||||
updateMatrix();
|
||||
const osg::Matrix& m = _scene_group->getInverseMatrix();
|
||||
return osg::Vec2f
|
||||
(
|
||||
m(0, 0) * pos[0] + m(1, 0) * pos[1] + m(3, 0),
|
||||
@@ -485,9 +461,6 @@ namespace canvas
|
||||
{
|
||||
if( child->getNameString() == NAME_TRANSFORM )
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
return;
|
||||
|
||||
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
|
||||
{
|
||||
SG_LOG
|
||||
@@ -563,6 +536,10 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setClip(const std::string& clip)
|
||||
{
|
||||
if( !_scene_group )
|
||||
// TODO warn?
|
||||
return;
|
||||
|
||||
osg::StateSet* ss = getOrCreateStateSet();
|
||||
if( !ss )
|
||||
return;
|
||||
@@ -617,7 +594,7 @@ namespace canvas
|
||||
}
|
||||
|
||||
if( !_scissor )
|
||||
_scissor = new RelativeScissor(_transform.get());
|
||||
_scissor = new RelativeScissor(_scene_group.get());
|
||||
|
||||
// <top>, <right>, <bottom>, <left>
|
||||
_scissor->x() = values[3];
|
||||
@@ -641,26 +618,26 @@ namespace canvas
|
||||
_scissor->_coord_reference = rf;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setRotation(unsigned int index, double r)
|
||||
{
|
||||
_node->getChild(NAME_TRANSFORM, index, true)->setDoubleValue("rot", r);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setRotation(unsigned int index, double r)
|
||||
{
|
||||
_node->getChild(NAME_TRANSFORM, index, true)->setDoubleValue("rot", r);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setTranslation(unsigned int index, double x, double y)
|
||||
{
|
||||
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
|
||||
tf->getChild("t", 0, true)->setDoubleValue(x);
|
||||
tf->getChild("t", 1, true)->setDoubleValue(y);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setTranslation(unsigned int index, double x, double y)
|
||||
{
|
||||
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
|
||||
tf->getChild("t", 0, true)->setDoubleValue(x);
|
||||
tf->getChild("t", 1, true)->setDoubleValue(y);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setTransformEnabled(unsigned int index, bool enabled)
|
||||
{
|
||||
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
|
||||
tf->setBoolValue("enabled", enabled);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setTransformEnabled(unsigned int index, bool enabled)
|
||||
{
|
||||
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
|
||||
tf->setBoolValue("enabled", enabled);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::BoundingBox Element::getBoundingBox() const
|
||||
@@ -674,8 +651,8 @@ namespace canvas
|
||||
|
||||
osg::BoundingBox bb;
|
||||
|
||||
if( _transform.valid() )
|
||||
bb.expandBy(_transform->getBound());
|
||||
if( _scene_group.valid() )
|
||||
bb.expandBy( _scene_group->getBound() );
|
||||
|
||||
return bb;
|
||||
}
|
||||
@@ -709,73 +686,11 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
osg::Matrix Element::getMatrix() const
|
||||
{
|
||||
if( !_transform )
|
||||
if( !_scene_group )
|
||||
return osg::Matrix::identity();
|
||||
|
||||
if( !(_attributes_dirty & TRANSFORM) )
|
||||
return _transform->getMatrix();
|
||||
|
||||
osg::Matrix m;
|
||||
for( size_t i = 0; i < _transform_types.size(); ++i )
|
||||
{
|
||||
// Skip unused indizes...
|
||||
if( _transform_types[i] == TT_NONE )
|
||||
continue;
|
||||
|
||||
SGPropertyNode* tf_node = _node->getChild("tf", i, true);
|
||||
if (!tf_node->getBoolValue("enabled", true)) {
|
||||
continue; // skip disabled transforms
|
||||
}
|
||||
|
||||
// Build up the matrix representation of the current transform node
|
||||
osg::Matrix tf;
|
||||
switch( _transform_types[i] )
|
||||
{
|
||||
case TT_MATRIX:
|
||||
tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
|
||||
tf_node->getDoubleValue("m[1]", 0),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[6]", 0),
|
||||
|
||||
tf_node->getDoubleValue("m[2]", 0),
|
||||
tf_node->getDoubleValue("m[3]", 1),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[7]", 0),
|
||||
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
|
||||
tf_node->getDoubleValue("m[4]", 0),
|
||||
tf_node->getDoubleValue("m[5]", 0),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[8]", 1) );
|
||||
break;
|
||||
case TT_TRANSLATE:
|
||||
tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
|
||||
tf_node->getDoubleValue("t[1]", 0),
|
||||
0 ) );
|
||||
break;
|
||||
case TT_ROTATE:
|
||||
tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
|
||||
break;
|
||||
case TT_SCALE:
|
||||
{
|
||||
float sx = tf_node->getDoubleValue("s[0]", 1);
|
||||
// sy defaults to sx...
|
||||
tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m.postMult( tf );
|
||||
}
|
||||
_transform->setMatrix(m);
|
||||
_attributes_dirty &= ~TRANSFORM;
|
||||
|
||||
return m;
|
||||
updateMatrix();
|
||||
return _scene_group->getMatrix();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -789,7 +704,7 @@ namespace canvas
|
||||
PropertyBasedElement(node),
|
||||
_canvas( canvas ),
|
||||
_parent( parent ),
|
||||
_transform( new osg::MatrixTransform ),
|
||||
_scene_group( new osg::MatrixTransform ),
|
||||
_style( parent_style )
|
||||
{
|
||||
staticInit();
|
||||
@@ -802,15 +717,15 @@ namespace canvas
|
||||
);
|
||||
|
||||
// Ensure elements are drawn in order they appear in the element tree
|
||||
_transform->getOrCreateStateSet()
|
||||
->setRenderBinDetails
|
||||
(
|
||||
0,
|
||||
"PreOrderBin",
|
||||
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS
|
||||
);
|
||||
_scene_group
|
||||
->getOrCreateStateSet()
|
||||
->setRenderBinDetails(
|
||||
0,
|
||||
"PreOrderBin",
|
||||
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS
|
||||
);
|
||||
|
||||
_transform->setUserData( new OSGUserData(this) );
|
||||
_scene_group->setUserData( new OSGUserData(this) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -898,11 +813,21 @@ namespace canvas
|
||||
void Element::setDrawable( osg::Drawable* drawable )
|
||||
{
|
||||
_drawable = drawable;
|
||||
assert( _drawable );
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
|
||||
if( !_drawable )
|
||||
{
|
||||
SG_LOG(SG_GL, SG_WARN, "canvas::Element::setDrawable: NULL drawable");
|
||||
return;
|
||||
}
|
||||
if( !_scene_group )
|
||||
{
|
||||
SG_LOG(SG_GL, SG_WARN, "canvas::Element::setDrawable: NULL scenegroup");
|
||||
return;
|
||||
}
|
||||
|
||||
auto geode = new osg::Geode;
|
||||
geode->addDrawable(_drawable);
|
||||
_transform->addChild(geode);
|
||||
_scene_group->addChild(geode);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -910,10 +835,10 @@ namespace canvas
|
||||
{
|
||||
if( _drawable.valid() )
|
||||
return _drawable->getOrCreateStateSet();
|
||||
if( _transform.valid() )
|
||||
return _transform->getOrCreateStateSet();
|
||||
|
||||
return 0;
|
||||
else if( _scene_group.valid() )
|
||||
return _scene_group->getOrCreateStateSet();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -923,5 +848,96 @@ namespace canvas
|
||||
setStyle(style.second);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::updateMatrix() const
|
||||
{
|
||||
if( !(_attributes_dirty & TRANSFORM) || !_scene_group )
|
||||
return;
|
||||
|
||||
osg::Matrix m;
|
||||
for( size_t i = 0; i < _transform_types.size(); ++i )
|
||||
{
|
||||
// Skip unused indizes...
|
||||
if( _transform_types[i] == TT_NONE )
|
||||
continue;
|
||||
|
||||
SGPropertyNode* tf_node = _node->getChild("tf", i, true);
|
||||
if (!tf_node->getBoolValue("enabled", true)) {
|
||||
continue; // skip disabled transforms
|
||||
}
|
||||
|
||||
// Build up the matrix representation of the current transform node
|
||||
osg::Matrix tf;
|
||||
switch( _transform_types[i] )
|
||||
{
|
||||
case TT_MATRIX:
|
||||
tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
|
||||
tf_node->getDoubleValue("m[1]", 0),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[6]", 0),
|
||||
|
||||
tf_node->getDoubleValue("m[2]", 0),
|
||||
tf_node->getDoubleValue("m[3]", 1),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[7]", 0),
|
||||
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
|
||||
tf_node->getDoubleValue("m[4]", 0),
|
||||
tf_node->getDoubleValue("m[5]", 0),
|
||||
0,
|
||||
tf_node->getDoubleValue("m[8]", 1) );
|
||||
break;
|
||||
case TT_TRANSLATE:
|
||||
tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
|
||||
tf_node->getDoubleValue("t[1]", 0),
|
||||
0 ) );
|
||||
break;
|
||||
case TT_ROTATE:
|
||||
tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
|
||||
break;
|
||||
case TT_SCALE:
|
||||
{
|
||||
float sx = tf_node->getDoubleValue("s[0]", 1);
|
||||
// sy defaults to sx...
|
||||
tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m.postMult( tf );
|
||||
}
|
||||
_scene_group->setMatrix(m);
|
||||
_attributes_dirty &= ~TRANSFORM;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::updateImpl(double dt)
|
||||
{
|
||||
updateMatrix();
|
||||
|
||||
// Update bounding box on manual update (manual updates pass zero dt)
|
||||
if( dt == 0 && _drawable )
|
||||
_drawable->getBound();
|
||||
|
||||
if( (_attributes_dirty & BLEND_FUNC) )
|
||||
{
|
||||
parseBlendFunc(
|
||||
_scene_group->getOrCreateStateSet(),
|
||||
_node->getChild("blend-source"),
|
||||
_node->getChild("blend-destination"),
|
||||
_node->getChild("blend-source-rgb"),
|
||||
_node->getChild("blend-destination-rgb"),
|
||||
_node->getChild("blend-source-alpha"),
|
||||
_node->getChild("blend-destination-alpha")
|
||||
);
|
||||
_attributes_dirty &= ~BLEND_FUNC;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
} // namespace simgear
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace canvas
|
||||
public PropertyBasedElement
|
||||
{
|
||||
public:
|
||||
using SceneGroupWeakPtr = osg::observer_ptr<osg::MatrixTransform>;
|
||||
|
||||
/**
|
||||
* Store pointer to window as user data
|
||||
@@ -142,8 +143,11 @@ namespace canvas
|
||||
*/
|
||||
virtual bool isVisible() const;
|
||||
|
||||
osg::MatrixTransform* getMatrixTransform();
|
||||
osg::MatrixTransform const* getMatrixTransform() const;
|
||||
/**
|
||||
* Get the according group in the OSG scene graph
|
||||
*/
|
||||
// TODO ref_ptr
|
||||
osg::MatrixTransform* getSceneGroup() const;
|
||||
|
||||
/**
|
||||
* Transform position to local coordinages.
|
||||
@@ -254,8 +258,8 @@ namespace canvas
|
||||
|
||||
mutable uint32_t _attributes_dirty = 0;
|
||||
|
||||
osg::observer_ptr<osg::MatrixTransform> _transform;
|
||||
std::vector<TransformType> _transform_types;
|
||||
SceneGroupWeakPtr _scene_group;
|
||||
std::vector<TransformType> _transform_types;
|
||||
|
||||
Style _style;
|
||||
RelativeScissor *_scissor = nullptr;
|
||||
@@ -585,6 +589,10 @@ namespace canvas
|
||||
|
||||
void setupStyle();
|
||||
|
||||
void updateMatrix() const;
|
||||
|
||||
virtual void updateImpl(double dt);
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<osg::Drawable> _drawable;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace canvas
|
||||
ElementFactories Group::_child_factories;
|
||||
const std::string Group::TYPE_NAME = "group";
|
||||
|
||||
void warnTransformExpired(const char* member_name)
|
||||
void warnSceneGroupExpired(const char* member_name)
|
||||
{
|
||||
SG_LOG( SG_GENERAL,
|
||||
SG_WARN,
|
||||
@@ -132,28 +132,28 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
ElementPtr Group::getElementById(const std::string& id)
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
{
|
||||
warnTransformExpired("getElementById");
|
||||
warnSceneGroupExpired("getElementById");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<GroupPtr> groups;
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
// TODO check search algorithm. Not completely breadth-first and might be
|
||||
// possible with using less dynamic memory
|
||||
std::vector<GroupPtr> child_groups;
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
{
|
||||
const ElementPtr& el = getChildByIndex(i);
|
||||
if( el->get<std::string>("id") == id )
|
||||
return el;
|
||||
|
||||
Group* group = dynamic_cast<Group*>(el.get());
|
||||
if( group )
|
||||
groups.push_back(group);
|
||||
if( Group* child_group = dynamic_cast<Group*>(el.get()) )
|
||||
child_groups.push_back(child_group);
|
||||
}
|
||||
|
||||
for(auto group: groups)
|
||||
for(auto group: child_groups)
|
||||
{
|
||||
ElementPtr el = group->getElementById(id);
|
||||
if( el )
|
||||
if( ElementPtr el = group->getElementById(id) )
|
||||
return el;
|
||||
}
|
||||
|
||||
@@ -163,32 +163,26 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::clearEventListener()
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
return warnTransformExpired("clearEventListener");
|
||||
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
getChildByIndex(i)->clearEventListener();
|
||||
|
||||
Element::clearEventListener();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::update(double dt)
|
||||
{
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
getChildByIndex(i)->update(dt);
|
||||
if( !_scene_group.valid() )
|
||||
return warnSceneGroupExpired("clearEventListener");
|
||||
|
||||
Element::update(dt);
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
getChildByIndex(i)->clearEventListener();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Group::traverse(EventVisitor& visitor)
|
||||
{
|
||||
// Iterate in reverse order as last child is displayed on top
|
||||
for(size_t i = _transform->getNumChildren(); i --> 0;)
|
||||
if( _scene_group.valid() )
|
||||
{
|
||||
if( getChildByIndex(i)->accept(visitor) )
|
||||
return true;
|
||||
// Iterate in reverse order as last child is displayed on top
|
||||
for(size_t i = _scene_group->getNumChildren(); i --> 0;)
|
||||
{
|
||||
if( getChildByIndex(i)->accept(visitor) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -203,13 +197,13 @@ namespace canvas
|
||||
bool handled = setStyleImpl(style, style_info);
|
||||
if( style_info->inheritable )
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
{
|
||||
warnTransformExpired("setStyle");
|
||||
warnSceneGroupExpired("setStyle");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
handled |= getChildByIndex(i)->setStyle(style, style_info);
|
||||
}
|
||||
|
||||
@@ -219,26 +213,20 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
osg::BoundingBox Group::getTransformedBounds(const osg::Matrix& m) const
|
||||
{
|
||||
osg::BoundingBox bb;
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
{
|
||||
warnTransformExpired("getTransformedBounds");
|
||||
return bb;
|
||||
warnSceneGroupExpired("getTransformedBounds");
|
||||
return {};
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
osg::BoundingBox bb;
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
{
|
||||
const ElementPtr& child = getChildByIndex(i);
|
||||
if( !child->getMatrixTransform()->getNodeMask() )
|
||||
auto child = getChildByIndex(i);
|
||||
if( !child || !child->isVisible() )
|
||||
continue;
|
||||
|
||||
bb.expandBy
|
||||
(
|
||||
child->getTransformedBounds
|
||||
(
|
||||
child->getMatrixTransform()->getMatrix() * m
|
||||
)
|
||||
);
|
||||
bb.expandBy( child->getTransformedBounds(child->getMatrix() * m) );
|
||||
}
|
||||
|
||||
return bb;
|
||||
@@ -254,6 +242,15 @@ namespace canvas
|
||||
return ElementFactory();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::updateImpl(double dt)
|
||||
{
|
||||
Element::updateImpl(dt);
|
||||
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
getChildByIndex(i)->update(dt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::childAdded(SGPropertyNode* child)
|
||||
{
|
||||
@@ -263,13 +260,13 @@ namespace canvas
|
||||
ElementFactory child_factory = getChildFactory( child->getNameString() );
|
||||
if( child_factory )
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
return warnTransformExpired("childAdded");
|
||||
if( !_scene_group.valid() )
|
||||
return warnSceneGroupExpired("childAdded");
|
||||
|
||||
ElementPtr element = child_factory(_canvas, child, _style, this);
|
||||
|
||||
// Add to osg scene graph...
|
||||
_transform->addChild( element->getMatrixTransform() );
|
||||
_scene_group->addChild(element->getSceneGroup());
|
||||
|
||||
// ...and ensure correct ordering
|
||||
handleZIndexChanged(element);
|
||||
@@ -290,7 +287,7 @@ namespace canvas
|
||||
|
||||
if( getChildFactory(node->getNameString()) )
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
// If transform is destroyed also all children are destroyed, so we can
|
||||
// not do anything here.
|
||||
return;
|
||||
@@ -330,16 +327,18 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::handleZIndexChanged(ElementPtr child, int z_index)
|
||||
{
|
||||
if( !child || !_transform.valid() )
|
||||
if( !child || !_scene_group.valid() )
|
||||
return;
|
||||
|
||||
osg::ref_ptr<osg::MatrixTransform> tf = child->getMatrixTransform();
|
||||
size_t index = _transform->getChildIndex(tf),
|
||||
// Keep reference to prevent deleting while removing and re-inserting later
|
||||
osg::ref_ptr<osg::MatrixTransform> tf = child->getSceneGroup();
|
||||
|
||||
size_t index = _scene_group->getChildIndex(tf),
|
||||
index_new = index;
|
||||
|
||||
for(;; ++index_new)
|
||||
{
|
||||
if( index_new + 1 == _transform->getNumChildren() )
|
||||
if( index_new + 1 == _scene_group->getNumChildren() )
|
||||
break;
|
||||
|
||||
// Move to end of block with same index (= move upwards until the next
|
||||
@@ -366,8 +365,8 @@ namespace canvas
|
||||
return;
|
||||
}
|
||||
|
||||
_transform->removeChild(index);
|
||||
_transform->insertChild(index_new, tf);
|
||||
_scene_group->removeChild(index);
|
||||
_scene_group->insertChild(index_new, tf);
|
||||
|
||||
SG_LOG
|
||||
(
|
||||
@@ -380,26 +379,27 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
ElementPtr Group::getChildByIndex(size_t index) const
|
||||
{
|
||||
assert(_transform.valid());
|
||||
OSGUserData* ud =
|
||||
static_cast<OSGUserData*>(_transform->getChild(index)->getUserData());
|
||||
assert(ud);
|
||||
if (ud)
|
||||
return ud->element;
|
||||
return nullptr;
|
||||
assert( _scene_group.valid() );
|
||||
|
||||
auto child = _scene_group->getChild(index);
|
||||
if( !child )
|
||||
return {};
|
||||
|
||||
auto ud = static_cast<OSGUserData*>(child->getUserData());
|
||||
return ud ? ud->element : ElementPtr();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ElementPtr Group::findChild( const SGPropertyNode* node,
|
||||
const std::string& id ) const
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
if( !_scene_group.valid() )
|
||||
{
|
||||
warnTransformExpired("findChild");
|
||||
warnSceneGroupExpired("findChild");
|
||||
return {};
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
|
||||
{
|
||||
ElementPtr el = getChildByIndex(i);
|
||||
|
||||
|
||||
@@ -88,8 +88,6 @@ namespace canvas
|
||||
|
||||
virtual void clearEventListener();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
virtual bool traverse(EventVisitor& visitor);
|
||||
|
||||
virtual bool setStyle( const SGPropertyNode* child,
|
||||
@@ -107,6 +105,8 @@ namespace canvas
|
||||
*/
|
||||
virtual ElementFactory getChildFactory(const std::string& type) const;
|
||||
|
||||
virtual void updateImpl(double dt);
|
||||
|
||||
virtual void childAdded(SGPropertyNode * child);
|
||||
virtual void childRemoved(SGPropertyNode * child);
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
|
||||
@@ -155,22 +155,207 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
Image::~Image()
|
||||
{
|
||||
if( _http_request ) {
|
||||
Canvas::getSystemAdapter()->getHTTPClient()->cancelRequest(_http_request, "image destroyed");
|
||||
}
|
||||
if( _http_request )
|
||||
{
|
||||
Canvas::getSystemAdapter()
|
||||
->getHTTPClient()
|
||||
->cancelRequest(_http_request, "image destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::update(double dt)
|
||||
void Image::valueChanged(SGPropertyNode* child)
|
||||
{
|
||||
Element::update(dt);
|
||||
// If the image is switched from invisible to visible, and it shows a
|
||||
// canvas, we need to delay showing it by one frame to ensure the canvas is
|
||||
// updated before the image is displayed.
|
||||
//
|
||||
// As canvas::Element handles and filters changes to the "visible" property
|
||||
// we can not check this in Image::childChanged but instead have to override
|
||||
// Element::valueChanged.
|
||||
if( !isVisible()
|
||||
&& child->getParent() == _node
|
||||
&& child->getNameString() == "visible"
|
||||
&& child->getBoolValue() )
|
||||
{
|
||||
CullCallback* cb =
|
||||
#if OSG_VERSION_LESS_THAN(3,3,2)
|
||||
static_cast<CullCallback*>
|
||||
#else
|
||||
dynamic_cast<CullCallback*>
|
||||
#endif
|
||||
( _geom->getCullCallback() );
|
||||
|
||||
if( cb )
|
||||
cb->cullNextFrame();
|
||||
}
|
||||
|
||||
Element::valueChanged(child);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSrcCanvas(CanvasPtr canvas)
|
||||
{
|
||||
CanvasPtr src_canvas = _src_canvas.lock(),
|
||||
self_canvas = _canvas.lock();
|
||||
|
||||
if( src_canvas )
|
||||
src_canvas->removeParentCanvas(self_canvas);
|
||||
if( self_canvas )
|
||||
self_canvas->removeChildCanvas(src_canvas);
|
||||
|
||||
_src_canvas = src_canvas = canvas;
|
||||
_attributes_dirty |= SRC_CANVAS;
|
||||
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
|
||||
|
||||
if( src_canvas )
|
||||
{
|
||||
setupDefaultDimensions();
|
||||
|
||||
if( self_canvas )
|
||||
{
|
||||
self_canvas->addChildCanvas(src_canvas);
|
||||
src_canvas->addParentCanvas(self_canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
CanvasWeakPtr Image::getSrcCanvas() const
|
||||
{
|
||||
return _src_canvas;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setImage(osg::ref_ptr<osg::Image> img)
|
||||
{
|
||||
// remove canvas...
|
||||
setSrcCanvas( CanvasPtr() );
|
||||
|
||||
_texture->setResizeNonPowerOfTwoHint(false);
|
||||
_texture->setImage(img);
|
||||
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
|
||||
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
|
||||
_geom->getOrCreateStateSet()
|
||||
->setTextureAttributeAndModes(0, _texture);
|
||||
|
||||
if( img )
|
||||
setupDefaultDimensions();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setFill(const std::string& fill)
|
||||
{
|
||||
osg::Vec4 color(1,1,1,1);
|
||||
if( !fill.empty() // If no color is given default to white
|
||||
&& !parseColor(fill, color) )
|
||||
return;
|
||||
setFill(color);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setFill(const osg::Vec4& color)
|
||||
{
|
||||
_colors->front() = color;
|
||||
_colors->dirty();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setOutset(const std::string& outset)
|
||||
{
|
||||
_outset = CSSBorder::parse(outset);
|
||||
_attributes_dirty |= DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setPreserveAspectRatio(const std::string& scale)
|
||||
{
|
||||
_preserve_aspect_ratio = SVGpreserveAspectRatio::parse(scale);
|
||||
_attributes_dirty |= SRC_RECT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSourceRect(const SGRect<float>& sourceRect)
|
||||
{
|
||||
_attributes_dirty |= SRC_RECT;
|
||||
_src_rect = sourceRect;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSlice(const std::string& slice)
|
||||
{
|
||||
_slice = CSSBorder::parse(slice);
|
||||
_attributes_dirty |= SRC_RECT | DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSliceWidth(const std::string& width)
|
||||
{
|
||||
_slice_width = CSSBorder::parse(width);
|
||||
_attributes_dirty |= DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const SGRect<float>& Image::getRegion() const
|
||||
{
|
||||
return _region;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Image::handleEvent(const EventPtr& event)
|
||||
{
|
||||
bool handled = Element::handleEvent(event);
|
||||
|
||||
CanvasPtr src_canvas = _src_canvas.lock();
|
||||
if( !src_canvas )
|
||||
return handled;
|
||||
|
||||
if( MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get()) )
|
||||
{
|
||||
mouse_event.reset( new MouseEvent(*mouse_event) );
|
||||
|
||||
mouse_event->client_pos = mouse_event->local_pos
|
||||
- toOsg(_region.getMin());
|
||||
|
||||
osg::Vec2f size(_region.width(), _region.height());
|
||||
if( _outset.isValid() )
|
||||
{
|
||||
CSSBorder::Offsets outset =
|
||||
_outset.getAbsOffsets(getTextureDimensions());
|
||||
|
||||
mouse_event->client_pos += osg::Vec2f(outset.l, outset.t);
|
||||
size.x() += outset.l + outset.r;
|
||||
size.y() += outset.t + outset.b;
|
||||
}
|
||||
|
||||
// Scale event pos according to canvas view size vs. displayed/screen size
|
||||
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
|
||||
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
|
||||
mouse_event->local_pos = mouse_event->client_pos;
|
||||
|
||||
handled |= src_canvas->handleMouseEvent(mouse_event);
|
||||
}
|
||||
else if( KeyboardEventPtr keyboard_event =
|
||||
dynamic_cast<KeyboardEvent*>(event.get()) )
|
||||
{
|
||||
handled |= src_canvas->handleKeyboardEvent(keyboard_event);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::updateImpl(double dt)
|
||||
{
|
||||
Element::updateImpl(dt);
|
||||
|
||||
osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>
|
||||
(
|
||||
_geom->getOrCreateStateSet()
|
||||
->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
|
||||
);
|
||||
simgear::canvas::CanvasPtr canvas = _src_canvas.lock();
|
||||
auto canvas = _src_canvas.lock();
|
||||
|
||||
if( (_attributes_dirty & SRC_CANVAS)
|
||||
// check if texture has changed (eg. due to resizing)
|
||||
@@ -400,188 +585,6 @@ namespace canvas
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::valueChanged(SGPropertyNode* child)
|
||||
{
|
||||
// If the image is switched from invisible to visible, and it shows a
|
||||
// canvas, we need to delay showing it by one frame to ensure the canvas is
|
||||
// updated before the image is displayed.
|
||||
//
|
||||
// As canvas::Element handles and filters changes to the "visible" property
|
||||
// we can not check this in Image::childChanged but instead have to override
|
||||
// Element::valueChanged.
|
||||
if( !isVisible()
|
||||
&& child->getParent() == _node
|
||||
&& child->getNameString() == "visible"
|
||||
&& child->getBoolValue() )
|
||||
{
|
||||
CullCallback* cb =
|
||||
#if OSG_VERSION_LESS_THAN(3,3,2)
|
||||
static_cast<CullCallback*>
|
||||
#else
|
||||
dynamic_cast<CullCallback*>
|
||||
#endif
|
||||
( _geom->getCullCallback() );
|
||||
|
||||
if( cb )
|
||||
cb->cullNextFrame();
|
||||
}
|
||||
|
||||
Element::valueChanged(child);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSrcCanvas(CanvasPtr canvas)
|
||||
{
|
||||
CanvasPtr src_canvas = _src_canvas.lock(),
|
||||
self_canvas = _canvas.lock();
|
||||
|
||||
if( src_canvas )
|
||||
src_canvas->removeParentCanvas(self_canvas);
|
||||
if( self_canvas )
|
||||
self_canvas->removeChildCanvas(src_canvas);
|
||||
|
||||
_src_canvas = src_canvas = canvas;
|
||||
_attributes_dirty |= SRC_CANVAS;
|
||||
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
|
||||
|
||||
if( src_canvas )
|
||||
{
|
||||
setupDefaultDimensions();
|
||||
|
||||
if( self_canvas )
|
||||
{
|
||||
self_canvas->addChildCanvas(src_canvas);
|
||||
src_canvas->addParentCanvas(self_canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
CanvasWeakPtr Image::getSrcCanvas() const
|
||||
{
|
||||
return _src_canvas;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setImage(osg::ref_ptr<osg::Image> img)
|
||||
{
|
||||
// remove canvas...
|
||||
setSrcCanvas( CanvasPtr() );
|
||||
|
||||
_texture->setResizeNonPowerOfTwoHint(false);
|
||||
_texture->setImage(img);
|
||||
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
|
||||
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
|
||||
_geom->getOrCreateStateSet()
|
||||
->setTextureAttributeAndModes(0, _texture);
|
||||
|
||||
if( img )
|
||||
setupDefaultDimensions();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setFill(const std::string& fill)
|
||||
{
|
||||
osg::Vec4 color(1,1,1,1);
|
||||
if( !fill.empty() // If no color is given default to white
|
||||
&& !parseColor(fill, color) )
|
||||
return;
|
||||
setFill(color);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setFill(const osg::Vec4& color)
|
||||
{
|
||||
_colors->front() = color;
|
||||
_colors->dirty();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setOutset(const std::string& outset)
|
||||
{
|
||||
_outset = CSSBorder::parse(outset);
|
||||
_attributes_dirty |= DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setPreserveAspectRatio(const std::string& scale)
|
||||
{
|
||||
_preserve_aspect_ratio = SVGpreserveAspectRatio::parse(scale);
|
||||
_attributes_dirty |= SRC_RECT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSourceRect(const SGRect<float>& sourceRect)
|
||||
{
|
||||
_attributes_dirty |= SRC_RECT;
|
||||
_src_rect = sourceRect;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSlice(const std::string& slice)
|
||||
{
|
||||
_slice = CSSBorder::parse(slice);
|
||||
_attributes_dirty |= SRC_RECT | DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::setSliceWidth(const std::string& width)
|
||||
{
|
||||
_slice_width = CSSBorder::parse(width);
|
||||
_attributes_dirty |= DEST_SIZE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const SGRect<float>& Image::getRegion() const
|
||||
{
|
||||
return _region;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Image::handleEvent(const EventPtr& event)
|
||||
{
|
||||
bool handled = Element::handleEvent(event);
|
||||
|
||||
CanvasPtr src_canvas = _src_canvas.lock();
|
||||
if( !src_canvas )
|
||||
return handled;
|
||||
|
||||
if( MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get()) )
|
||||
{
|
||||
mouse_event.reset( new MouseEvent(*mouse_event) );
|
||||
|
||||
mouse_event->client_pos = mouse_event->local_pos
|
||||
- toOsg(_region.getMin());
|
||||
|
||||
osg::Vec2f size(_region.width(), _region.height());
|
||||
if( _outset.isValid() )
|
||||
{
|
||||
CSSBorder::Offsets outset =
|
||||
_outset.getAbsOffsets(getTextureDimensions());
|
||||
|
||||
mouse_event->client_pos += osg::Vec2f(outset.l, outset.t);
|
||||
size.x() += outset.l + outset.r;
|
||||
size.y() += outset.t + outset.b;
|
||||
}
|
||||
|
||||
// Scale event pos according to canvas view size vs. displayed/screen size
|
||||
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
|
||||
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
|
||||
mouse_event->local_pos = mouse_event->client_pos;
|
||||
|
||||
handled |= src_canvas->handleMouseEvent(mouse_event);
|
||||
}
|
||||
else if( KeyboardEventPtr keyboard_event =
|
||||
dynamic_cast<KeyboardEvent*>(event.get()) )
|
||||
{
|
||||
handled |= src_canvas->handleKeyboardEvent(keyboard_event);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Image::childChanged(SGPropertyNode* child)
|
||||
{
|
||||
|
||||
@@ -53,7 +53,6 @@ namespace canvas
|
||||
ElementWeakPtr parent = 0 );
|
||||
virtual ~Image();
|
||||
|
||||
virtual void update(double dt);
|
||||
virtual void valueChanged(SGPropertyNode* child);
|
||||
|
||||
void setSrcCanvas(CanvasPtr canvas);
|
||||
@@ -109,6 +108,8 @@ namespace canvas
|
||||
SRC_CANVAS = DEST_SIZE << 1
|
||||
};
|
||||
|
||||
virtual void updateImpl(double dt);
|
||||
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
|
||||
void setupDefaultDimensions();
|
||||
|
||||
@@ -85,13 +85,13 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Map::update(double dt)
|
||||
void Map::updateImpl(double dt)
|
||||
{
|
||||
for( GeoNodes::iterator it = _geo_nodes.begin();
|
||||
it != _geo_nodes.end();
|
||||
++it )
|
||||
Group::updateImpl(dt);
|
||||
|
||||
for(auto& it: _geo_nodes)
|
||||
{
|
||||
GeoNodePair* geo_node = it->second.get();
|
||||
GeoNodePair* geo_node = it.second.get();
|
||||
if( !geo_node->isComplete()
|
||||
|| (!geo_node->isDirty() && !_projection_dirty) )
|
||||
continue;
|
||||
@@ -113,8 +113,6 @@ namespace canvas
|
||||
geo_node->setDirty(false);
|
||||
}
|
||||
_projection_dirty = false;
|
||||
|
||||
Group::update(dt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -45,17 +45,17 @@ namespace canvas
|
||||
ElementWeakPtr parent = 0 );
|
||||
virtual ~Map();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
virtual void childRemoved( SGPropertyNode * parent,
|
||||
SGPropertyNode * child );
|
||||
virtual void valueChanged(SGPropertyNode * child);
|
||||
|
||||
protected:
|
||||
virtual void updateImpl(double dt);
|
||||
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
void updateProjection(SGPropertyNode* type_node);
|
||||
|
||||
virtual void childAdded( SGPropertyNode* parent,
|
||||
SGPropertyNode* child );
|
||||
virtual void childRemoved( SGPropertyNode* parent,
|
||||
SGPropertyNode* child );
|
||||
virtual void valueChanged(SGPropertyNode* child);
|
||||
virtual void childChanged(SGPropertyNode* child);
|
||||
|
||||
using GeoNodes =
|
||||
std::unordered_map<SGPropertyNode*, std::shared_ptr<GeoNodePair>>;
|
||||
|
||||
@@ -690,40 +690,6 @@ namespace canvas
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Path::update(double dt)
|
||||
{
|
||||
if( _attributes_dirty & (CMDS | COORDS) )
|
||||
{
|
||||
_path->setSegments
|
||||
(
|
||||
_node->getChildValues<VGubyte, int>("cmd"),
|
||||
_node->getChildValues<VGfloat, float>("coord")
|
||||
);
|
||||
|
||||
_attributes_dirty &= ~(CMDS | COORDS);
|
||||
}
|
||||
|
||||
// SVG path overrides manual cmd/coord specification
|
||||
if ( _hasSVG && (_attributes_dirty & SVG))
|
||||
{
|
||||
CmdList cmds;
|
||||
CoordList coords;
|
||||
parseSVGPathToVGPath(_node->getStringValue("svg"), cmds, coords);
|
||||
_path->setSegments(cmds, coords);
|
||||
_attributes_dirty &= ~SVG;
|
||||
}
|
||||
|
||||
if ( _hasRect &&(_attributes_dirty & RECT))
|
||||
{
|
||||
parseRectToVGPath();
|
||||
_attributes_dirty &= ~RECT;
|
||||
|
||||
}
|
||||
|
||||
Element::update(dt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::BoundingBox Path::getTransformedBounds(const osg::Matrix& m) const
|
||||
{
|
||||
@@ -829,6 +795,39 @@ namespace canvas
|
||||
_node->getChild("border-radius", 1, true)->setDoubleValue(radiusY);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Path::updateImpl(double dt)
|
||||
{
|
||||
Element::updateImpl(dt);
|
||||
|
||||
if( _attributes_dirty & (CMDS | COORDS) )
|
||||
{
|
||||
_path->setSegments
|
||||
(
|
||||
_node->getChildValues<VGubyte, int>("cmd"),
|
||||
_node->getChildValues<VGfloat, float>("coord")
|
||||
);
|
||||
|
||||
_attributes_dirty &= ~(CMDS | COORDS);
|
||||
}
|
||||
|
||||
// SVG path overrides manual cmd/coord specification
|
||||
if( _hasSVG && (_attributes_dirty & SVG) )
|
||||
{
|
||||
CmdList cmds;
|
||||
CoordList coords;
|
||||
parseSVGPathToVGPath(_node->getStringValue("svg"), cmds, coords);
|
||||
_path->setSegments(cmds, coords);
|
||||
_attributes_dirty &= ~SVG;
|
||||
}
|
||||
|
||||
if( _hasRect &&(_attributes_dirty & RECT) )
|
||||
{
|
||||
parseRectToVGPath();
|
||||
_attributes_dirty &= ~RECT;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Path::childChanged(SGPropertyNode* child)
|
||||
{
|
||||
|
||||
@@ -40,8 +40,6 @@ namespace canvas
|
||||
ElementWeakPtr parent = 0 );
|
||||
virtual ~Path();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
|
||||
|
||||
/** Add a segment with the given command and coordinates */
|
||||
@@ -86,12 +84,14 @@ namespace canvas
|
||||
|
||||
bool _hasSVG : 1;
|
||||
bool _hasRect : 1;
|
||||
SGRect<float> _rect;
|
||||
SGRectf _rect;
|
||||
|
||||
virtual void updateImpl(double dt);
|
||||
|
||||
void parseRectToVGPath();
|
||||
|
||||
virtual void childRemoved(SGPropertyNode * child);
|
||||
virtual void childChanged(SGPropertyNode * child);
|
||||
|
||||
void parseRectToVGPath();
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
@@ -865,12 +865,12 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
osg::StateSet* Text::getOrCreateStateSet()
|
||||
{
|
||||
if( !_transform.valid() )
|
||||
return 0;
|
||||
if( !_scene_group.valid() )
|
||||
return nullptr;
|
||||
|
||||
// Only check for StateSet on Transform, as the text stateset is shared
|
||||
// between all text instances using the same font (texture).
|
||||
return _transform->getOrCreateStateSet();
|
||||
return _scene_group->getOrCreateStateSet();
|
||||
}
|
||||
|
||||
} // namespace canvas
|
||||
|
||||
Reference in New Issue
Block a user