Support group nodes #22

Merged
Bogdan Nagirniak merged 18 commits from BogdanNagirniak/blender:matx-group-nodes into matx-export-material 2023-09-18 12:49:19 +02:00
7 changed files with 69 additions and 41 deletions
Showing only changes of commit 6a68376723 - Show all commits

View File

@ -5,6 +5,8 @@
#include "node_parser.h" #include "node_parser.h"
#include "group_nodes.h" #include "group_nodes.h"
#include "BLI_vector.hh"
namespace blender::nodes::materialx { namespace blender::nodes::materialx {
NodeItem GroupNodeParser::compute() NodeItem GroupNodeParser::compute()
@ -18,15 +20,16 @@ NodeItem GroupNodeParser::compute()
return res; return res;
} }
std::string name = MaterialX::createValidName(ngroup->idname); std::string name = MaterialX::createValidName(ngroup->id.name);
MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType<MaterialX::NodeGraph>(name); MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType<MaterialX::NodeGraph>(name);
if (!group_graph) { if (!group_graph) {
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "<nodegraph name=%s>", name.c_str());
group_graph = graph_->addChild<MaterialX::NodeGraph>(name); group_graph = graph_->addChild<MaterialX::NodeGraph>(name);
} }
NodeItem out = NodeItem out =
GroupOutputNodeParser( GroupOutputNodeParser(
group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any) group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any, this)
.compute_full(); .compute_full();
/* We have to be in NodeParser's graph_, therefore copying output */ /* We have to be in NodeParser's graph_, therefore copying output */
@ -36,24 +39,45 @@ NodeItem GroupNodeParser::compute()
NodeItem GroupOutputNodeParser::compute() NodeItem GroupOutputNodeParser::compute()
{ {
NodeItem value = get_input_value(socket_out_->index(), to_type_); Vector<NodeItem> values;
NodeItem res = create_output(); for (auto socket_in : node_->input_sockets()) {
res.set_output(value); values.append(get_input_value(socket_in->index(), NodeItem::Type::Any));
}
Vector<NodeItem> outputs;
for (int i = 0; i < values.size(); ++i) {
if (values[i]) {
outputs.append(create_output());
outputs[i].set_output(values[i]);
outputs[i].output->setName("output" + std::to_string(i + 1));
}
}
return outputs[socket_out_->index()];
}
NodeItem GroupOutputNodeParser::compute_full()
{
NodeItem res = empty();
/* Checking if output was already computed */
res.output = graph_->getOutput("output" + std::to_string(socket_out_->index() + 1));
if (res.output) {
return res; return res;
} }
std::string GroupOutputNodeParser::name_out() const CLOG_INFO(LOG_MATERIALX_SHADER,
{ 1,
std::string name = "output"; "%s [%d] => %s",
if (node_->input_sockets().size() > 1) { node_->name,
name += std::to_string(socket_out_->index() + 1); node_->typeinfo->type,
} NodeItem::type(to_type_).c_str());
return name;
res = compute();
return res;
} }
NodeItem GroupInputNodeParser::compute() NodeItem GroupInputNodeParser::compute()
{ {
auto in = graph_->addInput(); //auto in = graph_->addInput();
return empty(); return empty();
} }

View File

@ -18,9 +18,7 @@ class GroupOutputNodeParser : public NodeParser {
public: public:
using NodeParser::NodeParser; using NodeParser::NodeParser;
NodeItem compute() override; NodeItem compute() override;
NodeItem compute_full() override;
protected:
std::string name_out() const override;
}; };
class GroupInputNodeParser : public NodeParser { class GroupInputNodeParser : public NodeParser {

View File

@ -62,18 +62,18 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, Material *mater
bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL);
if (output_node) { if (output_node) {
NodeParserData data = { NodeParserData data = {
doc.get(), depsgraph, material, NodeItem::Type::Material, NodeItem(doc.get())}; doc.get(), depsgraph, material, NodeItem::Type::Material, nullptr, NodeItem(doc.get())};
output_node->typeinfo->materialx_fn(&data, output_node, nullptr); output_node->typeinfo->materialx_fn(&data, output_node, nullptr);
} }
else { else {
DefaultMaterialNodeParser( DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material) doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
.compute_error(); .compute_error();
} }
} }
else { else {
DefaultMaterialNodeParser( DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material) doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
.compute(); .compute();
} }

View File

