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
This commit is contained in:
parent
350d508324
commit
83bbd9e45c
14 changed files with 352 additions and 219 deletions
|
@ -37,6 +37,7 @@ typedef boost::weak_ptr<PropertyBasedElement> PropertyBasedElementWeakPtr;
|
|||
namespace canvas
|
||||
{
|
||||
class Group;
|
||||
class Image;
|
||||
class MouseEvent;
|
||||
|
||||
class Placement;
|
||||
|
|
|
@ -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<Canvas*>(_elements[index].get())->getTexId();
|
||||
return boost::static_pointer_cast<Canvas>(_elements[index]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int CanvasMgr::getCanvasTexId(size_t index) const
|
||||
{
|
||||
CanvasPtr canvas = getCanvas(index);
|
||||
if( canvas )
|
||||
return canvas->getTexId();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <Canvas/canvas.hxx>
|
||||
#include <Canvas/canvas_mgr.hxx>
|
||||
#include <Canvas/property_helper.hxx>
|
||||
#include <osg/Array>
|
||||
#include <osg/Geometry>
|
||||
|
@ -28,43 +30,80 @@
|
|||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
/**
|
||||
* 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<float>& 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<CanvasMgr*>(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
|
||||
|
|
|
@ -20,11 +20,8 @@
|
|||
#define CANVAS_IMAGE_HXX_
|
||||
|
||||
#include "element.hxx"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <Canvas/canvas_fwd.hpp>
|
||||
#include <Canvas/rect.hxx>
|
||||
|
||||
#include <osg/Texture2D>
|
||||
|
||||
|
@ -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<float>& 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<osg::Texture2D> _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<float> _src_rect,
|
||||
_region;
|
||||
};
|
||||
|
||||
} // namespace canvas
|
||||
|
|
|
@ -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
|
||||
(
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <Viewer/CameraGroup.hxx>
|
||||
#include <Viewer/renderer.hxx>
|
||||
|
||||
#include <osg/BlendFunc>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
|
||||
|
@ -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<canvas::Window*>(element.get())->getDrawable()
|
||||
static_cast<canvas::Window*>(element.get())->getGroup()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ class GUIMgr:
|
|||
protected:
|
||||
osg::ref_ptr<GUIEventHandler> _event_handler;
|
||||
osg::ref_ptr<osg::MatrixTransform> _transform;
|
||||
osg::ref_ptr<osg::Geode> _geode_windows;
|
||||
|
||||
simgear::PropertyObject<int> _width,
|
||||
_height;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -43,6 +43,8 @@ class PropertyBasedMgr:
|
|||
|
||||
virtual void elementCreated(PropertyBasedElementPtr element) {}
|
||||
|
||||
virtual const SGPropertyNode* getPropertyRoot() const;
|
||||
|
||||
protected:
|
||||
|
||||
typedef boost::function<PropertyBasedElementPtr(SGPropertyNode*)>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -19,164 +19,78 @@
|
|||
#include "window.hxx"
|
||||
#include <Canvas/canvas.hxx>
|
||||
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgGA/GUIEventHandler>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
/**
|
||||
* 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<osg::Geode*>(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<float>& 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;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define CANVAS_WINDOW_HXX_
|
||||
|
||||
#include "property_based_element.hxx"
|
||||
#include "rect.hxx"
|
||||
#include <Canvas/elements/CanvasImage.hxx>
|
||||
#include <Canvas/MouseEvent.hxx>
|
||||
|
||||
#include <simgear/props/propertyObject.hxx>
|
||||
|
@ -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<int>& getRegion() const { return _region; }
|
||||
osg::Group* getGroup();
|
||||
const Rect<float>& getRegion() const;
|
||||
|
||||
void setCanvas(CanvasPtr canvas);
|
||||
CanvasWeakPtr getCanvas() const;
|
||||
|
@ -50,17 +50,7 @@ namespace canvas
|
|||
|
||||
protected:
|
||||
|
||||
bool _dirty;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> _geometry;
|
||||
osg::ref_ptr<osg::Vec3Array> _vertices;
|
||||
osg::ref_ptr<osg::Vec2Array> _tex_coords;
|
||||
|
||||
simgear::PropertyObject<int> _x, _y,
|
||||
_width, _height;
|
||||
Rect<int> _region;
|
||||
|
||||
CanvasWeakPtr _canvas;
|
||||
Image _image;
|
||||
};
|
||||
} // namespace canvas
|
||||
|
||||
|
|
|
@ -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) )
|
||||
|
|
Loading…
Reference in a new issue