From: Tim Moore Date: Fri, 25 Dec 2009 10:56:09 +0000 (+0100) Subject: generalize support for initializing effect parameters from several properties X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=650af0f7b08c8540b2f817377e418b6e594f39b0;p=simgear.git generalize support for initializing effect parameters from several properties --- diff --git a/simgear/scene/material/EffectBuilder.hxx b/simgear/scene/material/EffectBuilder.hxx index 615b2157..f86b87f1 100644 --- a/simgear/scene/material/EffectBuilder.hxx +++ b/simgear/scene/material/EffectBuilder.hxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -244,6 +245,43 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect, std::string getGlobalProperty(const SGPropertyNode* prop, const SGReaderWriterXMLOptions *); +template +std::vector +getVectorProperties(const SGPropertyNode* prop, + const SGReaderWriterXMLOptions *options, size_t vecSize, + NameItr defaultNames) +{ + using namespace std; + vector 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 { protected: @@ -384,11 +422,12 @@ class EffectExtendedPropListener : public InitializeWhenAdded, public: template 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(childNamesBegin, childNamesEnd); } @@ -399,7 +438,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(parent, _childNames->begin(), _childNames->end(), @@ -424,6 +467,9 @@ private: * own 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 void @@ -445,6 +491,25 @@ initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, } } +/* + * Initialize vector parameters from individual properties. + * The parameter may be updated at runtime. + * + * If the value is specified directly, set it. Otherwise, use the + * tag to look at the parameters. Again, if there is a value + * there set it directly. Otherwise, the parameter contains one or several + * 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 + * 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 void initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, @@ -452,21 +517,23 @@ initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj, NameItrType nameItr, const SGReaderWriterXMLOptions* options) { typedef typename OSGBridge::sg_type sg_type; + const int numComponents = props::NumComponents::num_components; const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop); if (!valProp) return; - if (valProp->nChildren() == 0) { + if (valProp->nChildren() == 0) { // Has ? (obj->*setter)(OSGBridge ::getOsgType(valProp->getValue())); } else { - string listenPropName = getGlobalProperty(valProp, options); - if (listenPropName.empty()) - return; + std::vector paramNames + = getVectorProperties(valProp, options,numComponents, nameItr); + if (paramNames.empty()) + throw BuilderException(); + std::vector::const_iterator pitr = paramNames.begin(); typedef OSGFunctor Functor; Effect::Updater* listener = new EffectExtendedPropListener - (Functor(obj, setter), listenPropName, nameItr, - nameItr + props::NumComponents::num_components); + (Functor(obj, setter), 0, pitr, pitr + numComponents); effect->addUpdater(listener); } }