forked from blender/blender
Implement type conversion for NodeItem #9
@ -12,125 +12,6 @@ namespace blender::nodes::materialx {
|
|||||||
|
|
||||||
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
NodeItem::NodeItem(MaterialX::GraphElement *graph) : graph_(graph) {}
|
||||||
|
|
||||||
NodeItem::Type NodeItem::type(const std::string &type_str)
|
|
||||||
{
|
|
||||||
if (type_str == "string") {
|
|
||||||
return Type::String;
|
|
||||||
}
|
|
||||||
if (type_str == "integer") {
|
|
||||||
return Type::Integer;
|
|
||||||
}
|
|
||||||
if (type_str == "float") {
|
|
||||||
return Type::Float;
|
|
||||||
}
|
|
||||||
if (type_str == "vector2") {
|
|
||||||
return Type::Vector2;
|
|
||||||
}
|
|
||||||
if (type_str == "vector3") {
|
|
||||||
return Type::Vector3;
|
|
||||||
}
|
|
||||||
if (type_str == "vector4") {
|
|
||||||
return Type::Vector4;
|
|
||||||
}
|
|
||||||
if (type_str == "color3") {
|
|
||||||
return Type::Color3;
|
|
||||||
}
|
|
||||||
if (type_str == "color4") {
|
|
||||||
return Type::Color4;
|
|
||||||
}
|
|
||||||
return Type::Other;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string NodeItem::type(Type tp)
|
|
||||||
{
|
|
||||||
switch (tp) {
|
|
||||||
case Type::String:
|
|
||||||
return "string";
|
|
||||||
case Type::Integer:
|
|
||||||
return "integer";
|
|
||||||
case Type::Float:
|
|
||||||
return "float";
|
|
||||||
case Type::Vector2:
|
|
||||||
return "vector2";
|
|
||||||
case Type::Vector3:
|
|
||||||
return "vector3";
|
|
||||||
case Type::Vector4:
|
|
||||||
return "vector4";
|
|
||||||
case Type::Color3:
|
|
||||||
return "color3";
|
|
||||||
case Type::Color4:
|
|
||||||
return "color4";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::empty() const
|
|
||||||
{
|
|
||||||
return NodeItem(graph_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeItem::set_input(const std::string &name,
|
|
||||||
const NodeItem &item,
|
|
||||||
const std::string &output_name)
|
|
||||||
{
|
|
||||||
if (item.value) {
|
|
||||||
Type t = item.type();
|
|
||||||
std::string mx_type = type(t);
|
|
||||||
switch (t) {
|
|
||||||
case Type::String:
|
|
||||||
set_input(name, item.value->asA<std::string>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Integer:
|
|
||||||
set_input(name, item.value->asA<int>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Float:
|
|
||||||
set_input(name, item.value->asA<float>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Vector2:
|
|
||||||
set_input(name, item.value->asA<MaterialX::Vector2>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Vector3:
|
|
||||||
set_input(name, item.value->asA<MaterialX::Vector3>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Vector4:
|
|
||||||
set_input(name, item.value->asA<MaterialX::Vector4>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Color3:
|
|
||||||
set_input(name, item.value->asA<MaterialX::Color3>(), mx_type);
|
|
||||||
break;
|
|
||||||
case Type::Color4:
|
|
||||||
set_input(name, item.value->asA<MaterialX::Color4>(), mx_type);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.node) {
|
|
||||||
node->setConnectedNode(name, item.node);
|
|
||||||
if (output_name != "") {
|
|
||||||
node->setConnectedOutput(name, item.node->getOutput(output_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", name.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeItem::set_input(const std::string &name,
|
|
||||||
const NodeItem &item,
|
|
||||||
Type in_type,
|
|
||||||
const std::string &output_name)
|
|
||||||
{
|
|
||||||
set_input(name, item.convert(in_type), output_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodeItem::add_output(const std::string &name, Type out_type)
|
|
||||||
{
|
|
||||||
node->addOutput(name, type(out_type));
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem::operator bool() const
|
NodeItem::operator bool() const
|
||||||
{
|
{
|
||||||
return value || node;
|
return value || node;
|
||||||
@ -270,67 +151,6 @@ NodeItem NodeItem::dotproduct(const NodeItem &other) const
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem NodeItem::if_else(IfType condition,
|
|
||||||
const NodeItem &other,
|
|
||||||
const NodeItem &if_val,
|
|
||||||
const NodeItem &else_val) const
|
|
||||||
{
|
|
||||||
switch (condition) {
|
|
||||||
case IfType::Less:
|
|
||||||
return other.if_else(IfType::Greater, *this, else_val, if_val);
|
|
||||||
case IfType::LessEq:
|
|
||||||
return other.if_else(IfType::GreaterEq, *this, else_val, if_val);
|
|
||||||
case IfType::NotEq:
|
|
||||||
return if_else(IfType::Eq, other, else_val, if_val);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem res = empty();
|
|
||||||
if (type() != Type::Float || other.type() != Type::Float) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto item1 = if_val;
|
|
||||||
auto item2 = else_val;
|
|
||||||
Type tp = adjust_types(item1, item2);
|
|
||||||
if (tp == Type::Empty) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<bool(float, float)> func = nullptr;
|
|
||||||
std::string mx_category;
|
|
||||||
switch (condition) {
|
|
||||||
case IfType::Greater:
|
|
||||||
mx_category = "ifgreater";
|
|
||||||
func = [](float a, float b) { return a > b; };
|
|
||||||
break;
|
|
||||||
case IfType::GreaterEq:
|
|
||||||
mx_category = "ifgreatereq";
|
|
||||||
func = [](float a, float b) { return a >= b; };
|
|
||||||
break;
|
|
||||||
case IfType::Eq:
|
|
||||||
mx_category = "ifequal";
|
|
||||||
func = [](float a, float b) { return a == b; };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value && other.value) {
|
|
||||||
res = func(value->asA<float>(), other.value->asA<float>()) ? item1 : item2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
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", item1);
|
|
||||||
res.set_input("in2", item2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const
|
NodeItem NodeItem::blend(const NodeItem &a, const NodeItem &b) const
|
||||||
{
|
{
|
||||||
return (val(1.0f) - *this) * a + *this * b;
|
return (val(1.0f) - *this) * a + *this * b;
|
||||||
@ -590,6 +410,72 @@ NodeItem NodeItem::convert(Type to_type) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::if_else(IfType condition,
|
||||||
|
const NodeItem &other,
|
||||||
|
const NodeItem &if_val,
|
||||||
|
const NodeItem &else_val) const
|
||||||
|
{
|
||||||
|
switch (condition) {
|
||||||
|
case IfType::Less:
|
||||||
|
return other.if_else(IfType::Greater, *this, else_val, if_val);
|
||||||
|
case IfType::LessEq:
|
||||||
|
return other.if_else(IfType::GreaterEq, *this, else_val, if_val);
|
||||||
|
case IfType::NotEq:
|
||||||
|
return if_else(IfType::Eq, other, else_val, if_val);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem res = empty();
|
||||||
|
if (type() != Type::Float || other.type() != Type::Float) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto item1 = if_val;
|
||||||
|
auto item2 = else_val;
|
||||||
|
Type tp = adjust_types(item1, item2);
|
||||||
BogdanNagirniak marked this conversation as resolved
|
|||||||
|
if (tp == Type::Empty) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::function<bool(float, float)> func = nullptr;
|
||||||
|
std::string mx_category;
|
||||||
|
switch (condition) {
|
||||||
|
case IfType::Greater:
|
||||||
|
mx_category = "ifgreater";
|
||||||
|
func = [](float a, float b) { return a > b; };
|
||||||
|
break;
|
||||||
|
case IfType::GreaterEq:
|
||||||
|
mx_category = "ifgreatereq";
|
||||||
|
func = [](float a, float b) { return a >= b; };
|
||||||
|
break;
|
||||||
|
case IfType::Eq:
|
||||||
|
mx_category = "ifequal";
|
||||||
|
func = [](float a, float b) { return a == b; };
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && other.value) {
|
||||||
|
res = func(value->asA<float>(), other.value->asA<float>()) ? item1 : item2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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", item1);
|
||||||
|
res.set_input("in2", item2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem NodeItem::empty() const
|
||||||
|
{
|
||||||
|
return NodeItem(graph_);
|
||||||
|
}
|
||||||
|
|
||||||
NodeItem::Type NodeItem::type() const
|
NodeItem::Type NodeItem::type() const
|
||||||
{
|
{
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -601,9 +487,143 @@ NodeItem::Type NodeItem::type() const
|
|||||||
return Type::Empty;
|
return Type::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeItem::is_arithmetic(Type t)
|
void NodeItem::set_input(const std::string &name,
|
||||||
|
const NodeItem &item,
|
||||||
|
const std::string &output_name)
|
||||||
{
|
{
|
||||||
return t >= Type::Float;
|
if (item.value) {
|
||||||
|
Type t = item.type();
|
||||||
|
std::string mx_type = type(t);
|
||||||
|
switch (t) {
|
||||||
|
case Type::String:
|
||||||
|
set_input(name, item.value->asA<std::string>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Integer:
|
||||||
|
set_input(name, item.value->asA<int>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Float:
|
||||||
|
set_input(name, item.value->asA<float>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Vector2:
|
||||||
|
set_input(name, item.value->asA<MaterialX::Vector2>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Vector3:
|
||||||
|
set_input(name, item.value->asA<MaterialX::Vector3>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Vector4:
|
||||||
|
set_input(name, item.value->asA<MaterialX::Vector4>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Color3:
|
||||||
|
set_input(name, item.value->asA<MaterialX::Color3>(), mx_type);
|
||||||
|
break;
|
||||||
|
case Type::Color4:
|
||||||
|
set_input(name, item.value->asA<MaterialX::Color4>(), mx_type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item.node) {
|
||||||
|
node->setConnectedNode(name, item.node);
|
||||||
|
if (output_name != "") {
|
||||||
|
node->setConnectedOutput(name, item.node->getOutput(output_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CLOG_WARN(LOG_MATERIALX_SHADER, "Empty item to input: %s", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &name,
|
||||||
|
const NodeItem &item,
|
||||||
|
Type in_type,
|
||||||
|
const std::string &output_name)
|
||||||
|
{
|
||||||
|
set_input(name, item.convert(in_type), output_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NodeItem::add_output(const std::string &name, Type out_type)
|
||||||
|
{
|
||||||
|
node->addOutput(name, type(out_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem::Type NodeItem::type(const std::string &tp)
|
||||||
|
{
|
||||||
|
if (tp == "string") {
|
||||||
|
return Type::String;
|
||||||
|
}
|
||||||
|
if (tp == "integer") {
|
||||||
|
return Type::Integer;
|
||||||
|
}
|
||||||
|
if (tp == "float") {
|
||||||
|
return Type::Float;
|
||||||
|
}
|
||||||
|
if (tp == "vector2") {
|
||||||
|
return Type::Vector2;
|
||||||
|
}
|
||||||
|
if (tp == "vector3") {
|
||||||
|
return Type::Vector3;
|
||||||
|
}
|
||||||
|
if (tp == "vector4") {
|
||||||
|
return Type::Vector4;
|
||||||
|
}
|
||||||
|
if (tp == "color3") {
|
||||||
|
return Type::Color3;
|
||||||
|
}
|
||||||
|
if (tp == "color4") {
|
||||||
|
return Type::Color4;
|
||||||
|
}
|
||||||
|
return Type::Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NodeItem::type(Type tp)
|
||||||
|
{
|
||||||
|
switch (tp) {
|
||||||
|
case Type::String:
|
||||||
|
return "string";
|
||||||
|
case Type::Integer:
|
||||||
|
return "integer";
|
||||||
|
case Type::Float:
|
||||||
|
return "float";
|
||||||
|
case Type::Vector2:
|
||||||
|
return "vector2";
|
||||||
|
case Type::Vector3:
|
||||||
|
return "vector3";
|
||||||
|
case Type::Vector4:
|
||||||
|
return "vector4";
|
||||||
|
case Type::Color3:
|
||||||
|
return "color3";
|
||||||
|
case Type::Color4:
|
||||||
|
return "color4";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NodeItem::is_arithmetic(Type tp)
|
||||||
|
{
|
||||||
|
return tp >= Type::Float;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
|
||||||
|
{
|
||||||
|
Type t1 = item1.type();
|
||||||
|
Type t2 = item2.type();
|
||||||
BogdanNagirniak marked this conversation as resolved
Outdated
Georgiy Markelov
commented
Type::Float -> Type::Integer Type::Float -> Type::Integer
Bogdan Nagirniak
commented
Integer isn't used in arithmetic operations Integer isn't used in arithmetic operations
|
|||||||
|
if (t1 == t2) {
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
|
if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
|
||||||
|
return Type::Empty;
|
||||||
|
}
|
||||||
|
if (t1 < t2) {
|
||||||
|
item1 = item1.convert(t2);
|
||||||
|
return t2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
item2 = item2.convert(t1);
|
||||||
|
return t1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeItem::is_arithmetic() const
|
bool NodeItem::is_arithmetic() const
|
||||||
@ -732,24 +752,4 @@ NodeItem NodeItem::arithmetic(const NodeItem &other,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeItem::Type NodeItem::adjust_types(NodeItem &item1, NodeItem &item2)
|
|
||||||
{
|
|
||||||
Type t1 = item1.type();
|
|
||||||
Type t2 = item2.type();
|
|
||||||
if (t1 == t2) {
|
|
||||||
return t1;
|
|
||||||
}
|
|
||||||
if (!is_arithmetic(t1) || !is_arithmetic(t2)) {
|
|
||||||
return Type::Empty;
|
|
||||||
}
|
|
||||||
if (t1 < t2) {
|
|
||||||
item1 = item1.convert(t2);
|
|
||||||
return t2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
item2 = item2.convert(t1);
|
|
||||||
return t1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::nodes::materialx
|
} // namespace blender::nodes::materialx
|
||||||
|
@ -35,23 +35,7 @@ class NodeItem {
|
|||||||
NodeItem(MaterialX::GraphElement *graph);
|
NodeItem(MaterialX::GraphElement *graph);
|
||||||
~NodeItem() = default;
|
~NodeItem() = default;
|
||||||
|
|
||||||
static Type type(const std::string &type_str);
|
/* Operators */
|
||||||
BogdanNagirniak marked this conversation as resolved
Georgiy Markelov
commented
Suggest add Suggest add `#pragma region` for such places
Bogdan Nagirniak
commented
It is not commonly used in Blender code It is not commonly used in Blender code
|
|||||||
static std::string type(Type tp);
|
|
||||||
|
|
||||||
NodeItem empty() const;
|
|
||||||
template<class T> NodeItem val(const T &data) const;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void set_input(const std::string &in_name, const T &value, const std::string &in_type);
|
|
||||||
void set_input(const std::string &in_name,
|
|
||||||
const NodeItem &item,
|
|
||||||
const std::string &out_name = "");
|
|
||||||
void set_input(const std::string &in_name,
|
|
||||||
const NodeItem &item,
|
|
||||||
Type in_type,
|
|
||||||
const std::string &out_name = "");
|
|
||||||
void add_output(const std::string &in_name, Type out_type);
|
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
NodeItem operator+(const NodeItem &other) const;
|
NodeItem operator+(const NodeItem &other) const;
|
||||||
NodeItem operator-(const NodeItem &other) const;
|
NodeItem operator-(const NodeItem &other) const;
|
||||||
@ -63,16 +47,13 @@ class NodeItem {
|
|||||||
bool operator==(const NodeItem &other) const;
|
bool operator==(const NodeItem &other) const;
|
||||||
bool operator!=(const NodeItem &other) const;
|
bool operator!=(const NodeItem &other) const;
|
||||||
|
|
||||||
|
/* Math functions */
|
||||||
NodeItem abs() const;
|
NodeItem abs() const;
|
||||||
NodeItem floor() const;
|
NodeItem floor() const;
|
||||||
NodeItem ceil() const;
|
NodeItem ceil() const;
|
||||||
NodeItem min(const NodeItem &other) const;
|
NodeItem min(const NodeItem &other) const;
|
||||||
NodeItem max(const NodeItem &other) const;
|
NodeItem max(const NodeItem &other) const;
|
||||||
NodeItem dotproduct(const NodeItem &other) const;
|
NodeItem dotproduct(const NodeItem &other) const;
|
||||||
NodeItem if_else(IfType condition,
|
|
||||||
const NodeItem &other,
|
|
||||||
const NodeItem &if_val,
|
|
||||||
const NodeItem &else_val) const;
|
|
||||||
NodeItem blend(const NodeItem &a, const NodeItem &b) const;
|
NodeItem blend(const NodeItem &a, const NodeItem &b) const;
|
||||||
NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const;
|
NodeItem clamp(const NodeItem &min_val, const NodeItem &max_val) const;
|
||||||
NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const;
|
NodeItem clamp(float min_val = 0.0f, float max_val = 1.0f) const;
|
||||||
@ -90,20 +71,40 @@ class NodeItem {
|
|||||||
NodeItem sqrt() const;
|
NodeItem sqrt() const;
|
||||||
NodeItem sign() const;
|
NodeItem sign() const;
|
||||||
NodeItem exp() const;
|
NodeItem exp() const;
|
||||||
|
|
||||||
NodeItem convert(Type to_type) const;
|
NodeItem convert(Type to_type) const;
|
||||||
|
NodeItem if_else(IfType condition,
|
||||||
|
const NodeItem &other,
|
||||||
|
const NodeItem &if_val,
|
||||||
|
const NodeItem &else_val) const;
|
||||||
|
|
||||||
|
/* Useful functions */
|
||||||
|
NodeItem empty() const;
|
||||||
|
template<class T> NodeItem val(const T &data) const;
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
|
/* Functions to set input and output */
|
||||||
|
template<class T>
|
||||||
|
void set_input(const std::string &in_name, const T &value, const std::string &in_type);
|
||||||
|
void set_input(const std::string &in_name,
|
||||||
|
const NodeItem &item,
|
||||||
|
const std::string &out_name = "");
|
||||||
|
void set_input(const std::string &in_name,
|
||||||
|
const NodeItem &item,
|
||||||
|
Type in_type,
|
||||||
|
const std::string &out_name = "");
|
||||||
|
void add_output(const std::string &in_name, Type out_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool is_arithmetic(Type t);
|
static Type type(const std::string &tp);
|
||||||
|
static std::string type(Type tp);
|
||||||
|
static bool is_arithmetic(Type tp);
|
||||||
|
static Type adjust_types(NodeItem &item1, NodeItem &item2);
|
||||||
|
|
||||||
bool is_arithmetic() const;
|
bool is_arithmetic() const;
|
||||||
|
|
||||||
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
|
NodeItem arithmetic(const std::string &category, std::function<float(float)> func) const;
|
||||||
NodeItem arithmetic(const NodeItem &other,
|
NodeItem arithmetic(const NodeItem &other,
|
||||||
const std::string &category,
|
const std::string &category,
|
||||||
std::function<float(float, float)> func) const;
|
std::function<float(float, float)> func) const;
|
||||||
static Type adjust_types(NodeItem &item1, NodeItem &item2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> NodeItem NodeItem::val(const T &data) const
|
template<class T> NodeItem NodeItem::val(const T &data) const
|
||||||
|
Loading…
Reference in New Issue
Block a user
Should
Integer
be here?Discussed: let it be here