Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of structs in MaterialX #1831

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4fdaa5e
Add support for recursive structs, with example.
ld-kerley Feb 28, 2024
82e43b7
fix python unit tests.
ld-kerley Jun 2, 2024
2205aa6
Addressing notes and refactor 'experimental' files to unit test locat…
ld-kerley Jun 11, 2024
5abd62d
fix signed vs unsigned windows warning.
ld-kerley Jun 11, 2024
364fe84
fix signed vs unsigned windows warning (part 2)
ld-kerley Jun 11, 2024
d9bfcf2
fix unreferenced parameter warning
ld-kerley Jun 11, 2024
445870f
fix dll linkage error
ld-kerley Jun 12, 2024
0ff2073
fix JS error
ld-kerley Jun 12, 2024
265fd6b
fix typo in comment
ld-kerley Jun 13, 2024
33f9431
remove separate header declaring forward declarations.
ld-kerley Sep 17, 2024
75c22bf
Removing unit test infrastructure for now - per Jonathan - will add s…
ld-kerley Sep 17, 2024
b90fb3f
removing separate Exceptions.h file - per Jonathans request.
ld-kerley Sep 18, 2024
881c908
refactor to use parseStructValueString()
ld-kerley Sep 18, 2024
b1aca0b
fix unit tests
ld-kerley Sep 19, 2024
6c43a57
Attempting to fix windows vs2019 build failure.
ld-kerley Sep 30, 2024
91a9d13
Attempting to fix windows vs2019 build failure - again
ld-kerley Sep 30, 2024
8ef3b29
Update letter case
jstone-lucasfilm Sep 30, 2024
9b612dd
Update letter case
jstone-lucasfilm Sep 30, 2024
211a6e7
Alphabetize includes within a module
jstone-lucasfilm Sep 30, 2024
3c5834f
Remove extra newline
jstone-lucasfilm Oct 3, 2024
9072720
Minor formatting update
jstone-lucasfilm Oct 3, 2024
9e6f230
Minor formatting updates
jstone-lucasfilm Oct 3, 2024
9801db0
Address Jonathans formatting notes.
ld-kerley Oct 21, 2024
bd13d3c
One more commit to address jonathans comments
ld-kerley Oct 21, 2024
4674117
Minor fix to spacing
jstone-lucasfilm Oct 21, 2024
682a569
Minor formatting fixes
jstone-lucasfilm Oct 21, 2024
f44b42d
Minor fix to spacing
jstone-lucasfilm Oct 21, 2024
177909d
Remove extra newline
jstone-lucasfilm Oct 21, 2024
281b813
Minor formatting fixes
jstone-lucasfilm Oct 21, 2024
c507f31
Re-word comment to address jonathans comments
ld-kerley Oct 22, 2024
c3f4504
make _size and _structIndex both uint16_t
ld-kerley Oct 22, 2024
359dea6
Moving getStructIndex() function per Jonathans request.
ld-kerley Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/JsMaterialX/JsMaterialXCore/JsValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ EMSCRIPTEN_BINDINGS(value)
.function("copy", &mx::Value::copy, ems::pure_virtual())
.function("getTypeString", &mx::Value::getTypeString)
.function("getValueString", &mx::Value::getValueString)
.class_function("createValueFromStrings", &mx::Value::createValueFromStrings)
BIND_CLASS_FUNC("createValueFromStrings", mx::Value, createValueFromStrings, 2, 3, stRef, stRef, mx::ConstTypeDefPtr)
.class_function("setFloatFormat", &mx::Value::setFloatFormat)
.class_function("setFloatPrecision", &mx::Value::setFloatPrecision)
.class_function("getFloatFormat", &mx::Value::getFloatFormat)
Expand Down
8 changes: 8 additions & 0 deletions source/MaterialXCore/Definition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,12 @@ vector<UnitDefPtr> UnitTypeDef::getUnitDefs() const
return unitDefs;
}

