]> git.mxchange.org Git - simgear.git/commitdiff
Merge branch 'jmt/waypt'
authorTim Moore <timoore33@gmail.com>
Tue, 30 Mar 2010 09:53:13 +0000 (11:53 +0200)
committerTim Moore <timoore33@gmail.com>
Tue, 30 Mar 2010 09:53:13 +0000 (11:53 +0200)
20 files changed:
Makefile.am
simgear/props/props.cxx
simgear/props/props.hxx
simgear/scene/material/Effect.cxx
simgear/scene/material/Effect.hxx
simgear/scene/material/EffectBuilder.cxx
simgear/scene/material/EffectBuilder.hxx
simgear/scene/material/TextureBuilder.cxx
simgear/scene/material/TextureBuilder.hxx
simgear/scene/material/makeEffect.cxx
simgear/scene/material/mat.cxx
simgear/scene/material/mat.hxx
simgear/scene/model/SGClipGroup.cxx
simgear/scene/model/SGClipGroup.hxx
simgear/scene/model/SGReaderWriterXMLOptions.hxx
simgear/scene/model/model.cxx
simgear/scene/model/model.hxx
simgear/scene/model/modellib.cxx
simgear/scene/sky/cloudfield.cxx
simgear/scene/sky/newcloud.cxx

index a57c42b3a0dd44463020c26eddba3071e34981f7..aac4221ef68f94f4fe973685fa4549a7a57f3379 100644 (file)
@@ -7,9 +7,7 @@ EXTRA_DIST = \
        README.plib \
        README.OpenAL \
        README.OSG \
-       projects \
-       SimGear.dsp \
-       SimGear.dsw
+       projects
 
 SUBDIRS        = simgear
 
index c662eb7f95f808ab54af4f33b4453c08c015063e..acbcc92dfb7ba8a1bdda4aba870c111af24c36db 100644 (file)
@@ -1027,17 +1027,22 @@ SGPropertyNode::getDisplayName (bool simplify) const
 }
 
 
