#include <simgear/canvas/CanvasEvent.hxx>
#include <simgear/props/PropertyBasedElement.hxx>
#include <simgear/misc/stdint.hxx> // for uint32_t
-#include <simgear/nasal/cppbind/Ghost.hxx>
#include <osg/BoundingBox>
#include <osg/MatrixTransform>
#include <boost/bind.hpp>
#include <boost/function.hpp>
+#include <boost/type_traits/is_base_of.hpp>
namespace osg
{
public PropertyBasedElement
{
public:
+
+ /**
+ * Store pointer to window as user data
+ */
+ class OSGUserData:
+ public osg::Referenced
+ {
+ public:
+ ElementPtr element;
+ OSGUserData(ElementPtr element);
+ };
+
typedef boost::function<bool(Element&, const SGPropertyNode*)>
StyleSetterFunc;
typedef boost::function<void(Element&, const SGPropertyNode*)>
{
StyleSetter setter; ///!< Function(s) for setting this style
std::string type; ///!< Interpolation type
+ bool inheritable; ///!< Whether children can inherit this style from
+ /// their parents
};
/**
- * Remove the property listener of the element.
- *
- * You will need to call the appropriate methods (#childAdded,
- * #childRemoved, #valueChanged) yourself to ensure the element still
- * receives the needed events.
+ * Coordinate reference frame (eg. "clip" property)
*/
- void removeListener();
+ enum ReferenceFrame
+ {
+ GLOBAL, ///!< Global coordinates
+ PARENT, ///!< Coordinates relative to parent coordinate frame
+ LOCAL ///!< Coordinates relative to local coordinates (parent
+ /// coordinates with local transformations applied)
+ };
/**
*
*/
virtual ~Element() = 0;
+ virtual void setSelf(const PropertyBasedElementPtr& self);
+ virtual void onDestroy();
+
ElementWeakPtr getWeakPtr() const;
+ ElementPtr getParent();
/**
* Called every frame to update internal state
*/
virtual void update(double dt);
- naRef addEventListener(const nasal::CallContext& ctx);
+ bool addEventListener(const std::string& type, const EventListener& cb);
+ virtual void clearEventListener();
virtual bool accept(EventVisitor& visitor);
virtual bool ascend(EventVisitor& visitor);
virtual bool handleEvent(canvas::EventPtr event);
- virtual bool hitBound( const osg::Vec2f& pos,
+ /**
+ *
+ * @param global_pos Position in global (canvas) coordinate frame
+ * @param parent_pos Position in parent coordinate frame
+ * @param local_pos Position in local (element) coordinate frame
+ */
+ virtual bool hitBound( const osg::Vec2f& global_pos,
+ const osg::Vec2f& parent_pos,
const osg::Vec2f& local_pos ) const;
/**
- * Get whether the element is visible or hidden (Can be changed with
- * setting property "visible" accordingly).
+ * Set visibility of the element.
+ */
+ void setVisible(bool visible);
+
+ /**
+ * Get whether the element is visible or hidden.
*/
bool isVisible() const;
- osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
+ osg::MatrixTransform* getMatrixTransform();
+ osg::MatrixTransform const* getMatrixTransform() const;
+
+ /**
+ * Transform position to local coordinages.
+ */
+ osg::Vec2f posToLocal(const osg::Vec2f& pos) const;
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
SGPropertyNode * child );
virtual void valueChanged(SGPropertyNode * child);
- virtual bool setStyle(const SGPropertyNode* child);
+ virtual bool setStyle( const SGPropertyNode* child,
+ const StyleInfo* style_info = 0 );
/**
* Set clipping shape
*/
void setClip(const std::string& clip);
+ /**
+ * Clipping coordinates reference frame
+ */
+ void setClipFrame(ReferenceFrame rf);
+
/**
* Write the given bounding box to the property tree
*/
*/
virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
+ /**
+ * Get the transformation matrix (product of all transforms)
+ */
+ osg::Matrix getMatrix() const;
+
+ /**
+ * Create an canvas Element
+ *
+ * @tparam Derived Type of element (needs to derive from Element)
+ */
+ template<typename Derived>
+ static
+ typename boost::enable_if<
+ boost::is_base_of<Element, Derived>,
+ ElementPtr
+ >::type create( const CanvasWeakPtr& canvas,
+ const SGPropertyNode_ptr& node,
+ const Style& style,
+ Element* parent )
+ {
+ ElementPtr el( new Derived(canvas, node, style, parent) );
+ el->setSelf(el);
+ return el;
+ }
+
protected:
enum Attributes
{
- LAST_ATTRIBUTE = 0x0001
+ TRANSFORM = 1,
+ BLEND_FUNC = TRANSFORM << 1,
+ SCISSOR_COORDS = BLEND_FUNC << 1,
+ LAST_ATTRIBUTE = SCISSOR_COORDS << 1
};
enum TransformType
TT_SCALE
};
+ class RelativeScissor;
+
CanvasWeakPtr _canvas;
Element *_parent;
- uint32_t _attributes_dirty;
+ mutable uint32_t _attributes_dirty;
- bool _transform_dirty;
- osg::ref_ptr<osg::MatrixTransform> _transform;
- std::vector<TransformType> _transform_types;
+ osg::observer_ptr<osg::MatrixTransform> _transform;
+ std::vector<TransformType> _transform_types;
Style _style;
std::vector<SGPropertyNode_ptr> _bounding_box;
+ RelativeScissor *_scissor;
- typedef std::vector<EventListenerPtr> Listener;
+ typedef std::vector<EventListener> Listener;
typedef std::map<Event::Type, Listener> ListenerMap;
ListenerMap _listener;
typedef std::map<std::string, StyleInfo> StyleSetters;
static StyleSetters _style_setters;
+ static void staticInit();
+
Element( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
* @tparam Derived (Derived) class type
*/
template<class Derived>
- bool isInit() const
+ static bool isInit()
{
static bool is_init = false;
if( is_init )
typename T2,
class Derived
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
- const boost::function<void (Derived&, T2)>& setter )
+ const boost::function<void (Derived&, T2)>& setter,
+ bool inheritable = true )
{
StyleInfo& style_info = _style_setters[ name ];
if( !type.empty() )
style_info.type = type;
}
+ // TODO check if changed?
+ style_info.inheritable = inheritable;
StyleSetter* style = &style_info.setter;
while( style->next )
typename T,
class Derived
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
- const boost::function<void (Derived&, T)>& setter )
+ const boost::function<void (Derived&, T)>& setter,
+ bool inheritable = true )
{
- return addStyle<T, T>(name, type, setter);
+ return addStyle<T, T>(name, type, setter, inheritable);
}
template<
typename T,
class Derived
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
- void (Derived::*setter)(T) )
+ void (Derived::*setter)(T),
+ bool inheritable = true )
{
return addStyle<T, T>
(
name,
type,
- boost::function<void (Derived&, T)>(setter)
+ boost::function<void (Derived&, T)>(setter),
+ inheritable
);
}
typename T2,
class Derived
>
+ static
StyleSetterFunc
addStyle( const std::string& name,
const std::string& type,
- void (Derived::*setter)(T2) )
+ void (Derived::*setter)(T2),
+ bool inheritable = true )
{
return addStyle<T1>
(
name,
type,
- boost::function<void (Derived&, T2)>(setter)
+ boost::function<void (Derived&, T2)>(setter),
+ inheritable
);
}
template<
class Derived
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
- void (Derived::*setter)(const std::string&) )
+ void (Derived::*setter)(const std::string&),
+ bool inheritable = true )
{
return addStyle<const char*, const std::string&>
(
name,
type,
- boost::function<void (Derived&, const std::string&)>(setter)
+ boost::function<void (Derived&, const std::string&)>(setter),
+ inheritable
);
}
class Other,
class OtherRef
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
void (Other::*setter)(T),
- OtherRef Derived::*instance_ref )
+ OtherRef Derived::*instance_ref,
+ bool inheritable = true )
{
- return addStyle<T, T>(name, type, bindOther(setter, instance_ref));
+ return addStyle<T, T>
+ (
+ name,
+ type,
+ bindOther(setter, instance_ref),
+ inheritable
+ );
}
template<
class Other,
class OtherRef
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
void (Other::*setter)(T2),
- OtherRef Derived::*instance_ref )
+ OtherRef Derived::*instance_ref,
+ bool inheritable = true )
{
- return addStyle<T1>(name, type, bindOther(setter, instance_ref));
+ return addStyle<T1>
+ (
+ name,
+ type,
+ bindOther(setter, instance_ref),
+ inheritable
+ );
}
template<
class Other,
class OtherRef
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
const boost::function<void (Other&, T2)>& setter,
- OtherRef Derived::*instance_ref )
+ OtherRef Derived::*instance_ref,
+ bool inheritable = true )
{
- return addStyle<T1>(name, type, bindOther(setter, instance_ref));
+ return addStyle<T1>
+ (
+ name,
+ type,
+ bindOther(setter, instance_ref),
+ inheritable
+ );
}
template<
class Other,
class OtherRef
>
+ static
StyleSetter
addStyle( const std::string& name,
const std::string& type,
void (Other::*setter)(const std::string&),
- OtherRef Derived::*instance_ref )
+ OtherRef Derived::*instance_ref,
+ bool inheritable = true )
{
return addStyle<const char*, const std::string&>
(
name,
type,
boost::function<void (Other&, const std::string&)>(setter),
- instance_ref
+ instance_ref,
+ inheritable
);
}
template<typename T, class Derived, class Other, class OtherRef>
+ static
boost::function<void (Derived&, T)>
bindOther( void (Other::*setter)(T), OtherRef Derived::*instance_ref )
{
}
template<typename T, class Derived, class Other, class OtherRef>
+ static
boost::function<void (Derived&, T)>
bindOther( const boost::function<void (Other&, T)>& setter,
OtherRef Derived::*instance_ref )
}
template<typename T1, typename T2, class Derived>
+ static
StyleSetterFuncUnchecked
bindStyleSetter( const std::string& name,
const boost::function<void (Derived&, T2)>& setter )
);
}
+ bool isStyleEmpty(const SGPropertyNode* child) const;
+ bool canApplyStyle(const SGPropertyNode* child) const;
+ bool setStyleImpl( const SGPropertyNode* child,
+ const StyleInfo* style_info = 0 );
+
+ const StyleInfo* getStyleInfo(const std::string& name) const;
+ const StyleSetter* getStyleSetter(const std::string& name) const;
+ const SGPropertyNode* getParentStyle(const SGPropertyNode* child) const;
+
virtual void childAdded(SGPropertyNode * child) {}
virtual void childRemoved(SGPropertyNode * child){}
virtual void childChanged(SGPropertyNode * child){}
};
} // namespace canvas
+
+ template<>
+ struct enum_traits<canvas::Element::ReferenceFrame>
+ {
+ static const char* name()
+ {
+ return "canvas::Element::ReferenceFrame";
+ }
+
+ static canvas::Element::ReferenceFrame defVal()
+ {
+ return canvas::Element::GLOBAL;
+ }
+
+ static bool validate(int frame)
+ {
+ return frame >= canvas::Element::GLOBAL
+ && frame <= canvas::Element::LOCAL;
+ }
+ };
+
} // namespace simgear
#endif /* CANVAS_ELEMENT_HXX_ */