ValuePtr AttributeDef::getValue() const
{
if (!hasValue())
return ValuePtr();

return Value::createValueFromStrings(getValueString(), getType(), getDocument()->getTypeDef(getType()));
}

MATERIALX_NAMESPACE_END
11 changes: 3 additions & 8 deletions source/MaterialXCore/Definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,11 @@ class MX_CORE_API TargetDef : public TypedElement

/// @class Member
/// A member element within a TypeDef.
class MX_CORE_API Member : public TypedElement
class MX_CORE_API Member : public ValueElement
{
public:
Member(ElementPtr parent, const string& name) :
TypedElement(parent, CATEGORY, name)
ValueElement(parent, CATEGORY, name)
{
}
virtual ~Member() { }
Expand Down Expand Up @@ -625,12 +625,7 @@ class MX_CORE_API AttributeDef : public TypedElement
///
/// @return A shared pointer to the typed value of this element, or an
/// empty shared pointer if no value is present.
ValuePtr getValue() const
{
if (!hasValue())
return ValuePtr();
return Value::createValueFromStrings(getValueString(), getType());
}
ValuePtr getValue() const;

/// @}
/// @name Elements
Expand Down
16 changes: 16 additions & 0 deletions source/MaterialXCore/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,22 @@ string ValueElement::getResolvedValueString(StringResolverPtr resolver) const
return resolver->resolve(getValueString(), getType());
}

ValuePtr ValueElement::getValue() const
{
if (!hasValue())
return ValuePtr();

return Value::createValueFromStrings(getValueString(), getType(), getDocument()->getTypeDef(getType()));
}

ValuePtr ValueElement::getResolvedValue(StringResolverPtr resolver) const
{
if (!hasValue())
return ValuePtr();

return Value::createValueFromStrings(getResolvedValueString(resolver), getType(), getDocument()->getTypeDef(getType()));
}

ValuePtr ValueElement::getDefaultValue() const
{
ConstElementPtr parent = getParent();
Expand Down
14 changes: 2 additions & 12 deletions source/MaterialXCore/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -1037,12 +1037,7 @@ class MX_CORE_API ValueElement : public TypedElement
///
/// @return A shared pointer to the typed value of this element, or an
/// empty shared pointer if no value is present.
ValuePtr getValue() const
{
if (!hasValue())
return ValuePtr();
return Value::createValueFromStrings(getValueString(), getType());
}
ValuePtr getValue() const;

/// Return the resolved value of an element as a generic value object, which
/// may be queried to access its data.
Expand All @@ -1052,12 +1047,7 @@ class MX_CORE_API ValueElement : public TypedElement
/// will be created at this scope and applied to the return value.
/// @return A shared pointer to the typed value of this element, or an
/// empty shared pointer if no value is present.
ValuePtr getResolvedValue(StringResolverPtr resolver = nullptr) const
{
if (!hasValue())
return ValuePtr();
return Value::createValueFromStrings(getResolvedValueString(resolver), getType());
}
ValuePtr getResolvedValue(StringResolverPtr resolver = nullptr) const;

/// Return the default value for this element as a generic value object, which
/// may be queried to access its data.
Expand Down
8 changes: 8 additions & 0 deletions source/MaterialXCore/Exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class MX_CORE_API Exception : public std::exception
string _msg;
};

/// @class ExceptionTypeError
/// An exception that is thrown when a type mismatch is encountered.
class MX_CORE_API ExceptionTypeError : public Exception
{
public:
using Exception::Exception;
};

MATERIALX_NAMESPACE_END

#endif
74 changes: 73 additions & 1 deletion source/MaterialXCore/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// SPDX-License-Identifier: Apache-2.0
//

#include <MaterialXCore/Definition.h>
#include <MaterialXCore/Document.h>
#include <MaterialXCore/Value.h>

#include <iomanip>
Expand Down Expand Up @@ -267,12 +269,18 @@ template <class T> ValuePtr TypedValue<T>::createFromString(const string& value)
// Value methods
//

