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 "group_nodes.h"
#include "BLI_vector.hh"
namespace blender::nodes::materialx {
NodeItem GroupNodeParser::compute()
@ -18,15 +20,16 @@ NodeItem GroupNodeParser::compute()
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);
if (!group_graph) {
CLOG_INFO(LOG_MATERIALX_SHADER, 1, "<nodegraph name=%s>", name.c_str());
group_graph = graph_->addChild<MaterialX::NodeGraph>(name);
}
NodeItem out =
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();
/* We have to be in NodeParser's graph_, therefore copying output */
@ -36,24 +39,45 @@ NodeItem GroupNodeParser::compute()
NodeItem GroupOutputNodeParser::compute()
{
NodeItem value = get_input_value(socket_out_->index(), to_type_);
NodeItem res = create_output();
res.set_output(value);
Vector<NodeItem> values;
for (auto socket_in : node_->input_sockets()) {
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;
}
std::string GroupOutputNodeParser::name_out() const
{
std::string name = "output";
if (node_->input_sockets().size() > 1) {
name += std::to_string(socket_out_->index() + 1);
}
return name;
CLOG_INFO(LOG_MATERIALX_SHADER,
1,
"%s [%d] => %s",
node_->name,
node_->typeinfo->type,
NodeItem::type(to_type_).c_str());
res = compute();
return res;
}
NodeItem GroupInputNodeParser::compute()
{
auto in = graph_->addInput();
//auto in = graph_->addInput();
return empty();
}

View File

@ -18,9 +18,7 @@ class GroupOutputNodeParser : public NodeParser {
public:
using NodeParser::NodeParser;
NodeItem compute() override;
protected:
std::string name_out() const override;
NodeItem compute_full() override;
};
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);
if (output_node) {
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);
}
else {
DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material)
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
.compute_error();
}
}
else {
DefaultMaterialNodeParser(
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material)
doc.get(), depsgraph, material, nullptr, nullptr, NodeItem::Type::Material, nullptr)
.compute();
}

View File

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

View File

@ -111,7 +111,7 @@ class NodeItem {
NodeItem add_output(const std::string &out_name, Type out_type);
/* 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;
void set_output(const NodeItem &item) const;

View File

@ -19,13 +19,15 @@ NodeParser::NodeParser(MaterialX::GraphElement *graph,
const Material *material,
const bNode *node,
const bNodeSocket *socket_out,
NodeItem::Type to_type)
NodeItem::Type to_type,
GroupNodeParser *group_parser)
: graph_(graph),
depsgraph_(depsgraph),
material_(material),
node_(node),
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();
/* Checking if node was already computed */
res.node = graph_->getNode(name_out());
res.node = graph_->getNode(node_name());
if (res.node) {
return res;
}
res.output = graph_->getOutput(name_out());
if (res.output) {
return res;
}
CLOG_INFO(LOG_MATERIALX_SHADER,
1,
@ -52,10 +50,7 @@ NodeItem NodeParser::compute_full()
res = compute();
if (res.node) {
res.node->setName(name_out());
}
else if (res.output) {
res.output->setName(name_out());
res.node->setName(node_name());
}
if (NodeItem::is_arithmetic(to_type_)) {
res = res.convert(to_type_);
@ -63,7 +58,7 @@ NodeItem NodeParser::compute_full()
return res;
}
std::string NodeParser::name_out() const
std::string NodeParser::node_name() const
{
std::string name = node_->name;
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()
{
return empty().create_output("");
return empty().create_output();
}
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();
switch (socket.type) {
case SOCK_CUSTOM:
/* Return empty */
break;
case SOCK_FLOAT: {
float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
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()) {
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();
}
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();
}
@ -194,7 +194,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
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);
return data.result;
}

View File

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