Restructure Canvas/PropertyBasedElement
Nodes inside the osg scenegraph now hold a strong reference to the according canvas element. Canvas elements in turn now only hold a weak reference to the according node. This simplifies for example the canvas::Group as it does not need to keep a list of children on its own anymore. This is now stored inside the scenegraph (as it was already before). The restructuring will also allow to use a canvas::Group for the canvas gui inside FlightGear and share for example the handling of stacking based on z-index.
This commit is contained in:
parent
c8af817eeb
commit
9bfa6ac1a1
@ -75,9 +75,13 @@ namespace canvas
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Canvas::~Canvas()
|
void Canvas::onDestroy()
|
||||||
{
|
{
|
||||||
|
if( _root_group )
|
||||||
|
{
|
||||||
|
_root_group->clearEventListener();
|
||||||
|
_root_group->onDestroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -111,19 +115,6 @@ namespace canvas
|
|||||||
return _texture.serviceable();
|
return _texture.serviceable();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Canvas::destroy()
|
|
||||||
{
|
|
||||||
if( _root_group )
|
|
||||||
_root_group->clearEventListener();
|
|
||||||
|
|
||||||
// TODO check if really not in use anymore
|
|
||||||
getProps()->getParent()
|
|
||||||
->removeChild( getProps()->getName(),
|
|
||||||
getProps()->getIndex(),
|
|
||||||
false );
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Canvas::addParentCanvas(const CanvasWeakPtr& canvas)
|
void Canvas::addParentCanvas(const CanvasWeakPtr& canvas)
|
||||||
{
|
{
|
||||||
@ -133,7 +124,8 @@ namespace canvas
|
|||||||
(
|
(
|
||||||
SG_GENERAL,
|
SG_GENERAL,
|
||||||
SG_WARN,
|
SG_WARN,
|
||||||
"Canvas::addParentCanvas: got an expired parent: " << _node->getPath()
|
"Canvas::addParentCanvas(" << _node->getPath(true) << "): "
|
||||||
|
"got an expired parent!"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -150,7 +142,8 @@ namespace canvas
|
|||||||
(
|
(
|
||||||
SG_GENERAL,
|
SG_GENERAL,
|
||||||
SG_WARN,
|
SG_WARN,
|
||||||
"Canvas::addChildCanvas: got an expired child: " << _node->getPath()
|
"Canvas::addChildCanvas(" << _node->getPath(true) << "): "
|
||||||
|
" got an expired child!"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ namespace canvas
|
|||||||
typedef osg::ref_ptr<CullCallback> CullCallbackPtr;
|
typedef osg::ref_ptr<CullCallback> CullCallbackPtr;
|
||||||
|
|
||||||
Canvas(SGPropertyNode* node);
|
Canvas(SGPropertyNode* node);
|
||||||
virtual ~Canvas();
|
virtual void onDestroy();
|
||||||
|
|
||||||
void setSystemAdapter(const SystemAdapterPtr& system_adapter);
|
void setSystemAdapter(const SystemAdapterPtr& system_adapter);
|
||||||
SystemAdapterPtr getSystemAdapter() const;
|
SystemAdapterPtr getSystemAdapter() const;
|
||||||
@ -80,7 +80,6 @@ namespace canvas
|
|||||||
CanvasMgr* getCanvasMgr() const;
|
CanvasMgr* getCanvasMgr() const;
|
||||||
|
|
||||||
bool isInit() const;
|
bool isInit() const;
|
||||||
void destroy();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a canvas which should be marked as dirty upon any change to this
|
* Add a canvas which should be marked as dirty upon any change to this
|
||||||
|
@ -43,19 +43,40 @@ namespace canvas
|
|||||||
const std::string NAME_TRANSFORM = "tf";
|
const std::string NAME_TRANSFORM = "tf";
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Element::removeListener()
|
Element::OSGUserData::OSGUserData(ElementPtr element):
|
||||||
|
element(element)
|
||||||
{
|
{
|
||||||
_node->removeChangeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Element::~Element()
|
Element::~Element()
|
||||||
{
|
{
|
||||||
removeListener();
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void Element::setSelf(const PropertyBasedElementPtr& self)
|
||||||
|
{
|
||||||
|
PropertyBasedElement::setSelf(self);
|
||||||
|
|
||||||
|
_transform->setUserData
|
||||||
|
(
|
||||||
|
new OSGUserData(boost::static_pointer_cast<Element>(self))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void Element::onDestroy()
|
||||||
|
{
|
||||||
|
if( !_transform.valid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The transform node keeps a reference on this element, so ensure it is
|
||||||
|
// deleted.
|
||||||
BOOST_FOREACH(osg::Group* parent, _transform->getParents())
|
BOOST_FOREACH(osg::Group* parent, _transform->getParents())
|
||||||
{
|
{
|
||||||
parent->removeChild(_transform);
|
parent->removeChild(_transform.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,14 +260,15 @@ namespace canvas
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
|
osg::MatrixTransform* Element::getMatrixTransform()
|
||||||
{
|
{
|
||||||
return _transform;
|
return _transform.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform const> Element::getMatrixTransform() const
|
//----------------------------------------------------------------------------
|
||||||
|
osg::MatrixTransform const* Element::getMatrixTransform() const
|
||||||
{
|
{
|
||||||
return _transform;
|
return _transform.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -45,6 +45,18 @@ namespace canvas
|
|||||||
public PropertyBasedElement
|
public PropertyBasedElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store pointer to window as user data
|
||||||
|
*/
|
||||||
|
class OSGUserData:
|
||||||
|
public osg::Referenced
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ElementPtr element;
|
||||||
|
OSGUserData(ElementPtr element);
|
||||||
|
};
|
||||||
|
|
||||||
typedef boost::function<bool(Element&, const SGPropertyNode*)>
|
typedef boost::function<bool(Element&, const SGPropertyNode*)>
|
||||||
StyleSetterFunc;
|
StyleSetterFunc;
|
||||||
typedef boost::function<void(Element&, const SGPropertyNode*)>
|
typedef boost::function<void(Element&, const SGPropertyNode*)>
|
||||||
@ -61,20 +73,14 @@ namespace canvas
|
|||||||
std::string type; ///!< Interpolation type
|
std::string type; ///!< Interpolation type
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the property listener of the element.
|
|
||||||
*
|
|
||||||
* You will need to call the appropriate methods (#childAdded,
|
|
||||||
* #childRemoved, #valueChanged) yourself to ensure the element still
|
|
||||||
* receives the needed events.
|
|
||||||
*/
|
|
||||||
void removeListener();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
virtual ~Element() = 0;
|
virtual ~Element() = 0;
|
||||||
|
|
||||||
|
virtual void setSelf(const PropertyBasedElementPtr& self);
|
||||||
|
virtual void onDestroy();
|
||||||
|
|
||||||
ElementWeakPtr getWeakPtr() const;
|
ElementWeakPtr getWeakPtr() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,8 +108,8 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
bool isVisible() const;
|
bool isVisible() const;
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
|
osg::MatrixTransform* getMatrixTransform();
|
||||||
osg::ref_ptr<osg::MatrixTransform const> getMatrixTransform() const;
|
osg::MatrixTransform const* getMatrixTransform() const;
|
||||||
|
|
||||||
virtual void childAdded( SGPropertyNode * parent,
|
virtual void childAdded( SGPropertyNode * parent,
|
||||||
SGPropertyNode * child );
|
SGPropertyNode * child );
|
||||||
@ -154,7 +160,7 @@ namespace canvas
|
|||||||
uint32_t _attributes_dirty;
|
uint32_t _attributes_dirty;
|
||||||
|
|
||||||
bool _transform_dirty;
|
bool _transform_dirty;
|
||||||
osg::ref_ptr<osg::MatrixTransform> _transform;
|
osg::observer_ptr<osg::MatrixTransform> _transform;
|
||||||
std::vector<TransformType> _transform_types;
|
std::vector<TransformType> _transform_types;
|
||||||
|
|
||||||
Style _style;
|
Style _style;
|
||||||
|
@ -96,25 +96,13 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ElementPtr Group::getChild(const SGPropertyNode* node)
|
ElementPtr Group::getChild(const SGPropertyNode* node)
|
||||||
{
|
{
|
||||||
ChildList::iterator child = findChild(node);
|
return findChild(node, "");
|
||||||
if( child == _children.end() )
|
|
||||||
return ElementPtr();
|
|
||||||
|
|
||||||
return child->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
ElementPtr Group::getChild(const std::string& id)
|
ElementPtr Group::getChild(const std::string& id)
|
||||||
{
|
{
|
||||||
for( ChildList::iterator child = _children.begin();
|
return findChild(0, id);
|
||||||
child != _children.end();
|
|
||||||
++child )
|
|
||||||
{
|
|
||||||
if( child->second->get<std::string>("id") == id )
|
|
||||||
return child->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ElementPtr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -147,10 +135,10 @@ namespace canvas
|
|||||||
{
|
{
|
||||||
std::vector<GroupPtr> groups;
|
std::vector<GroupPtr> groups;
|
||||||
|
|
||||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
{
|
{
|
||||||
const ElementPtr& el = child.second;
|
const ElementPtr& el = getChildByIndex(i);
|
||||||
if( el->getProps()->getStringValue("id") == id )
|
if( el->get<std::string>("id") == id )
|
||||||
return el;
|
return el;
|
||||||
|
|
||||||
GroupPtr group = boost::dynamic_pointer_cast<Group>(el);
|
GroupPtr group = boost::dynamic_pointer_cast<Group>(el);
|
||||||
@ -171,8 +159,9 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Group::clearEventListener()
|
void Group::clearEventListener()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
|
||||||
child.second->clearEventListener();
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
|
getChildByIndex(i)->clearEventListener();
|
||||||
|
|
||||||
Element::clearEventListener();
|
Element::clearEventListener();
|
||||||
}
|
}
|
||||||
@ -180,8 +169,8 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Group::update(double dt)
|
void Group::update(double dt)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
child.second->update(dt);
|
getChildByIndex(i)->update(dt);
|
||||||
|
|
||||||
Element::update(dt);
|
Element::update(dt);
|
||||||
}
|
}
|
||||||
@ -190,9 +179,9 @@ namespace canvas
|
|||||||
bool Group::traverse(EventVisitor& visitor)
|
bool Group::traverse(EventVisitor& visitor)
|
||||||
{
|
{
|
||||||
// Iterate in reverse order as last child is displayed on top
|
// Iterate in reverse order as last child is displayed on top
|
||||||
BOOST_REVERSE_FOREACH( ChildList::value_type child, _children )
|
for(size_t i = _transform->getNumChildren(); i --> 0;)
|
||||||
{
|
{
|
||||||
if( child.second->accept(visitor) )
|
if( getChildByIndex(i)->accept(visitor) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -210,9 +199,9 @@ namespace canvas
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
{
|
{
|
||||||
if( child.second->setStyle(style) )
|
if( getChildByIndex(i)->setStyle(style) )
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,16 +213,17 @@ namespace canvas
|
|||||||
{
|
{
|
||||||
osg::BoundingBox bb;
|
osg::BoundingBox bb;
|
||||||
|
|
||||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
{
|
{
|
||||||
if( !child.second->getMatrixTransform()->getNodeMask() )
|
const ElementPtr& child = getChildByIndex(i);
|
||||||
|
if( !child->getMatrixTransform()->getNodeMask() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bb.expandBy
|
bb.expandBy
|
||||||
(
|
(
|
||||||
child.second->getTransformedBounds
|
child->getTransformedBounds
|
||||||
(
|
(
|
||||||
child.second->getMatrixTransform()->getMatrix() * m
|
child->getMatrixTransform()->getMatrix() * m
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -255,10 +245,9 @@ namespace canvas
|
|||||||
|
|
||||||
// Add to osg scene graph...
|
// Add to osg scene graph...
|
||||||
_transform->addChild( element->getMatrixTransform() );
|
_transform->addChild( element->getMatrixTransform() );
|
||||||
_children.push_back( ChildList::value_type(child, element) );
|
|
||||||
|
|
||||||
// ...and ensure correct ordering
|
// ...and ensure correct ordering
|
||||||
handleZIndexChanged( --_children.end() );
|
handleZIndexChanged(element);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -279,8 +268,8 @@ namespace canvas
|
|||||||
|
|
||||||
if( _child_factories.find(node->getNameString()) != _child_factories.end() )
|
if( _child_factories.find(node->getNameString()) != _child_factories.end() )
|
||||||
{
|
{
|
||||||
ChildList::iterator child = findChild(node);
|
ElementPtr child = getChild(node);
|
||||||
if( child == _children.end() )
|
if( !child )
|
||||||
SG_LOG
|
SG_LOG
|
||||||
(
|
(
|
||||||
SG_GL,
|
SG_GL,
|
||||||
@ -289,8 +278,9 @@ namespace canvas
|
|||||||
);
|
);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_transform->removeChild( child->second->getMatrixTransform() );
|
// Remove child from the scenegraph (this automatically invalidates the
|
||||||
_children.erase(child);
|
// reference on the element hold by the MatrixTransform)
|
||||||
|
child->onDestroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -306,56 +296,52 @@ namespace canvas
|
|||||||
{
|
{
|
||||||
if( node->getParent()->getParent() == _node
|
if( node->getParent()->getParent() == _node
|
||||||
&& node->getNameString() == "z-index" )
|
&& node->getNameString() == "z-index" )
|
||||||
return handleZIndexChanged( findChild(node->getParent()),
|
return handleZIndexChanged( getChild(node->getParent()),
|
||||||
node->getIntValue() );
|
node->getIntValue() );
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Group::handleZIndexChanged(ChildList::iterator child, int z_index)
|
void Group::handleZIndexChanged(ElementPtr child, int z_index)
|
||||||
{
|
{
|
||||||
if( child == _children.end() )
|
if( !child )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
osg::Node* tf = child->second->getMatrixTransform();
|
osg::ref_ptr<osg::MatrixTransform> tf = child->getMatrixTransform();
|
||||||
int index = _transform->getChildIndex(tf),
|
size_t index = _transform->getChildIndex(tf),
|
||||||
index_new = index;
|
index_new = index;
|
||||||
|
|
||||||
ChildList::iterator next = child;
|
for(;; ++index_new)
|
||||||
++next;
|
|
||||||
|
|
||||||
while( next != _children.end()
|
|
||||||
&& next->first->getIntValue("z-index", 0) <= z_index )
|
|
||||||
{
|
{
|
||||||
++index_new;
|
if( index_new + 1 == _transform->getNumChildren() )
|
||||||
++next;
|
break;
|
||||||
|
|
||||||
|
// Move to end of block with same index (= move upwards until the next
|
||||||
|
// element has a higher index)
|
||||||
|
if( getChildByIndex(index_new + 1)->get<int>("z-index", 0) > z_index )
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( index_new != index )
|
if( index_new == index )
|
||||||
{
|
{
|
||||||
_children.insert(next, *child);
|
// We were not able to move upwards so now try downwards
|
||||||
}
|
for(;; --index_new)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ChildList::iterator prev = child,
|
if( index_new == 0 )
|
||||||
check = child;
|
break;
|
||||||
while( check != _children.begin()
|
|
||||||
&& (--check)->first->getIntValue("z-index", 0) > z_index )
|
// Move to end of block with same index (= move downwards until the
|
||||||
{
|
// previous element has the same or a lower index)
|
||||||
--index_new;
|
if( getChildByIndex(index_new - 1)->get<int>("z-index", 0) <= z_index )
|
||||||
--prev;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( index == index_new )
|
if( index == index_new )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_children.insert(prev, *child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_transform->removeChild(index);
|
_transform->removeChild(index);
|
||||||
_transform->insertChild(index_new, tf);
|
_transform->insertChild(index_new, tf);
|
||||||
|
|
||||||
_children.erase(child);
|
|
||||||
|
|
||||||
SG_LOG
|
SG_LOG
|
||||||
(
|
(
|
||||||
SG_GENERAL,
|
SG_GENERAL,
|
||||||
@ -365,14 +351,34 @@ namespace canvas
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
Group::ChildList::iterator Group::findChild(const SGPropertyNode* node)
|
ElementPtr Group::getChildByIndex(size_t index) const
|
||||||
{
|
{
|
||||||
return std::find_if
|
OSGUserData* ud =
|
||||||
(
|
static_cast<OSGUserData*>(_transform->getChild(index)->getUserData());
|
||||||
_children.begin(),
|
return ud->element;
|
||||||
_children.end(),
|
}
|
||||||
boost::bind(&ChildList::value_type::first, _1) == node
|
|
||||||
);
|
//----------------------------------------------------------------------------
|
||||||
|
ElementPtr Group::findChild( const SGPropertyNode* node,
|
||||||
|
const std::string& id ) const
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
|
{
|
||||||
|
ElementPtr el = getChildByIndex(i);
|
||||||
|
|
||||||
|
if( node )
|
||||||
|
{
|
||||||
|
if( el->getProps() == node )
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( el->get<std::string>("id") == id )
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ElementPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
@ -99,15 +99,16 @@ namespace canvas
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
static ElementFactories _child_factories;
|
static ElementFactories _child_factories;
|
||||||
ChildList _children;
|
|
||||||
|
|
||||||
virtual void childAdded(SGPropertyNode * child);
|
virtual void childAdded(SGPropertyNode * child);
|
||||||
virtual void childRemoved(SGPropertyNode * child);
|
virtual void childRemoved(SGPropertyNode * child);
|
||||||
virtual void childChanged(SGPropertyNode * child);
|
virtual void childChanged(SGPropertyNode * child);
|
||||||
|
|
||||||
void handleZIndexChanged(ChildList::iterator child, int z_index = 0);
|
void handleZIndexChanged(ElementPtr child, int z_index = 0);
|
||||||
|
|
||||||
ChildList::iterator findChild(const SGPropertyNode* node);
|
ElementPtr getChildByIndex(size_t index) const;
|
||||||
|
ElementPtr findChild( const SGPropertyNode* node,
|
||||||
|
const std::string& id ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
@ -350,22 +350,27 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Image::setSrcCanvas(CanvasPtr canvas)
|
void Image::setSrcCanvas(CanvasPtr canvas)
|
||||||
{
|
{
|
||||||
if( !_src_canvas.expired() )
|
CanvasPtr src_canvas = _src_canvas.lock(),
|
||||||
_src_canvas.lock()->removeParentCanvas(_canvas);
|
self_canvas = _canvas.lock();
|
||||||
if( !_canvas.expired() )
|
|
||||||
_canvas.lock()->removeChildCanvas(_src_canvas);
|
|
||||||
|
|
||||||
_src_canvas = canvas;
|
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;
|
_attributes_dirty |= SRC_CANVAS;
|
||||||
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
|
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
|
||||||
|
|
||||||
if( !_src_canvas.expired() )
|
if( src_canvas )
|
||||||
{
|
{
|
||||||
setupDefaultDimensions();
|
setupDefaultDimensions();
|
||||||
_src_canvas.lock()->addParentCanvas(_canvas);
|
|
||||||
|
|
||||||
if( !_canvas.expired() )
|
if( self_canvas )
|
||||||
_canvas.lock()->addChildCanvas(_src_canvas);
|
{
|
||||||
|
self_canvas->addChildCanvas(src_canvas);
|
||||||
|
src_canvas->addParentCanvas(self_canvas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,10 +30,29 @@ namespace simgear
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
PropertyBasedElement::~PropertyBasedElement()
|
PropertyBasedElement::~PropertyBasedElement()
|
||||||
|
{
|
||||||
|
onDestroy();
|
||||||
|
removeListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void PropertyBasedElement::removeListener()
|
||||||
{
|
{
|
||||||
_node->removeChangeListener(this);
|
_node->removeChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void PropertyBasedElement::destroy()
|
||||||
|
{
|
||||||
|
if( !_node )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO check if really not in use anymore
|
||||||
|
if( _node->getParent() )
|
||||||
|
_node->getParent()
|
||||||
|
->removeChild(_node->getName(), _node->getIndex(), false);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
SGConstPropertyNode_ptr PropertyBasedElement::getProps() const
|
SGConstPropertyNode_ptr PropertyBasedElement::getProps() const
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,20 @@ namespace simgear
|
|||||||
PropertyBasedElement(SGPropertyNode* node);
|
PropertyBasedElement(SGPropertyNode* node);
|
||||||
virtual ~PropertyBasedElement();
|
virtual ~PropertyBasedElement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the property listener of the element.
|
||||||
|
*
|
||||||
|
* You will need to call the appropriate methods (#childAdded,
|
||||||
|
* #childRemoved, #valueChanged) yourself to ensure the element still
|
||||||
|
* receives the needed events.
|
||||||
|
*/
|
||||||
|
void removeListener();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys this element (removes node from property tree)
|
||||||
|
*/
|
||||||
|
void destroy();
|
||||||
|
|
||||||
virtual void update(double delta_time_sec) = 0;
|
virtual void update(double delta_time_sec) = 0;
|
||||||
|
|
||||||
SGConstPropertyNode_ptr getProps() const;
|
SGConstPropertyNode_ptr getProps() const;
|
||||||
@ -67,6 +81,7 @@ namespace simgear
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void setSelf(const PropertyBasedElementPtr& self);
|
virtual void setSelf(const PropertyBasedElementPtr& self);
|
||||||
|
virtual void onDestroy() {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -126,6 +126,7 @@ namespace simgear
|
|||||||
_elements.resize(index + 1);
|
_elements.resize(index + 1);
|
||||||
}
|
}
|
||||||
else if( _elements[index] )
|
else if( _elements[index] )
|
||||||
|
{
|
||||||
SG_LOG
|
SG_LOG
|
||||||
(
|
(
|
||||||
SG_GENERAL,
|
SG_GENERAL,
|
||||||
@ -133,6 +134,10 @@ namespace simgear
|
|||||||
_name_elements << "[" << index << "] already exists!"
|
_name_elements << "[" << index << "] already exists!"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Give anything holding a reference to this element to release it
|
||||||
|
_elements[index]->onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
PropertyBasedElementPtr el = _element_factory(child);
|
PropertyBasedElementPtr el = _element_factory(child);
|
||||||
el->setSelf( el );
|
el->setSelf( el );
|
||||||
_elements[index] = el;
|
_elements[index] = el;
|
||||||
@ -158,8 +163,11 @@ namespace simgear
|
|||||||
"can't removed unknown " << _name_elements << "[" << index << "]!"
|
"can't removed unknown " << _name_elements << "[" << index << "]!"
|
||||||
);
|
);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// remove the element...
|
// remove the element...
|
||||||
|
_elements[index]->onDestroy();
|
||||||
_elements[index].reset();
|
_elements[index].reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace simgear
|
} // namespace simgear
|
||||||
|
Loading…
Reference in New Issue
Block a user