-const char *
+string
 SGPropertyNode::getPath (bool simplify) const
 {
-  // Calculate the complete path only once.
-  if (_parent != 0 && _path.empty()) {
-    _path = _parent->getPath(simplify);
-    _path += '/';
-    _path += getDisplayName(simplify);
+  typedef std::vector<SGConstPropertyNode_ptr> PList;
+  PList pathList;
+  for (const SGPropertyNode* node = this; node->_parent; node = node->_parent)
+    pathList.push_back(node);
+  string result;
+  for (PList::reverse_iterator itr = pathList.rbegin(),
+         rend = pathList.rend();
+       itr != rend;
+       ++itr) {
+    result += '/';
+    result += (*itr)->getDisplayName(simplify);
   }
-
-  return _path.c_str();
+  return result;
 }
 
 props::Type
index 984bb1b5717b37657b03ff9db88714910a39ca4c..b9ba6495e2858d8ce51a4e591931d08608778351 100644 (file)
@@ -994,7 +994,7 @@ public:
   /**
    * Get the path to this node from the root.
    */
-  const char * getPath (bool simplify = false) const;
+  std::string getPath (bool simplify = false) const;
 
 
   /**
@@ -1675,7 +1675,6 @@ private:
   simgear::PropertyList _children;
   simgear::PropertyList _removedChildren;
   std::vector<hash_table *> _linkedNodes;
-  mutable std::string _path;
   mutable std::string _buffer;
   hash_table * _path_cache;
   simgear::props::Type _type;
index 940b1f18b15873bd1722f6460287235aaa21683a..f2bcbcdc619cbbba615011667e3de8b80a0be6cf 100644 (file)
@@ -51,6 +51,7 @@
 #include <osg/RenderInfo>
 #include <osg/ShadeModel>
 #include <osg/StateSet>
+#include <osg/Stencil>
 #include <osg/TexEnv>
 #include <osg/Texture1D>
 #include <osg/Texture2D>
@@ -65,6 +66,7 @@
 #include <osgDB/ReadFile>
 #include <osgDB/Registry>
 
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
@@ -142,7 +144,7 @@ Effect::~Effect()
 }
 
 void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
-               const osgDB::ReaderWriter::Options* options)
+               const SGReaderWriterXMLOptions* options)
 {
     Pass* pass = new Pass;
     tniq->passes.push_back(pass);
@@ -158,6 +160,10 @@ void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
     }
 }
 
+// Default names for vector property components
+const char* vec3Names[] = {"x", "y", "z"};
+const char* vec4Names[] = {"x", "y", "z", "w"};
+
 osg::Vec4f getColor(const SGPropertyNode* prop)
 {
     if (prop->nChildren() == 0) {
@@ -187,12 +193,12 @@ osg::Vec4f getColor(const SGPropertyNode* prop)
 struct LightingBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options);
+                        const SGReaderWriterXMLOptions* options);
 };
 
 void LightingBuilder::buildAttribute(Effect* effect, Pass* pass,
                                      const SGPropertyNode* prop,
-                                     const osgDB::ReaderWriter::Options* options)
+                                     const SGReaderWriterXMLOptions* options)
 {
     const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
     if (!realProp)
@@ -206,7 +212,7 @@ InstallAttributeBuilder<LightingBuilder> installLighting("lighting");
 struct ShadeModelBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -228,7 +234,7 @@ InstallAttributeBuilder<ShadeModelBuilder> installShadeModel("shade-model");
 struct CullFaceBuilder : PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp) {
@@ -253,6 +259,24 @@ struct CullFaceBuilder : PassAttributeBuilder
 
 InstallAttributeBuilder<CullFaceBuilder> installCullFace("cull-face");
 
+struct ColorMaskBuilder : PassAttributeBuilder
+{
+    void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+                        const SGReaderWriterXMLOptions* options)
+    {
+        const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
+        if (!realProp)
+            return;
+
+        ColorMask *mask = new ColorMask;
+        Vec4 m = getColor(realProp);
+        mask->setMask(m.r(), m.g(), m.b(), m.a());
+        pass->setAttributeAndModes(mask);
+    }    
+};
+
+InstallAttributeBuilder<ColorMaskBuilder> installColorMask("color-mask");
+
 EffectNameValue<StateSet::RenderingHint> renderingHintInit[] =
 {
     { "default", StateSet::DEFAULT_BIN },
@@ -265,7 +289,7 @@ EffectPropertyMap<StateSet::RenderingHint> renderingHints(renderingHintInit);
 struct HintBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -281,7 +305,7 @@ InstallAttributeBuilder<HintBuilder> installHint("rendering-hint");
 struct RenderBinBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -308,7 +332,7 @@ InstallAttributeBuilder<RenderBinBuilder> installRenderBin("render-bin");
 struct MaterialBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options);
+                        const SGReaderWriterXMLOptions* options);
 };
 
 EffectNameValue<Material::ColorMode> colorModeInit[] =
@@ -324,7 +348,7 @@ EffectPropertyMap<Material::ColorMode> colorModes(colorModeInit);
 
 void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
                                      const SGPropertyNode* prop,
-                                     const osgDB::ReaderWriter::Options* options)
+                                     const SGReaderWriterXMLOptions* options)
 {
     if (!isAttributeActive(effect, prop))
         return;
@@ -394,7 +418,7 @@ EffectPropertyMap<BlendFunc::BlendFuncMode> blendFuncModes(blendFuncModesInit);
 struct BlendBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -475,6 +499,99 @@ struct BlendBuilder : public PassAttributeBuilder
 
 InstallAttributeBuilder<BlendBuilder> installBlend("blend");
 
+
+EffectNameValue<Stencil::Function> stencilFunctionInit[] =
+{
+    {"never", Stencil::NEVER },
+    {"less", Stencil::LESS},
+    {"equal", Stencil::EQUAL},
+    {"less-or-equal", Stencil::LEQUAL},
+    {"greater", Stencil::GREATER},
+    {"not-equal", Stencil::NOTEQUAL},
+    {"greater-or-equal", Stencil::GEQUAL},
+    {"always", Stencil::ALWAYS}
+};
+
+EffectPropertyMap<Stencil::Function> stencilFunction(stencilFunctionInit);
+
+EffectNameValue<Stencil::Operation> stencilOperationInit[] =
+{
+    {"keep", Stencil::KEEP},
+    {"zero", Stencil::ZERO},
+    {"replace", Stencil::REPLACE},
+    {"increase", Stencil::INCR},
+    {"decrease", Stencil::DECR},
+    {"invert", Stencil::INVERT},
+    {"increase-wrap", Stencil::INCR_WRAP},
+    {"decrease-wrap", Stencil::DECR_WRAP}
+};
+
+EffectPropertyMap<Stencil::Operation> stencilOperation(stencilOperationInit);
+
+struct StencilBuilder : public PassAttributeBuilder
+{
+    void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+                        const SGReaderWriterXMLOptions* options)
+    {
+        if (!isAttributeActive(effect, prop))
+            return;
+
+        const SGPropertyNode* pmode = getEffectPropertyChild(effect, prop,
+                                                             "mode");
+        if (pmode && !pmode->getValue<bool>()) {
+            pass->setMode(GL_STENCIL, StateAttribute::OFF);
+            return;
+        }
+        const SGPropertyNode* pfunction
+            = getEffectPropertyChild(effect, prop, "function");
+        const SGPropertyNode* pvalue
+            = getEffectPropertyChild(effect, prop, "value");
+        const SGPropertyNode* pmask
+            = getEffectPropertyChild(effect, prop, "mask");
+        const SGPropertyNode* psfail
+            = getEffectPropertyChild(effect, prop, "stencil-fail");
+        const SGPropertyNode* pzfail
+            = getEffectPropertyChild(effect, prop, "z-fail");
+        const SGPropertyNode* ppass
+            = getEffectPropertyChild(effect, prop, "pass");
+
+        Stencil::Function func = Stencil::ALWAYS;  // Always pass
+        int ref = 0;
+        unsigned int mask = ~0u;  // All bits on
+        Stencil::Operation sfailop = Stencil::KEEP;  // Keep the old values as default
+        Stencil::Operation zfailop = Stencil::KEEP;
+        Stencil::Operation passop = Stencil::KEEP;
+
+        ref_ptr<Stencil> stencilFunc = new Stencil;
+
+        if (pfunction)
+            findAttr(stencilFunction, pfunction, func);
+        if (pvalue)
+            ref = pvalue->getIntValue();
+        if (pmask) 
+            mask = pmask->getIntValue();
+
+        if (psfail)
+            findAttr(stencilOperation, psfail, sfailop);
+        if (pzfail)
+            findAttr(stencilOperation, pzfail, zfailop);
+        if (ppass)
+            findAttr(stencilOperation, ppass, passop);
+
+        // Set the stencil operation
+        stencilFunc->setFunction(func, ref, mask);
+
+        // Set the operation, s-fail, s-pass/z-fail, s-pass/z-pass
+        stencilFunc->setOperation(sfailop, zfailop, passop);
+
+        // Add the operation to pass
+        pass->setAttributeAndModes(stencilFunc.get());
+    }
+};
+
+InstallAttributeBuilder<StencilBuilder> installStencil("stencil");
+
+
 EffectNameValue<AlphaFunc::ComparisonFunction> alphaComparisonInit[] =
 {
     {"never", AlphaFunc::NEVER},
@@ -492,7 +609,7 @@ alphaComparison(alphaComparisonInit);
 struct AlphaTestBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -603,12 +720,12 @@ void reload_shaders()
 struct ShaderProgramBuilder : PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options);
+                        const SGReaderWriterXMLOptions* options);
 };
 
 void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
                                           const SGPropertyNode* prop,
-                                          const osgDB::ReaderWriter::Options*
+                                          const SGReaderWriterXMLOptions*
                                           options)
 {
     using namespace boost;
@@ -695,22 +812,24 @@ EffectNameValue<Uniform::Type> uniformTypesInit[] =
     {"float-vec3", Uniform::FLOAT_VEC3},
     {"float-vec4", Uniform::FLOAT_VEC4},
     {"sampler-1d", Uniform::SAMPLER_1D},
+    {"sampler-1d-shadow", Uniform::SAMPLER_1D_SHADOW},
     {"sampler-2d", Uniform::SAMPLER_2D},
-    {"sampler-3d", Uniform::SAMPLER_3D}
+    {"sampler-2d-shadow", Uniform::SAMPLER_2D_SHADOW},
+    {"sampler-3d", Uniform::SAMPLER_3D},
+    {"sampler-cube", Uniform::SAMPLER_CUBE}
 };
 EffectPropertyMap<Uniform::Type> uniformTypes(uniformTypesInit);
 
 struct UniformBuilder :public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
         const SGPropertyNode* nameProp = prop->getChild("name");
         const SGPropertyNode* typeProp = prop->getChild("type");
-        const SGPropertyNode* valProp
-            = getEffectPropertyChild(effect, prop, "value");
+        const SGPropertyNode* valProp = prop->getChild("value");
         string name;
         Uniform::Type uniformType = Uniform::FLOAT;
         if (nameProp) {
@@ -749,18 +868,29 @@ struct UniformBuilder :public PassAttributeBuilder
         uniform->setType(uniformType);
         switch (uniformType) {
         case Uniform::FLOAT:
-            uniform->set(valProp->getValue<float>());
+            initFromParameters(effect, valProp, uniform.get(),
+                               static_cast<bool (Uniform::*)(float)>(&Uniform::set),
+                               options);
             break;
         case Uniform::FLOAT_VEC3:
-            uniform->set(toOsg(valProp->getValue<SGVec3d>()));
+            initFromParameters(effect, valProp, uniform.get(),
+                               static_cast<bool (Uniform::*)(const Vec3&)>(&Uniform::set),
+                               vec3Names, options);
             break;
         case Uniform::FLOAT_VEC4:
-            uniform->set(toOsg(valProp->getValue<SGVec4d>()));
+            initFromParameters(effect, valProp, uniform.get(),
+                               static_cast<bool (Uniform::*)(const Vec4&)>(&Uniform::set),
+                               vec4Names, options);
             break;
         case Uniform::SAMPLER_1D:
         case Uniform::SAMPLER_2D:
         case Uniform::SAMPLER_3D:
-            uniform->set(valProp->getValue<int>());
+        case Uniform::SAMPLER_1D_SHADOW:
+        case Uniform::SAMPLER_2D_SHADOW:
+        case Uniform::SAMPLER_CUBE:
+            initFromParameters(effect, valProp, uniform.get(),
+                               static_cast<bool (Uniform::*)(int)>(&Uniform::set),
+                               options);
             break;
         default: // avoid compiler warning
             break;
@@ -777,7 +907,7 @@ InstallAttributeBuilder<UniformBuilder> installUniform("uniform");
 struct NameBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         // name can't use <use>
         string name = prop->getStringValue();
@@ -799,7 +929,7 @@ EffectPropertyMap<PolygonMode::Mode> polygonModeModes(polygonModeModesInit);
 struct PolygonModeBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -827,7 +957,7 @@ InstallAttributeBuilder<PolygonModeBuilder> installPolygonMode("polygon-mode");
 struct VertexProgramTwoSideBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -844,7 +974,7 @@ installTwoSide("vertex-program-two-side");
 struct VertexProgramPointSizeBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -874,7 +1004,7 @@ EffectPropertyMap<Depth::Function> depthFunction(depthFunctionInit);
 struct DepthBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options)
+                        const SGReaderWriterXMLOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -905,7 +1035,7 @@ struct DepthBuilder : public PassAttributeBuilder
 InstallAttributeBuilder<DepthBuilder> installDepth("depth");
 
 void buildTechnique(Effect* effect, const SGPropertyNode* prop,
-                    const osgDB::ReaderWriter::Options* options)
+                    const SGReaderWriterXMLOptions* options)
 {
     Technique* tniq = new Technique;
     effect->techniques.push_back(tniq);
@@ -1011,7 +1141,7 @@ bool makeParametersFromStateSet(SGPropertyNode* effectRoot, const StateSet* ss)
 
 // Walk the techniques property tree, building techniques and
 // passes.
-bool Effect::realizeTechniques(const osgDB::ReaderWriter::Options* options)
+bool Effect::realizeTechniques(const SGReaderWriterXMLOptions* options)
 {
     if (_isRealized)
         return true;
index 1f33b9e86d61209f7a0b1f6cb5c4a08b7aa64446..0690db3a76a5f17e36334fafd24429a1b778b2e9 100644 (file)
@@ -45,6 +45,7 @@ namespace simgear
 {
 class Technique;
 class Effect;
+class SGReaderWriterXMLOptions;
 
 /**
  * Object to be initialized at some point after an effect -- and its
@@ -89,7 +90,7 @@ public:
     /**
      * Build the techniques from the effect properties.
      */
-    bool realizeTechniques(const osgDB::ReaderWriter::Options* options = 0);
+    bool realizeTechniques(const SGReaderWriterXMLOptions* options = 0);
     /**
      * Updaters that should be derefed when the effect is
      * deleted. Updaters arrange to be run by listening on properties
@@ -144,7 +145,7 @@ protected:
     Cache* _cache;
     friend size_t hash_value(const Key& key);
     friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
-                              const osgDB::ReaderWriter::Options* options);
+                              const SGReaderWriterXMLOptions* options);
     bool _isRealized;
 };
 // Automatic support for boost hash function
@@ -153,11 +154,11 @@ size_t hash_value(const Effect::Key&);
 
 Effect* makeEffect(const std::string& name,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options = 0);
+                   const SGReaderWriterXMLOptions* options = 0);
 
 Effect* makeEffect(SGPropertyNode* prop,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options = 0);
+                   const SGReaderWriterXMLOptions* options = 0);
 
 bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
                                 const osg::StateSet* ss);
index 34f14ac84aed8f862dd0bc7591121465377e16c2..338fc9aa33a34f274598225bc967e7cb89d86e5c 100644 (file)
@@ -2,6 +2,7 @@
 #  include <simgear_config.h>
 #endif
 
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
 
 #include <simgear/math/SGMath.hxx>
@@ -41,13 +42,29 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
         return getEffectPropertyNode(effect, child);
 }
 
-string getGlobalProperty(const SGPropertyNode* prop)
+string getGlobalProperty(const SGPropertyNode* prop,
+                         const SGReaderWriterXMLOptions* options)
 {
     if (!prop)
         return string();
     const SGPropertyNode* useProp = prop->getChild("use");
     if (!useProp)
         return string();
+    string propName = useProp->getStringValue();
+    SGPropertyNode_ptr propRoot;
+    if (propName[0] == '/') {
+        return propName;
+    } else if ((propRoot = options->getPropRoot())) {
+        string result = propRoot->getPath();
+        result.append("/");
+        result.append(propName);
+        return result;
+    } else {
+        throw effect::
+            BuilderException("No property root to use with relative name "
+                             + propName);
+    }
+        
     return useProp->getStringValue();
 }
 
index be4b03452d035e0e89ff8b592bbf78fae61244f5..e9c7b6a97426c1a6726d671c9b9475115a642893 100644 (file)
@@ -33,6 +33,7 @@
 #include <simgear/math/SGMath.hxx>
 #include <simgear/props/AtomicChangeListener.hxx>
 #include <simgear/props/props.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/structure/exception.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/structure/Singleton.hxx>
@@ -46,6 +47,7 @@ namespace simgear
 {
 class Effect;
 class Pass;
+class SGReaderWriterXMLOptions;
 
 /**
  * Builder that returns an object, probably an OSG object.
@@ -56,10 +58,10 @@ class EffectBuilder : public SGReferenced
 public:
     virtual ~EffectBuilder() {}
     virtual T* build(Effect* effect, const SGPropertyNode*,
-                     const osgDB::ReaderWriter::Options* options) = 0;
+                     const SGReaderWriterXMLOptions* options) = 0;
     static T* buildFromType(Effect* effect, const std::string& type,
                             const SGPropertyNode*props,
-                            const osgDB::ReaderWriter::Options* options)
+                            const SGReaderWriterXMLOptions* options)
     {
         BuilderMap& builderMap = getMap();
         typename BuilderMap::iterator iter = builderMap.find(type);
@@ -154,6 +156,21 @@ EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
         _map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second));
 }
 
+// A one-way map that can be initialized using an array
+template<typename T>
+struct SimplePropertyMap
+{
+    typedef std::map<string, T> map_type;
+    map_type _map;
+    template<int N>
+    SimplePropertyMap(const EffectNameValue<T> (&attrs)[N])
+    {
+        for (int i = 0; i < N; ++i)
+        _map.insert(typename map_type::value_type(attrs[i].first,
+                                                  attrs[i].second));
+    }
+};
+
 class BuilderException : public sg_exception
 {
 public:
@@ -201,6 +218,42 @@ void findAttr(const effect::EffectPropertyMap<T>& pMap,
     findAttr(pMap, name, result);
 }
 
+// Versions that don't throw an error
+
+template<typename T>
+const T* findAttr(const effect::EffectPropertyMap<T>& pMap,
+                  const char* name)
+{
+    using namespace effect;
+    typename EffectPropertyMap<T>::BMap::iterator itr
+        = pMap._map.get<from>().find(name);
+    if (itr == pMap._map.end())
+        return 0;
+    else 
+        return &itr->second;
+}
+
+template<typename T>
+const T* findAttr(const effect::SimplePropertyMap<T>& pMap,
+                  const char* name)
+{
+    using namespace effect;
+    typename SimplePropertyMap<T>::map_type::const_iterator itr
+        = pMap._map.find(name);
+    if (itr == pMap._map.end())
+        return 0;
+    else 
+        return &itr->second;
+}
+
+template<typename T, template<class> class Map>
+const T* findAttr(const Map<T>& pMap,
+                     const std::string& name)
+{
+    return findAttr(pMap, name.c_str());
+}
+
+
 template<typename T>
 std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
 {
@@ -240,7 +293,45 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
  * @return empty if prop doesn't contain a <use> clause; otherwise the
  * mentioned node name.
  */
-std::string getGlobalProperty(const SGPropertyNode* prop);
+std::string getGlobalProperty(const SGPropertyNode* prop,
+                              const SGReaderWriterXMLOptions *);
+
+template<typename NameItr>
+std::vector<std::string>
+getVectorProperties(const SGPropertyNode* prop,
+                    const SGReaderWriterXMLOptions *options, size_t vecSize,
+                    NameItr defaultNames)
+{
+    using namespace std;
+    vector<string> result;
+    if (!prop)
+        return result;
+    PropertyList useProps = prop->getChildren("use");
+    if (useProps.size() == 1) {
+        string parentName = useProps[0]->getStringValue();
+        if (parentName.size() == 0 || parentName[0] != '/')
+            parentName = options->getPropRoot()->getPath() + "/" + parentName;
+        if (parentName[parentName.size() - 1] != '/')
+            parentName.append("/");
+        NameItr itr = defaultNames;
+        for (int i = 0; i < vecSize; ++i, ++itr)
+            result.push_back(parentName + *itr);
+    } else if (useProps.size() == vecSize) {
+        string parentName = useProps[0]->getStringValue();
+        parentName += "/";
+        for (PropertyList::const_iterator itr = useProps.begin(),
+                 end = useProps.end();
+             itr != end;
+             ++itr) {
+            string childName = (*itr)->getStringValue();
+            if (childName.size() == 0 || childName[0] != '/')
+                result.push_back(parentName + childName);
+            else
+                result.push_back(childName);
+        }
+    }
+    return result;
+}
 
 class PassAttributeBuilder : public SGReferenced
 {
@@ -255,7 +346,7 @@ protected:
 public:
     virtual void buildAttribute(Effect* effect, Pass* pass,
                                 const SGPropertyNode* prop,
-                                const osgDB::ReaderWriter::Options* options)
+                                const SGReaderWriterXMLOptions* options)
     = 0;
     static PassAttributeBuilder* find(const std::string& str)
     {
@@ -289,64 +380,116 @@ 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 Bridge
+{
+    typedef T sg_type;
+    static T get(const T& val) { return val; }
+};
 
 template<typename T>
-struct OSGBridge<const T> : public OSGBridge<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); }
 };
 
