Effects in models working for transparent materials and chrome animation
Implementation of animated effect values via the property system. Add names for TexEnvCombine attributes
This commit is contained in:
parent
cb07210bc7
commit
54c4055af3
@ -643,6 +643,15 @@
|
||||
<Filter
|
||||
Name="Lib_sgprops"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\condition.cxx">
|
||||
</File>
|
||||
@ -1249,6 +1258,12 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.hxx">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_sgbvh"
|
||||
|
@ -983,6 +983,14 @@
|
||||
<Filter
|
||||
Name="Lib_sgprops"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\condition.cxx"
|
||||
>
|
||||
@ -991,6 +999,11 @@
|
||||
RelativePath="..\..\simgear\props\condition.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx"
|
||||
>
|
||||
</File>
|
||||
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\props.cxx"
|
||||
>
|
||||
@ -1809,6 +1822,14 @@
|
||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.hxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_sgbvh"
|
||||
|
71
simgear/props/AtomicChangeListener.cxx
Normal file
71
simgear/props/AtomicChangeListener.cxx
Normal file
@ -0,0 +1,71 @@
|
||||
#include "AtomicChangeListener.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
MultiChangeListener::MultiChangeListener()
|
||||
{
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChanged()
|
||||
{
|
||||
valueChangedImplementation();
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChangedImplementation()
|
||||
{
|
||||
}
|
||||
|
||||
AtomicChangeListener::AtomicChangeListener(std::vector<SGPropertyNode*>& nodes)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
listenToProperties(nodes.begin(), nodes.end());
|
||||
}
|
||||
|
||||
void AtomicChangeListener::unregister_property(SGPropertyNode* node)
|
||||
{
|
||||
_valid = false;
|
||||
// not necessary, but good hygine
|
||||
vector<SGPropertyNode*>::iterator itr
|
||||
= find(_watched.begin(), _watched.end(), node);
|
||||
if (itr != _watched.end())
|
||||
*itr = 0;
|
||||
MultiChangeListener::unregister_property(node);
|
||||
}
|
||||
|
||||
void AtomicChangeListener::fireChangeListeners()
|
||||
{
|
||||
vector<SGSharedPtr<AtomicChangeListener> >& listeners
|
||||
= ListenerListSingleton::instance()->listeners;
|
||||
for (vector<SGSharedPtr<AtomicChangeListener> >::iterator itr = listeners.begin(),
|
||||
end = listeners.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
(*itr)->valuesChanged();
|
||||
(*itr)->_dirty = false;
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valueChangedImplementation()
|
||||
{
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
if (_valid)
|
||||
ListenerListSingleton::instance()->listeners.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valuesChanged()
|
||||
{
|
||||
}
|
||||
}
|
105
simgear/props/AtomicChangeListener.hxx
Normal file
105
simgear/props/AtomicChangeListener.hxx
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
|
||||
#define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
#include "ExtendedPropertyAdapter.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
// Performs an action when one of several nodes changes
|
||||
class MultiChangeListener : private SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
MultiChangeListener();
|
||||
template<typename Pitr>
|
||||
void listenToProperties(Pitr propsBegin, Pitr propsEnd)
|
||||
{
|
||||
for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
|
||||
(*itr)->addChangeListener(this);
|
||||
}
|
||||
void valueChanged();
|
||||
using SGPropertyChangeListener::unregister_property;
|
||||
private:
|
||||
virtual void valueChangedImplementation();
|
||||
|
||||
};
|
||||
|
||||
class AtomicChangeListener : public MultiChangeListener,
|
||||
public virtual SGReferenced
|
||||
{
|
||||
public:
|
||||
AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
|
||||
/**
|
||||
* Lookup / create child nodes from their relative names.
|
||||
*/
|
||||
template<typename Itr>
|
||||
AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
using namespace std;
|
||||
for (Itr itr = childNamesBegin, end = childNamesEnd;
|
||||
itr != end;
|
||||
++itr)
|
||||
_watched.push_back(makeNode(parent, *itr));
|
||||
listenToProperties(_watched.begin(), _watched.end());
|
||||
}
|
||||
bool isDirty() { return _dirty; }
|
||||
bool isValid() { return _valid; }
|
||||
void unregister_property(SGPropertyNode* node);
|
||||
static void fireChangeListeners();
|
||||
private:
|
||||
virtual void valueChangedImplementation();
|
||||
virtual void valuesChanged();
|
||||
bool _dirty;
|
||||
bool _valid;
|
||||
struct ListenerListSingleton : public Singleton<ListenerListSingleton>
|
||||
{
|
||||
std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
|
||||
};
|
||||
protected:
|
||||
std::vector<SGPropertyNode*> _watched;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
class ExtendedPropListener : public AtomicChangeListener
|
||||
{
|
||||
public:
|
||||
ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(nodes), _func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
|
||||
}
|
||||
template<typename Itr>
|
||||
ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
|
||||
_func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
}
|
||||
virtual void valuesChanged()
|
||||
{
|
||||
ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
|
||||
T val = adaptor();
|
||||
_func(val);
|
||||
}
|
||||
private:
|
||||
Func _func;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
72
simgear/props/ExtendedPropertyAdapter.hxx
Normal file
72
simgear/props/ExtendedPropertyAdapter.hxx
Normal file
@ -0,0 +1,72 @@
|
||||
#ifndef SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX
|
||||
#define SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
namespace props
|
||||
{
|
||||
// This should be in simgear/math/SGVec.hxx and friends
|
||||
|
||||
template<typename T> struct NumComponents;
|
||||
|
||||
template<> struct NumComponents<SGVec3d>
|
||||
{
|
||||
enum { num_components = 3 };
|
||||
};
|
||||
|
||||
template<> struct NumComponents<SGVec4d>
|
||||
{
|
||||
enum { num_components = 4 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename NodeContainer>
|
||||
class ExtendedPropertyAdapter
|
||||
{
|
||||
public:
|
||||
enum { num_components = props::NumComponents<T>::num_components };
|
||||
ExtendedPropertyAdapter(const NodeContainer& elements)
|
||||
: _elements(elements)
|
||||
{
|
||||
}
|
||||
T operator()() const
|
||||
{
|
||||
T result;
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
result[i] = _elements[i]->getValue<double>();
|
||||
return result;
|
||||
}
|
||||
void set(const T& val)
|
||||
{
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
_elements[i]->setValue(val[i]);
|
||||
}
|
||||
private:
|
||||
const NodeContainer& _elements;
|
||||
};
|
||||
|
||||
template<typename InIterator, typename OutIterator>
|
||||
inline void makeChildList(SGPropertyNode* prop, InIterator inBegin,
|
||||
InIterator inEnd, OutIterator outBegin)
|
||||
{
|
||||
std::transform(inBegin, inEnd, outBegin,
|
||||
boost::bind(static_cast<SGPropertyNode* (SGPropertyNode::*)(const char*, int, bool)>(&SGPropertyNode::getChild), prop, _1, 0, true));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -5,12 +5,15 @@ lib_LIBRARIES = libsgprops.a
|
||||
include_HEADERS = \
|
||||
condition.hxx \
|
||||
props.hxx \
|
||||
props_io.hxx
|
||||
props_io.hxx \
|
||||
AtomicChangeListener.hxx \
|
||||
ExtendedPropertyAdapter.hxx
|
||||
|
||||
libsgprops_a_SOURCES = \
|
||||
condition.cxx \
|
||||
props.cxx \
|
||||
props_io.cxx
|
||||
props_io.cxx \
|
||||
AtomicChangeListener.cxx
|
||||
|
||||
noinst_PROGRAMS = props_test
|
||||
|
||||
|
@ -1927,13 +1927,26 @@ inline bool SGPropertyNode::setValue(const T& val,
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node
|
||||
* Utility function for creation of a child property node.
|
||||
*/
|
||||
inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
|
||||
int index = 0)
|
||||
{
|
||||
return parent->getChild(name, index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node using a
|
||||
* relative path.
|
||||
*/
|
||||
namespace simgear
|
||||
{
|
||||
template<typename StringType>
|
||||
inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
|
||||
{
|
||||
return parent->getNode(name, true);
|
||||
}
|
||||
}
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "Effect.hxx"
|
||||
#include "EffectBuilder.hxx"
|
||||
#include "EffectGeode.hxx"
|
||||
#include "Technique.hxx"
|
||||
#include "Pass.hxx"
|
||||
#include "TextureBuilder.hxx"
|
||||
@ -856,6 +857,8 @@ bool makeParametersFromStateSet(SGPropertyNode* effectRoot, const StateSet* ss)
|
||||
} else {
|
||||
makeChild(blendNode, "active")->setValue(false);
|
||||
}
|
||||
string renderingHint = findName(renderingHints, ss->getRenderingHint());
|
||||
makeChild(paramRoot, "rendering-hint")->setStringValue(renderingHint);
|
||||
makeTextureParameters(paramRoot, ss);
|
||||
return true;
|
||||
}
|
||||
@ -872,6 +875,26 @@ bool Effect::realizeTechniques(const osgDB::ReaderWriter::Options* options)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
EffectGeode* eg = dynamic_cast<EffectGeode*>(node);
|
||||
if (!eg)
|
||||
return;
|
||||
Effect* effect = eg->getEffect();
|
||||
if (!effect)
|
||||
return;
|
||||
SGPropertyNode* root = getPropertyRoot();
|
||||
for (vector<SGSharedPtr<Updater> >::iterator itr = effect->_extraData.begin(),
|
||||
end = effect->_extraData.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
InitializeWhenAdded* adder
|
||||
= dynamic_cast<InitializeWhenAdded*>(itr->ptr());
|
||||
if (adder)
|
||||
adder->initOnAdd(effect, root);
|
||||
}
|
||||
}
|
||||
|
||||
bool Effect_writeLocalData(const Object& obj, osgDB::Output& fw)
|
||||
{
|
||||
const Effect& effect = static_cast<const Effect&>(obj);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <osgDB/ReaderWriter>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/scene/util/UpdateOnceCallback.hxx>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
@ -40,6 +41,32 @@ class CullVisitor;
|
||||
namespace simgear
|
||||
{
|
||||
class Technique;
|
||||
class Effect;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
@ -56,12 +83,30 @@ public:
|
||||
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 osgDB::ReaderWriter::Options* 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:
|
||||
std::vector<SGSharedPtr<Updater> > _extraData;
|
||||
~Effect();
|
||||
};
|
||||
Effect* makeEffect(const std::string& name,
|
||||
|
@ -2,6 +2,8 @@
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/scene/tgdb/userdata.hxx>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "EffectBuilder.hxx"
|
||||
@ -39,6 +41,16 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
|
||||
return getEffectPropertyNode(effect, child);
|
||||
}
|
||||
|
||||
string getGlobalProperty(const SGPropertyNode* prop)
|
||||
{
|
||||
if (!prop)
|
||||
return string();
|
||||
const SGPropertyNode* useProp = prop->getChild("use");
|
||||
if (!useProp)
|
||||
return string();
|
||||
return useProp->getStringValue();
|
||||
}
|
||||
|
||||
BuilderException::BuilderException()
|
||||
{
|
||||
}
|
||||
@ -66,4 +78,8 @@ bool isAttributeActive(Effect* effect, const SGPropertyNode* prop)
|
||||
return !activeProp || activeProp->getValue<bool>();
|
||||
}
|
||||
|
||||
namespace effect
|
||||
{
|
||||
const char* colorFields[] = {"red", "green", "blue", "alpha"};
|
||||
}
|
||||
}
|
||||
|
@ -18,21 +18,26 @@
|
||||
#define SIMGEAR_EFFECTBUILDER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/props/AtomicChangeListener.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
#include "Effect.hxx"
|
||||
/**
|
||||
* Support classes for parsing effects.
|
||||
*/
|
||||
@ -153,15 +158,10 @@ EffectPropertyMap<T>::EffectPropertyMap(const EffectNameValue<T> (&attrs)[N])
|
||||
|
||||
template<typename T>
|
||||
bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||
const SGPropertyNode* prop,
|
||||
const char* name,
|
||||
T& result)
|
||||
{
|
||||
using namespace effect;
|
||||
if (!prop)
|
||||
return false;
|
||||
const char* name = prop->getStringValue();
|
||||
if (!name)
|
||||
return false;
|
||||
typename EffectPropertyMap<T>::BMap::iterator itr
|
||||
= pMap._map.get<from>().find(name);
|
||||
if (itr == pMap._map.end()) {
|
||||
@ -172,6 +172,27 @@ bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||
const std::string& name,
|
||||
T& result)
|
||||
{
|
||||
return findAttr(pMap, name.c_str(), result);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool findAttr(const effect::EffectPropertyMap<T>& pMap,
|
||||
const SGPropertyNode* prop,
|
||||
T& result)
|
||||
{
|
||||
if (!prop)
|
||||
return false;
|
||||
const char* name = prop->getStringValue();
|
||||
if (!name)
|
||||
return false;
|
||||
return findAttr(pMap, name, result);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string findName(const effect::EffectPropertyMap<T>& pMap, T value)
|
||||
{
|
||||
@ -205,6 +226,14 @@ const SGPropertyNode* getEffectPropertyChild(Effect* effect,
|
||||
const SGPropertyNode* prop,
|
||||
const char* name);
|
||||
|
||||
/**
|
||||
* Get the name of a node mentioned in a <use> clause from the global property
|
||||
* tree.
|
||||
* @return empty if prop doesn't contain a <use> clause; otherwise the
|
||||
* mentioned node name.
|
||||
*/
|
||||
std::string getGlobalProperty(const SGPropertyNode* prop);
|
||||
|
||||
class BuilderException : public sg_exception
|
||||
{
|
||||
public:
|
||||
@ -257,5 +286,190 @@ struct InstallAttributeBuilder
|
||||
// false, the OSG attribute is not built at all. This is different
|
||||
// from any OSG mode settings that might be around.
|
||||
bool isAttributeActive(Effect* effect, const SGPropertyNode* prop);
|
||||
|
||||
namespace effect
|
||||
{
|
||||
/**
|
||||
* Bridge between types stored in properties and what OSG wants.
|
||||
*/
|
||||
template<typename T> struct OSGBridge;
|
||||
|
||||
template<typename T>
|
||||
struct OSGBridge<const T> : public OSGBridge<T>
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct OSGBridge<osg::Vec3f>
|
||||
{
|
||||
typedef SGVec3d sg_type;
|
||||
static osg::Vec3f getOsgType(const SGVec3d& val) { return toOsg(val); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct OSGBridge<osg::Vec3d>
|
||||
{
|
||||
typedef SGVec3d sg_type;
|
||||
static osg::Vec3d getOsgType(const SGVec3d& val) { return toOsg(val); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct OSGBridge<osg::Vec4f>
|
||||
{
|
||||
typedef SGVec4d sg_type;
|
||||
static osg::Vec4f getOsgType(const SGVec4d& val) { return toOsg(val); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct OSGBridge<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>
|
||||
{
|
||||
OSGFunctor(Obj* obj, void (Obj::*func)(const OSGParam&))
|
||||
: _obj(obj), _func(func) {}
|
||||
void operator()(const typename OSGBridge<OSGParam>::sg_type& val) const
|
||||
{
|
||||
((_obj.get())->*_func)(this->getOsgType(val));
|
||||
}
|
||||
osg::ref_ptr<Obj>_obj;
|
||||
void (Obj::*_func)(const OSGParam&);
|
||||
};
|
||||
|
||||
template<typename ObjType, typename OSGParamType>
|
||||
class ScalarChangeListener
|
||||
: public SGPropertyChangeListener, public InitializeWhenAdded,
|
||||
public Effect::Updater
|
||||
{
|
||||
public:
|
||||
typedef void (ObjType::*setter_type)(const OSGParamType);
|
||||
ScalarChangeListener(ObjType* obj, setter_type setter,
|
||||
const std::string& propName)
|
||||
: _obj(obj), _setter(setter)
|
||||
{
|
||||
_propName = new std::string(propName);
|
||||
}
|
||||
virtual ~ScalarChangeListener()
|
||||
{
|
||||
delete _propName;
|
||||
_propName = 0;
|
||||
}
|
||||
void valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
_obj->*setter(node->getValue<OSGParamType>());
|
||||
}
|
||||
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
|
||||
{
|
||||
SGPropertyNode* listenProp = makeNode(propRoot, *_propName);
|
||||
delete _propName;
|
||||
_propName = 0;
|
||||
if (listenProp)
|
||||
listenProp->addChangeListener(this, true);
|
||||
}
|
||||
private:
|
||||
osg::ref_ptr<ObjType> _obj;
|
||||
setter_type _setter;
|
||||
std::string* _propName;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
class EffectExtendedPropListener : public InitializeWhenAdded,
|
||||
public Effect::Updater
|
||||
{
|
||||
public:
|
||||
template<typename Itr>
|
||||
EffectExtendedPropListener(const Func& func,
|
||||
const std::string& propName, Itr childNamesBegin,
|
||||
Itr childNamesEnd)
|
||||
: _func(func)
|
||||
{
|
||||
_propName = new std::string(propName);
|
||||
_childNames = new std::vector<std::string>(childNamesBegin,
|
||||
childNamesEnd);
|
||||
}
|
||||
virtual ~EffectExtendedPropListener()
|
||||
{
|
||||
delete _propName;
|
||||
delete _childNames;
|
||||
}
|
||||
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
|
||||
{
|
||||
SGPropertyNode* parent = propRoot->getNode(*_propName, true);
|
||||
_propListener
|
||||
= new ExtendedPropListener<T, Func>(parent, _childNames->begin(),
|
||||
_childNames->end(),
|
||||
_func, true);
|
||||
delete _propName;
|
||||
_propName = 0;
|
||||
delete _childNames;
|
||||
_childNames = 0;
|
||||
}
|
||||
private:
|
||||
std::string* _propName;
|
||||
std::vector<std::string>* _childNames;
|
||||
SGSharedPtr<ExtendedPropListener<T, Func> > _propListener;
|
||||
Func _func;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the value and the possible updating of an effect
|
||||
* attribute. 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 its
|
||||
* 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.
|
||||
*/
|
||||
template<typename ObjType, typename OSGParamType>
|
||||
void
|
||||
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
|
||||
void (ObjType::*setter)(const OSGParamType))
|
||||
{
|
||||
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
|
||||
if (!valProp)
|
||||
return;
|
||||
if (valProp->nChildren() == 0) {
|
||||
obj->*setter(valProp->getValue<OSGParamType>());
|
||||
} else {
|
||||
std::string propName = getGlobalProperty(prop);
|
||||
ScalarChangeListener<ObjType, OSGParamType>* listener
|
||||
= new ScalarChangeListener<ObjType, OSGParamType>(obj, setter,
|
||||
propName);
|
||||
effect->addUpdater(listener);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ObjType, typename OSGParamType, typename NameItrType>
|
||||
void
|
||||
initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
|
||||
void (ObjType::*setter)(const OSGParamType&),
|
||||
NameItrType nameItr)
|
||||
{
|
||||
typedef typename OSGBridge<OSGParamType>::sg_type sg_type;
|
||||
const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
|
||||
if (!valProp)
|
||||
return;
|
||||
if (valProp->nChildren() == 0) {
|
||||
(obj->*setter)(OSGBridge<OSGParamType>
|
||||
::getOsgType(valProp->getValue<sg_type>()));
|
||||
} else {
|
||||
string listenPropName = getGlobalProperty(valProp);
|
||||
if (listenPropName.empty())
|
||||
return;
|
||||
typedef OSGFunctor<ObjType, OSGParamType> Functor;
|
||||
Effect::Updater* listener
|
||||
= new EffectExtendedPropListener<sg_type, Functor>
|
||||
(Functor(obj, setter), listenPropName, nameItr,
|
||||
nameItr + props::NumComponents<sg_type>::num_components);
|
||||
effect->addUpdater(listener);
|
||||
}
|
||||
}
|
||||
|
||||
extern const char* colorFields[];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -44,6 +44,14 @@ EffectGeode::EffectGeode(const EffectGeode& rhs, const osg::CopyOp& copyop) :
|
||||
{
|
||||
}
|
||||
|
||||
void EffectGeode::setEffect(Effect* effect)
|
||||
{
|
||||
_effect = effect;
|
||||
if (!_effect)
|
||||
return;
|
||||
addUpdateCallback(new Effect::InitializeCallback);
|
||||
}
|
||||
|
||||
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
{
|
||||
if (_effect.valid())
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
META_Node(simgear,EffectGeode);
|
||||
Effect* getEffect() const { return _effect.get(); }
|
||||
void setEffect(Effect* effect) { _effect = effect; }
|
||||
void setEffect(Effect* effect);
|
||||
virtual void resizeGLObjectBuffers(unsigned int maxSize);
|
||||
virtual void releaseGLObjects(osg::State* = 0) const;
|
||||
typedef DrawableList::iterator DrawablesIterator;
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/TexEnvCombine>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/Texture1D>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Texture3D>
|
||||
@ -48,6 +49,10 @@ using namespace osg;
|
||||
|
||||
using namespace effect;
|
||||
|
||||
TexEnvCombine* buildTexEnvCombine(Effect* effect,
|
||||
const SGPropertyNode* envProp);
|
||||
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,
|
||||
@ -134,6 +139,14 @@ void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
|
||||
if (env)
|
||||
pass->setTextureAttributeAndModes(unit, env);
|
||||
}
|
||||
const SGPropertyNode* combineProp = prop->getChild("texenv-combine");
|
||||
TexEnvCombine* combiner = 0;
|
||||
if (combineProp && ((combiner = buildTexEnvCombine(effect, combineProp))))
|
||||
pass->setTextureAttributeAndModes(unit, combiner);
|
||||
const SGPropertyNode* tgenProp = prop->getChild("texgen");
|
||||
TexGen* tgen = 0;
|
||||
if (tgenProp && (tgen = buildTexGen(effect, tgenProp)))
|
||||
pass->setTextureAttributeAndModes(unit, tgen);
|
||||
}
|
||||
|
||||
// InstallAttributeBuilder call is in Effect.cxx to force this file to
|
||||
@ -366,6 +379,197 @@ namespace
|
||||
TextureBuilder::Registrar installNoise("noise", new NoiseBuilder);
|
||||
}
|
||||
|
||||
EffectNameValue<TexEnvCombine::CombineParam> combineParamInit[] =
|
||||
{
|
||||
{"replace", TexEnvCombine::REPLACE},
|
||||
{"modulate", TexEnvCombine::MODULATE},
|
||||
{"add", TexEnvCombine::ADD},
|
||||
{"add-signed", TexEnvCombine::ADD_SIGNED},
|
||||
{"interpolate", TexEnvCombine::INTERPOLATE},
|
||||
{"subtract", TexEnvCombine::SUBTRACT},
|
||||
{"dot3-rgb", TexEnvCombine::DOT3_RGB},
|
||||
{"dot3-rgba", TexEnvCombine::DOT3_RGBA}
|
||||
};
|
||||
|
||||
EffectPropertyMap<TexEnvCombine::CombineParam> combineParams(combineParamInit);
|
||||
|
||||
EffectNameValue<TexEnvCombine::SourceParam> sourceParamInit[] =
|
||||
{
|
||||
{"constant", TexEnvCombine::CONSTANT},
|
||||
{"primary_color", TexEnvCombine::PRIMARY_COLOR},
|
||||
{"previous", TexEnvCombine::PREVIOUS},
|
||||
{"texture", TexEnvCombine::TEXTURE},
|
||||
{"texture0", TexEnvCombine::TEXTURE0},
|
||||
{"texture1", TexEnvCombine::TEXTURE1},
|
||||
{"texture2", TexEnvCombine::TEXTURE2},
|
||||
{"texture3", TexEnvCombine::TEXTURE3},
|
||||
{"texture4", TexEnvCombine::TEXTURE4},
|
||||
{"texture5", TexEnvCombine::TEXTURE5},
|
||||
{"texture6", TexEnvCombine::TEXTURE6},
|
||||
{"texture7", TexEnvCombine::TEXTURE7}
|
||||
};
|
||||
|
||||
EffectPropertyMap<TexEnvCombine::SourceParam> sourceParams(sourceParamInit);
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
|
||||
|
||||
TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp)
|
||||
{
|
||||
if (!isAttributeActive(effect, envProp))
|
||||
return 0;
|
||||
TexEnvCombine* result = new TexEnvCombine;
|
||||
const SGPropertyNode* p = 0;
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "combine-rgb"))) {
|
||||
TexEnvCombine::CombineParam crgb = TexEnvCombine::MODULATE;
|
||||
findAttr(combineParams, p, crgb);
|
||||
result->setCombine_RGB(crgb);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "combine-alpha"))) {
|
||||
TexEnvCombine::CombineParam calpha = TexEnvCombine::MODULATE;
|
||||
findAttr(combineParams, p, calpha);
|
||||
result->setCombine_RGB(calpha);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source0-rgb"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource0_RGB(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source1-rgb"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource1_RGB(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source2-rgb"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource2_RGB(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source0-alpha"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::TEXTURE;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource0_Alpha(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source1-alpha"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::PREVIOUS;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource1_Alpha(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "source2-alpha"))) {
|
||||
TexEnvCombine::SourceParam source = TexEnvCombine::CONSTANT;
|
||||
findAttr(sourceParams, p, source);
|
||||
result->setSource2_Alpha(source);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand0-rgb"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand0_RGB(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand1-rgb"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_COLOR;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand1_RGB(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand2-rgb"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand2_RGB(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand0-alpha"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand0_Alpha(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand1-alpha"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand1_Alpha(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "operand2-alpha"))) {
|
||||
TexEnvCombine::OperandParam op = TexEnvCombine::SRC_ALPHA;
|
||||
findAttr(operandParams, p, op);
|
||||
result->setOperand2_Alpha(op);
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "scale-rgb"))) {
|
||||
result->setScale_RGB(p->getValue<float>());
|
||||
}
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "scale-alpha"))) {
|
||||
result->setScale_Alpha(p->getValue<float>());
|
||||
}
|
||||
#if 0
|
||||
if ((p = getEffectPropertyChild(effect, envProp, "constant-color"))) {
|
||||
SGVec4d color = p->getValue<SGVec4d>();
|
||||
result->setConstantColor(toOsg(color));
|
||||
} else if ((p = getEffectPropertyChild(effect, envProp,
|
||||
"light-direction"))) {
|
||||
SGVec3d direction = p->getValue<SGVec3d>();
|
||||
result->setConstantColorAsLightDirection(toOsg(direction));
|
||||
}
|
||||
#endif
|
||||
const SGPropertyNode* colorNode = envProp->getChild("constant-color");
|
||||
if (colorNode)
|
||||
initFromParameters(effect, colorNode, result,
|
||||
&TexEnvCombine::setConstantColor, colorFields);
|
||||
return result;
|
||||
}
|
||||
|
||||
EffectNameValue<TexGen::Mode> tgenModeInit[] =
|
||||
{
|
||||
{ "object-linear", TexGen::OBJECT_LINEAR},
|
||||
{ "eye-linear", TexGen::EYE_LINEAR},
|
||||
{ "sphere-map", TexGen::SPHERE_MAP},
|
||||
{ "normal-map", TexGen::NORMAL_MAP},
|
||||
{ "reflection-map", TexGen::REFLECTION_MAP}
|
||||
};
|
||||
|
||||
EffectPropertyMap<TexGen::Mode> tgenModes(tgenModeInit);
|
||||
|
||||
EffectNameValue<TexGen::Coord> tgenCoordInit[] =
|
||||
{
|
||||
{"s", TexGen::S},
|
||||
{"t", TexGen::T},
|
||||
{"r", TexGen::R},
|
||||
{"q", TexGen::Q}
|
||||
};
|
||||
|
||||
EffectPropertyMap<TexGen::Coord> tgenCoords(tgenCoordInit);
|
||||
|
||||
TexGen* buildTexGen(Effect* effect, const SGPropertyNode* tgenProp)
|
||||
{
|
||||
if (!isAttributeActive(effect, tgenProp))
|
||||
return 0;
|
||||
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);
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool makeTextureParameters(SGPropertyNode* paramRoot, const StateSet* ss)
|
||||
{
|
||||
SGPropertyNode* texUnit = makeChild(paramRoot, "texture");
|
||||
|
@ -170,7 +170,7 @@ Effect* makeEffect(SGPropertyNode* prop,
|
||||
const SGPropertyNode* inheritProp = prop->getChild("inherits-from");
|
||||
Effect* parent = 0;
|
||||
if (inheritProp) {
|
||||
parent = makeEffect(inheritProp->getStringValue(), realizeTechniques,
|
||||
parent = makeEffect(inheritProp->getStringValue(), false,
|
||||
options);
|
||||
if(parent)
|
||||
{
|
||||
|
@ -20,6 +20,12 @@
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
//yuck
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <osg/Geode>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgDB/WriteFile>
|
||||
@ -132,6 +138,45 @@ public:
|
||||
private:
|
||||
osg::ref_ptr<osg::Referenced> mReferenced;
|
||||
};
|
||||
|
||||
void makeEffectAnimations(PropertyList& animation_nodes,
|
||||
PropertyList& effect_nodes)
|
||||
{
|
||||
for (PropertyList::iterator itr = animation_nodes.begin();
|
||||
itr != animation_nodes.end();
|
||||
++itr) {
|
||||
SGPropertyNode* animProp = itr->ptr();
|
||||
SGPropertyNode* typeProp = animProp->getChild("type");
|
||||
if (!typeProp || strcmp(typeProp->getStringValue(), "shader"))
|
||||
continue;
|
||||
SGPropertyNode* shaderProp = animProp->getChild("shader");
|
||||
if (!shaderProp || strcmp(shaderProp->getStringValue(), "chrome"))
|
||||
continue;
|
||||
*itr = 0;
|
||||
SGPropertyNode* textureProp = animProp->getChild("texture");
|
||||
if (!textureProp)
|
||||
continue;
|
||||
SGPropertyNode_ptr effectProp = new SGPropertyNode();
|
||||
makeChild(effectProp.ptr(), "inherits-from")
|
||||
->setValue("Effects/chrome");
|
||||
SGPropertyNode* paramsProp = makeChild(effectProp.get(), "parameters");
|
||||
makeChild(paramsProp, "chrome-texture")
|
||||
->setValue(textureProp->getStringValue());
|
||||
PropertyList objectNameNodes = animProp->getChildren("object-name");
|
||||
for (PropertyList::iterator objItr = objectNameNodes.begin(),
|
||||
end = objectNameNodes.end();
|
||||
objItr != end;
|
||||
++objItr)
|
||||
effectProp->addChild("object-name")
|
||||
->setStringValue((*objItr)->getStringValue());
|
||||
effect_nodes.push_back(effectProp);
|
||||
}
|
||||
animation_nodes.erase(remove_if(animation_nodes.begin(),
|
||||
animation_nodes.end(),
|
||||
!boost::bind(&SGPropertyNode_ptr::valid,
|
||||
_1)),
|
||||
animation_nodes.end());
|
||||
}
|
||||
}
|
||||
|
||||
static osg::Node *
|
||||
@ -368,13 +413,14 @@ sgLoad3DModel_internal(const string &path,
|
||||
options.get()));
|
||||
}
|
||||
PropertyList effect_nodes = props->getChildren("effect");
|
||||
PropertyList animation_nodes = props->getChildren("animation");
|
||||
// Some material animations (eventually all) are actually effects.
|
||||
makeEffectAnimations(animation_nodes, effect_nodes);
|
||||
{
|
||||
ref_ptr<Node> modelWithEffects
|
||||
= instantiateEffects(group.get(), effect_nodes, options.get());
|
||||
group = static_cast<Group*>(modelWithEffects.get());
|
||||
}
|
||||
std::vector<SGPropertyNode_ptr> animation_nodes;
|
||||
animation_nodes = props->getChildren("animation");
|
||||
for (unsigned i = 0; i < animation_nodes.size(); ++i)
|
||||
/// OSGFIXME: duh, why not only model?????
|
||||
SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
|
||||
|
@ -212,7 +212,7 @@ public:
|
||||
: _options(options)
|
||||
{
|
||||
}
|
||||
virtual void apply(osg::Node& node);
|
||||
virtual void apply(osg::Group& node);
|
||||
virtual void apply(osg::Geode& geode);
|
||||
EffectMap& getEffectMap() { return _effectMap; }
|
||||
const EffectMap& getEffectMap() const { return _effectMap; }
|
||||
@ -227,7 +227,7 @@ protected:
|
||||
osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
|
||||
};
|
||||
|
||||
void MakeEffectVisitor::apply(osg::Node& node)
|
||||
void MakeEffectVisitor::apply(osg::Group& node)
|
||||
{
|
||||
SGPropertyNode_ptr savedEffectRoot;
|
||||
const string& nodeName = node.getName();
|
||||
|
@ -21,6 +21,7 @@ include_HEADERS = \
|
||||
RenderConstants.hxx \
|
||||
SplicingVisitor.hxx \
|
||||
StateAttributeFactory.hxx \
|
||||
UpdateOnceCallback.hxx \
|
||||
VectorArrayAdapter.hxx
|
||||
|
||||
|
||||
@ -35,6 +36,7 @@ libsgutil_a_SOURCES = \
|
||||
PrimitiveUtils.cxx \
|
||||
SplicingVisitor.cxx \
|
||||
StateAttributeFactory.cxx \
|
||||
QuadTreeBuilder.cxx
|
||||
QuadTreeBuilder.cxx \
|
||||
UpdateOnceCallback.cxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
39
simgear/scene/util/UpdateOnceCallback.cxx
Normal file
39
simgear/scene/util/UpdateOnceCallback.cxx
Normal file
@ -0,0 +1,39 @@
|
||||
// UpdateOnceCallback.hxx
|
||||
//
|
||||
// Copyright (C) 2009 Tim Moore timoore@redhat.com
|
||||
//
|
||||
// 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 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
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "UpdateOnceCallback.hxx"
|
||||
|
||||
#include <osg/Node>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using namespace osg;
|
||||
|
||||
void UpdateOnceCallback::operator()(Node* node, NodeVisitor* nv)
|
||||
{
|
||||
doUpdate(node, nv);
|
||||
node->removeUpdateCallback(this);
|
||||
// The callback could be deleted now.
|
||||
}
|
||||
|
||||
void UpdateOnceCallback::doUpdate(Node* node, NodeVisitor* nv)
|
||||
{
|
||||
traverse(node, nv);
|
||||
}
|
||||
}
|
44
simgear/scene/util/UpdateOnceCallback.hxx
Normal file
44
simgear/scene/util/UpdateOnceCallback.hxx
Normal file
@ -0,0 +1,44 @@
|
||||
// UpdateOnceCallback.hxx
|
||||
//
|
||||
// Copyright (C) 2009 Tim Moore timoore@redhat.com
|
||||
//
|
||||
// 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 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
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SIMGEAR_UPDATEONCECALLBACK_HXX
|
||||
#define SIMGEAR_UPDATEONCECALLBACK_HXX 1
|
||||
#include <osg/NodeCallback>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
class UpdateOnceCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
UpdateOnceCallback() {}
|
||||
UpdateOnceCallback(const UpdateOnceCallback& nc, const osg::CopyOp& copyop)
|
||||
: osg::NodeCallback(nc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
META_Object(simgear,UpdateOnceCallback);
|
||||
|
||||
virtual void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
|
||||
/**
|
||||
* Do not override; use doUpdate instead!
|
||||
*/
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user