From 83bbd9e45c1f04dbeac986a383cd6e253a7f9590 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Thu, 9 Aug 2012 14:50:20 +0200 Subject: [PATCH] Canvas: Image/Window unifying and allow using canvas inside canvas. - Refactor and unify common functionality of canvas::Window and canvas::Image - Make canvas::Image actually work - Allow using canvases inside canvas::Image * Use new canvas:// "protocol" to allow using canvases in place of images - Prepare for categorizing canvases: * Move canvases to /canvas/by-index * Later support linking to other nodes in subbranches of /canvas --- src/Canvas/canvas_fwd.hpp | 1 + src/Canvas/canvas_mgr.cxx | 18 +- src/Canvas/canvas_mgr.hxx | 12 ++ src/Canvas/elements/CanvasImage.cxx | 280 +++++++++++++++++++++------- src/Canvas/elements/CanvasImage.hxx | 48 +++-- src/Canvas/elements/element.cxx | 4 +- src/Canvas/gui_mgr.cxx | 25 ++- src/Canvas/gui_mgr.hxx | 1 - src/Canvas/property_based_mgr.cxx | 6 + src/Canvas/property_based_mgr.hxx | 2 + src/Canvas/rect.hxx | 10 + src/Canvas/window.cxx | 144 +++----------- src/Canvas/window.hxx | 18 +- src/GUI/CanvasWidget.cxx | 2 +- 14 files changed, 352 insertions(+), 219 deletions(-) diff --git a/src/Canvas/canvas_fwd.hpp b/src/Canvas/canvas_fwd.hpp index c56612fd9..56b40fcb2 100644 --- a/src/Canvas/canvas_fwd.hpp +++ b/src/Canvas/canvas_fwd.hpp @@ -37,6 +37,7 @@ typedef boost::weak_ptr PropertyBasedElementWeakPtr; namespace canvas { class Group; + class Image; class MouseEvent; class Placement; diff --git a/src/Canvas/canvas_mgr.cxx b/src/Canvas/canvas_mgr.cxx index 21fcccf80..a17507623 100644 --- a/src/Canvas/canvas_mgr.cxx +++ b/src/Canvas/canvas_mgr.cxx @@ -30,7 +30,7 @@ CanvasPtr canvasFactory(SGPropertyNode* node) //------------------------------------------------------------------------------ CanvasMgr::CanvasMgr(): - PropertyBasedMgr("/canvas", "texture", &canvasFactory) + PropertyBasedMgr("/canvas/by-index", "texture", &canvasFactory) { Canvas::addPlacementFactory ( @@ -46,11 +46,21 @@ CanvasMgr::CanvasMgr(): } //------------------------------------------------------------------------------ -unsigned int CanvasMgr::getCanvasTexId(size_t index) const +CanvasPtr CanvasMgr::getCanvas(size_t index) const { if( index >= _elements.size() || !_elements[index] ) - return 0; + return CanvasPtr(); - return static_cast(_elements[index].get())->getTexId(); + return boost::static_pointer_cast(_elements[index]); +} + +//------------------------------------------------------------------------------ +unsigned int CanvasMgr::getCanvasTexId(size_t index) const +{ + CanvasPtr canvas = getCanvas(index); + if( canvas ) + return canvas->getTexId(); + else + return 0; } diff --git a/src/Canvas/canvas_mgr.hxx b/src/Canvas/canvas_mgr.hxx index 10cbe9a76..568da3d61 100644 --- a/src/Canvas/canvas_mgr.hxx +++ b/src/Canvas/canvas_mgr.hxx @@ -19,6 +19,7 @@ #ifndef CANVAS_MGR_H_ #define CANVAS_MGR_H_ +#include "canvas_fwd.hpp" #include "property_based_mgr.hxx" class CanvasMgr: @@ -27,9 +28,20 @@ class CanvasMgr: public: CanvasMgr(); + /** + * Get ::Canvas by index + * + * @param index Index of texture node in /canvas/by-index/ + */ + CanvasPtr getCanvas(size_t index) const; + /** * Get OpenGL texture name for given canvas * + * @deprecated This was only meant to be used by the PUI CanvasWidget + * implementation as PUI can't handle osg::Texture objects. + * Use getCanvas(index)->getTexture() instead. + * * @param Index of canvas * @return OpenGL texture name */ diff --git a/src/Canvas/elements/CanvasImage.cxx b/src/Canvas/elements/CanvasImage.cxx index 5bbed177e..3addb4901 100644 --- a/src/Canvas/elements/CanvasImage.cxx +++ b/src/Canvas/elements/CanvasImage.cxx @@ -20,6 +20,8 @@ #include +#include +#include #include #include #include @@ -28,43 +30,80 @@ #include
#include
+#include + +/** + * Callback to enable/disable rendering of canvas displayed inside windows or + * other canvases. + */ +class CullCallback: + public osg::Drawable::CullCallback +{ + public: + CullCallback(Canvas::CameraCullCallback* camera_cull); + + private: + Canvas::CameraCullCallback *_camera_cull; + + virtual bool cull( osg::NodeVisitor* nv, + osg::Drawable* drawable, + osg::RenderInfo* renderInfo ) const; +}; + +//------------------------------------------------------------------------------ +CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull): + _camera_cull( camera_cull ) +{ + +} + +//------------------------------------------------------------------------------ +bool CullCallback::cull( osg::NodeVisitor* nv, + osg::Drawable* drawable, + osg::RenderInfo* renderInfo ) const +{ + _camera_cull->enableRendering(); + + // TODO check if window/image should be culled + return false; +} + namespace canvas { //---------------------------------------------------------------------------- Image::Image(SGPropertyNode_ptr node): - Element(node, COLOR | COLOR_FILL | BOUNDING_BOX), - _texture(new osg::Texture2D) + Element(node, COLOR_FILL | BOUNDING_BOX), + _texture(new osg::Texture2D), + _node_src_rect( node->getNode("source", 0, true) ), + _src_rect(0,0,0,0), + _region(0,0,0,0) { - _source_rect = node->getChild("source"); - _geom = new osg::Geometry; _geom->setUseDisplayList(false); - + osg::StateSet *stateSet = _geom->getOrCreateStateSet(); stateSet->setTextureAttributeAndModes(0, _texture.get()); stateSet->setDataVariance(osg::Object::STATIC); // allocate arrays for the image - _vertices = new osg::Vec2Array; + _vertices = new osg::Vec3Array(4); _vertices->setDataVariance(osg::Object::STATIC); - _vertices->reserve(4); _geom->setVertexArray(_vertices); - - _texCoords = new osg::Vec2Array; + + _texCoords = new osg::Vec2Array(4); _texCoords->setDataVariance(osg::Object::STATIC); - _texCoords->reserve(4); _geom->setTexCoordArray(0, _texCoords); - - _colors = new osg::Vec4Array; + + _colors = new osg::Vec4Array(4); _colors->setDataVariance(osg::Object::STATIC); _geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); _geom->setColorArray(_colors); - + osg::DrawArrays* prim = new osg::DrawArrays(osg::PrimitiveSet::QUADS); - prim->set(osg::PrimitiveSet::QUADS, 0, 1); + prim->set(osg::PrimitiveSet::QUADS, 0, 4); prim->setDataVariance(osg::Object::STATIC); _geom->addPrimitiveSet(prim); - + setDrawable(_geom); } @@ -79,69 +118,184 @@ namespace canvas { Element::update(dt); - if( _attributes_dirty & SRC_RECT ) { - _attributes_dirty &= ~SRC_RECT; - int texWidth = _texture->getTextureWidth(); - int texHeight = _texture->getTextureHeight(); - - double x0 = _source_rect->getDoubleValue("left"), - x1 = _source_rect->getDoubleValue("right"), - y0 = _source_rect->getDoubleValue("top"), - y1 = _source_rect->getDoubleValue("bottom"); - double width = x1 - x0, height = y1 - y0; - - _vertices->clear(); - _vertices->push_back(osg::Vec2(0, 0)); - _vertices->push_back(osg::Vec2(width, 0)); - _vertices->push_back(osg::Vec2(width, height)); - _vertices->push_back(osg::Vec2(0, height)); + if( _attributes_dirty & DEST_SIZE ) + { + (*_vertices)[0].set(_region.l(), _region.t(), 0); + (*_vertices)[1].set(_region.r(), _region.t(), 0); + (*_vertices)[2].set(_region.r(), _region.b(), 0); + (*_vertices)[3].set(_region.l(), _region.b(), 0); _vertices->dirty(); - - double u0 = x0 / texWidth, - u1 = x1 / texWidth, - v0 = y0 / texHeight, - v1 = y1 / texHeight; - - _texCoords->clear(); - _texCoords->push_back(osg::Vec2(u0, v0)); - _texCoords->push_back(osg::Vec2(u1, v0)); - _texCoords->push_back(osg::Vec2(u1, v1)); - _texCoords->push_back(osg::Vec2(u0, v1)); - _texCoords->dirty(); + + _attributes_dirty &= ~DEST_SIZE; + _geom->dirtyBound(); } + + if( _attributes_dirty & SRC_RECT ) + { + double u0 = _src_rect.l(), + u1 = _src_rect.r(), + v0 = _src_rect.b(), + v1 = _src_rect.t(); + + if( !_node_src_rect->getBoolValue("normalized", true) ) + { + osg::Texture2D *texture = !_canvas.expired() + ? _canvas.lock()->getTexture() + : _texture.get(); + + int texWidth = texture->getTextureWidth(); + int texHeight = texture->getTextureHeight(); + + u0 /= texWidth; + u1 /= texWidth; + v0 /= texHeight; + v1 /= texHeight; + } + + (*_texCoords)[0].set(u0, v0); + (*_texCoords)[1].set(u1, v0); + (*_texCoords)[2].set(u1, v1); + (*_texCoords)[3].set(u0, v1); + _texCoords->dirty(); + + _attributes_dirty &= ~SRC_RECT; + } + } + + //---------------------------------------------------------------------------- + void Image::setCanvas(CanvasPtr canvas) + { + _canvas = canvas; + _geom->getOrCreateStateSet() + ->setTextureAttribute(0, canvas ? canvas->getTexture() : 0); + _geom->setCullCallback( + canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0 + ); + } + + //---------------------------------------------------------------------------- + CanvasWeakPtr Image::getCanvas() const + { + return _canvas; + } + + //---------------------------------------------------------------------------- + void Image::setImage(osg::Image *img) + { + // remove canvas... + setCanvas( CanvasPtr() ); + + _texture->setImage(img); + _geom->getOrCreateStateSet() + ->setTextureAttributeAndModes(0, _texture); + } + + //---------------------------------------------------------------------------- + const Rect& Image::getRegion() const + { + return _region; + } + + //---------------------------------------------------------------------------- + void Image::valueChanged(SGPropertyNode *node) + { + if( node->getParent() == _node_src_rect ) + { + _attributes_dirty |= SRC_RECT; + + if( node->getNameString() == "left" ) + _src_rect.setLeft( node->getFloatValue() ); + else if( node->getNameString() == "right" ) + _src_rect.setRight( node->getFloatValue() ); + else if( node->getNameString() == "top" ) + _src_rect.setTop( node->getFloatValue() ); + else if( node->getNameString() == "bottom" ) + _src_rect.setBottom( node->getFloatValue() ); + } + else + Element::valueChanged(node); } //---------------------------------------------------------------------------- void Image::childChanged(SGPropertyNode* child) { const std::string& name = child->getNameString(); - - if (_source_rect == child) - _attributes_dirty |= SRC_RECT; - else if (name == "file") { - SGPath tpath = globals->resolve_ressource_path(child->getStringValue()); - if (tpath.isNull() || !tpath.exists()) { - SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such image: " << child->getStringValue()); - } else { - _texture->setImage(osgDB::readImageFile(tpath.c_str())); - _attributes_dirty |= SRC_RECT; + + if( name == "x" ) + { + _region.setX( child->getFloatValue() ); + _attributes_dirty |= DEST_SIZE; + } + else if( name == "y" ) + { + _region.setY( child->getFloatValue() ); + _attributes_dirty |= DEST_SIZE; + } + else if( name == "size" ) + { + if( child->getIndex() == 0 ) + _region.setWidth( child->getFloatValue() ); + else + _region.setHeight( child->getFloatValue() ); + + _attributes_dirty |= DEST_SIZE; + } + else if( name == "file" ) + { + static const std::string CANVAS_PROTOCOL = "canvas://"; + const std::string& path = child->getStringValue(); + + if( boost::starts_with(path, CANVAS_PROTOCOL) ) + { + CanvasMgr* canvas_mgr = + dynamic_cast(globals->get_subsystem("Canvas")); + if( !canvas_mgr ) + { + SG_LOG(SG_GL, SG_ALERT, "canvas::Image: Failed to get CanvasMgr"); + return; } - } - } - //---------------------------------------------------------------------------- - void Image::colorChanged(const osg::Vec4& color) - { - _colors->clear(); - for (int i=0; i<4; ++i) { - _colors->push_back(color); + const SGPropertyNode* canvas_node = + canvas_mgr->getPropertyRoot() + ->getParent() + ->getNode( path.substr(CANVAS_PROTOCOL.size()) ); + if( !canvas_node ) + { + SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such canvas: " << path); + return; + } + + // TODO add support for other means of addressing canvases (eg. by + // name) + CanvasPtr canvas = canvas_mgr->getCanvas( canvas_node->getIndex() ); + if( !canvas ) + { + SG_LOG(SG_GL, SG_ALERT, "canvas::Image: Invalid canvas: " << path); + return; + } + + setCanvas(canvas); } - _colors->dirty(); + else + { + SGPath tpath = globals->resolve_ressource_path(path); + if( tpath.isNull() || !tpath.exists() ) + { + SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such image: " << path); + return; + } + + setImage( osgDB::readImageFile(tpath.c_str()) ); + } + } } //---------------------------------------------------------------------------- - void Image::colorFillChanged(const osg::Vec4& /*color*/) + void Image::colorFillChanged(const osg::Vec4& color) { + for( int i = 0; i < 4; ++i ) + (*_colors)[i] = color; + _colors->dirty(); } } // namespace canvas diff --git a/src/Canvas/elements/CanvasImage.hxx b/src/Canvas/elements/CanvasImage.hxx index c115277d0..934df7a0a 100644 --- a/src/Canvas/elements/CanvasImage.hxx +++ b/src/Canvas/elements/CanvasImage.hxx @@ -20,11 +20,8 @@ #define CANVAS_IMAGE_HXX_ #include "element.hxx" - -#include - -#include -#include +#include +#include #include @@ -35,33 +32,58 @@ namespace canvas public Element { public: + /** + * @param node Property node containing settings for this image: + * rect/[left/right/top/bottom] Dimensions of source + * rect + * size[0-1] Dimensions of rectangle + * [x,y] Position of rectangle + */ Image(SGPropertyNode_ptr node); ~Image(); virtual void update(double dt); + void setCanvas(CanvasPtr canvas); + CanvasWeakPtr getCanvas() const; + + void setImage(osg::Image *img); + + const Rect& getRegion() const; + + /** + * Callback for every changed child node + */ + virtual void valueChanged(SGPropertyNode *node); + protected: - enum TextAttributes + enum ImageAttributes { SRC_RECT = LAST_ATTRIBUTE << 1, // Source image rectangle + DEST_SIZE = SRC_RECT << 1 // Element size }; - SGPropertyNode_ptr _source_rect, - _dest_rect; - + /** + * Callback for changed direct child nodes + */ virtual void childChanged(SGPropertyNode * child); - virtual void colorChanged(const osg::Vec4& color); virtual void colorFillChanged(const osg::Vec4& color); void handleHit(float x, float y); osg::ref_ptr _texture; - + // TODO optionally forward events to canvas + CanvasWeakPtr _canvas; + osg::Geometry *_geom; - osg::Vec2Array *_vertices; + osg::Vec3Array *_vertices; osg::Vec2Array *_texCoords; - osg::Vec4Array* _colors; + osg::Vec4Array* _colors; + + SGPropertyNode *_node_src_rect; + Rect _src_rect, + _region; }; } // namespace canvas diff --git a/src/Canvas/elements/element.cxx b/src/Canvas/elements/element.cxx index b01b36966..01fbf1a5d 100644 --- a/src/Canvas/elements/element.cxx +++ b/src/Canvas/elements/element.cxx @@ -226,10 +226,10 @@ namespace canvas _node->addChangeListener(this); if( _attributes_used & COLOR ) - linkColorNodes("color", _node, _color, osg::Vec4f(0,1,0,1)); + linkColorNodes("color", _node, _color, osg::Vec4f(0,0,0,1)); if( _attributes_used & COLOR_FILL ) - linkColorNodes("color-fill", _node, _color_fill, osg::Vec4f(1,0,1,1)); + linkColorNodes("color-fill", _node, _color_fill, osg::Vec4f(1,1,1,1)); SG_LOG ( diff --git a/src/Canvas/gui_mgr.cxx b/src/Canvas/gui_mgr.cxx index 34b356f0a..7d581e6c9 100644 --- a/src/Canvas/gui_mgr.cxx +++ b/src/Canvas/gui_mgr.cxx @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -94,7 +95,6 @@ GUIMgr::GUIMgr(): PropertyBasedMgr("/sim/gui/canvas", "window", &windowFactory), _event_handler( new GUIEventHandler(this) ), _transform( new osg::MatrixTransform ), - _geode_windows( new osg::Geode ), _width(_props, "size[0]"), _height(_props, "size[1]"), _last_push(-1) @@ -104,18 +104,31 @@ GUIMgr::GUIMgr(): osg::Camera* camera = flightgear::getGUICamera( flightgear::CameraGroup::getDefault() ); assert(camera); + camera->addChild(_transform); osg::Viewport* vp = camera->getViewport(); handleResize(vp->x(), vp->y(), vp->width(), vp->height()); - _transform->addChild(_geode_windows); - camera->addChild(_transform); - Canvas::addPlacementFactory ( "window", boost::bind(&GUIMgr::addPlacement, this, _1, _2) ); + + osg::StateSet* stateSet = _transform->getOrCreateStateSet(); + stateSet->setDataVariance(osg::Object::STATIC); + stateSet->setRenderBinDetails(1000, "RenderBin"); + + // speed optimization? + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + stateSet->setAttribute(new osg::BlendFunc( + osg::BlendFunc::SRC_ALPHA, + osg::BlendFunc::ONE_MINUS_SRC_ALPHA) + ); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateSet->setMode(GL_FOG, osg::StateAttribute::OFF); + stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); } //------------------------------------------------------------------------------ @@ -141,9 +154,9 @@ void GUIMgr::shutdown() //------------------------------------------------------------------------------ void GUIMgr::elementCreated(PropertyBasedElementPtr element) { - _geode_windows->addDrawable + _transform->addChild ( - static_cast(element.get())->getDrawable() + static_cast(element.get())->getGroup() ); } diff --git a/src/Canvas/gui_mgr.hxx b/src/Canvas/gui_mgr.hxx index 6b010a020..76722ec7d 100644 --- a/src/Canvas/gui_mgr.hxx +++ b/src/Canvas/gui_mgr.hxx @@ -51,7 +51,6 @@ class GUIMgr: protected: osg::ref_ptr _event_handler; osg::ref_ptr _transform; - osg::ref_ptr _geode_windows; simgear::PropertyObject _width, _height; diff --git a/src/Canvas/property_based_mgr.cxx b/src/Canvas/property_based_mgr.cxx index 1d57228df..d02e7ed6f 100644 --- a/src/Canvas/property_based_mgr.cxx +++ b/src/Canvas/property_based_mgr.cxx @@ -100,6 +100,12 @@ void PropertyBasedMgr::childRemoved( SGPropertyNode * parent, _elements[index].reset(); } +//------------------------------------------------------------------------------ +const SGPropertyNode* PropertyBasedMgr::getPropertyRoot() const +{ + return _props; +} + //------------------------------------------------------------------------------ PropertyBasedMgr::PropertyBasedMgr( const std::string& path_root, const std::string& name_elements, diff --git a/src/Canvas/property_based_mgr.hxx b/src/Canvas/property_based_mgr.hxx index 904b3c619..e80f85cfd 100644 --- a/src/Canvas/property_based_mgr.hxx +++ b/src/Canvas/property_based_mgr.hxx @@ -43,6 +43,8 @@ class PropertyBasedMgr: virtual void elementCreated(PropertyBasedElementPtr element) {} + virtual const SGPropertyNode* getPropertyRoot() const; + protected: typedef boost::function diff --git a/src/Canvas/rect.hxx b/src/Canvas/rect.hxx index b3b42cc4e..f140cebf2 100644 --- a/src/Canvas/rect.hxx +++ b/src/Canvas/rect.hxx @@ -49,11 +49,21 @@ namespace canvas T width() const { return _x2 - _x1; } T height() const { return _y2 - _y1; } + void setX(T x) { T w = width(); _x1 = x; _x2 = x + w; } + void setY(T y) { T h = height(); _y1 = y; _y2 = y + h; } + void setWidth(T w) { _x2 = _x1 + w; } + void setHeight(T h) { _y2 = _y1 + h; } + T l() const { return _x1; } T r() const { return _x2; } T t() const { return _y1; } T b() const { return _y2; } + void setLeft(T l) { _x1 = l; } + void setRight(T r) { _x2 = r; } + void setTop(T t) { _y1 = t; } + void setBottom(T b) { _y2 = b; } + bool contains(T x, T y) const { return _x1 <= x && x <= _x2 diff --git a/src/Canvas/window.cxx b/src/Canvas/window.cxx index 304f0168c..43c9a1654 100644 --- a/src/Canvas/window.cxx +++ b/src/Canvas/window.cxx @@ -19,164 +19,78 @@ #include "window.hxx" #include -#include -#include -#include #include #include -/** - * Callback to enable/disable rendering of canvas displayed inside windows - */ -class CullCallback: - public osg::Drawable::CullCallback -{ - public: - CullCallback(Canvas::CameraCullCallback* camera_cull); - - private: - Canvas::CameraCullCallback *_camera_cull; - - virtual bool cull( osg::NodeVisitor* nv, - osg::Drawable* drawable, - osg::RenderInfo* renderInfo ) const; -}; - -//------------------------------------------------------------------------------ -CullCallback::CullCallback(Canvas::CameraCullCallback* camera_cull): - _camera_cull( camera_cull ) -{ - -} - -//------------------------------------------------------------------------------ -bool CullCallback::cull( osg::NodeVisitor* nv, - osg::Drawable* drawable, - osg::RenderInfo* renderInfo ) const -{ - _camera_cull->enableRendering(); - return false; -} - namespace canvas { //---------------------------------------------------------------------------- Window::Window(SGPropertyNode* node): PropertyBasedElement(node), - _dirty(true), - _geometry( new osg::Geometry ), - _vertices( new osg::Vec3Array(4) ), - _tex_coords( new osg::Vec2Array(4) ), - _x(node, "x"), - _y(node, "y"), - _width(node, "size[0]"), - _height(node, "size[1]") + _image(node) { - _x = 50; - _y = 100; - _width = 400; - _height = 300; + // TODO probably better remove default position and size + node->setFloatValue("x", 50); + node->setFloatValue("y", 100); + node->setFloatValue("size[0]", 400); + node->setFloatValue("size[1]", 300); - _geometry->setVertexArray(_vertices); - _geometry->setTexCoordArray(0,_tex_coords); - - osg::Vec4Array* colors = new osg::Vec4Array(1); - (*colors)[0].set(1.0f,1.0f,1.0,1.0f); - _geometry->setColorArray(colors); - _geometry->setColorBinding(osg::Geometry::BIND_OVERALL); - - _geometry->addPrimitiveSet( - new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4) - ); - _geometry->setDataVariance(osg::Object::DYNAMIC); - - osg::StateSet* stateSet = _geometry->getOrCreateStateSet(); - stateSet->setRenderBinDetails(1000, "RenderBin"); - - // speed optimization? - stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); - stateSet->setAttribute(new osg::BlendFunc( - osg::BlendFunc::SRC_ALPHA, - osg::BlendFunc::ONE_MINUS_SRC_ALPHA) - ); - stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); - stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - stateSet->setMode(GL_FOG, osg::StateAttribute::OFF); - stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); - stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + node->setFloatValue("source/right", 1); + node->setFloatValue("source/bottom", 1); + node->setBoolValue("source/normalized", true); } //---------------------------------------------------------------------------- Window::~Window() { - BOOST_FOREACH(osg::Node* parent, _geometry->getParents()) + BOOST_FOREACH(osg::Group* parent, getGroup()->getParents()) { - osg::Geode* geode = dynamic_cast(parent); - if( geode ) - geode->removeDrawable(_geometry); + parent->removeChild(getGroup()); } } //---------------------------------------------------------------------------- void Window::update(double delta_time_sec) { - if( !_dirty ) - return; - _dirty = false; - - _region.set(_x, _y, _width, _height); - - int z = 0; // TODO do we need to use z for depth ordering? - - (*_vertices)[0].set(_region.l(), _region.t(), z); - (*_vertices)[1].set(_region.r(), _region.t(), z); - (*_vertices)[2].set(_region.r(), _region.b(), z); - (*_vertices)[3].set(_region.l(), _region.b(), z); - - float l = 0, t = 1, b = 0, r = 1; - (*_tex_coords)[0].set(l,t); - (*_tex_coords)[1].set(r,t); - (*_tex_coords)[2].set(r,b); - (*_tex_coords)[3].set(l,b); - - _geometry->dirtyDisplayList(); + _image.update(delta_time_sec); } //---------------------------------------------------------------------------- - void Window::valueChanged (SGPropertyNode * node) + void Window::valueChanged(SGPropertyNode * node) { - if( node->getParent() != _node ) - return; + _image.valueChanged(node); + } - const std::string& name = node->getNameString(); - if( name == "x" || name == "y" || name == "size" ) - _dirty = true; + //---------------------------------------------------------------------------- + osg::Group* Window::getGroup() + { + return _image.getMatrixTransform(); + } + + //---------------------------------------------------------------------------- + const Rect& Window::getRegion() const + { + return _image.getRegion(); } //---------------------------------------------------------------------------- void Window::setCanvas(CanvasPtr canvas) { - _canvas = canvas; - _geometry->getOrCreateStateSet() - ->setTextureAttribute(0, canvas ? canvas->getTexture() : 0); - _geometry->dirtyDisplayList(); - _geometry->setCullCallback( - canvas ? new CullCallback(canvas->getCameraCullCallback()) : 0 - ); + _image.setCanvas(canvas); } //---------------------------------------------------------------------------- CanvasWeakPtr Window::getCanvas() const { - return _canvas; + return _image.getCanvas(); } //---------------------------------------------------------------------------- bool Window::handleMouseEvent(const MouseEvent& event) { - if( !_canvas.expired() ) - return _canvas.lock()->handleMouseEvent(event); + if( !getCanvas().expired() ) + return getCanvas().lock()->handleMouseEvent(event); else return false; } diff --git a/src/Canvas/window.hxx b/src/Canvas/window.hxx index 647bea1ae..3a94f4c8e 100644 --- a/src/Canvas/window.hxx +++ b/src/Canvas/window.hxx @@ -20,7 +20,7 @@ #define CANVAS_WINDOW_HXX_ #include "property_based_element.hxx" -#include "rect.hxx" +#include #include #include @@ -40,8 +40,8 @@ namespace canvas virtual void update(double delta_time_sec); virtual void valueChanged (SGPropertyNode * node); - osg::Drawable* getDrawable() { return _geometry; } - const Rect& getRegion() const { return _region; } + osg::Group* getGroup(); + const Rect& getRegion() const; void setCanvas(CanvasPtr canvas); CanvasWeakPtr getCanvas() const; @@ -50,17 +50,7 @@ namespace canvas protected: - bool _dirty; - - osg::ref_ptr _geometry; - osg::ref_ptr _vertices; - osg::ref_ptr _tex_coords; - - simgear::PropertyObject _x, _y, - _width, _height; - Rect _region; - - CanvasWeakPtr _canvas; + Image _image; }; } // namespace canvas diff --git a/src/GUI/CanvasWidget.cxx b/src/GUI/CanvasWidget.cxx index fea0f150f..1db2f9391 100644 --- a/src/GUI/CanvasWidget.cxx +++ b/src/GUI/CanvasWidget.cxx @@ -32,7 +32,7 @@ CanvasWidget::CanvasWidget( int x, int y, } // Get the first unused canvas slot - SGPropertyNode* canvas_root = fgGetNode("/canvas", true); + SGPropertyNode* canvas_root = fgGetNode("/canvas/by-index", true); for(int index = 0;; ++index) { if( !canvas_root->getChild("texture", index) )