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