-template<typename Obj, typename OSGParam>
-struct OSGFunctor : public OSGBridge<OSGParam>
+/**
+ * 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 OSGParam, typename Obj, 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 OSGParam, typename Obj>
+struct OSGFunctor<OSGParam, Obj, 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;
 };
 
-template<typename ObjType, typename OSGParamType>
+/**
+ * Typical convenience constructors
+ */
+template<typename OSGParam, typename Obj, typename Func>
+OSGFunctor<OSGParam, Obj, Func> make_OSGFunctor(Obj* obj, const Func& func)
+{
+    return OSGFunctor<OSGParam, Obj, Func>(obj, func);
+}
+
+template<typename OSGParam, typename Obj>
+OSGFunctor<OSGParam, Obj, void (Obj::*const)(const OSGParam&)>
+make_OSGFunctor(Obj* obj, void (Obj::*const func)(const OSGParam&))
+{
+    return OSGFunctor<OSGParam, Obj,
+        void (Obj::* const)(const OSGParam&)>(obj, func);
+}
+
+template<typename OSGParamType, typename ObjType, typename F>
 class ScalarChangeListener
     : public SGPropertyChangeListener, public InitializeWhenAdded,
       public Effect::Updater
 {
 public:
-    typedef void (ObjType::*setter_type)(const OSGParamType);
-    ScalarChangeListener(ObjType* obj, setter_type setter,
+    ScalarChangeListener(ObjType* obj, const F& setter,
                          const std::string& propName)
         : _obj(obj), _setter(setter)
     {
@@ -359,7 +502,7 @@ public:
     }
     void valueChanged(SGPropertyNode* node)
     {
-        _obj->*setter(node->getValue<OSGParamType>());
+        _setter(_obj.get(), node->getValue<OSGParamType>());
     }
     void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
     {
@@ -371,7 +514,7 @@ public:
     }
 private:
     osg::ref_ptr<ObjType> _obj;
-    setter_type _setter;
+    F _setter;
     std::string* _propName;
 };
 
@@ -382,11 +525,12 @@ class EffectExtendedPropListener : public InitializeWhenAdded,
 public:
     template<typename Itr>
     EffectExtendedPropListener(const Func& func,
-                               const std::string& propName, Itr childNamesBegin,
+                               const std::string* propName, Itr childNamesBegin,
                                Itr childNamesEnd)
-        : _func(func)
+        : _propName(0), _func(func)
     {
-        _propName = new std::string(propName);
+        if (propName)
+            _propName = new std::string(*propName);
         _childNames = new std::vector<std::string>(childNamesBegin,
                                                    childNamesEnd);
     }
@@ -397,7 +541,11 @@ public:
     }
     void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
     {
-        SGPropertyNode* parent = propRoot->getNode(*_propName, true);
+        SGPropertyNode* parent = 0;
+        if (_propName)
+            parent = propRoot->getNode(*_propName, true);
+        else
+            parent = propRoot;
         _propListener
             = new ExtendedPropListener<T, Func>(parent, _childNames->begin(),
                                                 _childNames->end(),
@@ -414,6 +562,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,
@@ -422,52 +579,97 @@ private:
  * own <use> tag referring to a property in the global property tree;
  * install a change listener that will set the attribute when the
  * property changes.
+ *
+ * For relative property names, the property root found in options is
+ * used.
  */
-template<typename ObjType, typename OSGParamType>
+template<typename OSGParamType, typename ObjType, typename F>
 void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
-                   void (ObjType::*setter)(const OSGParamType))
+                   const F& setter, const SGReaderWriterXMLOptions* options)
 {
     const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
     if (!valProp)
         return;
     if (valProp->nChildren() == 0) {
-        obj->*setter(valProp->getValue<OSGParamType>());
+        setter(obj, valProp->getValue<OSGParamType>());
     } else {
-        std::string propName = getGlobalProperty(prop);
-        ScalarChangeListener<ObjType, OSGParamType>* listener
-            = new ScalarChangeListener<ObjType, OSGParamType>(obj, setter,
-                                                              propName);
+        std::string propName = getGlobalProperty(valProp, options);
+        ScalarChangeListener<OSGParamType, ObjType, F>* listener
+            = new ScalarChangeListener<OSGParamType, ObjType, F>(obj, setter,
+                                                                 propName);
         effect->addUpdater(listener);
     }
 }
 
