1 // Interface for 2D Canvas elements
3 // Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #ifndef CANVAS_ELEMENT_HXX_
20 #define CANVAS_ELEMENT_HXX_
22 #include <simgear/canvas/canvas_fwd.hxx>
23 #include <simgear/canvas/CanvasEvent.hxx>
24 #include <simgear/props/PropertyBasedElement.hxx>
25 #include <simgear/misc/stdint.hxx> // for uint32_t
26 #include <simgear/nasal/cppbind/Ghost.hxx>
28 #include <osg/BoundingBox>
29 #include <osg/MatrixTransform>
31 #include <boost/bind.hpp>
32 #include <boost/function.hpp>
45 public PropertyBasedElement
48 typedef boost::function<bool(Element&, const SGPropertyNode*)>
50 typedef boost::function<void(Element&, const SGPropertyNode*)>
51 StyleSetterFuncUnchecked;
56 SGSharedPtr<StyleSetter> next;
60 StyleSetter setter; ///!< Function(s) for setting this style
61 std::string type; ///!< Interpolation type
65 * Remove the property listener of the element.
67 * You will need to call the appropriate methods (#childAdded,
68 * #childRemoved, #valueChanged) yourself to ensure the element still
69 * receives the needed events.
71 void removeListener();
76 virtual ~Element() = 0;
78 ElementWeakPtr getWeakPtr() const;
81 * Called every frame to update internal state
83 * @param dt Frame time in seconds
85 virtual void update(double dt);
87 naRef addEventListener(const nasal::CallContext& ctx);
88 virtual void clearEventListener();
90 virtual bool accept(EventVisitor& visitor);
91 virtual bool ascend(EventVisitor& visitor);
92 virtual bool traverse(EventVisitor& visitor);
94 virtual bool handleEvent(canvas::EventPtr event);
96 virtual bool hitBound( const osg::Vec2f& pos,
97 const osg::Vec2f& local_pos ) const;
100 * Get whether the element is visible or hidden (Can be changed with
101 * setting property "visible" accordingly).
103 bool isVisible() const;
105 osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
106 osg::ref_ptr<osg::MatrixTransform const> getMatrixTransform() const;
108 virtual void childAdded( SGPropertyNode * parent,
109 SGPropertyNode * child );
110 virtual void childRemoved( SGPropertyNode * parent,
111 SGPropertyNode * child );
112 virtual void valueChanged(SGPropertyNode * child);
114 virtual bool setStyle(const SGPropertyNode* child);
119 * @note Only "rect(<top>, <right>, <bottom>, <left>)" is supported
120 * @see http://www.w3.org/TR/CSS21/visufx.html#propdef-clip
122 void setClip(const std::string& clip);
125 * Write the given bounding box to the property tree
127 void setBoundingBox(const osg::BoundingBox& bb);
130 * Get bounding box with children/drawables transformed by passed matrix
132 virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
139 LAST_ATTRIBUTE = BLEND_FUNC << 1
151 CanvasWeakPtr _canvas;
154 uint32_t _attributes_dirty;
156 bool _transform_dirty;
157 osg::ref_ptr<osg::MatrixTransform> _transform;
158 std::vector<TransformType> _transform_types;
161 std::vector<SGPropertyNode_ptr> _bounding_box;
163 typedef std::vector<EventListenerPtr> Listener;
164 typedef std::map<Event::Type, Listener> ListenerMap;
166 ListenerMap _listener;
168 typedef std::map<std::string, StyleInfo> StyleSetters;
169 static StyleSetters _style_setters;
171 Element( const CanvasWeakPtr& canvas,
172 const SGPropertyNode_ptr& node,
173 const Style& parent_style,
177 * Returns false on first call and true on any successive call. Use to
178 * perform initialization tasks which are only required once per element
181 * @tparam Derived (Derived) class type
183 template<class Derived>
186 static bool is_init = false;
195 * Register a function for setting a style specified by the given property
197 * @param name Property name
198 * @param type Interpolation type
199 * @param setter Setter function
201 * @tparam T1 Type of value used to retrieve value from property
203 * @tparam T2 Type of value the setter function expects
204 * @tparam Derived Type of class the setter can be applied to
206 * @note T1 needs to be convertible to T2
214 addStyle( const std::string& name,
215 const std::string& type,
216 const boost::function<void (Derived&, T2)>& setter )
218 StyleInfo& style_info = _style_setters[ name ];
221 if( !style_info.type.empty() && type != style_info.type )
226 "changing animation type for '" << name << "': "
227 << style_info.type << " -> " << type
230 style_info.type = type;
233 StyleSetter* style = &style_info.setter;
237 style = style->next = new StyleSetter;
239 style->func = boost::bind
241 &type_match<Derived>::call,
244 bindStyleSetter<T1>(name, setter)
254 addStyle( const std::string& name,
255 const std::string& type,
256 const boost::function<void (Derived&, T)>& setter )
258 return addStyle<T, T>(name, type, setter);
266 addStyle( const std::string& name,
267 const std::string& type,
268 void (Derived::*setter)(T) )
270 return addStyle<T, T>
274 boost::function<void (Derived&, T)>(setter)
284 addStyle( const std::string& name,
285 const std::string& type,
286 void (Derived::*setter)(T2) )
292 boost::function<void (Derived&, T2)>(setter)
300 addStyle( const std::string& name,
301 const std::string& type,
302 void (Derived::*setter)(const std::string&) )
304 return addStyle<const char*, const std::string&>
308 boost::function<void (Derived&, const std::string&)>(setter)
319 addStyle( const std::string& name,
320 const std::string& type,
321 void (Other::*setter)(T),
322 OtherRef Derived::*instance_ref )
324 return addStyle<T, T>(name, type, bindOther(setter, instance_ref));
335 addStyle( const std::string& name,
336 const std::string& type,
337 void (Other::*setter)(T2),
338 OtherRef Derived::*instance_ref )
340 return addStyle<T1>(name, type, bindOther(setter, instance_ref));
351 addStyle( const std::string& name,
352 const std::string& type,
353 const boost::function<void (Other&, T2)>& setter,
354 OtherRef Derived::*instance_ref )
356 return addStyle<T1>(name, type, bindOther(setter, instance_ref));
365 addStyle( const std::string& name,
366 const std::string& type,
367 void (Other::*setter)(const std::string&),
368 OtherRef Derived::*instance_ref )
370 return addStyle<const char*, const std::string&>
374 boost::function<void (Other&, const std::string&)>(setter),
379 template<typename T, class Derived, class Other, class OtherRef>
380 boost::function<void (Derived&, T)>
381 bindOther( void (Other::*setter)(T), OtherRef Derived::*instance_ref )
383 return boost::bind(setter, boost::bind(instance_ref, _1), _2);
386 template<typename T, class Derived, class Other, class OtherRef>
387 boost::function<void (Derived&, T)>
388 bindOther( const boost::function<void (Other&, T)>& setter,
389 OtherRef Derived::*instance_ref )
396 &reference_from_pointer<Other, OtherRef>,
397 boost::bind(instance_ref, _1)
403 template<typename T1, typename T2, class Derived>
404 StyleSetterFuncUnchecked
405 bindStyleSetter( const std::string& name,
406 const boost::function<void (Derived&, T2)>& setter )
411 // We will only call setters with Derived instances, so we can safely
413 boost::bind(&derived_cast<Derived>, _1),
414 boost::bind(&getValue<T1>, _2)
418 virtual void childAdded(SGPropertyNode * child) {}
419 virtual void childRemoved(SGPropertyNode * child){}
420 virtual void childChanged(SGPropertyNode * child){}
422 void setDrawable(osg::Drawable* drawable);
425 * Get stateset of drawable if available or use transform otherwise
427 osg::StateSet* getOrCreateStateSet();
433 osg::ref_ptr<osg::Drawable> _drawable;
435 Element(const Element&);// = delete
437 template<class Derived>
438 static Derived& derived_cast(Element& el)
440 return static_cast<Derived&>(el);
443 template<class T, class SharedPtr>
444 static T& reference_from_pointer(const SharedPtr& p)
446 return *get_pointer(p);
450 * Helper to call a function only of the element type can be converted to
453 * @return Whether the function has been called
455 template<class Derived>
458 static bool call( Element& el,
459 const SGPropertyNode* prop,
460 const StyleSetterFuncUnchecked& func )
462 Derived* d = dynamic_cast<Derived*>(&el);
471 } // namespace canvas
472 } // namespace simgear
474 #endif /* CANVAS_ELEMENT_HXX_ */