Throw an exception when an undefine attribute value is found in an effect.
Also, fix a typo in TexEnvCombine operand attributes.
return useProp->getStringValue();
}
+namespace effect
+{
BuilderException::BuilderException()
{
}
BuilderException::~BuilderException() throw()
{
+}
}
bool isAttributeActive(Effect* effect, const SGPropertyNode* prop)
_map.insert(typename BMap::value_type(attrs[i].first, attrs[i].second));
}
+class BuilderException : public sg_exception
+{
+public:
+ BuilderException();
+ BuilderException(const char* message, const char* origin = 0);
+ BuilderException(const std::string& message, const std::string& = "");
+ virtual ~BuilderException() throw();
+};
}
template<typename T>
-bool findAttr(const effect::EffectPropertyMap<T>& pMap,
+void findAttr(const effect::EffectPropertyMap<T>& pMap,
const char* name,
T& result)
{
typename EffectPropertyMap<T>::BMap::iterator itr
= pMap._map.get<from>().find(name);
if (itr == pMap._map.end()) {
- return false;
+ throw effect::BuilderException(string("findAttr: could not find attribute ")
+ + string(name));
} else {
result = itr->second;
- return true;
}
}
template<typename T>
-inline bool findAttr(const effect::EffectPropertyMap<T>& pMap,
+inline void findAttr(const effect::EffectPropertyMap<T>& pMap,
const std::string& name,
T& result)
{
- return findAttr(pMap, name.c_str(), result);
+ findAttr(pMap, name.c_str(), result);
}
template<typename T>
-bool findAttr(const effect::EffectPropertyMap<T>& pMap,
+void findAttr(const effect::EffectPropertyMap<T>& pMap,
const SGPropertyNode* prop,
T& result)
{
if (!prop)
- return false;
+ throw effect::BuilderException("findAttr: empty property");
const char* name = prop->getStringValue();
if (!name)
- return false;
- return findAttr(pMap, name, result);
+ throw effect::BuilderException("findAttr: no name for lookup");
+ findAttr(pMap, name, result);
}
template<typename T>
*/
std::string getGlobalProperty(const SGPropertyNode* prop);
-class BuilderException : public sg_exception
-{
-public:
- BuilderException();
- BuilderException(const char* message, const char* origin = 0);
- BuilderException(const std::string& message, const std::string& = "");
- virtual ~BuilderException() throw();
-};
-
class PassAttributeBuilder : public SGReferenced
{
protected:
const string& texType)
{
Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
- findAttr(filterModes, getEffectPropertyChild(effect, props, "filter"),
- minFilter);
+ const SGPropertyNode* ep = 0;
+ if ((ep = getEffectPropertyChild(effect, props, "filter")))
+ findAttr(filterModes, ep, minFilter);
Texture::FilterMode magFilter = Texture::LINEAR;
- findAttr(filterModes, getEffectPropertyChild(effect, props,
- "mag-filter"),
- magFilter);
+ if ((ep = getEffectPropertyChild(effect, props, "mag-filter")))
+ findAttr(filterModes, ep, magFilter);
const SGPropertyNode* pWrapS
= getEffectPropertyChild(effect, props, "wrap-s");
Texture::WrapMode sWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapS, sWrap);
+ if (pWrapS)
+ findAttr(wrapModes, pWrapS, sWrap);
const SGPropertyNode* pWrapT
= getEffectPropertyChild(effect, props, "wrap-t");
Texture::WrapMode tWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapT, tWrap);
+ if (pWrapT)
+ findAttr(wrapModes, pWrapT, tWrap);
const SGPropertyNode* pWrapR
= getEffectPropertyChild(effect, props, "wrap-r");
Texture::WrapMode rWrap = Texture::CLAMP;
- findAttr(wrapModes, pWrapR, rWrap);
+ if (pWrapR)
+ findAttr(wrapModes, pWrapR, rWrap);
const SGPropertyNode* pImage
= getEffectPropertyChild(effect, props, "image");
string imageName;
EffectNameValue<TexEnvCombine::OperandParam> opParamInit[] =
{
- {"src_color", TexEnvCombine::SRC_COLOR},
- {"one_minus_src_color", TexEnvCombine::ONE_MINUS_SRC_COLOR},
- {"src_alpha", TexEnvCombine::SRC_ALPHA},
- {"one_minus_src_alpha", TexEnvCombine::ONE_MINUS_SRC_ALPHA}
+ {"src-color", TexEnvCombine::SRC_COLOR},
+ {"one-minus-src-color", TexEnvCombine::ONE_MINUS_SRC_COLOR},
+ {"src-alpha", TexEnvCombine::SRC_ALPHA},
+ {"one-minus-src-alpha", TexEnvCombine::ONE_MINUS_SRC_ALPHA}
};
EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
TexGen* result = new TexGen;
const SGPropertyNode* p = 0;
TexGen::Mode mode = TexGen::OBJECT_LINEAR;
- if (findAttr(tgenModes, getEffectPropertyChild(effect, tgenProp, "mode"),
- mode))
- result->setMode(mode);
+ findAttr(tgenModes, getEffectPropertyChild(effect, tgenProp, "mode"), mode);
+ result->setMode(mode);
const SGPropertyNode* planesNode = tgenProp->getChild("planes");
if (planesNode) {
for (int i = 0; i < planesNode->nChildren(); ++i) {
const SGPropertyNode* planeNode = planesNode->getChild(i);
TexGen::Coord coord;
- if (!findAttr(tgenCoords, planeNode->getName(), coord)) {
- SG_LOG(SG_INPUT, SG_ALERT, "Unknown TexGen plane "
- << planeNode->getName());
- } else {
- const SGPropertyNode* realNode
- = getEffectPropertyNode(effect, planeNode);
- SGVec4d plane = realNode->getValue<SGVec4d>();
- result->setPlane(coord, toOsg(plane));
- }
+ findAttr(tgenCoords, planeNode->getName(), coord);
+ const SGPropertyNode* realNode
+ = getEffectPropertyNode(effect, planeNode);
+ SGVec4d plane = realNode->getValue<SGVec4d>();
+ result->setPlane(coord, toOsg(plane));
}
}
return result;
}
makeChild(texUnit, "active")->setValue(true);
makeChild(texUnit, "type")->setValue("2d");
+ string filter = findName(filterModes,
+ texture->getFilter(Texture::MIN_FILTER));
+ string magFilter = findName(filterModes,
+ texture->getFilter(Texture::MAG_FILTER));
string wrapS = findName(wrapModes, texture->getWrap(Texture::WRAP_S));
string wrapT = findName(wrapModes, texture->getWrap(Texture::WRAP_T));
string wrapR = findName(wrapModes, texture->getWrap(Texture::WRAP_R));
makeChild(texUnit, "image")->setStringValue(imageName);
+ makeChild(texUnit, "filter")->setStringValue(filter);
+ makeChild(texUnit, "mag-filter")->setStringValue(magFilter);
makeChild(texUnit, "wrap-s")->setStringValue(wrapS);
makeChild(texUnit, "wrap-t")->setStringValue(wrapT);
makeChild(texUnit, "wrap-r")->setStringValue(wrapR);
#endif
#include "Effect.hxx"
+#include "EffectBuilder.hxx"
#include "Technique.hxx"
#include "Pass.hxx"
bool realizeTechniques,
const osgDB::ReaderWriter::Options* options)
{
- OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
- EffectMap::iterator itr = effectMap.find(name);
- if (itr != effectMap.end())
- return itr->second.get();
+ {
+ OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
+ EffectMap::iterator itr = effectMap.find(name);
+ if (itr != effectMap.end())
+ return itr->second.get();
+ }
string effectFileName(name);
effectFileName += ".eff";
string absFileName
= osgDB::findDataFile(effectFileName, options);
if (absFileName.empty()) {
- SG_LOG(SG_INPUT, SG_WARN, "can't find \"" << effectFileName << "\"");
+ SG_LOG(SG_INPUT, SG_ALERT, "can't find \"" << effectFileName << "\"");
return 0;
}
SGPropertyNode_ptr effectProps = new SGPropertyNode();
- readProperties(absFileName, effectProps.ptr(), 0, true);
- Effect* result = makeEffect(effectProps.ptr(), realizeTechniques, options);
- if (result)
- effectMap.insert(make_pair(name, result));
- return result;
+ try {
+ readProperties(absFileName, effectProps.ptr(), 0, true);
+ }
+ catch (sg_io_exception& e) {
+ SG_LOG(SG_INPUT, SG_ALERT, "error reading \"" << absFileName << "\": "
+ << e.getFormattedMessage());
+ return 0;
+ }
+ ref_ptr<Effect> result = makeEffect(effectProps.ptr(), realizeTechniques,
+ options);
+ if (result.valid()) {
+ OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
+ pair<EffectMap::iterator, bool> irslt
+ = effectMap.insert(make_pair(name, result));
+ if (!irslt.second) {
+ // Another thread beat us to it!. Discard our newly
+ // constructed Effect and use the one in the cache.
+ result = irslt.first->second;
+ }
+ }
+ return result.release();
}
}
}
}
- Effect* effect = 0;
+ ref_ptr<Effect> effect;
// Merge with the parent effect, if any
SGPropertyNode_ptr inheritProp = prop->getChild("inherits-from");
Effect* parent = 0;
//prop->removeChild("inherits-from");
parent = makeEffect(inheritProp->getStringValue(), false, options);
if (parent) {
- Effect::Cache* cache = parent->getCache();
Effect::Key key;
+ key.unmerged = prop;
if (options) {
- key = Effect::Key(prop, options->getDatabasePathList());
- } else {
- osgDB::FilePathList dummy;
- key = Effect::Key(prop, dummy);
+ key.paths = options->getDatabasePathList();
+ }
+ Effect::Cache* cache = 0;
+ Effect::Cache::iterator itr;
+ {
+ OpenThreads::ScopedLock<OpenThreads::ReentrantMutex>
+ lock(effectMutex);
+ cache = parent->getCache();
+ itr = cache->find(key);
+ if (itr != cache->end())
+ effect = itr->second.get();
}
- Effect::Cache::iterator itr = cache->find(key);
- if (itr != cache->end()) {
- effect = itr->second.get();
- } else {
+ if (!effect.valid()) {
effect = new Effect;
effect->root = new SGPropertyNode;
mergePropertyTrees(effect->root, prop, parent->root);
- cache->insert(make_pair(key, effect));
+ effect->parametersProp = effect->root->getChild("parameters");
+ OpenThreads::ScopedLock<OpenThreads::ReentrantMutex>
+ lock(effectMutex);
+ pair<Effect::Cache::iterator, bool> irslt
+ = cache->insert(make_pair(key, effect));
+ if (!irslt.second)
+ effect = irslt.first->second;
}
} else {
- SG_LOG(SG_INPUT, SG_WARN, "can't find base effect " <<
+ SG_LOG(SG_INPUT, SG_ALERT, "can't find base effect " <<
inheritProp->getStringValue());
+ return 0;
}
- }
- if (!effect) {
+ } else {
effect = new Effect;
effect->root = prop;
+ effect->parametersProp = effect->root->getChild("parameters");
+ }
+ if (realizeTechniques) {
+ try {
+ OpenThreads::ScopedLock<OpenThreads::ReentrantMutex>
+ lock(effectMutex);
+ effect->realizeTechniques(options);
+ }
+ catch (BuilderException& e) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Error building technique: "
+ << e.getFormattedMessage());
+ return 0;
+ }
}
- effect->parametersProp = effect->root->getChild("parameters");
- if (realizeTechniques)
- effect->realizeTechniques(options);
- return effect;
+ return effect.release();
}
}