-template<typename ObjType, typename OSGParamType, typename NameItrType>
+template<typename OSGParamType, typename ObjType, typename SetterReturn>
+inline void
+initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
+                   SetterReturn (ObjType::*setter)(const OSGParamType),
+                   const SGReaderWriterXMLOptions* options)
+{
+    initFromParameters<OSGParamType>(effect, prop, obj,
+                                     boost::bind(setter, _1, _2), options);
+}
+
+/*
+ * Initialize vector parameters from individual properties.
+ * The parameter may be updated at runtime.
+ *
+ * If the value is specified directly, set it. Otherwise, use the
+ * <use> tag to look at the parameters. Again, if there is a value
+ * there set it directly. Otherwise, the parameter contains one or several
+ * <use> tags. If there is one tag, it is a property that is the root
+ * for the values needed to update the parameter; nameIter holds the
+ * names of the properties relative to the root. If there are several
+ * <use> tags, they each hold the name of the property holding the
+ * value for the corresponding vector member.
+ *
+ * Install a change listener that will set the attribute when the
+ * property changes.
+ *
+ * For relative property names, the property root found in options is
+ * used.
+ */
+template<typename OSGParamType, typename ObjType, typename NameItrType,
+         typename F>
 void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
-                   void (ObjType::*setter)(const OSGParamType&),
-                   NameItrType nameItr)
+                   const F& setter,
+                   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) {
-        (obj->*setter)(OSGBridge<OSGParamType>
-                     ::getOsgType(valProp->getValue<sg_type>()));
+    if (valProp->nChildren() == 0) { // Has <use>?
+        setter(obj, Bridge<OSGParamType>::get(valProp->getValue<sg_type>()));
     } else {
-        string listenPropName = getGlobalProperty(valProp);
-        if (listenPropName.empty())
-            return;
-        typedef OSGFunctor<ObjType, OSGParamType> Functor;
+        std::vector<std::string> paramNames
+            = getVectorProperties(valProp, options,numComponents, nameItr);
+        if (paramNames.empty())
+            throw BuilderException();
+        std::vector<std::string>::const_iterator pitr = paramNames.begin();
         Effect::Updater* listener
-            =  new EffectExtendedPropListener<sg_type, Functor>
-            (Functor(obj, setter), listenPropName, nameItr,
-             nameItr + props::NumComponents<sg_type>::num_components);
+            =  new_EEPropListener<sg_type>(make_OSGFunctor<OSGParamType>
+                                           (obj, setter),
+                                           0, pitr, pitr + numComponents);
         effect->addUpdater(listener);
     }
 }
 