@ -63,7 +63,7 @@ std::string NodeItem::type(Type type)
{ {
switch (type) { switch (type) {
case Type::Any: case Type::Any:
return ""; return "any";
case Type::String: case Type::String:
return "string"; return "string";
case Type::Filename: case Type::Filename:
@ -693,10 +693,10 @@ NodeItem NodeItem::add_output(const std::string &out_name, Type out_type)
return res; return res;
} }
NodeItem NodeItem::create_output(const std::string &out_name) const NodeItem NodeItem::create_output() const
{ {
NodeItem res = empty(); NodeItem res = empty();
res.output = graph_->addOutput(out_name); res.output = graph_->addOutput();
return res; return res;
} }

View File

@ -111,7 +111,7 @@ class NodeItem {
NodeItem add_output(const std::string &out_name, Type out_type); NodeItem add_output(const std::string &out_name, Type out_type);
/* Output functions */ /* Output functions */
NodeItem create_output(const std::string &out_name) const; NodeItem create_output() const;
template<class T> void set_output(const T &value, Type out_type) const; template<class T> void set_output(const T &value, Type out_type) const;
void set_output(const NodeItem &item) const; void set_output(const NodeItem &item) const;

View File

@ -19,13 +19,15 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const Material *material, const Material *material,
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
NodeItem::Type to_type) NodeItem::Type to_type,
GroupNodeParser *group_parser)
: graph_(graph), : graph_(graph),
depsgraph_(depsgraph), depsgraph_(depsgraph),
material_(material), material_(material),
node_(node), node_(node),
socket_out_(socket_out), socket_out_(socket_out),
to_type_(to_type) to_type_(to_type),
group_parser_(group_parser)
{ {
} }
@ -34,14 +36,10 @@ NodeItem NodeParser::compute_full()
NodeItem res = empty(); NodeItem res = empty();
/* Checking if node was already computed */ /* Checking if node was already computed */
res.node = graph_->getNode(name_out()); res.node = graph_->getNode(node_name());
if (res.node) { if (res.node) {
return res; return res;
} }
res.output = graph_->getOutput(name_out());
if (res.output) {
return res;
}
CLOG_INFO(LOG_MATERIALX_SHADER, CLOG_INFO(LOG_MATERIALX_SHADER,
1, 1,
@ -52,10 +50,7 @@ NodeItem NodeParser::compute_full()
res = compute(); res = compute();
if (res.node) { if (res.node) {
res.node->setName(name_out()); res.node->setName(node_name());
}
else if (res.output) {
res.output->setName(name_out());
} }
if (NodeItem::is_arithmetic(to_type_)) { if (NodeItem::is_arithmetic(to_type_)) {
res = res.convert(to_type_); res = res.convert(to_type_);
@ -63,7 +58,7 @@ NodeItem NodeParser::compute_full()
return res; return res;
} }
std::string NodeParser::name_out() const std::string NodeParser::node_name() const
{ {
std::string name = node_->name; std::string name = node_->name;
if (node_->output_sockets().size() > 1) { if (node_->output_sockets().size() > 1) {
@ -82,7 +77,7 @@ NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type typ
NodeItem NodeParser::create_output() NodeItem NodeParser::create_output()
{ {
return empty().create_output(""); return empty().create_output();
} }
NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type) NodeItem NodeParser::get_input_default(const std::string &name, NodeItem::Type to_type)
@ -135,6 +130,9 @@ NodeItem NodeParser::get_input_default(const bNodeSocket &socket, NodeItem::Type
{ {
NodeItem res = empty(); NodeItem res = empty();
switch (socket.type) { switch (socket.type) {
case SOCK_CUSTOM:
/* Return empty */
break;
case SOCK_FLOAT: { case SOCK_FLOAT: {
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value; float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
res.value = MaterialX::Value::createValue<float>(v); res.value = MaterialX::Value::createValue<float>(v);
@ -178,11 +176,13 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
} }
if (from_node->is_group()) { if (from_node->is_group()) {
return GroupNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) return GroupNodeParser(
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_)
.compute_full(); .compute_full();
} }
if (from_node->is_group_input()) { if (from_node->is_group_input()) {
return GroupInputNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type) return GroupInputNodeParser(
graph_, depsgraph_, material_, from_node, link->fromsock, to_type, group_parser_)
.compute_full(); .compute_full();
} }
@ -194,7 +194,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
return empty(); return empty();
} }
NodeParserData data = {graph_, depsgraph_, material_, to_type, empty()}; NodeParserData data = {graph_, depsgraph_, material_, to_type, group_parser_, empty()};
from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock); from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock);
return data.result; return data.result;
} }

View File

@ -16,6 +16,8 @@ namespace blender::nodes::materialx {
extern struct CLG_LogRef *LOG_MATERIALX_SHADER; extern struct CLG_LogRef *LOG_MATERIALX_SHADER;
class GroupNodeParser;
class NodeParser { class NodeParser {
protected: protected:
MaterialX::GraphElement *graph_; MaterialX::GraphElement *graph_;
@ -24,6 +26,7 @@ class NodeParser {
const bNode *node_; const bNode *node_;
const bNodeSocket *socket_out_; const bNodeSocket *socket_out_;
NodeItem::Type to_type_; NodeItem::Type to_type_;
GroupNodeParser *group_parser_;
public: public:
NodeParser(MaterialX::GraphElement *graph, NodeParser(MaterialX::GraphElement *graph,
@ -31,14 +34,15 @@ class NodeParser {
const Material *material, const Material *material,
const bNode *node, const bNode *node,
const bNodeSocket *socket_out, const bNodeSocket *socket_out,
NodeItem::Type to_type); NodeItem::Type to_type,
GroupNodeParser *group_parser);
virtual ~NodeParser() = default; virtual ~NodeParser() = default;
virtual NodeItem compute() = 0; virtual NodeItem compute() = 0;
virtual NodeItem compute_full(); virtual NodeItem compute_full();
protected: protected:
virtual std::string name_out() const; std::string node_name() const;
NodeItem create_node(const std::string &category, NodeItem::Type type); NodeItem create_node(const std::string &category, NodeItem::Type type);
NodeItem create_output(); NodeItem create_output();
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type); NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
@ -70,6 +74,7 @@ struct NodeParserData {
const Depsgraph *depsgraph; const Depsgraph *depsgraph;
const Material *material; const Material *material;
NodeItem::Type to_type; NodeItem::Type to_type;
GroupNodeParser *group_parser;
NodeItem result; NodeItem result;
}; };
@ -90,7 +95,8 @@ struct NodeParserData {
void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *out) \ void node_shader_materialx(void *data, struct bNode *node, struct bNodeSocket *out) \
{ \ { \
materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); \ materialx::NodeParserData *d = reinterpret_cast<materialx::NodeParserData *>(data); \
d->result = MaterialXNodeParser(d->graph, d->depsgraph, d->material, node, out, d->to_type) \ d->result = MaterialXNodeParser( \
d->graph, d->depsgraph, d->material, node, out, d->to_type, d->group_parser) \
.compute_full(); \ .compute_full(); \
} }