X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fcanvas%2FCanvas.cxx;h=c7898b4535df604b07de4b0ccda9fa545af708af;hb=23413b47818b042620eeeaf306ffe6d1ae81852d;hp=74ccb60bd92136d1a690238156ee226041373aec;hpb=2fe9ad595f017d49a00f5579f724f81aa55d7c8a;p=simgear.git diff --git a/simgear/canvas/Canvas.cxx b/simgear/canvas/Canvas.cxx index 74ccb60b..c7898b45 100644 --- a/simgear/canvas/Canvas.cxx +++ b/simgear/canvas/Canvas.cxx @@ -19,8 +19,8 @@ #include "Canvas.hxx" #include "CanvasEventManager.hxx" #include "CanvasEventVisitor.hxx" -#include -#include +#include "CanvasPlacement.hxx" +#include #include #include @@ -31,7 +31,6 @@ #include #include -#include namespace simgear { @@ -49,8 +48,12 @@ namespace canvas void Canvas::CullCallback::operator()( osg::Node* node, osg::NodeVisitor* nv ) { - if( (nv->getTraversalMask() & simgear::MODEL_BIT) && !_canvas.expired() ) - _canvas.lock()->enableRendering(); + if( (nv->getTraversalMask() & simgear::MODEL_BIT) ) + { + CanvasPtr canvas = _canvas.lock(); + if( canvas ) + canvas->enableRendering(); + } traverse(node, nv); } @@ -73,25 +76,29 @@ namespace canvas { _status = 0; setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y); - } - //---------------------------------------------------------------------------- - Canvas::~Canvas() - { + _root_group.reset( new Group(this, _node) ); + // Remove automatically created property listener as we forward them on our + // own + _root_group->removeListener(); + _cull_callback = new CullCallback(this); } //---------------------------------------------------------------------------- - void Canvas::setSystemAdapter(const SystemAdapterPtr& system_adapter) + Canvas::~Canvas() { - _system_adapter = system_adapter; - _texture.setSystemAdapter(system_adapter); + } //---------------------------------------------------------------------------- - SystemAdapterPtr Canvas::getSystemAdapter() const + void Canvas::onDestroy() { - return _system_adapter; + if( _root_group ) + { + _root_group->clearEventListener(); + _root_group->onDestroy(); + } } //---------------------------------------------------------------------------- @@ -112,16 +119,6 @@ namespace canvas return _texture.serviceable(); } - //---------------------------------------------------------------------------- - void Canvas::destroy() - { - // TODO check if really not in use anymore - getProps()->getParent() - ->removeChild( getProps()->getName(), - getProps()->getIndex(), - false ); - } - //---------------------------------------------------------------------------- void Canvas::addParentCanvas(const CanvasWeakPtr& canvas) { @@ -131,7 +128,8 @@ namespace canvas ( SG_GENERAL, SG_WARN, - "Canvas::addParentCanvas: got an expired parent: " << _node->getPath() + "Canvas::addParentCanvas(" << _node->getPath(true) << "): " + "got an expired parent!" ); return; } @@ -148,7 +146,8 @@ namespace canvas ( SG_GENERAL, SG_WARN, - "Canvas::addChildCanvas: got an expired child: " << _node->getPath() + "Canvas::addChildCanvas(" << _node->getPath(true) << "): " + " got an expired child!" ); return; } @@ -171,10 +170,19 @@ namespace canvas //---------------------------------------------------------------------------- GroupPtr Canvas::createGroup(const std::string& name) { - return boost::dynamic_pointer_cast - ( - _root_group->createChild("group", name) - ); + return _root_group->createChild(name); + } + + //---------------------------------------------------------------------------- + GroupPtr Canvas::getGroup(const std::string& name) + { + return _root_group->getChild(name); + } + + //---------------------------------------------------------------------------- + GroupPtr Canvas::getOrCreateGroup(const std::string& name) + { + return _root_group->getOrCreateChild(name); } //---------------------------------------------------------------------------- @@ -183,6 +191,14 @@ namespace canvas return _root_group; } + //---------------------------------------------------------------------------- + void Canvas::setLayout(const LayoutRef& layout) + { + _layout = layout; + _layout->setCanvas(this); + _status |= LAYOUT_DIRTY; + } + //---------------------------------------------------------------------------- void Canvas::enableRendering(bool force) { @@ -194,11 +210,10 @@ namespace canvas //---------------------------------------------------------------------------- void Canvas::update(double delta_time_sec) { - if( (!_texture.serviceable() && _status != STATUS_DIRTY) - || (_status & CREATE_FAILED) ) + if( _status & (CREATE_FAILED | MISSING_SIZE) ) return; - if( _status == STATUS_DIRTY ) + if( _status & STATUS_DIRTY ) { _texture.setSize(_size_x, _size_y); @@ -217,15 +232,16 @@ namespace canvas osg::Camera* camera = _texture.getCamera(); + // TODO Allow custom render order? For now just keep in order with + // property tree. + camera->setRenderOrder(osg::Camera::PRE_RENDER, _node->getIndex()); + osg::Vec4 clear_color(0.0f, 0.0f, 0.0f , 1.0f); parseColor(_node->getStringValue("background"), clear_color); camera->setClearColor(clear_color); camera->addChild(_root_group->getMatrixTransform()); - // Ensure objects are drawn in order of traversal - camera->getOrCreateStateSet()->setBinName("TraversalOrderBin"); - if( _texture.serviceable() ) { setStatusFlags(STATUS_OK); @@ -239,23 +255,36 @@ namespace canvas } } + if( _layout ) + { + if( (_status & LAYOUT_DIRTY) ) + { + _layout->setGeometry(SGRecti(0, 0, _view_width, _view_height)); + _status &= ~LAYOUT_DIRTY; + } + else + _layout->update(); + } + if( _visible || _render_always ) { - BOOST_FOREACH(CanvasWeakPtr canvas, _child_canvases) + BOOST_FOREACH(CanvasWeakPtr canvas_weak, _child_canvases) { // TODO should we check if the image the child canvas is displayed // within is really visible? - if( !canvas.expired() ) - canvas.lock()->_visible = true; + CanvasPtr canvas = canvas_weak.lock(); + if( canvas ) + canvas->_visible = true; } if( _render_dirty ) { // Also mark all canvases this canvas is displayed within as dirty - BOOST_FOREACH(CanvasWeakPtr canvas, _parent_canvases) + BOOST_FOREACH(CanvasWeakPtr canvas_weak, _parent_canvases) { - if( !canvas.expired() ) - canvas.lock()->_render_dirty = true; + CanvasPtr canvas = canvas_weak.lock(); + if( canvas ) + canvas->_render_dirty = true; } } @@ -298,11 +327,7 @@ namespace canvas if( placement_factory != _placement_factories.end() ) { Placements& placements = _placements[ node->getIndex() ] = - placement_factory->second - ( - node, - boost::static_pointer_cast(_self.lock()) - ); + placement_factory->second(node, this); node->setStringValue ( "status-msg", @@ -315,12 +340,22 @@ namespace canvas } //---------------------------------------------------------------------------- - naRef Canvas::addEventListener(const nasal::CallContext& ctx) + bool Canvas::addEventListener( const std::string& type, + const EventListener& cb ) + { + if( !_root_group.get() ) + throw std::runtime_error("Canvas::addEventListener: no root group!"); + + return _root_group->addEventListener(type, cb); + } + + //---------------------------------------------------------------------------- + bool Canvas::dispatchEvent(const EventPtr& event) { if( !_root_group.get() ) - naRuntimeError(ctx.c, "Canvas: No root group!"); + throw std::runtime_error("Canvas::dispatchEvent: no root group!"); - return _root_group->addEventListener(ctx); + return _root_group->dispatchEvent(event); } //---------------------------------------------------------------------------- @@ -375,6 +410,7 @@ namespace canvas if( _view_width == w ) return; _view_width = w; + _status |= LAYOUT_DIRTY; _texture.setViewSize(_view_width, _view_height); } @@ -385,6 +421,7 @@ namespace canvas if( _view_height == h ) return; _view_height = h; + _status |= LAYOUT_DIRTY; _texture.setViewSize(_view_width, _view_height); } @@ -410,18 +447,25 @@ namespace canvas //---------------------------------------------------------------------------- bool Canvas::handleMouseEvent(const MouseEventPtr& event) { - if( !_root_group.get() ) + if( !_root_group ) return false; EventVisitor visitor( EventVisitor::TRAVERSE_DOWN, event->getClientPos(), - event->getDelta() ); + _root_group ); if( !_root_group->accept(visitor) ) return false; return _event_manager->handleEvent(event, visitor.getPropagationPath()); } + //---------------------------------------------------------------------------- + bool Canvas::propagateEvent( EventPtr const& event, + EventPropagationPath const& path ) + { + return _event_manager->propagateEvent(event, path); + } + //---------------------------------------------------------------------------- void Canvas::childAdded( SGPropertyNode * parent, SGPropertyNode * child ) @@ -453,8 +497,10 @@ namespace canvas //---------------------------------------------------------------------------- void Canvas::valueChanged(SGPropertyNode* node) { - if( boost::starts_with(node->getNameString(), "status") - || node->getParent()->getNameString() == "bounding-box" ) + const std::string& name = node->getNameString(); + + if( boost::starts_with(name, "status") + || boost::starts_with(name, "data-") ) return; _render_dirty = true; @@ -462,21 +508,26 @@ namespace canvas if( node->getParent()->getParent() == _node && node->getParent()->getNameString() == "placement" ) { - bool placement_dirty = false; - BOOST_FOREACH(Placements& placements, _placements) + size_t index = node->getIndex(); + if( index < _placements.size() ) { - BOOST_FOREACH(PlacementPtr& placement, placements) + Placements& placements = _placements[index]; + if( !placements.empty() ) { - // check if change can be directly handled by placement - if( placement->getProps() == node->getParent() - && !placement->childChanged(node) ) - placement_dirty = true; + bool placement_dirty = false; + BOOST_FOREACH(PlacementPtr& placement, placements) + { + // check if change can be directly handled by placement + if( placement->getProps() == node->getParent() + && !placement->childChanged(node) ) + placement_dirty = true; + } + + if( !placement_dirty ) + return; } } - if( !placement_dirty ) - return; - // prevent double updates... for( size_t i = 0; i < _dirty_placements.size(); ++i ) { @@ -488,7 +539,7 @@ namespace canvas } else if( node->getParent() == _node ) { - if( node->getNameString() == "background" ) + if( name == "background" ) { osg::Vec4 color; if( _texture.getCamera() && parseColor(node->getStringValue(), color) ) @@ -497,35 +548,41 @@ namespace canvas _render_dirty = true; } } - else if( node->getNameString() == "mipmapping" - || node->getNameString() == "coverage-samples" - || node->getNameString() == "color-samples" ) + else if( name == "mipmapping" + || name == "coverage-samples" + || name == "color-samples" ) { _sampling_dirty = true; } - else if( node->getNameString() == "additive-blend" ) + else if( name == "additive-blend" ) { _texture.useAdditiveBlend( node->getBoolValue() ); } - else if( node->getNameString() == "render-always" ) + else if( name == "render-always" ) { _render_always = node->getBoolValue(); } - else if( node->getNameString() == "size" ) + else if( name == "size" ) { if( node->getIndex() == 0 ) setSizeX( node->getIntValue() ); else if( node->getIndex() == 1 ) setSizeY( node->getIntValue() ); } - else if( node->getNameString() == "view" ) + else if( name == "update" ) + { + if( _root_group ) + _root_group->update(0); + return update(0); + } + else if( name == "view" ) { if( node->getIndex() == 0 ) setViewWidth( node->getIntValue() ); else if( node->getIndex() == 1 ) setViewHeight( node->getIntValue() ); } - else if( node->getNameString() == "freeze" ) + else if( name == "freeze" ) _texture.setRender( node->getBoolValue() ); else handled = false; @@ -576,27 +633,38 @@ namespace canvas ( SG_GENERAL, SG_WARN, - "Canvas::addPlacementFactory: replace existing factor for type " << type + "Canvas::addPlacementFactory: replace existing factory '" << type << "'" ); _placement_factories[type] = factory; } //---------------------------------------------------------------------------- - void Canvas::setSelf(const PropertyBasedElementPtr& self) + void Canvas::removePlacementFactory(const std::string& type) { - PropertyBasedElement::setSelf(self); - - CanvasPtr canvas = boost::static_pointer_cast(self); + PlacementFactoryMap::iterator it = _placement_factories.find(type); + if( it == _placement_factories.end() ) + SG_LOG + ( + SG_GENERAL, + SG_WARN, + "Canvas::removePlacementFactory: no such factory '" << type << "'" + ); + else + _placement_factories.erase(it); + } - _root_group.reset( new Group(canvas, _node) ); - _root_group->setSelf(_root_group); - // Remove automatically created property listener as we forward them on our - // own - _root_group->removeListener(); + //---------------------------------------------------------------------------- + void Canvas::setSystemAdapter(const SystemAdapterPtr& system_adapter) + { + _system_adapter = system_adapter; + } - _cull_callback = new CullCallback(canvas); + //---------------------------------------------------------------------------- + SystemAdapterPtr Canvas::getSystemAdapter() + { + return _system_adapter; } //---------------------------------------------------------------------------- @@ -615,7 +683,7 @@ namespace canvas _status_msg = "Missing size-y"; else if( _status & CREATE_FAILED ) _status_msg = "Creating render target failed"; - else if( _status == STATUS_DIRTY ) + else if( _status & STATUS_DIRTY ) _status_msg = "Creation pending..."; else _status_msg = "Ok"; @@ -623,6 +691,7 @@ namespace canvas //---------------------------------------------------------------------------- Canvas::PlacementFactoryMap Canvas::_placement_factories; + SystemAdapterPtr Canvas::_system_adapter; } // namespace canvas } // namespace simgear