+template<typename OSGParamType, typename ObjType, typename NameItrType,
+         typename SetterReturn>
+inline void
+initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
+                   SetterReturn (ObjType::*setter)(const OSGParamType&),
+                   NameItrType nameItr, const SGReaderWriterXMLOptions* options)
+{
+    initFromParameters<OSGParamType>(effect, prop, obj,
+                                     boost::bind(setter, _1, _2), nameItr,
+                                     options);
+}
 extern const char* colorFields[];
 }
 }
index a924b95571055057d3e378b86ff0ba10ad7a439a..7dc7aed64b1e5d15284b9049eb1757c215ceaeac 100644 (file)
@@ -35,6 +35,7 @@
 #include <boost/tuple/tuple.hpp>
 #include <boost/tuple/tuple_comparison.hpp>
 
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/math/SGMath.hxx>
@@ -50,13 +51,14 @@ using namespace osg;
 using namespace effect;
 
 TexEnvCombine* buildTexEnvCombine(Effect* effect,
-                                  const SGPropertyNode* envProp);
+                                  const SGPropertyNode* envProp,
+                                  const SGReaderWriterXMLOptions* options);
 TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
 
 // Hack to force inclusion of TextureBuilder.cxx in library
 osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
                                             const SGPropertyNode*props,
-                                            const osgDB::ReaderWriter::Options*
+                                            const SGReaderWriterXMLOptions*
                                             options)
 {
     return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
@@ -98,7 +100,7 @@ TexEnv* buildTexEnv(Effect* effect, const SGPropertyNode* prop)
 
 void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
                                         const SGPropertyNode* prop,
-                                        const osgDB::ReaderWriter::Options* options)
+                                        const SGReaderWriterXMLOptions* options)
 {
     if (!isAttributeActive(effect, prop))
         return;
@@ -141,7 +143,8 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
     }
     const SGPropertyNode* combineProp = prop->getChild("texenv-combine");
     TexEnvCombine* combiner = 0;
