forked from blender/blender
Support group nodes #22
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(); \
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user