]> git.mxchange.org Git - simgear.git/commitdiff
Prepare effects animation code to use general functor setters
authorTim Moore <timoore33@gmail.com>
Sat, 26 Dec 2009 22:56:21 +0000 (23:56 +0100)
committerTim Moore <timoore33@gmail.com>
Tue, 9 Mar 2010 10:02:56 +0000 (11:02 +0100)
simgear/scene/material/EffectBuilder.hxx

index f86b87f10ec290f8bd83cb2429cc90603b98d2b1..10e8004b1ed7bf3035880ddaa76bc27f255ff69a 100644 (file)
@@ -329,56 +329,109 @@ bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
 namespace effect
 {
 /**
- * Bridge between types stored in properties and what OSG wants.
+ * Bridge between types stored in properties and what OSG or the
+ * effects code want.
  */
-template<typename T> struct OSGBridge;
+template<typename T> struct Bridge;
 
+/**
+ * Default just passes on the same type.
+ *
+ */
 template<typename T>
-struct OSGBridge<const T> : public OSGBridge<T>
+struct Bridge
 {
+    typedef T sg_type;
+    static T get(const T& val) { return val; }
 };
 
+template<typename T>
+struct Bridge<const T> : public Bridge<T>
+{
+};
+
+// Save some typing...
+template<typename InType, typename OutType>
+struct BridgeOSGVec
+{
+    typedef InType sg_type;
+    static OutType get(const InType& val) { return toOsg(val); }
+};
 template<>
-struct OSGBridge<osg::Vec3f>
+struct Bridge<osg::Vec3f> : public BridgeOSGVec<SGVec3d, osg::Vec3f>
 {
-    typedef SGVec3d sg_type;
-    static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
 };
 
 template<>
-struct OSGBridge<osg::Vec3d>
+struct Bridge<osg::Vec3d> : public BridgeOSGVec<SGVec3d, osg::Vec3d>
 {
-    typedef SGVec3d sg_type;
-    static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
 };
 
 template<>
-struct OSGBridge<osg::Vec4f>
+struct Bridge<osg::Vec4f> : public BridgeOSGVec<SGVec4d, osg::Vec4f>
 {
-    typedef SGVec4d sg_type;
-    static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
 };
 
 template<>
-struct OSGBridge<osg::Vec4d>
+struct Bridge<osg::Vec4d> : public BridgeOSGVec<SGVec4d, osg::Vec4d>
 {
-    typedef SGVec4d sg_type;
-    static osg::Vec4d getOsgType(const SGVec4d& val) { return toOsg(val); }
 };
 
+/**
+ * Functor for calling a function on an osg::Referenced object and a
+ * value (e.g., an SGVec4d from a property) which will be converted to
+ * the equivalent OSG type.
+ *
+ * General version, function takes obj, val
+ */
+template<typename Obj, typename OSGParam, typename Func>
+struct OSGFunctor : public Bridge<OSGParam>
+{
+    OSGFunctor(Obj* obj, const Func& func)
+        : _obj(obj), _func(func) {}
+    void operator()(const typename Bridge<OSGParam>::sg_type& val) const
+    {
+        _func(_obj, this->get(val));
+    }
+    osg::ref_ptr<Obj>_obj;
+    const Func _func;
+};
+
+/**
+ * Version which uses a pointer to member function instead.
+ */
 template<typename Obj, typename OSGParam>
-struct OSGFunctor : public OSGBridge<OSGParam>
+struct OSGFunctor<Obj, OSGParam, void (Obj::* const)(const OSGParam&)>
+    : public Bridge<OSGParam>
 {
-    OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
+    typedef void (Obj::*const MemFunc)(const OSGParam&);
+    OSGFunctor(Obj* obj, MemFunc func)
         : _obj(obj), _func(func) {}
-    void operator()(const typename OSGBridge<OSGParam>::sg_type& val) const
+    void operator()(const typename Bridge<OSGParam>::sg_type& val) const
     {
-        ((_obj.get())->*_func)(this->getOsgType(val));
+        (_obj->*_func)(this->get(val));
     }
     osg::ref_ptr<Obj>_obj;
-    void (Obj::*_func)(const OSGParam&);
+    MemFunc _func;
 };
 
+/**
+ * Typical convenience constructors
+ */
+template<typename Obj, typename OSGParam, typename Func>
+OSGFunctor<Obj, OSGParam, Func> make_OSGFunctor(Obj* obj, const Func& func)
+{
+    return OSGFunctor<Obj, OSGParam, Func>(obj, func);
+}
+
+template<typename Obj, typename OSGParam>
+OSGFunctor<Obj, OSGParam, void (Obj::*const)(const OSGParam&)>
+make_OSGFunctor(Obj* obj, void (Obj::*const func)(const OSGParam&))
+{
+    return OSGFunctor<Obj, OSGParam,
+        void (Obj::* const)(const OSGParam&)>(obj, func);
+}
+
 template<typename ObjType, typename OSGParamType>
 class ScalarChangeListener
     : public SGPropertyChangeListener, public InitializeWhenAdded,
@@ -459,6 +512,15 @@ private:
     Func _func;
 };
 
+template<typename T, typename Func, typename Itr>
+Effect::Updater*
+new_EEPropListener(const Func& func, const std::string* propName,
+                   const Itr& namesBegin, const Itr& namesEnd)
+{
+    return new EffectExtendedPropListener<T, Func>
+        (func, 0, namesBegin, namesEnd);
+}
+
 /**
  * Initialize the value and the possible updating of an effect
  * attribute. If the value is specified directly, set it. Otherwise,
@@ -516,24 +578,23 @@ initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
                    void (ObjType::*setter)(const OSGParamType&),
                    NameItrType nameItr, const SGReaderWriterXMLOptions* options)
 {
-    typedef typename OSGBridge<OSGParamType>::sg_type sg_type;
+    typedef typename Bridge<OSGParamType>::sg_type sg_type;
     const int numComponents = props::NumComponents<sg_type>::num_components;
     const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
     if (!valProp)
         return;
     if (valProp->nChildren() == 0) { // Has <use>?
-        (obj->*setter)(OSGBridge<OSGParamType>
-                     ::getOsgType(valProp->getValue<sg_type>()));
+        (obj->*setter)(Bridge<OSGParamType>
+                     ::get(valProp->getValue<sg_type>()));
     } else {
         std::vector<std::string> paramNames
             = getVectorProperties(valProp, options,numComponents, nameItr);
         if (paramNames.empty())
             throw BuilderException();
         std::vector<std::string>::const_iterator pitr = paramNames.begin();
-        typedef OSGFunctor<ObjType, OSGParamType> Functor;
         Effect::Updater* listener
-            =  new EffectExtendedPropListener<sg_type, Functor>
-            (Functor(obj, setter), 0, pitr, pitr + numComponents);
+            =  new_EEPropListener<sg_type>(make_OSGFunctor(obj, setter), 0,
+                                           pitr, pitr + numComponents);
         effect->addUpdater(listener);
     }
 }