-    if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp))))
+    if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp,
+                                                       options))))
         pass->setTextureAttributeAndModes(unit, combiner);
     const SGPropertyNode* tgenProp = prop->getChild("texgen");
     TexGen* tgen = 0;
@@ -177,7 +180,7 @@ EffectPropertyMap<Texture::WrapMode> wrapModes(wrapModesInit);
 
 
 TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
-                      const osgDB::ReaderWriter::Options* options,
+                      const SGReaderWriterXMLOptions* options,
                       const string& texType)
 {
     Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
@@ -213,7 +216,7 @@ TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
 }
 
 void setAttrs(const TexTuple& attrs, Texture* tex,
-              const osgDB::ReaderWriter::Options* options)
+              const SGReaderWriterXMLOptions* options)
 {
     const string& imageName = attrs.get<0>();
     if (imageName.empty()) {
@@ -253,7 +256,7 @@ class TexBuilder : public TextureBuilder
 public:
     TexBuilder(const string& texType) : _type(texType) {}
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const osgDB::ReaderWriter::Options* options);
+                   const SGReaderWriterXMLOptions* options);
 protected:
     typedef map<TexTuple, ref_ptr<T> > TexMap;
     TexMap texMap;
@@ -262,7 +265,7 @@ protected:
 
 template<typename T>
 Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
-                              const osgDB::ReaderWriter::Options* options)
+                              const SGReaderWriterXMLOptions* options)
 {
     TexTuple attrs = makeTexTuple(effect, props, options, _type);
     typename TexMap::iterator itr = texMap.find(attrs);
@@ -286,11 +289,11 @@ class WhiteTextureBuilder : public TextureBuilder
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const osgDB::ReaderWriter::Options* options);
+                   const SGReaderWriterXMLOptions* options);
 };
 
 Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
-                                    const osgDB::ReaderWriter::Options* options)
+                                    const SGReaderWriterXMLOptions* options)
 {
     return StateAttributeFactory::instance()->getWhiteTexture();
 }
@@ -304,11 +307,11 @@ class TransparentTextureBuilder : public TextureBuilder
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const osgDB::ReaderWriter::Options* options);
+                   const SGReaderWriterXMLOptions* options);
 };
 
 Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*,
-                                    const osgDB::ReaderWriter::Options* options)
+                                    const SGReaderWriterXMLOptions* options)
 {
     return StateAttributeFactory::instance()->getTransparentTexture();
 }
@@ -368,14 +371,14 @@ class NoiseBuilder : public TextureBuilder
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const osgDB::ReaderWriter::Options* options);
+                   const SGReaderWriterXMLOptions* options);
 protected:
     typedef map<int, ref_ptr<Texture3D> > NoiseMap;
     NoiseMap _noises;
 };
 
 Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
-                             const osgDB::ReaderWriter::Options* options)
+                             const SGReaderWriterXMLOptions* options)
 {
     int texSize = 64;
     const SGPropertyNode* sizeProp = getEffectPropertyChild(effect, props,
@@ -443,7 +446,8 @@ EffectNameValue<TexEnvCombine::OperandParam> opParamInit[] =
 
 EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
 
-TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
+TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp,
+                                  const SGReaderWriterXMLOptions* options)
 {
     if (!isAttributeActive(effect, envProp))
         return 0;
@@ -538,7 +542,8 @@ TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
     const SGPropertyNode* colorNode = envProp->getChild("constant-color");
     if (colorNode)
         initFromParameters(effect, colorNode, result,
-                           &TexEnvCombine::setConstantColor, colorFields);
+                           &TexEnvCombine::setConstantColor, colorFields,
+                           options);
     return result;
 }
 
index ca6c54945f3eb902a88eeb5f10e14e1b1c5fd066..55df27360e178bb531a9d83afc0502050917ab9e 100644 (file)
@@ -29,13 +29,13 @@ public:
     // Hack to force inclusion of TextureBuilder.cxx in library
     static osg::Texture* buildFromType(Effect* effect, const std::string& type,
                                        const SGPropertyNode*props,
-                                       const osgDB::ReaderWriter::Options* options);
+                                       const SGReaderWriterXMLOptions* options);
 };
 
 struct TextureUnitBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const osgDB::ReaderWriter::Options* options);
+                        const SGReaderWriterXMLOptions* options);
 };
 
 
