#ifndef _gpuCacheMaterial_h_
#define _gpuCacheMaterial_h_
#include <map>
#include <vector>
#include <assert.h>
#include <memory>
#include <unordered_map>
#include <boost/noncopyable.hpp>
#include <boost/functional/hash.hpp>
#include <maya/MColor.h>
#include <maya/MString.h>
namespace GPUCache {
struct MStringHash : std::unary_function<MString, std::size_t>
{
std::size_t operator()(
const MString& key)
const
{
unsigned int length = key.
length();
const char* begin = key.
asChar();
return boost::hash_range(begin, begin + length);
}
};
class MaterialNode;
class MaterialProperty : boost::noncopyable
{
public:
typedef std::shared_ptr<const MaterialProperty> Ptr;
typedef std::weak_ptr<const MaterialProperty> WPtr;
typedef std::shared_ptr<MaterialProperty> MPtr;
typedef std::shared_ptr<const MaterialNode> NodePtr;
typedef std::weak_ptr<const MaterialNode> NodeWPtr;
enum Type {
kBool,
kInt32,
kFloat,
kFloat2,
kFloat3,
kRGB,
kString,
};
struct PropertyData;
typedef std::shared_ptr<PropertyData> PropertyDataPtr;
typedef std::map<double,PropertyDataPtr> SampleMap;
static MPtr create(
const MString& name, Type type);
MaterialProperty(
const MString& name, Type type);
~MaterialProperty();
const MString& name()
const {
return fName; }
Type type() const { return fType; }
bool asBool(double seconds) const;
void setBool(double seconds, bool value);
int asInt32(double seconds) const;
void setInt32(double seconds, int value);
float asFloat(double seconds) const;
void setFloat(double seconds, float value);
void asFloat2(double seconds, float& x, float& y) const;
void setFloat2(double seconds, float x, float y);
void asFloat3(double seconds, float& x, float& y, float& z) const;
void setFloat3(double seconds, float x, float y, float z);
const MColor& asColor(
double seconds)
const;
void setColor(
double seconds,
const MColor& value);
const MString& asString(
double seconds)
const;
void setString(
double seconds,
const MString& value);
void setDefault(bool value);
void setDefault(int value);
void setDefault(float value);
void setDefault(float x, float y);
void setDefault(float x, float y, float z);
void setDefault(
const MColor& value);
void setDefault(
const MString& value);
bool getDefaultAsBool() const;
int getDefaultAsInt32() const;
float getDefaultAsFloat() const;
void getDefaultAsFloat2(float& x, float& y) const;
void getDefaultAsFloat3(float& x, float& y, float& z) const;
const MColor& getDefaultAsColor()
const;
const MString& getDefaultAsString()
const;
bool isDefault() const { return fValues.empty(); }
bool isAnimated() const { return fValues.size() > 1; }
const SampleMap& getSamples() const { return fValues; }
void connect(const NodePtr& node, const Ptr& prop)
{ assert(node && prop); fSourceNode = node; fSourceProp = prop; }
const NodePtr srcNode() const
{ return fSourceNode.lock(); }
const Ptr srcProp() const
{ return fSourceProp.lock(); }
private:
struct BoolPropertyData;
struct Int32PropertyData;
struct FloatPropertyData;
struct Float2PropertyData;
struct Float3PropertyData;
struct ColorPropertyData;
struct StringPropertyData;
static PropertyDataPtr createData(Type type);
template<typename T>
const T* findValue(double seconds) const
{
if (isAnimated()) {
SampleMap::const_iterator it = fValues.upper_bound(seconds);
if (it != fValues.begin()) --it;
return static_cast<const T*>((*it).second.get());
}
else if (fValues.size() == 1) {
return static_cast<const T*>((*fValues.begin()).second.get());
}
else {
return static_cast<const T*>(fDefaultValue.get());
}
}
void setValue(double seconds, const PropertyDataPtr& data)
{
assert(fValues.find(seconds) == fValues.end());
fValues.insert(std::make_pair(seconds, data));
}
const Type fType;
PropertyDataPtr fDefaultValue;
SampleMap fValues;
NodeWPtr fSourceNode;
WPtr fSourceProp;
};
class MaterialPropertyRef : boost::noncopyable
{
public:
MaterialPropertyRef() {}
~MaterialPropertyRef() {}
const MaterialProperty::Ptr operator->() const
{ assert(fProp); return fProp; }
MaterialProperty::MPtr operator->()
{ assert(fProp); return fProp; }
operator MaterialProperty::MPtr& ()
{ assert(fProp); return fProp;}
operator const MaterialProperty::Ptr () const
{ assert(fProp); return fProp;}
bool operator== (const MaterialProperty::Ptr& rv) const
{ assert(fProp); return fProp == rv; }
private:
friend class MaterialNode;
void initialize(MaterialProperty::MPtr& prop)
{ fProp = prop; }
MaterialProperty::MPtr fProp;
};
class MaterialNodeVisitor : boost::noncopyable
{
public:
virtual ~MaterialNodeVisitor() {}
};
class MaterialNode : boost::noncopyable
{
public:
typedef std::shared_ptr<const MaterialNode> Ptr;
typedef std::weak_ptr<const MaterialNode> WPtr;
typedef std::shared_ptr<MaterialNode> MPtr;
typedef std::unordered_map<MString,MaterialProperty::Ptr,MStringHash> PropertyMap;
static MaterialNode::MPtr create(
const MString& name,
const MString& nodeType);
: fName(name), fType(type)
{}
virtual ~MaterialNode() {}
const MString& name()
const {
return fName; }
const MString& type()
const {
return fType; }
MaterialProperty::MPtr createProperty(
const MString& name, MaterialProperty::Type type);
MaterialProperty::MPtr findProperty(
const MString& name);
MaterialProperty::Ptr findProperty(
const MString& name)
const;
const PropertyMap& properties() const { return fProperties; }
virtual void accept(MaterialNodeVisitor& visitor) const = 0;
protected:
void createProperty(
const MString& name, MaterialProperty::Type type, MaterialPropertyRef& ref);
private:
PropertyMap fProperties;
};
class MaterialGraph : boost::noncopyable
{
public:
typedef std::shared_ptr<const MaterialGraph> Ptr;
typedef std::shared_ptr<MaterialGraph> MPtr;
typedef std::weak_ptr<const MaterialGraph> WPtr;
typedef std::unordered_map<MString, MaterialNode::Ptr, MStringHash > NamedMap;
: fName(name)
{}
virtual ~MaterialGraph() {}
{ return fName; }
void addNode(const MaterialNode::Ptr& node)
{ assert(node); fMaterialNodeMap.insert(std::make_pair(node->name(), node)); }
const NamedMap& getNodes() const
{ return fMaterialNodeMap; }
void setRootNode(const MaterialNode::Ptr& node)
{ assert(node); fRootNode = node; }
const MaterialNode::Ptr& rootNode() const
{ return fRootNode; }
bool isAnimated() const;
private:
NamedMap fMaterialNodeMap;
MaterialNode::Ptr fRootNode;
};
class MaterialGraphMap : boost::noncopyable
{
public:
typedef std::shared_ptr<const MaterialGraphMap> Ptr;
typedef std::shared_ptr<MaterialGraphMap> MPtr;
typedef std::unordered_map<MString, MaterialGraph::Ptr, MStringHash > NamedMap;
MaterialGraphMap() {}
virtual ~MaterialGraphMap() {}
void addMaterialGraph(const MaterialGraph::Ptr& graph);
const NamedMap& getGraphs() const
{ return fMaterialGraphMap; }
const MaterialGraph::Ptr find(
const MString name)
const;
private:
NamedMap fMaterialGraphMap;
};
}
#endif