Blender V4.5
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 1,
44 "%s [%d] => %s",
45 node_->name,
46 node_->typeinfo->type_legacy,
47 NodeItem::type(to_type_).c_str());
48
49 res = compute();
50 if (res.node) {
51 res.node->setName(res_node_name);
52 }
53 }
54 return res.convert(to_type_);
55}
56
57std::string NodeParser::node_name(const char *override_output_name) const
58{
61 to_type_ :
63 const StringRef socket_out_name = (override_output_name) ? override_output_name :
64 (socket_out_) ? socket_out_->name :
65 "";
66 return graph_.unique_node_name(node_, socket_out_name, to_type);
67}
68
69NodeItem NodeParser::create_node(const std::string &category, NodeItem::Type type)
70{
71 return empty().create_node(category, type);
72}
73
74NodeItem NodeParser::create_node(const std::string &category,
75 NodeItem::Type type,
77{
78 return empty().create_node(category, type, inputs);
79}
80
81NodeItem NodeParser::create_input(const std::string &name, const NodeItem &item)
82{
83 return empty().create_input(name, item);
84}
85
86NodeItem NodeParser::create_output(const std::string &name, const NodeItem &item)
87{
88 return empty().create_output(name, item);
89}
90
92{
93 return get_default(node_->input_by_identifier(name), to_type);
94}
95
97{
98 return get_default(node_->input_socket(index), to_type);
99}
100
102{
103 return get_input_link(node_->input_by_identifier(name), to_type, false);
104}
105
107{
108 return get_input_link(node_->input_socket(index), to_type, false);
109}
110
112{
113 return get_input_value(node_->input_by_identifier(name), to_type);
114}
115
117{
118 return get_input_value(node_->input_socket(index), to_type);
119}
120
122{
123 return get_default(node_->output_by_identifier(name), to_type);
124}
125
127{
128 return get_default(node_->output_socket(index), to_type);
129}
130
132{
133 return graph_.empty_node();
134}
135
136NodeItem NodeParser::texcoord_node(NodeItem::Type type, const std::string &attribute_name)
137{
139 std::string name = TEXCOORD_NODE_NAME;
140 if (type == NodeItem::Type::Vector3) {
141 name += "_vector3";
142 }
143 NodeItem res = graph_.get_node(name);
144 if (!res.node) {
145 /* TODO: Use "Pref" generated texture coordinates for 3D, but needs
146 * work in USD and Hydra mesh export. */
147 const bool is_active_uvmap = attribute_name == "" ||
148 attribute_name == graph_.export_params.original_active_uvmap_name;
149 if (graph_.export_params.new_active_uvmap_name == "st" && is_active_uvmap) {
150 res = create_node("texcoord", type);
151 }
152 else {
153 const std::string &geomprop = (is_active_uvmap) ?
154 graph_.export_params.new_active_uvmap_name :
155 attribute_name;
156 res = create_node("geompropvalue", type, {{"geomprop", val(geomprop)}});
157 }
158 res.node->setName(name);
159 }
160 return res;
161}
162
163NodeItem NodeParser::get_default(const bNodeSocket &socket, NodeItem::Type to_type)
164{
165 NodeItem res = empty();
167 return res;
168 }
169
170 switch (socket.type) {
171 case SOCK_CUSTOM:
172 /* Return empty */
173 break;
174 case SOCK_FLOAT: {
175 float v = socket.default_value_typed<bNodeSocketValueFloat>()->value;
176 res.value = MaterialX::Value::createValue<float>(v);
177 break;
178 }
179 case SOCK_VECTOR: {
180 const float *v = socket.default_value_typed<bNodeSocketValueVector>()->value;
181 res.value = MaterialX::Value::createValue<MaterialX::Vector3>(
182 MaterialX::Vector3(v[0], v[1], v[2]));
183 break;
184 }
185 case SOCK_RGBA: {
186 const float *v = socket.default_value_typed<bNodeSocketValueRGBA>()->value;
187 res.value = MaterialX::Value::createValue<MaterialX::Color4>(
188 MaterialX::Color4(v[0], v[1], v[2], v[3]));
189 break;
190 }
191 default: {
192 CLOG_WARN(LOG_MATERIALX_SHADER, "Unsupported socket type: %d", socket.type);
193 }
194 }
195 return res.convert(to_type);
196}
197
200 bool use_group_default)
201{
202 const bNodeLink *link = socket.link;
203 if (!(link && link->is_used())) {
204 return empty();
205 }
206
207 const bNode *from_node = link->fromnode;
208
209 /* Passing reroute nodes. */
210 while (from_node->is_reroute()) {
211 link = from_node->input_socket(0).link;
212 if (!(link && link->is_used())) {
213 return empty();
214 }
215 from_node = link->fromnode;
216 }
217
218 if (from_node->is_group()) {
219 return GroupNodeParser(
220 graph_, from_node, link->fromsock, to_type, group_parser_, use_group_default)
221 .compute_full();
222 }
223 if (from_node->is_group_input()) {
224 return GroupInputNodeParser(
225 graph_, from_node, link->fromsock, to_type, group_parser_, use_group_default)
226 .compute_full();
227 }
228
229 if (!from_node->typeinfo->materialx_fn) {
231 "Unsupported node: %s [%d]",
232 from_node->name,
233 from_node->typeinfo->type_legacy);
234 return empty();
235 }
236
237 NodeParserData data = {graph_, to_type, group_parser_, empty()};
238 from_node->typeinfo->materialx_fn(&data, const_cast<bNode *>(from_node), link->fromsock);
239 return data.result;
240}
241
243{
244 NodeItem res = get_input_link(socket, to_type, true);
245 if (!res) {
246 res = get_default(socket, to_type);
247 }
248 return res;
249}
250
251} // namespace blender::nodes::materialx
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ELEM(...)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLG_LOGREF_DECLARE_GLOBAL(var, id)
Definition CLG_log.h:145
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
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 eGPUType type)
struct CLG_LogRef * LOG_MATERIALX_SHADER
constexpr StringRef TEXCOORD_NODE_NAME
static blender::bke::bNodeSocketTemplate inputs[]
struct bNodeLink * link
bNodeTypeHandle * typeinfo
char name[64]
NodeItem get_node(StringRef name) const
Definition node_graph.cc:95