index 1a8efcdbb058912c2e95f3b2bc16073ee8403dcf..4ce5841f5d2a0ae303862dc133e6396dca0bb928 100644 (file)
@@ -31,6 +31,7 @@
 #include <osgDB/Registry>
 
 #include <simgear/debug/logstream.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/SplicingVisitor.hxx>
@@ -116,7 +117,7 @@ void mergePropertyTrees(SGPropertyNode* resultNode,
 
 Effect* makeEffect(const string& name,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options)
+                   const SGReaderWriterXMLOptions* options)
 {
     {
         OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
@@ -159,7 +160,7 @@ Effect* makeEffect(const string& name,
 
 Effect* makeEffect(SGPropertyNode* prop,
                    bool realizeTechniques,
-                   const osgDB::ReaderWriter::Options* options)
+                   const SGReaderWriterXMLOptions* options)
 {
     // Give default names to techniques and passes
     vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique");
index 2fc7e9c84c3573c09a958419fbff39ca08e21c5a..5947579e1f5c4af23d94d222aa4945791a75ffb2 100644 (file)
@@ -49,6 +49,7 @@
 #include <simgear/debug/logstream.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sgstream.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/model/model.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
@@ -68,12 +69,12 @@ using namespace simgear;
 ////////////////////////////////////////////////////////////////////////
 
 SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l,
-                                             const osgDB::ReaderWriter::Options* o ) :
-  effect(e), texture_path(t), effect_realized(l), options(o)
+                                             const SGReaderWriterXMLOptions* o)
+    : effect(e), texture_path(t), effect_realized(l), options(o)
 {
 }
 
-SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
+SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options,
                         const SGPropertyNode *props )
 {
     init();
@@ -81,6 +82,17 @@ SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
     buildEffectProperties(options);
 }
 
+SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
+                        const SGPropertyNode *props )
+{
+    osg::ref_ptr<const SGReaderWriterXMLOptions> sgOptions;
+    if (options)
+        sgOptions = new SGReaderWriterXMLOptions(*options);
+    init();
+    read_properties( sgOptions.get(), props );
+    buildEffectProperties(sgOptions.get());
+}
+
 SGMaterial::~SGMaterial (void)
 {
 }
@@ -91,7 +103,7 @@ SGMaterial::~SGMaterial (void)
 ////////////////////////////////////////////////////////////////////////
 
 void
-SGMaterial::read_properties(const osgDB::ReaderWriter::Options* options,
+SGMaterial::read_properties(const SGReaderWriterXMLOptions* options,
                             const SGPropertyNode *props)
 {
                                // Gather the path(s) to the texture(s)
@@ -245,10 +257,12 @@ Effect* SGMaterial::get_effect(int n)
     return _status[i].effect.get();
 }
 
-void SGMaterial::buildEffectProperties(const osgDB::ReaderWriter::Options*
-                                       options)
+void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options)
 {
     using namespace osg;
+    ref_ptr<SGReaderWriterXMLOptions> xmlOptions;
+    if (options)
+        xmlOptions = new SGReaderWriterXMLOptions(*options);
     ref_ptr<SGMaterialUserData> user = new SGMaterialUserData(this);
     SGPropertyNode_ptr propRoot = new SGPropertyNode();
     makeChild(propRoot, "inherits-from")->setStringValue(effect);
@@ -279,7 +293,7 @@ void SGMaterial::buildEffectProperties(const osgDB::ReaderWriter::Options*
             ->setStringValue(wrapu ? "repeat" : "clamp");
         makeChild(texProp, "wrap-t")
             ->setStringValue(wrapv ? "repeat" : "clamp");
-        matState.effect = makeEffect(effectProp, false, options);
+        matState.effect = makeEffect(effectProp, false, xmlOptions.get());
         matState.effect->setUserData(user.get());
     }
 }
index ac2e5f1bb26d6343b708e82a63f56c9e5fed673c..619ae8dae08bae9c62ccfb1ad68c1a7b8c071eea 100644 (file)
 #include <simgear/math/SGMath.hxx>
 
 #include <osg/ref_ptr>
-#include <osgDB/ReaderWriter>
 
 namespace osg
 {
 class StateSet;
 }
 
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
@@ -87,6 +87,8 @@ public:
    */
   SGMaterial( const osgDB::ReaderWriter::Options*, const SGPropertyNode *props);
 
+  SGMaterial(const simgear::SGReaderWriterXMLOptions*,
+             const SGPropertyNode *props);
   /**
    * Destructor.
    */
@@ -271,11 +273,11 @@ protected:
 
   struct _internal_state {
       _internal_state(simgear::Effect *e, const std::string &t, bool l,
-                      const osgDB::ReaderWriter::Options *o);
+                      const simgear::SGReaderWriterXMLOptions *o);
       osg::ref_ptr<simgear::Effect> effect;
       std::string texture_path;
       bool effect_realized;
-      osg::ref_ptr<const osgDB::ReaderWriter::Options> options;
+      osg::ref_ptr<const simgear::SGReaderWriterXMLOptions> options;
   };
 
 private:
@@ -361,9 +363,9 @@ private:
   // Internal constructors and methods.
   ////////////////////////////////////////////////////////////////////
 
-  void read_properties(const osgDB::ReaderWriter::Options* options,
+  void read_properties(const simgear::SGReaderWriterXMLOptions* options,
                         const SGPropertyNode *props);
-  void buildEffectProperties(const osgDB::ReaderWriter::Options* options);
+  void buildEffectProperties(const simgear::SGReaderWriterXMLOptions* options);
 };
 
 
index 758a5b6a197de8166918c11499a38770324ecd71..6d2ab7f1920de92c138774f29120f23de8babad8 100644 (file)
@@ -70,8 +70,18 @@ public:
   osg::ref_ptr<osg::RefMatrix> mModelView;
 };
 
