forked from blender/blender
Support group nodes #22
@ -149,10 +149,12 @@ if(WITH_MATERIALX)
|
|||||||
materialx/material.cc
|
materialx/material.cc
|
||||||
materialx/node_item.cc
|
materialx/node_item.cc
|
||||||
materialx/node_parser.cc
|
materialx/node_parser.cc
|
||||||
|
materialx/group_nodes.cc
|
||||||
|
|
||||||
materialx/material.h
|
materialx/material.h
|
||||||
materialx/node_item.h
|
materialx/node_item.h
|
||||||
materialx/node_parser.h
|
materialx/node_parser.h
|
||||||
|
materialx/group_nodes.h
|
||||||
)
|
)
|
||||||
list(APPEND LIB
|
list(APPEND LIB
|
||||||
MaterialXCore
|
MaterialXCore
|
||||||
|
65
source/blender/nodes/shader/materialx/group_nodes.cc
Normal file
65
source/blender/nodes/shader/materialx/group_nodes.cc
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "node_parser.h"
|
||||||
|
#include "group_nodes.h"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
NodeItem GroupNodeParser::compute()
|
||||||
|
{
|
||||||
|
NodeItem res = empty();
|
||||||
|
|
||||||
|
const bNodeTree *ngroup = reinterpret_cast<const bNodeTree *>(node_->id);
|
||||||
|
ngroup->ensure_topology_cache();
|
||||||
|
const bNode *node_out = ngroup->group_output_node();
|
||||||
|
if (!node_out) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name = MaterialX::createValidName(node_->name); /* or ngroup->name */
|
||||||
|
MaterialX::NodeGraphPtr group_graph = graph_->getChildOfType<MaterialX::NodeGraph>(name);
|
||||||
|
if (!group_graph) {
|
||||||
|
group_graph = graph_->addChild<MaterialX::NodeGraph>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupOutputNodeParser parser(
|
||||||
|
group_graph.get(), depsgraph_, material_, node_out, socket_out_, NodeItem::Type::Any);
|
||||||
|
NodeItem out = parser.compute_full();
|
||||||
|
res.node = group_graph;
|
||||||
|
if (parser.output) {
|
||||||
|
res = create_node("constant", out.type());
|
||||||
|
res.set_input("value", parser.output);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem GroupOutputNodeParser::compute()
|
||||||
|
{
|
||||||
|
NodeItem res = get_input_link(socket_out_->index(), to_type_);
|
||||||
|
if (res) {
|
||||||
|
output = graph_->addOutput(MaterialX::EMPTY_STRING, NodeItem::type(res.type()));
|
||||||
|
output->setValue(1.0f);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem GroupInputNodeParser::compute()
|
||||||
|
{
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeItem GroupInputNodeParser::compute_full()
|
||||||
|
{
|
||||||
|
CLOG_INFO(LOG_MATERIALX_SHADER,
|
||||||
|
1,
|
||||||
|
"%s [%d] => %s",
|
||||||
|
node_->name,
|
||||||
|
node_->typeinfo->type,
|
||||||
|
NodeItem::type(to_type_).c_str());
|
||||||
|
|
||||||
|
return compute();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
33
source/blender/nodes/shader/materialx/group_nodes.h
Normal file
33
source/blender/nodes/shader/materialx/group_nodes.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "node_parser.h"
|
||||||
|
|
||||||
|
namespace blender::nodes::materialx {
|
||||||
|
|
||||||
|
class GroupNodeParser : public NodeParser {
|
||||||
|
public:
|
||||||
|
using NodeParser::NodeParser;
|
||||||
|
NodeItem compute() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupOutputNodeParser : public NodeParser {
|
||||||
|
public:
|
||||||
|
MaterialX::OutputPtr output;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using NodeParser::NodeParser;
|
||||||
|
NodeItem compute() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GroupInputNodeParser : public NodeParser {
|
||||||
|
public:
|
||||||
|
using NodeParser::NodeParser;
|
||||||
|
NodeItem compute() override;
|
||||||
|
NodeItem compute_full() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::nodes::materialx
|
@ -675,13 +675,15 @@ void NodeItem::set_input(const std::string &in_name, const NodeItem &item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeItem::set_input(const std::string &in_name, MaterialX::OutputPtr output)
|
||||||
|
{
|
||||||
|
node->setConnectedOutput(in_name, output);
|
||||||
|
}
|
||||||
|
|
||||||
void NodeItem::set_input_output(const std::string &in_name,
|
void NodeItem::set_input_output(const std::string &in_name,
|
||||||
const NodeItem &item,
|
const NodeItem &item,
|
||||||
const std::string &out_name)
|
const std::string &out_name)
|
||||||
{
|
{
|
||||||
if (!item.node) {
|
|
||||||
BLI_assert_unreachable();
|
|
||||||
}
|
|
||||||
node->setConnectedNode(in_name, item.node);
|
node->setConnectedNode(in_name, item.node);
|
||||||
node->setConnectedOutput(in_name, item.node->getOutput(out_name));
|
node->setConnectedOutput(in_name, item.node->getOutput(out_name));
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ class NodeItem {
|
|||||||
/* Functions to set input and output */
|
/* Functions to set input and output */
|
||||||
template<class T> void set_input(const std::string &in_name, const T &value, Type in_type);
|
template<class T> void set_input(const std::string &in_name, const T &value, Type in_type);
|
||||||
void set_input(const std::string &in_name, const NodeItem &item);
|
void set_input(const std::string &in_name, const NodeItem &item);
|
||||||
|
void set_input(const std::string &in_name, MaterialX::OutputPtr output);
|
||||||
void set_input_output(const std::string &in_name,
|
void set_input_output(const std::string &in_name,
|
||||||
const NodeItem &item,
|
const NodeItem &item,
|
||||||
const std::string &out_name);
|
const std::string &out_name);
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "node_parser.h"
|
#include "node_parser.h"
|
||||||
|
|
||||||
|
#include "group_nodes.h"
|
||||||
|
|
||||||
#include "BKE_node_runtime.hh"
|
#include "BKE_node_runtime.hh"
|
||||||
|
|
||||||
namespace blender::nodes::materialx {
|
namespace blender::nodes::materialx {
|
||||||
@ -54,7 +56,7 @@ NodeItem NodeParser::compute_full()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NodeParser::node_name()
|
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) {
|
||||||
@ -155,7 +157,7 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
|
|||||||
const bNode *from_node = link->fromnode;
|
const bNode *from_node = link->fromnode;
|
||||||
|
|
||||||
/* Passing NODE_REROUTE nodes */
|
/* Passing NODE_REROUTE nodes */
|
||||||
while (from_node->type == NODE_REROUTE) {
|
while (from_node->is_reroute()) {
|
||||||
link = from_node->input_socket(0).link;
|
link = from_node->input_socket(0).link;
|
||||||
if (!(link && link->is_used())) {
|
if (!(link && link->is_used())) {
|
||||||
return empty();
|
return empty();
|
||||||
@ -163,6 +165,11 @@ NodeItem NodeParser::get_input_link(const bNodeSocket &socket, NodeItem::Type to
|
|||||||
from_node = link->fromnode;
|
from_node = link->fromnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (from_node->is_group()) {
|
||||||
|
return GroupNodeParser(graph_, depsgraph_, material_, from_node, link->fromsock, to_type)
|
||||||
|
.compute_full();
|
||||||
|
}
|
||||||
|
|
||||||
if (!from_node->typeinfo->materialx_fn) {
|
if (!from_node->typeinfo->materialx_fn) {
|
||||||
CLOG_WARN(LOG_MATERIALX_SHADER,
|
CLOG_WARN(LOG_MATERIALX_SHADER,
|
||||||
"Unsupported node: %s [%d]",
|
"Unsupported node: %s [%d]",
|
||||||
|
@ -38,7 +38,7 @@ class NodeParser {
|
|||||||
virtual NodeItem compute_full();
|
virtual NodeItem compute_full();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string node_name();
|
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 get_input_default(const std::string &name, NodeItem::Type to_type);
|
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type);
|
||||||
NodeItem get_input_default(int index, NodeItem::Type to_type);
|
NodeItem get_input_default(int index, NodeItem::Type to_type);
|
||||||
|
@ -260,7 +260,7 @@ static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder
|
|||||||
NODE_SHADER_MATERIALX_BEGIN
|
NODE_SHADER_MATERIALX_BEGIN
|
||||||
{
|
{
|
||||||
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
NodeItem scale = get_input_value("Scale", NodeItem::Type::Float);
|
||||||
NodeItem detail = get_input_value("Detail", NodeItem::Type::Float);
|
NodeItem detail = get_input_default("Detail", NodeItem::Type::Float);
|
||||||
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
NodeItem lacunarity = get_input_value("Lacunarity", NodeItem::Type::Float);
|
||||||
|
|
||||||
NodeItem position = create_node("position", NodeItem::Type::Vector3);
|
NodeItem position = create_node("position", NodeItem::Type::Vector3);
|
||||||
@ -268,9 +268,7 @@ NODE_SHADER_MATERIALX_BEGIN
|
|||||||
|
|
||||||
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
|
NodeItem res = create_node("fractal3d", NodeItem::Type::Color3);
|
||||||
res.set_input("position", position);
|
res.set_input("position", position);
|
||||||
if (detail.value) {
|
res.set_input("octaves", val(int(detail.value->asA<float>())));
|
||||||
res.set_input("octaves", val(int(detail.value->asA<float>())));
|
|
||||||
}
|
|
||||||
res.set_input("lacunarity", lacunarity);
|
res.set_input("lacunarity", lacunarity);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user