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"
22 #include <osg/Drawable>
26 const std::string NAME_TRANSFORM = "tf";
27 const std::string NAME_COLOR = "color";
28 const std::string NAME_COLOR_FILL = "color-fill";
30 //----------------------------------------------------------------------------
36 //----------------------------------------------------------------------------
37 SGPropertyNode* Element::getPropertyNode()
42 //----------------------------------------------------------------------------
43 void Element::update(double dt)
45 if( _transform_dirty )
48 for( size_t i = 0; i < _transform_types.size(); ++i )
50 // Skip unused indizes...
51 if( _transform_types[i] == TT_NONE )
54 SGPropertyNode* tf_node = _node->getChild("tf", i, true);
56 // Build up the matrix representation of the current transform node
58 switch( _transform_types[i] )
61 tf = osg::Matrix( tf_node->getDoubleValue("a", 1),
62 tf_node->getDoubleValue("b", 0), 0, 0,
64 tf_node->getDoubleValue("c", 0),
65 tf_node->getDoubleValue("d", 1), 0, 0,
68 tf_node->getDoubleValue("e", 0),
69 tf_node->getDoubleValue("f", 0), 0, 1 );
72 tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("tx", 0),
73 tf_node->getDoubleValue("ty", 0),
77 tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
81 float sx = tf_node->getDoubleValue("sx", 1);
82 // sy defaults to sx...
83 tf.makeScale( sx, tf_node->getDoubleValue("sy", sx), 1 );
91 _transform->setMatrix(m);
92 _transform_dirty = false;
95 if( _attributes_dirty & COLOR )
97 colorChanged( osg::Vec4( _color[0]->getFloatValue(),
98 _color[1]->getFloatValue(),
99 _color[2]->getFloatValue(),
101 _attributes_dirty &= ~COLOR;
104 if( _attributes_dirty & COLOR_FILL )
106 colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
107 _color_fill[1]->getFloatValue(),
108 _color_fill[2]->getFloatValue(),
110 _attributes_dirty &= ~COLOR_FILL;
113 if( _drawable && (_attributes_dirty & BOUNDING_BOX) )
115 _bounding_box[0]->setFloatValue(_drawable->getBound()._min.x());
116 _bounding_box[1]->setFloatValue(_drawable->getBound()._min.y());
117 _bounding_box[2]->setFloatValue(_drawable->getBound()._max.x());
118 _bounding_box[3]->setFloatValue(_drawable->getBound()._max.y());
120 _attributes_dirty &= ~BOUNDING_BOX;
124 //----------------------------------------------------------------------------
125 osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
130 //----------------------------------------------------------------------------
131 Element::Element(SGPropertyNode* node, uint32_t attributes_used):
134 _attributes_used( attributes_used ),
135 _attributes_dirty( 0 ),
136 _transform_dirty( false ),
137 _transform( new osg::MatrixTransform )
140 _node->addChangeListener(this);
142 if( _attributes_used & COLOR )
143 linkColorNodes("color", _color, osg::Vec4f(0,1,0,1));
144 if( _attributes_used & COLOR_FILL )
145 linkColorNodes("color-fill", _color_fill);
146 if( _attributes_used & BOUNDING_BOX )
148 SGPropertyNode* bb = _node->getChild("bounding-box", 0, true);
149 _bounding_box[0] = bb->getChild("x-min", 0, true);
150 _bounding_box[1] = bb->getChild("y-min", 0, true);
151 _bounding_box[2] = bb->getChild("x-max", 0, true);
152 _bounding_box[3] = bb->getChild("y-max", 0, true);
159 "New canvas element " << node->getPath()
163 //----------------------------------------------------------------------------
164 void Element::linkColorNodes( const char* name,
165 SGPropertyNode** nodes,
166 const osg::Vec4& def )
168 // Don't tie to allow the usage of aliases
169 SGPropertyNode* color = _node->getChild(name, 0, true);
171 static const char* color_names[] = {"red", "green", "blue"};
172 for( size_t i = 0; i < sizeof(color_names)/sizeof(color_names[0]); ++i )
177 color->getFloatValue(color_names[i], def[i])
179 nodes[i] = color->getChild(color_names[i]);
183 //----------------------------------------------------------------------------
184 void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
186 if( parent == _node )
188 if( child->getNameString() == NAME_TRANSFORM )
190 if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
191 _transform_types.resize( child->getIndex() + 1 );
193 _transform_types[ child->getIndex() ] = TT_NONE;
194 _transform_dirty = true;
199 else if( parent->getParent() == _node
200 && parent->getNameString() == NAME_TRANSFORM )
202 assert(parent->getIndex() < static_cast<int>(_transform_types.size()));
204 const std::string& name = child->getNameString();
206 TransformType& type = _transform_types[parent->getIndex()];
208 if( name == "a" || name == "b" || name == "c"
209 || name == "d" || name == "e" || name == "f" )
211 else if( name == "tx" || name == "ty" )
213 else if( name == "rot" )
215 else if( name == "sx" || name == "sy" )
222 "Unknown transform element " << child->getPath()
225 _transform_dirty = true;
229 //----------------------------------------------------------------------------
230 void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
232 if( parent != _node )
235 if( child->getNameString() == NAME_TRANSFORM )
237 assert(child->getIndex() < static_cast<int>(_transform_types.size()));
238 _transform_types[ child->getIndex() ] = TT_NONE;
240 while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
241 _transform_types.pop_back();
243 _transform_dirty = true;
249 //----------------------------------------------------------------------------
250 void Element::valueChanged(SGPropertyNode* child)
252 SGPropertyNode *parent = child->getParent();
253 if( parent->getParent() == _node )
255 if( parent->getNameString() == NAME_TRANSFORM )
256 _transform_dirty = true;
257 else if( parent->getNameString() == NAME_COLOR )
258 _attributes_dirty |= COLOR;
259 else if( parent->getNameString() == NAME_COLOR_FILL )
260 _attributes_dirty |= COLOR_FILL;
266 } // namespace canvas