Files
SDL3CPlusPlus/MaterialX/source/MaterialXCore/Value.h
T
2026-01-06 13:25:49 +00:00

316 lines
8.6 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#ifndef MATERIALX_VALUE_H
#define MATERIALX_VALUE_H
/// @file
/// Generic value classes
#include <MaterialXCore/Exception.h>
#include <MaterialXCore/Types.h>
#include <MaterialXCore/Util.h>
MATERIALX_NAMESPACE_BEGIN
/// A vector of integers.
using IntVec = vector<int>;
/// A vector of booleans.
using BoolVec = vector<bool>;
/// A vector of floats.
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>;
/// 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 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
{
public:
/// Float formats to use when converting values to strings.
enum FloatFormat
{
FloatFormatDefault = 0,
FloatFormatFixed = 1,
FloatFormatScientific = 2
};
public:
Value()
{
}
virtual ~Value() { }
/// Create a new value from an object of any valid MaterialX type.
template <class T> static ValuePtr createValue(const T& data)
{
return std::make_shared<TypedValue<T>>(data);
}
// Create a new value from a C-style string.
static ValuePtr createValue(const char* data)
{
return createValue(data ? string(data) : EMPTY_STRING);
}
/// 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, ConstTypeDefPtr typeDef = nullptr);
/// Create a deep copy of the value.
virtual ValuePtr copy() const = 0;
/// @name Data Accessors
/// @{
/// Return true if this value is of the given type.
template <class T> bool isA() const;
/// Return our underlying data as an object of the given type.
/// If the given type doesn't match our own data type, then an
/// exception is thrown.
template <class T> const T& asA() const;
/// Return the type string for this value.
virtual const string& getTypeString() const = 0;
/// Return the value string for this value.
virtual string getValueString() const = 0;
/// Set float formatting for converting values to strings.
/// Formats to use are FloatFormatFixed, FloatFormatScientific
/// or FloatFormatDefault to set default format.
static void setFloatFormat(FloatFormat format);
/// Set float precision for converting values to strings.
static void setFloatPrecision(int precision);
/// Return the current float format.
static FloatFormat getFloatFormat();
/// Return the current float precision.
static int getFloatPrecision();
// Returns true if value data matches.
virtual bool isEqual(ConstValuePtr other) const = 0;
protected:
template <class T> friend class ValueRegistry;
using CreatorFunction = ValuePtr (*)(const string&);
using CreatorMap = std::unordered_map<string, CreatorFunction>;
private:
static CreatorMap _creatorMap;
};
/// The class template for typed subclasses of Value
template <class T> class TypedValue : public Value
{
public:
MX_CORE_API TypedValue() :
_data{}
{
}
MX_CORE_API explicit TypedValue(const T& value) :
_data(value)
{
}
MX_CORE_API virtual ~TypedValue() { }
/// Create a deep copy of the value.
MX_CORE_API ValuePtr copy() const override
{
return Value::createValue<T>(_data);
}
/// Set stored data object.
MX_CORE_API void setData(const T& value)
{
_data = value;
}
/// Set stored data object.
MX_CORE_API void setData(const TypedValue<T>& value)
{
_data = value._data;
}
/// Return stored data object.
MX_CORE_API const T& getData() const
{
return _data;
}
/// Return type string.
MX_CORE_API const string& getTypeString() const override;
/// Return value string.
MX_CORE_API string getValueString() const override;
// Returns true if value data matches.
MX_CORE_API bool isEqual(ConstValuePtr other) const override
{
if (!other || !other->isA<T>())
{
return false;
}
return _data == other->asA<T>();
}
//
// Static helper methods
//
/// Create a new value of this type from a value string.
/// @return A shared pointer to a typed value, or an empty shared pointer
/// if the conversion to the given data type cannot be performed.
MX_CORE_API static ValuePtr createFromString(const string& value);
public:
MX_CORE_API static const string TYPE;
private:
T _data;
};
/// A subclass for aggregate values with multiple members
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;
// Returns true if value data matches.
bool isEqual(ConstValuePtr other) 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
{
public:
explicit ScopedFloatFormatting(Value::FloatFormat format, int precision = -1);
~ScopedFloatFormatting();
private:
Value::FloatFormat _format;
int _precision;
};
/// Return the type string associated with the given data type.
template <class T> MX_CORE_API const string& getTypeString();
/// Convert the given data value to a value string.
template <class T> MX_CORE_API string toValueString(const T& data);
/// Convert the given value string to a data value of the given type.
/// @throws ExceptionTypeError if the conversion cannot be performed.
template <class T> MX_CORE_API T fromValueString(const string& value);
/// Tokenize the string representation of a struct value i.e, "{1;2;3}" into a
/// vector of substrings.
/// Note: "{1;2;{3;4;5}}" will be split in to ["1", "2", "{3;4;5}"]
MX_CORE_API StringVec parseStructValueString(const string& value);
/// Forward declaration of specific template instantiations.
/// Base types
MX_CORE_EXTERN_TEMPLATE(TypedValue<int>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<bool>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<float>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Color3>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Color4>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Vector2>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Vector3>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Vector4>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Matrix33>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<Matrix44>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<string>);
/// Array types
MX_CORE_EXTERN_TEMPLATE(TypedValue<IntVec>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<BoolVec>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<FloatVec>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<StringVec>);
/// Alias types
MX_CORE_EXTERN_TEMPLATE(TypedValue<long>);
MX_CORE_EXTERN_TEMPLATE(TypedValue<double>);
MATERIALX_NAMESPACE_END
#endif