ValuePtr Value::createValueFromStrings(const string& value, const string& type)
ValuePtr Value::createValueFromStrings(const string& value, const string& type, ConstTypeDefPtr typeDef)
{
CreatorMap::iterator it = _creatorMap.find(type);
if (it != _creatorMap.end())
return it->second(value);

if (typeDef && !typeDef->getMembers().empty())
{
// If we're given a TypeDef pointer that has child members, then we can create a new AggregateValue.
return AggregateValue::createAggregateValueFromString(value, type, typeDef);
}

return TypedValue<string>::createFromString(value);
}

Expand All @@ -291,6 +299,70 @@ template <class T> const T& Value::asA() const
return typedVal->getData();
}

template <>
MX_CORE_API bool Value::isA<AggregateValue>() const
{
return dynamic_cast<const AggregateValue*>(this) != nullptr;
}

template <>
MX_CORE_API const AggregateValue& Value::asA<AggregateValue>() const
{
const AggregateValue* typedVal = dynamic_cast<const AggregateValue*>(this);
if (!typedVal)
{
throw ExceptionTypeError("Incorrect type specified for value");
}
return *typedVal;
}

/// Return value string.
string AggregateValue::getValueString() const
{
if (_data.empty())
return "";

std::string result = "{";
std::string separator = "";
for (const auto& val : _data)
{
result += separator + val->getValueString();
separator = ";";
}
result += "}";

return result;
}

AggregateValuePtr AggregateValue::createAggregateValueFromString(const string& value, const string& type, ConstTypeDefPtr typeDefPtr)
{
StringVec subValues = parseStructValueString(value);

AggregateValuePtr result = AggregateValue::createAggregateValue(type);
const auto& members = typeDefPtr->getMembers();

if (subValues.size() != members.size())
{
std::stringstream ss;
ss << "Wrong number of initializers - expect " << members.size();
throw Exception(ss.str());
}

auto doc = typeDefPtr->getDocument();
for (size_t i = 0; i < members.size(); ++i)
{
const auto& member = members[i];

// This will return nullptr if the type is not a listed typedef.
ConstTypeDefPtr subTypeDef = doc->getTypeDef(members[i]->getType());

// Calling Value::createValueFromStrings() here allows support for recursively nested structs.
result->appendValue(Value::createValueFromStrings(subValues[i], member->getType(), subTypeDef));
}

return result;
}

ScopedFloatFormatting::ScopedFloatFormatting(Value::FloatFormat format, int precision) :
_format(Value::getFloatFormat()),
_precision(Value::getFloatPrecision())
Expand Down
81 changes: 72 additions & 9 deletions source/MaterialXCore/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,22 @@ using BoolVec = vector<bool>;
using FloatVec = vector<float>;

class Value;
class AggregateValue;

/// A shared pointer to a Value
using ValuePtr = shared_ptr<Value>;
/// A shared pointer to a const Value
using ConstValuePtr = shared_ptr<const Value>;

template <class T> class TypedValue;
/// A shared pointer to an Aggregate Value
using AggregateValuePtr = shared_ptr<AggregateValue>;
/// A shared pointer to a const Aggregate Value
using ConstAggregateValuePtr = shared_ptr<const AggregateValue>;

/// @class ExceptionTypeError
/// An exception that is thrown when a type mismatch is encountered.
class MX_CORE_API ExceptionTypeError : public Exception
{
public:
using Exception::Exception;
};
class TypeDef;
using ConstTypeDefPtr = shared_ptr<const TypeDef>;

template <class T> class TypedValue;

/// A generic, discriminated value, whose type may be queried dynamically.
class MX_CORE_API Value
Expand Down Expand Up @@ -73,7 +74,7 @@ class MX_CORE_API Value
/// Create a new value instance from value and type strings.
/// @return A shared pointer to a typed value, or an empty shared pointer
/// if the conversion to the given data type cannot be performed.
static ValuePtr createValueFromStrings(const string& value, const string& type);
static ValuePtr createValueFromStrings(const string& value, const string& type, ConstTypeDefPtr typeDef = nullptr);

