Implement type conversion for NodeItem #9

Merged
Bogdan Nagirniak merged 12 commits from BogdanNagirniak/blender:matx-nodeitem-type into matx-export-material 2023-09-05 12:03:24 +02:00
2 changed files with 53 additions and 135 deletions
Showing only changes of commit 0cdb6a7bd1 - Show all commits

View File

@ -187,29 +187,14 @@ bool NodeItem::operator==(const NodeItem &other) const
return false;
}
Type mx_type;
auto val1 = value;
auto val2 = other.value;
if (!adjust_types(val1, val2, mx_type)) {
NodeItem item1 = *this;
NodeItem item2 = other;
Type tp = adjust_types(item1, item2);
if (tp == Type::Empty) {
return false;
}
switch (mx_type) {
case Type::Vector2:
return val1->asA<MaterialX::Vector2>() == val2->asA<MaterialX::Vector2>();
case Type::Vector3:
return val1->asA<MaterialX::Vector3>() == val2->asA<MaterialX::Vector3>();
case Type::Vector4:
return val1->asA<MaterialX::Vector4>() == val2->asA<MaterialX::Vector4>();
case Type::Float:
return val1->asA<float>() == val2->asA<float>();
case Type::Color3:
return val1->asA<MaterialX::Color3>() == val2->asA<MaterialX::Color3>();
case Type::Color4:
return val1->asA<MaterialX::Color4>() == val2->asA<MaterialX::Color4>();
default:
break;
}
return false;
return item1.value->getValueString() == item2.value->getValueString();
}
bool NodeItem::operator!=(const NodeItem &other) const
@ -307,10 +292,10 @@ NodeItem NodeItem::if_else(IfType condition,
return res;
}
auto val1 = if_val;
auto val2 = else_val;
Type mx_type;
if (!adjust_types(val1, val2, mx_type)) {
auto item1 = if_val;
auto item2 = else_val;
Type tp = adjust_types(item1, item2);
if (tp == Type::Empty) {
return res;
}
@ -334,14 +319,14 @@ NodeItem NodeItem::if_else(IfType condition,
}
if (value && other.value) {
res = func(value->asA<float>(), other.value->asA<float>()) ? val1 : val2;
res = func(value->asA<float>(), other.value->asA<float>()) ? item1 : item2;
}
else {
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, type(mx_type));
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, type(tp));
res.set_input("value1", *this);
res.set_input("value2", other);
res.set_input("in1", val1);
res.set_input("in2", val2);
res.set_input("in1", item1);
res.set_input("in2", item2);
}
return res;
@ -626,7 +611,7 @@ bool NodeItem::is_arithmetic() const
return is_arithmetic(type());
}
NodeItem NodeItem::arithmetic(const std::string &mx_category,
NodeItem NodeItem::arithmetic(const std::string &category,
std::function<float(float)> func) const
{
NodeItem res = empty();
@ -675,67 +660,63 @@ NodeItem NodeItem::arithmetic(const std::string &mx_category,
}
}
else {
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, type(t));
res.node = graph_->addNode(category, MaterialX::EMPTY_STRING, type(t));
res.set_input("in", *this);
}
return res;
}
NodeItem NodeItem::arithmetic(const NodeItem &other,
const std::string &mx_category,
const std::string &category,
std::function<float(float, float)> func) const
{
NodeItem res = empty();
if (!is_arithmetic() || !other.is_arithmetic()) {
NodeItem item1 = *this;
NodeItem item2 = other;
Type tp = adjust_types(item1, item2);
if (tp == Type::Empty) {
return res;
}
Type mx_type;
if (value && other.value) {
auto val1 = value;
auto val2 = other.value;
if (!adjust_types(val1, val2, mx_type)) {
return res;
}
switch (mx_type) {
switch (tp) {
case Type::Float: {
float v1 = val1->asA<float>();
float v2 = val2->asA<float>();
float v1 = item1.value->asA<float>();
float v2 = item2.value->asA<float>();
res.value = MaterialX::Value::createValue<float>(func(v1, v2));
break;
}
case Type::Color3: {
auto v1 = val1->asA<MaterialX::Color3>();
auto v2 = val2->asA<MaterialX::Color3>();
auto v1 = item1.value->asA<MaterialX::Color3>();
auto v2 = item2.value->asA<MaterialX::Color3>();
res.value = MaterialX::Value::createValue<MaterialX::Color3>(
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
break;
}
case Type::Color4: {
auto v1 = val1->asA<MaterialX::Color4>();
auto v2 = val2->asA<MaterialX::Color4>();
auto v1 = item1.value->asA<MaterialX::Color4>();
auto v2 = item2.value->asA<MaterialX::Color4>();
res.value = MaterialX::Value::createValue<MaterialX::Color4>(
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])});
break;
}
case Type::Vector2: {
auto v1 = val1->asA<MaterialX::Vector2>();
auto v2 = val2->asA<MaterialX::Vector2>();
auto v1 = item1.value->asA<MaterialX::Vector2>();
auto v2 = item2.value->asA<MaterialX::Vector2>();
res.value = MaterialX::Value::createValue<MaterialX::Vector2>(
{func(v1[0], v2[0]), func(v1[1], v2[1])});
break;
}
case Type::Vector3: {
auto v1 = val1->asA<MaterialX::Vector3>();
auto v2 = val2->asA<MaterialX::Vector3>();
auto v1 = item1.value->asA<MaterialX::Vector3>();
auto v2 = item2.value->asA<MaterialX::Vector3>();
res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2])});
break;
}
case Type::Vector4: {
auto v1 = val1->asA<MaterialX::Vector4>();
auto v2 = val2->asA<MaterialX::Vector4>();
auto v1 = item1.value->asA<MaterialX::Vector4>();
auto v2 = item2.value->asA<MaterialX::Vector4>();
res.value = MaterialX::Value::createValue<MaterialX::Vector4>(
{func(v1[0], v2[0]), func(v1[1], v2[1]), func(v1[2], v2[2]), func(v1[3], v2[3])});
break;
@ -745,91 +726,31 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
}
}
else {
auto val1 = *this;
auto val2 = other;
if (!adjust_types(val1, val2, mx_type)) {
return res;
}
res.node = graph_->addNode(mx_category, MaterialX::EMPTY_STRING, type(mx_type));
res.set_input("in1", val1);
res.set_input("in2", val2);
res.node = graph_->addNode(category, MaterialX::EMPTY_STRING, type(tp));
res.set_input("in1", item1);
res.set_input("in2", item2);
}
return res;
}
MaterialX::ValuePtr NodeItem::float_to_type(float v, Type mx_type)
NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
{
MaterialX::ValuePtr res;
switch (mx_type) {
case Type::Float:
res = MaterialX::Value::createValue<float>(v);
break;
case Type::Vector2:
res = MaterialX::Value::createValue<MaterialX::Vector2>({v, v});
break;
case Type::Vector3:
res = MaterialX::Value::createValue<MaterialX::Vector3>({v, v, v});
break;
case Type::Vector4:
res = MaterialX::Value::createValue<MaterialX::Vector4>({v, v, v, v});
break;
case Type::Color3:
res = MaterialX::Value::createValue<MaterialX::Color3>({v, v, v});
break;
case Type::Color4:
res = MaterialX::Value::createValue<MaterialX::Color4>({v, v, v, v});
break;
default:
BLI_assert_unreachable();
Type t1 = item1.type();
Type t2 = item2.type();
if (t1 == t2) {
return t1;
}
return res;
if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
return Type::Empty;
}
bool NodeItem::adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, Type &mx_type)
{
Type t1 = type(val1->getTypeString());
Type t2 = type(val2->getTypeString());
if (t1 != t2) {
if (t1 == Type::Float) {
val1 = float_to_type(val1->asA<float>(), t2);
mx_type = t2;
}
else if (t2 == Type::Float) {
val2 = float_to_type(val2->asA<float>(), t1);
mx_type = t1;
if (t1 < t2) {
item1 = item1.convert(t2);
return t2;
}
else {
return false;
item2 = item2.convert(t1);
return t1;
}
}
else {
mx_type = t1;
}
return true;
}
bool NodeItem::adjust_types(NodeItem &val1, NodeItem &val2, Type &mx_type)
{
Type t1 = val1.type();
Type t2 = val2.type();
if (t1 != t2) {
if (val1.value && t1 == Type::Float) {
val1.value = float_to_type(val1.value->asA<float>(), t2);
mx_type = t2;
}
else if (val2.value && t2 == Type::Float) {
val2.value = float_to_type(val2.value->asA<float>(), t1);
mx_type = t1;
}
else {
return false;
}
}
else {
mx_type = t1;
}
return true;
}
} // namespace blender::nodes::materialx

View File

@ -88,14 +88,11 @@ class NodeItem {
bool is_arithmetic() const;
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func) const;
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
NodeItem arithmetic(const NodeItem &other,
const std::string &mx_category,
const std::string &category,
std::function<float(float, float)> func) const;
static MaterialX::ValuePtr float_to_type(float v, Type mx_type);
/* Functions for adjusting values to make equal types */
static bool adjust_types(MaterialX::ValuePtr &val1, MaterialX::ValuePtr &val2, Type &mx_type);
static bool adjust_types(NodeItem &val1, NodeItem &val2, Type &mx_type);
static Type adjust_types(NodeItem &item1, NodeItem &item2);
};
template<class T> NodeItem NodeItem::val(const T &data) const