1 // Interface for 2D canvas element
3 // Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "element.hxx"
20 #include <Canvas/property_helper.hxx>
22 #include <osg/Drawable>
30 const std::string NAME_TRANSFORM = "tf";
31 const std::string NAME_COLOR = "color";
32 const std::string NAME_COLOR_FILL = "color-fill";
34 //----------------------------------------------------------------------------
40 //----------------------------------------------------------------------------
41 void Element::update(double dt)
43 if( !_transform->getNodeMask() )
44 // Don't do anything if element is hidden
47 if( _transform_dirty )
50 for( size_t i = 0; i < _transform_types.size(); ++i )
52 // Skip unused indizes...
53 if( _transform_types[i] == TT_NONE )
56 SGPropertyNode* tf_node = _node->getChild("tf", i, true);
58 // Build up the matrix representation of the current transform node
60 switch( _transform_types[i] )
63 tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
64 tf_node->getDoubleValue("m[1]", 0), 0, 0,
66 tf_node->getDoubleValue("m[2]", 0),
67 tf_node->getDoubleValue("m[3]", 1), 0, 0,
70 tf_node->getDoubleValue("m[4]", 0),
71 tf_node->getDoubleValue("m[5]", 0), 0, 1 );
74 tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
75 tf_node->getDoubleValue("t[1]", 0),
79 tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
83 float sx = tf_node->getDoubleValue("s[0]", 1);
84 // sy defaults to sx...
85 tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
93 _transform->setMatrix(m);
94 _transform_dirty = false;
97 if( _attributes_dirty & COLOR )
99 colorChanged( osg::Vec4( _color[0]->getFloatValue(),
100 _color[1]->getFloatValue(),
101 _color[2]->getFloatValue(),
102 _color[3]->getFloatValue() ) );
103 _attributes_dirty &= ~COLOR;
106 if( _attributes_dirty & COLOR_FILL )
108 colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
109 _color_fill[1]->getFloatValue(),
110 _color_fill[2]->getFloatValue(),
111 _color_fill[3]->getFloatValue() ) );
112 _attributes_dirty &= ~COLOR_FILL;
115 if( !_bounding_box.empty() )
119 const osg::BoundingBox& bb = _drawable->getBound();
120 _bounding_box[0]->setFloatValue(bb._min.x());
121 _bounding_box[1]->setFloatValue(bb._min.y());
122 _bounding_box[2]->setFloatValue(bb._max.x());
123 _bounding_box[3]->setFloatValue(bb._max.y());
127 //----------------------------------------------------------------------------
128 osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
133 //----------------------------------------------------------------------------
134 void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
136 if( parent == _node )
138 if( child->getNameString() == NAME_TRANSFORM )
140 if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
141 _transform_types.resize( child->getIndex() + 1 );
143 _transform_types[ child->getIndex() ] = TT_NONE;
144 _transform_dirty = true;
149 else if( parent->getParent() == _node
150 && parent->getNameString() == NAME_TRANSFORM )
152 assert(parent->getIndex() < static_cast<int>(_transform_types.size()));
154 const std::string& name = child->getNameString();
156 TransformType& type = _transform_types[parent->getIndex()];
160 else if( name == "t" )
162 else if( name == "rot" )
164 else if( name == "s" )
167 _transform_dirty = true;
171 //----------------------------------------------------------------------------
172 void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
174 if( parent != _node )
177 if( child->getNameString() == NAME_TRANSFORM )
179 assert(child->getIndex() < static_cast<int>(_transform_types.size()));
180 _transform_types[ child->getIndex() ] = TT_NONE;
182 while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
183 _transform_types.pop_back();
185 _transform_dirty = true;
191 //----------------------------------------------------------------------------
192 void Element::valueChanged(SGPropertyNode* child)
194 SGPropertyNode *parent = child->getParent();
195 if( parent->getParent() == _node )
197 if( parent->getNameString() == NAME_TRANSFORM )
198 _transform_dirty = true;
199 else if( !_color.empty() && _color[0]->getParent() == parent )
200 _attributes_dirty |= COLOR;
201 else if( !_color_fill.empty() && _color_fill[0]->getParent() == parent )
202 _attributes_dirty |= COLOR_FILL;
204 else if( parent == _node )
206 if( child->getNameString() == "update" )
208 else if( child->getNameString() == "visible" )
209 // TODO check if we need another nodemask
210 _transform->setNodeMask( child->getBoolValue() ? 0xffffffff : 0 );
216 //----------------------------------------------------------------------------
217 Element::Element(SGPropertyNode_ptr node, uint32_t attributes_used):
218 _attributes_used( attributes_used ),
219 _attributes_dirty( attributes_used ),
220 _transform_dirty( false ),
221 _transform( new osg::MatrixTransform ),
226 _node->addChangeListener(this);
228 if( _attributes_used & COLOR )
229 linkColorNodes("color", _node, _color, osg::Vec4f(0,1,0,1));
231 if( _attributes_used & COLOR_FILL )
232 linkColorNodes("color-fill", _node, _color_fill, osg::Vec4f(1,0,1,1));
238 "New canvas element " << node->getPath()
242 //----------------------------------------------------------------------------
243 void Element::setDrawable( osg::Drawable* drawable )
245 _drawable = drawable;
248 osg::ref_ptr<osg::Geode> geode = new osg::Geode;
249 geode->addDrawable(_drawable);
250 _transform->addChild(geode);
252 if( _attributes_used & BOUNDING_BOX )
254 SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
255 _bounding_box.resize(4);
256 _bounding_box[0] = bb_node->getChild("min-x", 0, true);
257 _bounding_box[1] = bb_node->getChild("min-y", 0, true);
258 _bounding_box[2] = bb_node->getChild("max-x", 0, true);
259 _bounding_box[3] = bb_node->getChild("max-y", 0, true);
263 } // namespace canvas