-// Copyright (C) 2008 Timothy Moore timoore@redhat.com
+// Copyright (C) 2008 - 2009 Tim Moore timoore@redhat.com
//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
+// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
#ifndef SIMGEAR_EFFECT_HXX
#define SIMGEAR_EFFECT_HXX 1
#include <vector>
+#include <string>
+#include <boost/tr1/unordered_map.hpp>
+
+#include <boost/functional/hash.hpp>
#include <osg/Object>
+#include <osgDB/ReaderWriter>
+
+#include <simgear/props/props.hxx>
+#include <simgear/scene/util/UpdateOnceCallback.hxx>
namespace osg
{
namespace simgear
{
class Technique;
+class Effect;
+class SGReaderWriterXMLOptions;
+
+/**
+ * Object to be initialized at some point after an effect -- and its
+ * containing effect geode -- are hooked into the scene graph. Some
+ * things, like manipulations of the global property tree, are are
+ * only safe in the update process.
+ */
+
+class InitializeWhenAdded
+{
+public:
+ InitializeWhenAdded() : _initialized(false) {};
+ virtual ~InitializeWhenAdded() {};
+ void initOnAdd(Effect* effect, SGPropertyNode* propRoot)
+ {
+ if (!_initialized) {
+ initOnAddImpl(effect, propRoot);
+ _initialized = true;
+ }
+ }
+ bool getInitialized() const { return _initialized; }
+private:
+ virtual void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot) = 0;
+ bool _initialized;
+};
class Effect : public osg::Object
{
public:
META_Object(simgear,Effect)
- Effect() {}
+ Effect();
Effect(const Effect& rhs,
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
osg::StateSet* getDefaultStateSet();
std::vector<osg::ref_ptr<Technique> > techniques;
+ SGPropertyNode_ptr root;
+ // Pointer to the parameters node, if it exists
+ SGPropertyNode_ptr parametersProp;
Technique* chooseTechnique(osg::RenderInfo* renderInfo);
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* state = 0) const;
+ /**
+ * Build the techniques from the effect properties.
+ */
+ 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
+ * or something.
+ */
+ struct Updater : public virtual SGReferenced
+ {
+ virtual ~Updater() {}
+ };
+ void addUpdater(Updater* data) { _extraData.push_back(data); }
+ // Callback that is added to the effect geode to initialize the
+ // effect.
+ friend struct InitializeCallback;
+ struct InitializeCallback : public UpdateOnceCallback
+ {
+ void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
+ };
protected:
- ~Effect() {}
+ std::vector<SGSharedPtr<Updater> > _extraData;
+ ~Effect();
+ // Support for a cache of effects that inherit from this one, so
+ // Effect objects with the same parameters and techniques can be
+ // shared.
+ struct Key
+ {
+ Key() {}
+ Key(SGPropertyNode* unmerged_, const osgDB::FilePathList& paths_)
+ : unmerged(unmerged_), paths(paths_)
+ {
+ }
+ Key& operator=(const Key& rhs)
+ {
+ unmerged = rhs.unmerged;
+ paths = rhs.paths;
+ return *this;
+ }
+ SGPropertyNode_ptr unmerged;
+ osgDB::FilePathList paths;
+ struct EqualTo
+ {
+ bool operator()(const Key& lhs, const Key& rhs) const;
+ };
+ };
+ typedef std::tr1::unordered_map<Key, osg::ref_ptr<Effect>,
+ boost::hash<Key>, Key::EqualTo> Cache;
+ Cache* getCache()
+ {
+ if (!_cache)
+ _cache = new Cache;
+ return _cache;
+ }
+ Cache* _cache;
+ friend size_t hash_value(const Key& key);
+ friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
+ const SGReaderWriterXMLOptions* options);
+ bool _isRealized;
};
+// Automatic support for boost hash function
+size_t hash_value(const Effect::Key&);
+
+
+Effect* makeEffect(const std::string& name,
+ bool realizeTechniques,
+ const SGReaderWriterXMLOptions* options = 0);
+
+Effect* makeEffect(SGPropertyNode* prop,
+ bool realizeTechniques,
+ const SGReaderWriterXMLOptions* options = 0);
+
+bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
+ const osg::StateSet* ss);
+
+namespace effect
+{
+/**
+ * The function that implements effect property tree inheritance.
+ */
+void mergePropertyTrees(SGPropertyNode* resultNode,
+ const SGPropertyNode* left,
+ const SGPropertyNode* right);
+}
}
#endif