00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef SIMGEAR_EFFECTBUILDER_HXX
00018 #define SIMGEAR_EFFECTBUILDER_HXX 1
00019
00020 #include <algorithm>
00021 #include <iterator>
00022 #include <map>
00023 #include <string>
00024 #include <cstring>
00025
00026 #include <osgDB/Registry>
00027
00028 #include <boost/bind.hpp>
00029 #include <boost/multi_index_container.hpp>
00030 #include <boost/multi_index/member.hpp>
00031 #include <boost/multi_index/ordered_index.hpp>
00032
00033 #include <simgear/math/SGMath.hxx>
00034 #include <simgear/props/AtomicChangeListener.hxx>
00035 #include <simgear/props/props.hxx>
00036 #include <simgear/structure/exception.hxx>
00037 #include <simgear/structure/SGSharedPtr.hxx>
00038 #include <simgear/structure/Singleton.hxx>
00039
00040 #include "Effect.hxx"
00045 namespace simgear
00046 {
00047 class Effect;
00048 class Pass;
00049
00053 template<typename T>
00054 class EffectBuilder : public SGReferenced
00055 {
00056 public:
00057 virtual ~EffectBuilder() {}
00058 virtual T* build(Effect* effect, const SGPropertyNode*,
00059 const osgDB::ReaderWriter::Options* options) = 0;
00060 static T* buildFromType(Effect* effect, const std::string& type,
00061 const SGPropertyNode*props,
00062 const osgDB::ReaderWriter::Options* options)
00063 {
00064 BuilderMap& builderMap = getMap();
00065 typename BuilderMap::iterator iter = builderMap.find(type);
00066 if (iter != builderMap.end())
00067 return iter->second->build(effect, props, options);
00068 else
00069 return 0;
00070 }
00071 struct Registrar;
00072 friend struct Registrar;
00073 struct Registrar
00074 {
00075 Registrar(const std::string& type, EffectBuilder* builder)
00076 {
00077 getMap().insert(std::make_pair(type, builder));
00078 }
00079 };
00080 protected:
00081 typedef std::map<std::string, SGSharedPtr<EffectBuilder> > BuilderMap;
00082 struct BuilderMapSingleton : public simgear::Singleton<BuilderMapSingleton>
00083 {
00084 BuilderMap _map;
00085 };
00086 static BuilderMap& getMap()
00087 {
00088 return BuilderMapSingleton::instance()->_map;
00089 }
00090 };
00091
00092
00093
00094
00095
00096
00097
00098 namespace effect
00099 {
00100 using boost::multi_index_container;
00101 using namespace boost::multi_index;
00102
00103
00104
00105 struct from{};
00106 struct to{};
00107
00108 template <typename T>
00109 struct EffectNameValue
00110 {
00111
00112 const char* first;
00113 T second;
00114 };
00115
00116
00117
00118
00119 template<typename FromType,typename ToType>
00120 struct bidirectional_map
00121 {
00122 typedef std::pair<FromType,ToType> value_type;
00123
00124
00125
00126
00127
00128
00129 typedef multi_index_container<
00130 value_type,
00131 indexed_by<
00132 ordered_unique<
00133 tag<from>, member<value_type, FromType, &value_type::first> >,
00134 ordered_unique<
00135 tag<to>, member<value_type, ToType, &value_type::second> >
00136 >
00137 > type;
00138 };
00139
00140 template<typename T>
00141 struct EffectPropertyMap
00142 {
00143 typedef typename bidirectional_map<std::string, T>::type BMap;
00144 BMap _map;
00145 template<int N>
00146 EffectPropertyMap(const EffectNameValue<T> (&attrs)[N]);
00147 };
00148
00149 template<typename T>
00150 template<int N>
00151 EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
00152 {
00153 for (int i = 0; i < N; ++i)
00154 _map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second));
00155 }
00156
00157 class BuilderException : public sg_exception
00158 {
00159 public:
00160 BuilderException();
00161 BuilderException(const char* message, const char* origin = 0);
00162 BuilderException(const std::string& message, const std::string& = "");
00163 virtual ~BuilderException() throw();
00164 };
00165 }
00166
00167 template<typename T>
00168 void findAttr(const effect::EffectPropertyMap<T>& pMap,
00169 const char* name,
00170 T& result)
00171 {
00172 using namespace effect;
00173 typename EffectPropertyMap<T>::BMap::iterator itr
00174 = pMap._map.get<from>().find(name);
00175 if (itr == pMap._map.end()) {
00176 throw effect::BuilderException(string("findAttr: could not find attribute ")
00177 + string(name));
00178 } else {
00179 result = itr->second;
00180 }
00181 }
00182
00183 template<typename T>
00184 inline void findAttr(const effect::EffectPropertyMap<T>& pMap,
00185 const std::string& name,
00186 T& result)
00187 {
00188 findAttr(pMap, name.c_str(), result);
00189 }
00190
00191 template<typename T>
00192 void findAttr(const effect::EffectPropertyMap<T>& pMap,
00193 const SGPropertyNode* prop,
00194 T& result)
00195 {
00196 if (!prop)
00197 throw effect::BuilderException("findAttr: empty property");
00198 const char* name = prop->getStringValue();
00199 if (!name)
00200 throw effect::BuilderException("findAttr: no name for lookup");
00201 findAttr(pMap, name, result);
00202 }
00203
00204 template<typename T>
00205 std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
00206 {
00207 using namespace effect;
00208 std::string result;
00209 typename EffectPropertyMap<T>::BMap::template index_iterator<to>::type itr
00210 = pMap._map.get<to>().find(value);
00211 if (itr != pMap._map.get<to>().end())
00212 result = itr->first;
00213 return result;
00214 }
00215
00216 template<typename T>
00217 std::string findName(const effect::EffectPropertyMap<T>& pMap, GLenum value)
00218 {
00219 return findName(pMap, static_cast<T>(value));
00220 }
00221
00227 const SGPropertyNode* getEffectPropertyNode(Effect* effect,
00228 const SGPropertyNode* prop);
00233 const SGPropertyNode* getEffectPropertyChild(Effect* effect,
00234 const SGPropertyNode* prop,
00235 const char* name);
00236
00243 std::string getGlobalProperty(const SGPropertyNode* prop);
00244
00245 class PassAttributeBuilder : public SGReferenced
00246 {
00247 protected:
00248 typedef std::map<const std::string, SGSharedPtr<PassAttributeBuilder> >
00249 PassAttrMap;
00250
00251 struct PassAttrMapSingleton : public simgear::Singleton<PassAttrMapSingleton>
00252 {
00253 PassAttrMap passAttrMap;
00254 };
00255 public:
00256 virtual void buildAttribute(Effect* effect, Pass* pass,
00257 const SGPropertyNode* prop,
00258 const osgDB::ReaderWriter::Options* options)
00259 = 0;
00260 static PassAttributeBuilder* find(const std::string& str)
00261 {
00262 PassAttrMap::iterator itr
00263 = PassAttrMapSingleton::instance()->passAttrMap.find(str);
00264 if (itr == PassAttrMapSingleton::instance()->passAttrMap.end())
00265 return 0;
00266 else
00267 return itr->second.ptr();
00268 }
00269 template<typename T> friend struct InstallAttributeBuilder;
00270 };
00271
00272 template<typename T>
00273 struct InstallAttributeBuilder
00274 {
00275 InstallAttributeBuilder(const string& name)
00276 {
00277 PassAttributeBuilder::PassAttrMapSingleton::instance()
00278 ->passAttrMap.insert(make_pair(name, new T));
00279 }
00280 };
00281
00282
00283
00284
00285
00286
00287 bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
00288
00289 namespace effect
00290 {
00294 template<typename T> struct OSGBridge;
00295
00296 template<typename T>
00297 struct OSGBridge<const T> : public OSGBridge<T>
00298 {
00299 };
00300
00301 template<>
00302 struct OSGBridge<osg::Vec3f>
00303 {
00304 typedef SGVec3d sg_type;
00305 static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
00306 };
00307
00308 template<>
00309 struct OSGBridge<osg::Vec3d>
00310 {
00311 typedef SGVec3d sg_type;
00312 static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
00313 };
00314
00315 template<>
00316 struct OSGBridge<osg::Vec4f>
00317 {
00318 typedef SGVec4d sg_type;
00319 static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
00320 };
00321
00322 template<>
00323 struct OSGBridge<osg::Vec4d>
00324 {
00325 typedef SGVec4d sg_type;
00326 static osg::Vec4d getOsgType(const SGVec4d& val) { return toOsg(val); }
00327 };
00328
00329 template<typename Obj, typename OSGParam>
00330 struct OSGFunctor : public OSGBridge<OSGParam>
00331 {
00332 OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
00333 : _obj(obj), _func(func) {}
00334 void operator()(const typename OSGBridge<OSGParam>::sg_type& val) const
00335 {
00336 ((_obj.get())->*_func)(this->getOsgType(val));
00337 }
00338 osg::ref_ptr<Obj>_obj;
00339 void (Obj::*_func)(const OSGParam&);
00340 };
00341
00342 template<typename ObjType, typename OSGParamType>
00343 class ScalarChangeListener
00344 : public SGPropertyChangeListener, public InitializeWhenAdded,
00345 public Effect::Updater
00346 {
00347 public:
00348 typedef void (ObjType::*setter_type)(const OSGParamType);
00349 ScalarChangeListener(ObjType* obj, setter_type setter,
00350 const std::string& propName)
00351 : _obj(obj), _setter(setter)
00352 {
00353 _propName = new std::string(propName);
00354 }
00355 virtual ~ScalarChangeListener()
00356 {
00357 delete _propName;
00358 _propName = 0;
00359 }
00360 void valueChanged(SGPropertyNode* node)
00361 {
00362 _obj->*setter(node->getValue<OSGParamType>());
00363 }
00364 void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
00365 {
00366 SGPropertyNode* listenProp = makeNode(propRoot, *_propName);
00367 delete _propName;
00368 _propName = 0;
00369 if (listenProp)
00370 listenProp->addChangeListener(this, true);
00371 }
00372 private:
00373 osg::ref_ptr<ObjType> _obj;
00374 setter_type _setter;
00375 std::string* _propName;
00376 };
00377
00378 template<typename T, typename Func>
00379 class EffectExtendedPropListener : public InitializeWhenAdded,
00380 public Effect::Updater
00381 {
00382 public:
00383 template<typename Itr>
00384 EffectExtendedPropListener(const Func& func,
00385 const std::string& propName, Itr childNamesBegin,
00386 Itr childNamesEnd)
00387 : _func(func)
00388 {
00389 _propName = new std::string(propName);
00390 _childNames = new std::vector<std::string>(childNamesBegin,
00391 childNamesEnd);
00392 }
00393 virtual ~EffectExtendedPropListener()
00394 {
00395 delete _propName;
00396 delete _childNames;
00397 }
00398 void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
00399 {
00400 SGPropertyNode* parent = propRoot->getNode(*_propName, true);
00401 _propListener
00402 = new ExtendedPropListener<T, Func>(parent, _childNames->begin(),
00403 _childNames->end(),
00404 _func, true);
00405 delete _propName;
00406 _propName = 0;
00407 delete _childNames;
00408 _childNames = 0;
00409 }
00410 private:
00411 std::string* _propName;
00412 std::vector<std::string>* _childNames;
00413 SGSharedPtr<ExtendedPropListener<T, Func> > _propListener;
00414 Func _func;
00415 };
00416
00426 template<typename ObjType, typename OSGParamType>
00427 void
00428 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
00429 void (ObjType::*setter)(const OSGParamType))
00430 {
00431 const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
00432 if (!valProp)
00433 return;
00434 if (valProp->nChildren() == 0) {
00435 obj->*setter(valProp->getValue<OSGParamType>());
00436 } else {
00437 std::string propName = getGlobalProperty(prop);
00438 ScalarChangeListener<ObjType, OSGParamType>* listener
00439 = new ScalarChangeListener<ObjType, OSGParamType>(obj, setter,
00440 propName);
00441 effect->addUpdater(listener);
00442 }
00443 }
00444
00445 template<typename ObjType, typename OSGParamType, typename NameItrType>
00446 void
00447 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
00448 void (ObjType::*setter)(const OSGParamType&),
00449 NameItrType nameItr)
00450 {
00451 typedef typename OSGBridge<OSGParamType>::sg_type sg_type;
00452 const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
00453 if (!valProp)
00454 return;
00455 if (valProp->nChildren() == 0) {
00456 (obj->*setter)(OSGBridge<OSGParamType>
00457 ::getOsgType(valProp->getValue<sg_type>()));
00458 } else {
00459 string listenPropName = getGlobalProperty(valProp);
00460 if (listenPropName.empty())
00461 return;
00462 typedef OSGFunctor<ObjType, OSGParamType> Functor;
00463 Effect::Updater* listener
00464 = new EffectExtendedPropListener<sg_type, Functor>
00465 (Functor(obj, setter), listenPropName, nameItr,
00466 nameItr + props::NumComponents<sg_type>::num_components);
00467 effect->addUpdater(listener);
00468 }
00469 }
00470
00471 extern const char* colorFields[];
00472 }
00473 }
00474 #endif