/// Create a deep copy of the value.
virtual ValuePtr copy() const = 0;
Expand Down Expand Up @@ -193,6 +194,68 @@ template <class T> class MX_CORE_API TypedValue : public Value
T _data;
};

/// The class template for typed subclasses of Value
class MX_CORE_API AggregateValue : public Value
{
public:
AggregateValue(const string& typeName) :
_typeName(typeName)
{
}
virtual ~AggregateValue() { }

/// Create a deep copy of the value.
ValuePtr copy() const override
{
auto result = createAggregateValue(_typeName);
for (const auto& val : _data)
{
result->appendValue(val->copy());
}
return result;
}

/// Append a member value to the aggregate.
void appendValue(ConstValuePtr valuePtr)
{
_data.emplace_back(valuePtr);
}

const vector<ConstValuePtr>& getMembers() const
{
return _data;
}

/// Query an indexed member value from the aggregate.
ConstValuePtr getMemberValue(size_t index) const
{
return _data[index];
}

/// Return type string.
const string& getTypeString() const override { return _typeName; }

/// Return value string.
string getValueString() const override;

//
// Static helper methods
//

/// Create a new value from an object of any valid MaterialX type.
static AggregateValuePtr createAggregateValue(const string& typeName)
{
return std::make_shared<AggregateValue>(typeName);
}

static AggregateValuePtr createAggregateValueFromString(const string& value, const string& type, ConstTypeDefPtr typeDefPtr);

private:
const string _typeName;

vector<ConstValuePtr> _data;
};

/// @class ScopedFloatFormatting
/// An RAII class for controlling the float formatting of values.
class MX_CORE_API ScopedFloatFormatting
Expand Down
37 changes: 37 additions & 0 deletions source/MaterialXGenGlsl/GlslSyntax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,41 @@ bool GlslSyntax::remapEnumeration(const string& value, TypeDesc type, const stri
return true;
}

StructTypeSyntaxPtr GlslSyntax::createStructSyntax(const string& structTypeName, const string& defaultValue,
const string& uniformDefaultValue, const string& typeAlias,
const string& typeDefinition) const
{
return std::make_shared<GlslStructTypeSyntax>(
this,
structTypeName,
defaultValue,
uniformDefaultValue,
typeAlias,
typeDefinition);
}

string GlslStructTypeSyntax::getValue(const Value& value, bool /* uniform */) const
{
const AggregateValue& aggValue = static_cast<const AggregateValue&>(value);

string result = aggValue.getTypeString() + "(";

string separator = "";
for (const auto& memberValue : aggValue.getMembers())
{
result += separator;
separator = ",";

auto memberTypeName = memberValue->getTypeString();
auto memberTypeDesc = TypeDesc::get(memberTypeName);

// Recursively use the syntax to generate the output, so we can supported nested structs.
result += _parentSyntax->getValue(memberTypeDesc, *memberValue, true);
}

result += ")";

return result;
}

MATERIALX_NAMESPACE_END
14 changes: 14 additions & 0 deletions source/MaterialXGenGlsl/GlslSyntax.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ class MX_GENGLSL_API GlslSyntax : public Syntax
static const StringVec VEC2_MEMBERS;
static const StringVec VEC3_MEMBERS;
static const StringVec VEC4_MEMBERS;

protected:
StructTypeSyntaxPtr createStructSyntax(const string& structTypeName, const string& defaultValue,
const string& uniformDefaultValue, const string& typeAlias,
const string& typeDefinition) const override;
};

/// Specialization of TypeSyntax for aggregate types.
class MX_GENGLSL_API GlslStructTypeSyntax : public StructTypeSyntax
{
public:
using StructTypeSyntax::StructTypeSyntax;

string getValue(const Value& value, bool uniform) const override;
};

MATERIALX_NAMESPACE_END
Expand Down
Loading