-osgUtil::RegisterRenderBinProxy
-SGClipGroup::clipBinProxy("ClipRenderBin", new SGClipGroup::ClipRenderBin);
+struct SGClipGroup::ClipBinRegistrar
+{
+    ClipBinRegistrar()
+    {
+        osgUtil::RenderBin
+            ::addRenderBinPrototype("ClipRenderBin",
+                                    new SGClipGroup::ClipRenderBin);
+    }
+    static ClipBinRegistrar registrar;
+};
+
+SGClipGroup::ClipBinRegistrar SGClipGroup::ClipBinRegistrar::registrar;
 
 class SGClipGroup::CullCallback : public osg::NodeCallback {
 public:
index eb0e0ddbb778815372a035f2f0062db570553f3a..9820ec1d11cb6a8d00e55219f55373172f0f995d 100644 (file)
@@ -49,10 +49,8 @@ public:
 protected:
   class CullCallback;
   class ClipRenderBin;
-
+  struct ClipBinRegistrar;
   std::vector<osg::ref_ptr<osg::ClipPlane> > mClipPlanes;
-
-  static osgUtil::RegisterRenderBinProxy clipBinProxy;
 };
 
 #endif
index 17532aeece9728eff39d755478d08ff63f0780fa..cca34824d82cc7d57d249d69427246470a4cf180 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef SGREADERWRITERXMLOPTIONS_HXX
 #define SGREADERWRITERXMLOPTIONS_HXX 1
 
-#include <osgDB/ReaderWriter>
+#include <osgDB/Registry>
 #include <simgear/scene/model/modellib.hxx>
 #include <simgear/props/props.hxx>
 
index 59f33694956d600a31858e939f93bae7fd17a568..1ea486f0d13afc5b1dae4353c449539f77df3d85 100644 (file)
@@ -33,6 +33,7 @@
 #include <simgear/props/props_io.hxx>
 #include <simgear/props/condition.hxx>
 
+#include "SGReaderWriterXMLOptions.hxx"
 #include "model.hxx"
 
 using std::vector;
@@ -209,7 +210,7 @@ class MakeEffectVisitor : public SplicingVisitor
 public:
     typedef std::map<string, SGPropertyNode_ptr> EffectMap;
     using SplicingVisitor::apply;
-    MakeEffectVisitor(const osgDB::ReaderWriter::Options* options = 0)
+    MakeEffectVisitor(const SGReaderWriterXMLOptions* options = 0)
         : _options(options)
     {
     }
@@ -225,7 +226,7 @@ public:
 protected:
     EffectMap _effectMap;
     SGPropertyNode_ptr _currentEffectParent;
-    osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
+    osg::ref_ptr<const SGReaderWriterXMLOptions> _options;
 };
 
 void MakeEffectVisitor::apply(osg::Group& node)
@@ -302,7 +303,7 @@ protected:
 
 ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
                                  PropertyList& effectProps,
-                                 const osgDB::ReaderWriter::Options* options)
+                                 const SGReaderWriterXMLOptions* options)
 {
     SGPropertyNode_ptr defaultEffectPropRoot;
     MakeEffectVisitor visitor(options);
index 49dc0666e1307ee9245ab0e4f93bde30c9624915..c2097fdcd52930cab553b80cd5cae13b53cc4ea7 100644 (file)
 #include <simgear/props/props.hxx>
 #include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
 
+namespace simgear
+{
+class SGReaderWriterXMLOptions;
+}
+
 osg::Texture2D*
 SGLoadTexture2D(bool staticTexture, const std::string& path,
                 const osgDB::ReaderWriter::Options* options = 0,
@@ -97,7 +102,7 @@ public:
 osg::ref_ptr<osg::Node>
 instantiateEffects(osg::Node* model,
                    PropertyList& effectProps,
-                   const osgDB::ReaderWriter::Options* options);
+                   const SGReaderWriterXMLOptions* options);
 
 /**
  * Transform an OSG subgraph by substituting the Effects and
@@ -110,7 +115,7 @@ instantiateEffects(osg::Node* model,
 
 inline osg::ref_ptr<osg::Node>
 instantiateEffects(osg::Node* model,
-                   const osgDB::ReaderWriter::Options* options)
+                   const SGReaderWriterXMLOptions* options)
 {
     PropertyList effectProps;
     return instantiateEffects(model, effectProps, options);
index 6a13c516fdfbe5a10a15f870665d823a6be70535..4b457f5e48bc2aeece69d10e7e44acbfb07bd882 100644 (file)
@@ -71,8 +71,12 @@ osg::Node* loadFile(const string& path, osgDB::ReaderWriter::Options* options)
     ref_ptr<Node> model = readRefNodeFile(path, options);
     if (!model)
         return 0;
-    if (boost::iends_with(path, ".ac"))
-        model = instantiateEffects(model.get(), options);
+    if (boost::iends_with(path, ".ac")) {
+        ref_ptr<SGReaderWriterXMLOptions> sgOptions;
+        if (options)
+            sgOptions = new SGReaderWriterXMLOptions(*options);
+        model = instantiateEffects(model.get(), sgOptions.get());
+    }
      return model.release();
 }
 }
index 829a55852996ced6aaef997eb1800ac22d6ee53c..b99a2d167e904daf723710c5c982e50e376f02ce 100644 (file)
@@ -132,7 +132,8 @@ bool SGCloudField::reposition( const SGVec3f& p, const SGVec3f& up, double lon,
         field_transform->setMatrix( LAT*LON*T );
     }
     
-    field_root->getStateSet()->setRenderBinDetails(asl, "DepthSortedBin");
+    // Render the clouds in order from farthest away layer to nearest one.
+    field_root->getStateSet()->setRenderBinDetails(CLOUDS_BIN, "DepthSortedBin");
 
     return true;
 }
index 162f137a0c58c38941c449d99cbdd2d27fe88f1d..6d35ad998b224074b7ebe08d8385f7c8bb38986a 100644 (file)
@@ -46,6 +46,7 @@
 #include <simgear/misc/PathOptions.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/scene/model/model.hxx>
+#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
 
@@ -108,9 +109,11 @@ SGNewCloud::SGNewCloud(string type,
                                      "texture"),
                            "image"),
                  texture);
-        osg::ref_ptr<osgDB::ReaderWriter::Options> options
+        ref_ptr<osgDB::ReaderWriter::Options> options
             = makeOptionsFromPath(tex_path);
-        if ((effect = makeEffect(pcloudEffect, true, options)))
+        ref_ptr<SGReaderWriterXMLOptions> sgOptions
+            = new SGReaderWriterXMLOptions(*options.get());
+        if ((effect = makeEffect(pcloudEffect, true, sgOptions.get())))
             effectMap.insert(EffectMap::value_type(texture, effect));
     } else {
         effect = iter->second.get();