Blender V5.0
node_parser.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "node_parser.h"
6
7#include "group_nodes.h"
8
9#include "BKE_node_runtime.hh"
10
12
13constexpr StringRef TEXCOORD_NODE_NAME = "node_texcoord";
14
16
18 const bNode *node,
19 const bNodeSocket *socket_out,
21 GroupNodeParser *group_parser)
22 : graph_(graph),
23 node_(node),
24 socket_out_(socket_out),
26 group_parser_(group_parser)
27{
28}
29
31{
32 NodeItem res = empty();
33
35 return res;
36 }
37
38 /* Checking if node was already computed */
39 const std::string res_node_name = node_name();
40 res = graph_.get_node(res_node_name);
41 if (!res.node) {
43 "%s [%d] => %s",
44 node_->name,
45 node_->typeinfo->type_legacy,
46 NodeItem::type(to_type_).c_str());
47
48 res = compute();
49 if (res.node) {
50 res.node->setName(res_node_name);
51 }
52 }
53 return res.convert(to_type_);
54}
55
56std::string NodeParser::node_name(const char *override_output_name) const
57{
60 to_type_ :
62 const StringRef socket_out_name = (override_output_name) ? override_output_name :
63 (socket_out_) ? socket_out_->identifier :
64 "";
65 return graph_.unique_node_name(node_, socket_out_name, to_type);
66}
67
68NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type)
69{
70 return empty().create_node(category, type);
71}
72
73NodeItem NodeParser::create_node(const std::string &category,
74 NodeItem::Type type,
76{
77 return empty().create_node(category, type, inputs);
78}
79
80NodeItem NodeParser::create_input(const std::string &name, const NodeItem &item)
81{
82 return empty().create_input(name, item);
83}
84
85NodeItem NodeParser::create_output(const std::string &name, const NodeItem &item)
86{
87 return empty().create_output(name, item);
88}
89
91{
92 return get_default(*node_->input_by_identifier(name), to_type);
93}
94
96{
97 return get_default(node_->input_socket(index), to_type);
98}
99
101{
102 return get_input_link(*node_->input_by_identifier(name), to_type, false);
103}
104
106{
107 return get_input_link(node_->input_socket(index), to_type, false);
108}
109
111{
112 return get_input_value(*node_->input_by_identifier(name), to_type);
113}
114
116{
117 return get_input_value(node_->input_socket(index), to_type);
118}
119
121{
122 return get_default(*node_->output_by_identifier(name), to_type);
123}
124
126{
127 return get_default(node_->output_socket(index), to_type);
128}
129
131{
132 return graph_.empty_node();
133}
134
135NodeItem NodeParser::texcoord_node(NodeItem::Type type, const std::string &attribute_name)
136{
138 std::string name = TEXCOORD_NODE_NAME;
139 if (type == NodeItem::Type::Vector3) {
140 name += "_vector3";
141 }
142 NodeItem res = graph_.get_node(name);
143 if (!res.node) {
144 /* TODO: Use "Pref" generated texture coordinates for 3D, but needs
145 * work in USD and Hydra mesh export. */
146 const bool is_active_uvmap = attribute_name == "" ||
147 attribute_name == graph_.export_params.original_active_uvmap_name;
148 if (graph_.export_params.new_active_uvmap_name == "st" && is_active_uvmap) {
149 res = create_node("texcoord", type);
150 }
151 else {
152 const std::string &geomprop = (is_active_uvmap) ?
153 graph_.export_params.new_active_uvmap_name :
154 attribute_name;
155 res = create_node("geompropvalue", type, {{"geomprop", val(geomprop)}});
156 }
157 res.node->setName(name);
158 }
159 return res;
160}
161
162NodeItem NodeParser::get_default(const bNodeSocket &socket, NodeItem::Type to_type)
163{
164 NodeItem res = empty();
166 return res;
167 }
168
169 switch (socket.type) {
170 case SOCK_CUSTOM:
171 /* Return empty */
172 break;
173 case SOCK_FLOAT: {
174 float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
175 res.value = MaterialX::Value::createValue<float>(v);
176 break;
177 }
178 case SOCK_VECTOR: {
179 const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
180 res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
181 MaterialX::Vector3(v[0], v[1], v[2]));
182 break;
183 }
184 case SOCK_RGBA: {
185 const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
186 res.value = MaterialX::Value::createValue<MaterialX::Color4>(
187 MaterialX::Color4(v[0], v[1], v[2], v[3]));
188 break;
189 }
190 default: {
191 CLOG_WARN(LOG_IO_MATERIALX, "Unsupported socket type: %d", socket.type);
192 }
193 }
194 return res.convert(to_type);
195}
196
199 bool use_group_default)
200{
201 const bNodeLink *link = socket.link;
202 if (!(link && link->is_used())) {
203 return empty();
204 }
205
206 const bNode *from_node = link->fromnode;
207
208 /* Passing reroute nodes. */
209 while (from_node->is_reroute()) {
210 link = from_node->input_socket(0).link;
211 if (!(link && link->is_used())) {
212 return empty();
213 }
214 from_node = link->fromnode;
215 }
216
217 if (from_node->is_group()) {
218 return GroupNodeParser(
219 graph_, from_node, link->fromsock, to_type, group_parser_, use_group_default)
220 .compute_full();
221 }
222 if (from_node->is_group_input()) {
223 return GroupInputNodeParser(
224 graph_, from_node, link->fromsock, to_type, group_parser_, use_group_default)
225 .compute_full();
226 }
227
228 if (!from_node->typeinfo->materialx_fn) {
230 "Unsupported node: %s [%d]",
231 from_node->name,
232 from_node->typeinfo->type_legacy);
233 return empty();
234 }
235
236 NodeParserData data = {graph_, to_type, group_parser_, empty()};
237 from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock);
238 return data.result;
239}
240
242{
243 NodeItem res = get_input_link(socket, to_type, true);
244 if (!res) {
245 res = get_default(socket, to_type);
246 }
247 return res;
248}
249
250} // namespace blender::nodes::materialx
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ELEM(...)
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
#define CLG_LOGREF_DECLARE_GLOBAL(var, id)
Definition CLG_log.h:139
struct bNodeLink bNodeLink
struct bNode bNode
eNodeSocketDatatype
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_CUSTOM
@ SOCK_RGBA
struct bNodeSocket bNodeSocket
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
NodeItem create_input(const std::string &name, const NodeItem &item) const
Definition node_item.cc:929
static bool is_arithmetic(Type type)
Definition node_item.cc:116
NodeItem convert(Type to_type) const
Definition node_item.cc:517
NodeItem create_output(const std::string &name, const NodeItem &item) const
Definition node_item.cc:946
static bool is_convertible(eNodeSocketDatatype from_type, Type to_type)
Definition node_item.cc:482
static Type type(const std::string &type_str)
Definition node_item.cc:16
std::vector< std::pair< std::string, NodeItem > > Inputs
Definition node_item.h:20
NodeItem create_node(const std::string &category, Type type) const
Definition node_item.cc:831
NodeItem get_input_value(const std::string &name, NodeItem::Type to_type)
std::string node_name(const char *override_output_name=nullptr) const
NodeParser(NodeGraph &graph, const bNode *node, const bNodeSocket *socket_out, NodeItem::Type to_type, GroupNodeParser *group_parser)
NodeItem create_input(const std::string &name, const NodeItem &item)
NodeItem get_input_link(const std::string &name, NodeItem::Type to_type)
NodeItem texcoord_node(NodeItem::Type type=NodeItem::Type::Vector2, const std::string &attribute_name="")
NodeItem get_input_default(const std::string &name, NodeItem::Type to_type)
NodeItem get_output_default(const std::string &name, NodeItem::Type to_type)
NodeItem create_node(const std::string &category, NodeItem::Type type)
NodeItem create_output(const std::string &name, const NodeItem &item)
NodeItem val(const T &data) const
Definition node_parser.h:73
static Type to_type(const GPUType type)
constexpr StringRef TEXCOORD_NODE_NAME
struct CLG_LogRef * LOG_IO_MATERIALX
static blender::bke::bNodeSocketTemplate inputs[]
const char * name
struct bNodeLink * link
bNodeTypeHandle * typeinfo
char name[64]
NodeItem get_node(StringRef name) const
Definition node_graph.cc:95