]> git.mxchange.org Git - flightgear.git/blob - src/Canvas/elements/element.cxx
Fix Win32 build, hopefully.
[flightgear.git] / src / Canvas / elements / element.cxx
1 // Interface for 2D canvas element
2 //
3 // Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
4 //
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.
9 //
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.
14 //
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.
18
19 #include "element.hxx"
20 #include <cassert>
21
22 #include <osg/Drawable>
23
24 namespace canvas
25 {
26   const std::string NAME_TRANSFORM = "tf";
27   const std::string NAME_COLOR = "color";
28   const std::string NAME_COLOR_FILL = "color-fill";
29
30   //----------------------------------------------------------------------------
31   Element::~Element()
32   {
33
34   }
35
36   //----------------------------------------------------------------------------
37   SGPropertyNode* Element::getPropertyNode()
38   {
39     return _node;
40   }
41
42   //----------------------------------------------------------------------------
43   void Element::update(double dt)
44   {
45     if( _transform_dirty )
46     {
47       osg::Matrix m;
48       for( size_t i = 0; i < _transform_types.size(); ++i )
49       {
50         // Skip unused indizes...
51         if( _transform_types[i] == TT_NONE )
52           continue;
53
54         SGPropertyNode* tf_node = _node->getChild("tf", i, true);
55
56         // Build up the matrix representation of the current transform node
57         osg::Matrix tf;
58         switch( _transform_types[i] )
59         {
60           case TT_MATRIX:
61             tf = osg::Matrix( tf_node->getDoubleValue("a", 1),
62                               tf_node->getDoubleValue("b", 0), 0, 0,
63
64                               tf_node->getDoubleValue("c", 0),
65                               tf_node->getDoubleValue("d", 1), 0, 0,
66
67                               0,    0,    1, 0,
68                               tf_node->getDoubleValue("e", 0),
69                               tf_node->getDoubleValue("f", 0), 0, 1 );
70             break;
71           case TT_TRANSLATE:
72             tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("tx", 0),
73                                           tf_node->getDoubleValue("ty", 0),
74                                           0 ) );
75             break;
76           case TT_ROTATE:
77             tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
78             break;
79           case TT_SCALE:
80           {
81             float sx = tf_node->getDoubleValue("sx", 1);
82             // sy defaults to sx...
83             tf.makeScale( sx, tf_node->getDoubleValue("sy", sx), 1 );
84             break;
85           }
86           default:
87             break;
88         }
89         m.postMult( tf );
90       }
91       _transform->setMatrix(m);
92       _transform_dirty = false;
93     }
94
95     if( _attributes_dirty & COLOR )
96     {
97       colorChanged( osg::Vec4( _color[0]->getFloatValue(),
98                                _color[1]->getFloatValue(),
99                                _color[2]->getFloatValue(),
100                                1 ) );
101       _attributes_dirty &= ~COLOR;
102     }
103
104     if( _attributes_dirty & COLOR_FILL )
105     {
106       colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
107                                    _color_fill[1]->getFloatValue(),
108                                    _color_fill[2]->getFloatValue(),
109                                    1 ) );
110       _attributes_dirty &= ~COLOR_FILL;
111     }
112
113     if( _drawable && (_attributes_dirty & BOUNDING_BOX) )
114     {
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());
119
120       _attributes_dirty &= ~BOUNDING_BOX;
121     }
122   }
123
124   //----------------------------------------------------------------------------
125   osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
126   {
127     return _transform;
128   }
129
130   //----------------------------------------------------------------------------
131   Element::Element(SGPropertyNode* node, uint32_t attributes_used):
132     _node( node ),
133     _drawable( 0 ),
134     _attributes_used( attributes_used ),
135     _attributes_dirty( 0 ),
136     _transform_dirty( false ),
137     _transform( new osg::MatrixTransform )
138   {
139     assert( _node );
140     _node->addChangeListener(this);
141
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 )
147     {
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);
153     }
154
155     SG_LOG
156     (
157       SG_GL,
158       SG_DEBUG,
159       "New canvas element " << node->getPath()
160     );
161   }
162
163   //----------------------------------------------------------------------------
164   void Element::linkColorNodes( const char* name,
165                                 SGPropertyNode** nodes,
166                                 const osg::Vec4& def )
167   {
168     // Don't tie to allow the usage of aliases
169     SGPropertyNode* color = _node->getChild(name, 0, true);
170
171     static const char* color_names[] = {"red", "green", "blue"};
172     for( size_t i = 0; i < sizeof(color_names)/sizeof(color_names[0]); ++i )
173     {
174       color->setFloatValue
175       (
176         color_names[i],
177         color->getFloatValue(color_names[i], def[i])
178       );
179       nodes[i] = color->getChild(color_names[i]);
180     }
181   }
182
183   //----------------------------------------------------------------------------
184   void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
185   {
186     if( parent == _node )
187     {
188       if( child->getNameString() == NAME_TRANSFORM )
189       {
190         if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
191           _transform_types.resize( child->getIndex() + 1 );
192
193         _transform_types[ child->getIndex() ] = TT_NONE;
194         _transform_dirty = true;
195       }
196       else
197         childAdded(child);
198     }
199     else if(    parent->getParent() == _node
200              && parent->getNameString() == NAME_TRANSFORM )
201     {
202       assert(parent->getIndex() < static_cast<int>(_transform_types.size()));
203
204       const std::string& name = child->getNameString();
205
206       TransformType& type = _transform_types[parent->getIndex()];
207
208       if(    name == "a" || name == "b" || name == "c"
209           || name == "d" || name == "e" || name == "f" )
210         type = TT_MATRIX;
211       else if( name == "tx" || name == "ty" )
212         type = TT_TRANSLATE;
213       else if( name == "rot" )
214         type = TT_ROTATE;
215       else if( name == "sx" || name == "sy" )
216         type = TT_SCALE;
217       else
218         SG_LOG
219         (
220           SG_GL,
221           SG_WARN,
222           "Unknown transform element " << child->getPath()
223         );
224
225       _transform_dirty = true;
226     }
227   }
228
229   //----------------------------------------------------------------------------
230   void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
231   {
232     if( parent != _node )
233       return;
234
235     if( child->getNameString() == NAME_TRANSFORM )
236     {
237       assert(child->getIndex() < static_cast<int>(_transform_types.size()));
238       _transform_types[ child->getIndex() ] = TT_NONE;
239
240       while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
241         _transform_types.pop_back();
242
243       _transform_dirty = true;
244     }
245     else
246       childRemoved(child);
247   }
248
249   //----------------------------------------------------------------------------
250   void Element::valueChanged(SGPropertyNode* child)
251   {
252     SGPropertyNode *parent = child->getParent();
253     if( parent->getParent() == _node )
254     {
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;
261     }
262     else
263       childChanged(child);
264   }
265
266 } // namespace canvas