Implement type conversion for NodeItem #10

Closed
Bogdan Nagirniak wants to merge 9 commits from BogdanNagirniak/blender:matx-nodeitem-type into matx-export-material

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 188 additions and 0 deletions
Showing only changes of commit 87237c88e3 - Show all commits

View File

@ -431,6 +431,179 @@ NodeItem NodeItem::exp() const
return arithmetic("exp", [](float a) { return std::expf(a); });
}
NodeItem NodeItem::convert(Type to_type) const
{
Type t = type();
if (t == to_type) {
return *this;
}
if (!is_arithmetic(t) || !is_arithmetic(to_type)) {
return empty();
}
switch (t) {
case Type::Vector2:
switch (to_type) {
case Type::Vector4:
return convert(Type::Vector3).convert(Type::Vector4);
case Type::Color3:
return convert(Type::Vector3).convert(Type::Color3);
case Type::Color4:
return convert(Type::Vector3).convert(Type::Color3).convert(Type::Color4);
default:
break;
}
break;
case Type::Vector3:
switch (to_type) {
case Type::Color4:
return convert(Type::Color3).convert(Type::Color4);
default:
break;
}
break;
case Type::Vector4:
switch (to_type) {
case Type::Vector2:
return convert(Type::Vector3).convert(Type::Vector2);
case Type::Color3:
return convert(Type::Vector3).convert(Type::Color3);
default:
break;
}
break;
case Type::Color3:
switch (to_type) {
case Type::Vector2:
return convert(Type::Vector3).convert(Type::Vector2);
case Type::Vector4:
return convert(Type::Vector3).convert(Type::Vector4);
default:
break;
}
break;
case Type::Color4:
switch (to_type) {
case Type::Vector2:
return convert(Type::Vector4).convert(Type::Vector3).convert(Type::Vector2);
case Type::Vector3:
return convert(Type::Vector4).convert(Type::Vector3);
default:
break;
}
break;
default:
break;
}
NodeItem res = empty();
if (value) {
switch (t) {
case Type::Float: {
float v = value->asA<float>();
switch (to_type) {
case Type::Vector2:
res.value = MaterialX::Value::createValue<MaterialX::Vector2>({v, v});
break;
case Type::Vector3:
res.value = MaterialX::Value::createValue<MaterialX::Vector3>({v, v, v});
break;
case Type::Vector4:
res.value = MaterialX::Value::createValue<MaterialX::Vector4>({v, v, v, 1.0f});
break;
case Type::Color3:
res.value = MaterialX::Value::createValue<MaterialX::Color3>({v, v, v});
break;
case Type::Color4:
res.value = MaterialX::Value::createValue<MaterialX::Color4>({v, v, v, 1.0f});
break;
default:
BLI_assert_unreachable();
}
break;
}
case Type::Vector2: {
auto v = value->asA<MaterialX::Vector2>();
switch (to_type) {
case Type::Vector3:
res.value = MaterialX::Value::createValue<MaterialX::Vector3>({v[0], v[1], 0.0f});
break;
default:
BLI_assert_unreachable();
}
break;
}
case Type::Vector3: {
auto v = value->asA<MaterialX::Vector3>();
switch (to_type) {
case Type::Vector2:
res.value = MaterialX::Value::createValue<MaterialX::Vector2>({v[0], v[1]});
break;
case Type::Vector4:
res.value =
MaterialX::Value::createValue<MaterialX::Vector4>({v[0], v[1], v[2], 0.0f});
break;
case Type::Color3:
res.value = MaterialX::Value::createValue<MaterialX::Color3>({v[0], v[1], v[2]});
break;
default:
BLI_assert_unreachable();
}
break;
}
case Type::Vector4: {
auto v = value->asA<MaterialX::Vector4>();
switch (to_type) {
case Type::Vector3:
res.value = MaterialX::Value::createValue<MaterialX::Vector3>({v[0], v[1], v[2]});
break;
case Type::Color4:
res.value = MaterialX::Value::createValue<MaterialX::Color4>({v[0], v[1], v[2], v[3]});
break;
default:
BLI_assert_unreachable();
}
break;
}
case Type::Color3: {
auto v = value->asA<MaterialX::Color3>();
switch (to_type) {
case Type::Vector3:
res.value = MaterialX::Value::createValue<MaterialX::Vector3>({v[0], v[1], v[2]});
break;
case Type::Color4:
res.value = MaterialX::Value::createValue<MaterialX::Color4>({v[0], v[1], v[2], 1.0f});
break;
default:
BLI_assert_unreachable();
}
break;
}
case Type::Color4: {
auto v = value->asA<MaterialX::Color4>();
switch (to_type) {
case Type::Vector4:
res.value = MaterialX::Value::createValue<MaterialX::Vector4>({v[0], v[1], v[2], v[3]});
break;
case Type::Color3:
res.value = MaterialX::Value::createValue<MaterialX::Color3>({v[0], v[1], v[2]});
break;
default:
BLI_assert_unreachable();
}
break;
}
default:
BLI_assert_unreachable();
}
}
else {
res.node = graph_->addNode("convert", MaterialX::EMPTY_STRING, type(to_type));
res.set_input("in", *this);
}
return res;
}
NodeItem NodeItem::to_color3() const
{
Type mx_type = type();
@ -493,6 +666,16 @@ NodeItem::Type NodeItem::type() const
return Type::Empty;
}
bool NodeItem::is_arithmetic(Type t)
{
return t >= Type::Float;
}
bool NodeItem::is_arithmetic() const
{
return is_arithmetic(type());
}
NodeItem NodeItem::arithmetic(const std::string &mx_category,
std::function<float(float)> func) const
{

View File

@ -79,11 +79,16 @@ class NodeItem {
NodeItem sign() const;
NodeItem exp() const;
NodeItem convert(Type to_type) const;
NodeItem to_color3() const;
bool is_numeric() const;
Type type() const;
private:
static bool is_arithmetic(Type t);
bool is_arithmetic() const;
NodeItem arithmetic(const std::string &mx_category, std::function<float(float)> func) const;
NodeItem arithmetic(const NodeItem &other,
const std::string &mx_category,