summaryrefslogtreecommitdiff
path: root/Runtime/Graphics/SubstanceInput.h
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Graphics/SubstanceInput.h')
-rw-r--r--Runtime/Graphics/SubstanceInput.h243
1 files changed, 243 insertions, 0 deletions
diff --git a/Runtime/Graphics/SubstanceInput.h b/Runtime/Graphics/SubstanceInput.h
new file mode 100644
index 0000000..bb0a661
--- /dev/null
+++ b/Runtime/Graphics/SubstanceInput.h
@@ -0,0 +1,243 @@
+#pragma once
+
+#include "Configuration/UnityConfigure.h"
+
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+#include "External/Allegorithmic/builds/Engines/include/substance/inputdesc.h"
+#include "Texture2D.h"
+
+enum ProceduralPropertyType
+{
+ ProceduralPropertyType_Boolean = 0,
+ ProceduralPropertyType_Float,
+ ProceduralPropertyType_Vector2,
+ ProceduralPropertyType_Vector3,
+ ProceduralPropertyType_Vector4,
+ ProceduralPropertyType_Color3,
+ ProceduralPropertyType_Color4,
+ ProceduralPropertyType_Enum,
+ ProceduralPropertyType_Texture
+};
+
+inline bool IsSubstanceAnyFloatType (SubstanceInputType type) { return type >= Substance_IType_Float && type <= Substance_IType_Float4; }
+inline bool IsSubstanceAnyIntType (SubstanceInputType type) { return (type == Substance_IType_Integer) || (type == Substance_IType_Integer2) || (type == Substance_IType_Integer3) || (type == Substance_IType_Integer4); }
+inline int GetRequiredInputComponentCount (SubstanceInputType type)
+{
+ switch (type)
+ {
+ case Substance_IType_Float:
+ case Substance_IType_Integer:
+ return 1;
+ case Substance_IType_Float2:
+ case Substance_IType_Integer2:
+ return 2;
+ case Substance_IType_Float3:
+ case Substance_IType_Integer3:
+ return 3;
+ case Substance_IType_Float4:
+ case Substance_IType_Integer4:
+ return 4;
+ default:
+ AssertString("Not supported");
+ return -1;
+ }
+}
+
+struct SubstanceEnumItem
+{
+ DECLARE_SERIALIZE(SubstanceEnumItem)
+
+ int value;
+ UnityStr text;
+};
+
+struct SubstanceValue
+{
+ DECLARE_SERIALIZE(SubstanceValue)
+
+ float scalar[4];
+ PPtr<Texture2D> texture;
+
+ SubstanceValue() { memset(scalar, 0, sizeof(float)*4); }
+};
+
+struct SubstanceInput
+{
+ DECLARE_SERIALIZE(SubstanceInput)
+
+ // type & names
+ UnityStr name;
+ UnityStr label;
+ UnityStr group;
+ ProceduralPropertyType type;
+ SubstanceValue value;
+ SubstanceInputType internalType;
+ unsigned int internalIndex;
+ unsigned int internalIdentifier;
+ unsigned int shuffledIdentifier;
+
+ // Ranges and step
+ float minimum;
+ float maximum;
+ float step;
+
+ // Enum values
+ std::vector<SubstanceEnumItem> enumValues;
+ std::vector<std::string> GetEnumOptions() const
+ {
+ std::vector<std::string> enumOptions;
+ std::vector<SubstanceEnumItem>::const_iterator it;
+ for (it=enumValues.begin();it!=enumValues.end();++it)
+ {
+ enumOptions.push_back(it->text);
+ }
+ return enumOptions;
+ }
+
+ // Flags
+ enum Flag
+ {
+ Flag_SkipHint = 1<<0, // input is in head of the graph so the cache is not usefull
+ Flag_Modified = 1<<1, // input has been modified
+ Flag_Cached = 1<<2, // input is cached to speed up modifications
+ Flag_Awake = 1<<3, // this flag is set when AwakeFromLoad comes, this to rebuild all without having hints everywhere
+ Flag_Clamp = 1<<4 // needs to clamp value when set
+ };
+ unsigned int flags;
+ bool IsFlagEnabled(const Flag& flag) const { return flags & (unsigned int)flag; }
+ void EnableFlag(const Flag& flag, bool enabled=true) { if (enabled) flags |= (unsigned int)flag; else flags &= ~(unsigned int)flag; }
+
+ // Altered texture links
+ std::set<unsigned int> alteredTexturesUID;
+
+ SubstanceInput ()
+ {
+ type = ProceduralPropertyType_Float;
+ flags = SubstanceInput::Flag_Awake;
+ value.scalar[0] = value.scalar[1] = value.scalar[2] = value.scalar[3] = 0.0F;
+ internalType = Substance_IType_Float;
+ internalIndex = 0;
+ internalIdentifier = 0;
+
+ minimum = -std::numeric_limits<float>::max();
+ maximum = std::numeric_limits<float>::max();
+ }
+};
+
+inline void ClampSubstanceInputValues (const SubstanceInput& input, SubstanceValue& value)
+{
+ // validate combo value
+ if (input.type==ProceduralPropertyType_Enum && input.enumValues.size()>0)
+ {
+ std::vector<SubstanceEnumItem>::const_iterator it;
+ for (it=input.enumValues.begin();it!=input.enumValues.end();++it)
+ {
+ if ((int)value.scalar[0]==it->value)
+ return;
+ }
+ value.scalar[0] = (float)input.enumValues[0].value;
+ return;
+ }
+
+ // clamp scalar values
+ if (input.IsFlagEnabled(SubstanceInput::Flag_Clamp))
+ {
+ int count = GetRequiredInputComponentCount(input.internalType);
+
+ if (IsSubstanceAnyIntType(input.internalType))
+ {
+ for (int index=0;index<count;++index)
+ value.scalar[index] = (float)clamp<int>((int)(value.scalar[index]+0.5f), (int)input.minimum, (int)input.maximum);
+ }
+ else
+ {
+ for (int index=0;index<count;++index)
+ value.scalar[index] = clamp<float>(value.scalar[index], input.minimum, input.maximum);
+ }
+ } // step integers
+ else if (IsSubstanceAnyIntType(input.internalType))
+ {
+ int count = GetRequiredInputComponentCount(input.internalType);
+ for (int index=0;index<count;++index)
+ value.scalar[index] = (float)((int)(value.scalar[index]+0.5f));
+ }
+}
+
+inline bool AreSubstanceInputValuesEqual(SubstanceInputType type, SubstanceValue& first, SubstanceValue& second)
+{
+ if (IsSubstanceAnyFloatType(type))
+ {
+ return memcmp(first.scalar, second.scalar,
+ sizeof(float)*GetRequiredInputComponentCount(type))==0;
+ }
+ else if (IsSubstanceAnyIntType(type))
+ {
+ int count = GetRequiredInputComponentCount(type);
+
+ for (int index=0;index<count;++index)
+ {
+ if ((int)first.scalar[index]!=(int)second.scalar[index])
+ return false;
+ }
+ return true;
+ }
+ else if (type==Substance_IType_Image)
+ {
+ return first.texture==second.texture;
+ }
+ return false;
+}
+
+typedef std::vector<SubstanceInput> SubstanceInputs;
+
+template<class T>
+void SubstanceEnumItem::Transfer(T& transfer)
+{
+ TRANSFER(value);
+ TRANSFER(text);
+}
+
+template<class T>
+void SubstanceValue::Transfer(T& transfer)
+{
+ TRANSFER(scalar[0]);
+ TRANSFER(scalar[1]);
+ TRANSFER(scalar[2]);
+ TRANSFER(scalar[3]);
+ TRANSFER(texture);
+}
+
+template<class T>
+void SubstanceInput::Transfer(T& transfer)
+{
+ // type & names
+ TRANSFER(name);
+ TRANSFER(label);
+ TRANSFER(group);
+ transfer.Transfer(reinterpret_cast<int&> (type), "type");
+ TRANSFER(value);
+ transfer.Transfer(reinterpret_cast<int&> (internalType), "internalType");
+ TRANSFER(internalIndex);
+ TRANSFER(internalIdentifier);
+
+ // Range and step
+ TRANSFER(minimum);
+ TRANSFER(maximum);
+ TRANSFER(step);
+
+ // Flags
+ TRANSFER(flags);
+
+ // Altered texture links
+ TRANSFER(alteredTexturesUID);
+
+ // Enum
+ TRANSFER(enumValues);
+
+ // Update status
+ if (transfer.IsReading())
+ {
+ EnableFlag(Flag_Awake, true);
+ EnableFlag(Flag_Cached, false);
+ }
+}