Blender V5.0
node_shader_mix.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include "BKE_material.hh"
12
14#include "BLI_math_vector.h"
15#include "BLI_string_utf8.h"
16
17#include "DNA_material_types.h"
18
20#include "UI_resources.hh"
21
22#include "node_shader_util.hh"
23#include "node_util.hh"
24
26
27#include "NOD_multi_function.hh"
29
30#include "RNA_access.hh"
31#include "RNA_enum_types.hh"
32
34
36
38{
39 b.is_function_node();
40 /* WARNING:
41 * Input socket indices must be kept in sync with ntree_shader_disconnect_inactive_mix_branches
42 */
43 b.add_input<decl::Float>("Factor", "Factor_Float")
44 .default_value(0.5f)
45 .min(0.0f)
46 .max(1.0f)
47 .subtype(PROP_FACTOR)
48 .no_muted_links()
49 .description("Amount of mixing between the A and B inputs")
50 .compositor_domain_priority(2);
51 b.add_input<decl::Vector>("Factor", "Factor_Vector")
52 .default_value(float3(0.5f))
53 .min(0.0f)
54 .max(1.0f)
55 .subtype(PROP_FACTOR)
56 .no_muted_links()
57 .description("Amount of mixing between the A and B vector inputs")
58 .compositor_domain_priority(2);
59
60 b.add_input<decl::Float>("A", "A_Float")
61 .min(-10000.0f)
62 .max(10000.0f)
63 .is_default_link_socket()
64 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
65 .description("Value of the first floating number input")
66 .compositor_domain_priority(0);
67 b.add_input<decl::Float>("B", "B_Float")
68 .min(-10000.0f)
69 .max(10000.0f)
70 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
71 .description("Value of the second floating number input")
72 .compositor_domain_priority(1);
73
74 b.add_input<decl::Vector>("A", "A_Vector")
76 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
77 .description("Value of the first vector input")
78 .compositor_domain_priority(0);
79 b.add_input<decl::Vector>("B", "B_Vector")
81 .description("Value of the second vector input")
82 .compositor_domain_priority(1);
83
84 b.add_input<decl::Color>("A", "A_Color")
85 .default_value({0.5f, 0.5f, 0.5f, 1.0f})
86 .is_default_link_socket()
87 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
88 .description("Value of the first color input")
89 .compositor_domain_priority(0);
90 b.add_input<decl::Color>("B", "B_Color")
91 .default_value({0.5f, 0.5f, 0.5f, 1.0f})
92 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
93 .description("Value of the second color input")
94 .compositor_domain_priority(1);
95
96 b.add_input<decl::Rotation>("A", "A_Rotation")
98 .translation_context(BLT_I18NCONTEXT_ID_NODETREE)
99 .compositor_domain_priority(0);
100 b.add_input<decl::Rotation>("B", "B_Rotation")
102 .compositor_domain_priority(1);
103
104 b.add_output<decl::Float>("Result", "Result_Float");
105 b.add_output<decl::Vector>("Result", "Result_Vector");
106 b.add_output<decl::Color>("Result", "Result_Color");
107 b.add_output<decl::Rotation>("Result", "Result_Rotation");
108};
109
110static void sh_node_mix_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
111{
112 const NodeShaderMix &data = node_storage(*static_cast<const bNode *>(ptr->data));
113 layout->prop(ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
114 switch (data.data_type) {
115 case SOCK_FLOAT:
116 break;
117 case SOCK_VECTOR:
118 layout->prop(ptr, "factor_mode", UI_ITEM_NONE, "", ICON_NONE);
119 break;
120 case SOCK_RGBA:
121 layout->prop(ptr, "blend_type", UI_ITEM_NONE, "", ICON_NONE);
122 layout->prop(ptr, "clamp_result", UI_ITEM_NONE, std::nullopt, ICON_NONE);
123 break;
124 case SOCK_ROTATION:
125 break;
126 default:
128 }
129 layout->prop(ptr, "clamp_factor", UI_ITEM_NONE, std::nullopt, ICON_NONE);
130}
131
132static void sh_node_mix_label(const bNodeTree * /*ntree*/,
133 const bNode *node,
134 char *label,
135 int label_maxncpy)
136{
137 const NodeShaderMix &storage = node_storage(*node);
138 if (storage.data_type == SOCK_RGBA) {
139 const char *name;
140 bool enum_label = RNA_enum_name(rna_enum_ramp_blend_items, storage.blend_type, &name);
141 if (!enum_label) {
142 name = N_("Unknown");
143 }
144 BLI_strncpy_utf8(label, IFACE_(name), label_maxncpy);
145 return;
146 }
147 BLI_strncpy_utf8(label, IFACE_("Mix"), label_maxncpy);
148}
149
150static int sh_node_mix_ui_class(const bNode *node)
151{
152 const NodeShaderMix &storage = node_storage(*node);
153 const eNodeSocketDatatype data_type = eNodeSocketDatatype(storage.data_type);
154
155 switch (data_type) {
156 case SOCK_VECTOR:
158 case SOCK_RGBA:
159 return NODE_CLASS_OP_COLOR;
160 default:
162 }
163}
164
165static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
166{
167 const NodeShaderMix &storage = node_storage(*node);
168 const eNodeSocketDatatype data_type = eNodeSocketDatatype(storage.data_type);
169
170 bNodeSocket *sock_factor = static_cast<bNodeSocket *>(node->inputs.first);
171 bNodeSocket *sock_factor_vec = static_cast<bNodeSocket *>(sock_factor->next);
172
173 bool use_vector_factor = data_type == SOCK_VECTOR &&
175
176 bke::node_set_socket_availability(*ntree, *sock_factor, !use_vector_factor);
177
178 bke::node_set_socket_availability(*ntree, *sock_factor_vec, use_vector_factor);
179
180 for (bNodeSocket *socket = sock_factor_vec->next; socket != nullptr; socket = socket->next) {
181 bke::node_set_socket_availability(*ntree, *socket, socket->type == data_type);
182 }
183
184 LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
185 bke::node_set_socket_availability(*ntree, *socket, socket->type == data_type);
186 }
187}
188
190 public:
191 std::string socket_name;
194 {
195 bNode &node = params.add_node("ShaderNodeMix");
196 node_storage(node).data_type = SOCK_RGBA;
197 node_storage(node).blend_type = type;
198 params.update_and_connect_available_socket(node, socket_name);
199 }
200};
201
203{
205 switch (eNodeSocketDatatype(params.other_socket().type)) {
206 case SOCK_BOOLEAN:
207 case SOCK_INT:
208 case SOCK_FLOAT:
209 type = SOCK_FLOAT;
210 break;
211 case SOCK_VECTOR:
212 type = SOCK_VECTOR;
213 break;
214 case SOCK_RGBA:
215 type = SOCK_RGBA;
216 break;
217 case SOCK_ROTATION:
218 type = SOCK_ROTATION;
219 break;
220 default:
221 return;
222 }
223
224 int weight = 0;
225 if (params.in_out() == SOCK_OUT) {
226 params.add_item(IFACE_("Result"), [type](LinkSearchOpParams &params) {
227 bNode &node = params.add_node("ShaderNodeMix");
228 node_storage(node).data_type = type;
229 params.update_and_connect_available_socket(node, "Result");
230 });
231 }
232 else {
233 params.add_item(
235 [type](LinkSearchOpParams &params) {
236 bNode &node = params.add_node("ShaderNodeMix");
237 node_storage(node).data_type = type;
238 params.update_and_connect_available_socket(node, "A");
239 },
240 weight);
241 weight--;
242 params.add_item(
244 [type](LinkSearchOpParams &params) {
245 bNode &node = params.add_node("ShaderNodeMix");
246 node_storage(node).data_type = type;
247 params.update_and_connect_available_socket(node, "B");
248 },
249 weight);
250 weight--;
251 if (ELEM(type, SOCK_VECTOR, SOCK_RGBA)) {
252 params.add_item(
253 IFACE_("Factor (Non-Uniform)"),
255 bNode &node = params.add_node("ShaderNodeMix");
256 node_storage(node).data_type = SOCK_VECTOR;
257 node_storage(node).factor_mode = NODE_MIX_MODE_NON_UNIFORM;
258 params.update_and_connect_available_socket(node, "Factor");
259 },
260 weight);
261 weight--;
262 }
263 if (type != SOCK_ROTATION) {
264 params.add_item(
265 IFACE_("Factor"),
266 [type](LinkSearchOpParams &params) {
267 bNode &node = params.add_node("ShaderNodeMix");
268 node_storage(node).data_type = type;
269 params.update_and_connect_available_socket(node, "Factor");
270 },
271 weight);
272 weight--;
273 }
274 }
275
276 if (type == SOCK_ROTATION) {
277 return;
278 }
279
280 if (type != SOCK_RGBA) {
281 weight--;
282 }
283 const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result";
284 for (const EnumPropertyItem *item = rna_enum_ramp_blend_items; item->identifier != nullptr;
285 item++)
286 {
287 if (item->name != nullptr && item->identifier[0] != '\0') {
288 params.add_item(IFACE_(item->name), SocketSearchOp{socket_name, item->value}, weight);
289 }
290 }
291}
292
293static void node_mix_init(bNodeTree * /*tree*/, bNode *node)
294{
296 data->data_type = SOCK_FLOAT;
297 data->factor_mode = NODE_MIX_MODE_UNIFORM;
298 data->clamp_factor = 1;
299 data->clamp_result = 0;
300 data->blend_type = MA_RAMP_BLEND;
301 node->storage = data;
302}
303
304static const char *gpu_shader_get_name(eNodeSocketDatatype data_type,
305 const bool non_uniform,
306 const int blend_type)
307{
308 switch (data_type) {
309 case SOCK_FLOAT:
310 return "node_mix_float";
311 case SOCK_VECTOR:
312 return (non_uniform) ? "node_mix_vector_non_uniform" : "node_mix_vector";
313 case SOCK_RGBA:
314 switch (blend_type) {
315 case MA_RAMP_BLEND:
316 return "node_mix_blend";
317 case MA_RAMP_ADD:
318 return "node_mix_add";
319 case MA_RAMP_MULT:
320 return "node_mix_mult";
321 case MA_RAMP_SUB:
322 return "node_mix_sub";
323 case MA_RAMP_SCREEN:
324 return "node_mix_screen";
325 case MA_RAMP_DIV:
326 return "node_mix_div_fallback";
327 case MA_RAMP_DIFF:
328 return "node_mix_diff";
330 return "node_mix_exclusion";
331 case MA_RAMP_DARK:
332 return "node_mix_dark";
333 case MA_RAMP_LIGHT:
334 return "node_mix_light";
335 case MA_RAMP_OVERLAY:
336 return "node_mix_overlay";
337 case MA_RAMP_DODGE:
338 return "node_mix_dodge";
339 case MA_RAMP_BURN:
340 return "node_mix_burn";
341 case MA_RAMP_HUE:
342 return "node_mix_hue";
343 case MA_RAMP_SAT:
344 return "node_mix_sat";
345 case MA_RAMP_VAL:
346 return "node_mix_val";
347 case MA_RAMP_COLOR:
348 return "node_mix_color";
349 case MA_RAMP_SOFT:
350 return "node_mix_soft";
351 case MA_RAMP_LINEAR:
352 return "node_mix_linear";
353 default:
355 return nullptr;
356 }
357 case SOCK_ROTATION:
358 return nullptr;
359 default:
361 return nullptr;
362 }
363}
364
366 bNode *node,
367 bNodeExecData * /*execdata*/,
370{
371 const NodeShaderMix &storage = node_storage(*node);
372 const bool is_non_uniform = storage.factor_mode == NODE_MIX_MODE_NON_UNIFORM;
373 const bool is_color_mode = storage.data_type == SOCK_RGBA;
374 const bool is_vector_mode = storage.data_type == SOCK_VECTOR;
375 const int blend_type = storage.blend_type;
376 const char *name = gpu_shader_get_name(
377 eNodeSocketDatatype(storage.data_type), is_non_uniform, blend_type);
378
379 if (name == nullptr) {
380 return 0;
381 }
382
383 if (storage.clamp_factor) {
384 if (is_non_uniform && is_vector_mode) {
385 const float min[3] = {0.0f, 0.0f, 0.0f};
386 const float max[3] = {1.0f, 1.0f, 1.0f};
387 const GPUNodeLink *factor_link = in[1].link ? in[1].link : GPU_uniform(in[1].vec);
388 GPU_link(mat,
389 "node_mix_clamp_vector",
390 factor_link,
393 &in[1].link);
394 }
395 else {
396 const float min = 0.0f;
397 const float max = 1.0f;
398 const GPUNodeLink *factor_link = in[0].link ? in[0].link : GPU_uniform(in[0].vec);
399 GPU_link(mat,
400 "node_mix_clamp_value",
401 factor_link,
404 &in[0].link);
405 }
406 }
407
408 int ret = GPU_stack_link(mat, node, name, in, out);
409
410 if (ret && is_color_mode && storage.clamp_result) {
411 const float min[4] = {0.0f, 0.0f, 0.0f, 0.0f};
412 const float max[4] = {1.0f, 1.0f, 1.0f, 1.0f};
413 GPU_link(mat,
414 "node_mix_clamp_color",
415 out[2].link,
418 &out[2].link);
419 }
420 return ret;
421}
422
423class MixColorFunction : public mf::MultiFunction {
424 private:
425 const bool clamp_factor_;
426 const bool clamp_result_;
427 const int blend_type_;
428
429 public:
430 MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
431 : clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type)
432 {
433 static const mf::Signature signature = []() {
434 mf::Signature signature;
435 mf::SignatureBuilder builder{"MixColor", signature};
436 builder.single_input<float>("Factor");
437 builder.single_input<ColorGeometry4f>("A");
438 builder.single_input<ColorGeometry4f>("B");
439 builder.single_output<ColorGeometry4f>("Result");
440 return signature;
441 }();
442 this->set_signature(&signature);
443 }
444
445 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
446 {
447 const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
448 const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A");
449 const VArray<ColorGeometry4f> &col2 = params.readonly_single_input<ColorGeometry4f>(2, "B");
450 MutableSpan<ColorGeometry4f> results = params.uninitialized_single_output<ColorGeometry4f>(
451 3, "Result");
452
453 if (clamp_factor_) {
454 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
455 results[i] = col1[i];
456 ramp_blend(blend_type_, results[i], std::clamp(fac[i], 0.0f, 1.0f), col2[i]);
457 });
458 }
459 else {
460 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
461 results[i] = col1[i];
462 ramp_blend(blend_type_, results[i], fac[i], col2[i]);
463 });
464 }
465
466 if (clamp_result_) {
467 mask.foreach_index_optimized<int64_t>(
468 [&](const int64_t i) { clamp_v3(results[i], 0.0f, 1.0f); });
469 }
470 }
471};
472
473static const mf::MultiFunction *get_multi_function(const bNode &node)
474{
475 const NodeShaderMix *data = (NodeShaderMix *)node.storage;
476 bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM;
477 const bool clamp_factor = data->clamp_factor;
478 switch (data->data_type) {
479 case SOCK_FLOAT: {
480 if (clamp_factor) {
481 static auto fn = mf::build::SI3_SO<float, float, float, float>(
482 "Clamp Mix Float", [](float t, const float a, const float b) {
483 return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
484 });
485 return &fn;
486 }
487 static auto fn = mf::build::SI3_SO<float, float, float, float>(
488 "Mix Float",
489 [](const float t, const float a, const float b) { return math::interpolate(a, b, t); });
490 return &fn;
491 }
492 case SOCK_VECTOR: {
493 if (clamp_factor) {
494 if (uniform_factor) {
495 static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
496 "Clamp Mix Vector", [](const float t, const float3 a, const float3 b) {
497 return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
498 });
499 return &fn;
500 }
501 static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
502 "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) {
503 t = math::clamp(t, 0.0f, 1.0f);
504 return a * (float3(1.0f) - t) + b * t;
505 });
506 return &fn;
507 }
508 if (uniform_factor) {
509 static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
510 "Mix Vector", [](const float t, const float3 a, const float3 b) {
511 return math::interpolate(a, b, t);
512 });
513 return &fn;
514 }
515 static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
516 "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) {
517 return a * (float3(1.0f) - t) + b * t;
518 });
519 return &fn;
520 }
521 case SOCK_ROTATION: {
522 if (clamp_factor) {
523 static auto fn =
524 mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
525 "Clamp Mix Rotation",
526 [](const float t, const math::Quaternion &a, const math::Quaternion &b) {
527 return math::interpolate(a, b, math::clamp(t, 0.0f, 1.0f));
528 });
529 return &fn;
530 }
531 static auto fn =
532 mf::build::SI3_SO<float, math::Quaternion, math::Quaternion, math::Quaternion>(
533 "Mix Rotation",
534 [](const float t, const math::Quaternion &a, const math::Quaternion &b) {
535 return math::interpolate(a, b, t);
536 });
537 return &fn;
538 }
539 }
541 return nullptr;
542}
543
545{
546 const NodeShaderMix &storage = node_storage(builder.node());
547
548 if (storage.data_type == SOCK_RGBA) {
550 storage.clamp_factor, storage.clamp_result, storage.blend_type);
551 }
552 else {
553 const mf::MultiFunction *fn = get_multi_function(builder.node());
554 builder.set_matching_fn(fn);
555 }
556}
557
559#ifdef WITH_MATERIALX
560{
561 const NodeShaderMix *data = (NodeShaderMix *)node_->storage;
562
563 NodeItem factor = empty();
564 NodeItem value1 = empty();
565 NodeItem value2 = empty();
566 switch (data->data_type) {
567 case SOCK_FLOAT:
568 factor = get_input_value(0, NodeItem::Type::Float);
569 value1 = get_input_value(2, NodeItem::Type::Float);
570 value2 = get_input_value(3, NodeItem::Type::Float);
571 break;
572
573 case SOCK_VECTOR:
574 if (data->factor_mode == NODE_MIX_MODE_UNIFORM) {
575 factor = get_input_value(0, NodeItem::Type::Float);
576 }
577 else {
578 factor = get_input_value(1, NodeItem::Type::Vector3);
579 }
580 value1 = get_input_value(4, NodeItem::Type::Vector3);
581 value2 = get_input_value(5, NodeItem::Type::Vector3);
582 break;
583
584 case SOCK_RGBA:
585 factor = get_input_value(0, NodeItem::Type::Float);
586 value1 = get_input_value(6, NodeItem::Type::Color3);
587 value2 = get_input_value(7, NodeItem::Type::Color3);
588 break;
589
590 default:
592 }
593
594 if (data->clamp_factor) {
595 factor = factor.clamp();
596 }
597 NodeItem res = factor.mix(value1, value2);
598 if (data->data_type == SOCK_RGBA) {
599 /* TODO: Apply data->blend_type */
600
601 if (data->clamp_result) {
602 res = res.clamp();
603 }
604 }
605 return res;
606}
607#endif
609
610} // namespace blender::nodes::node_sh_mix_cc
611
613{
614 namespace file_ns = blender::nodes::node_sh_mix_cc;
615
616 static blender::bke::bNodeType ntype;
617 common_node_type_base(&ntype, "ShaderNodeMix", SH_NODE_MIX);
618 ntype.ui_name = "Mix";
619 ntype.ui_description = "Mix values by a factor";
620 ntype.enum_name_legacy = "MIX";
622 ntype.declare = file_ns::sh_node_mix_declare;
623 ntype.ui_class = file_ns::sh_node_mix_ui_class;
624 ntype.gpu_fn = file_ns::gpu_shader_mix;
625 ntype.updatefunc = file_ns::sh_node_mix_update;
626 ntype.initfunc = file_ns::node_mix_init;
629 ntype.build_multi_function = file_ns::sh_node_mix_build_multi_function;
630 ntype.draw_buttons = file_ns::sh_node_mix_layout;
631 ntype.labelfunc = file_ns::sh_node_mix_label;
632 ntype.gather_link_search_ops = file_ns::node_mix_gather_link_searches;
633 ntype.materialx_fn = file_ns::node_shader_materialx;
634
636}
General operations, lookup, etc. for materials.
void ramp_blend(int type, float r_col[3], float fac, const float col[3])
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:453
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1240
#define NODE_CLASS_OP_VECTOR
Definition BKE_node.hh:450
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:449
#define SH_NODE_MIX
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define LISTBASE_FOREACH(type, var, list)
MINLINE void clamp_v3(float vec[3], float min, float max)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_NODETREE
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
@ MA_RAMP_LIGHT
@ MA_RAMP_COLOR
@ MA_RAMP_SAT
@ MA_RAMP_HUE
@ MA_RAMP_LINEAR
@ MA_RAMP_DIV
@ MA_RAMP_EXCLUSION
@ MA_RAMP_ADD
@ MA_RAMP_DODGE
@ MA_RAMP_SUB
@ MA_RAMP_SCREEN
@ MA_RAMP_SOFT
@ MA_RAMP_DARK
@ MA_RAMP_BURN
@ MA_RAMP_BLEND
@ MA_RAMP_VAL
@ MA_RAMP_OVERLAY
@ MA_RAMP_MULT
@ MA_RAMP_DIFF
@ SOCK_OUT
@ SOCK_IN
@ NODE_MIX_MODE_UNIFORM
@ NODE_MIX_MODE_NON_UNIFORM
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_FLOAT
@ SOCK_ROTATION
@ SOCK_RGBA
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
bool GPU_link(GPUMaterial *mat, const char *name,...)
GPUNodeLink * GPU_uniform(const float *num)
@ PROP_FACTOR
Definition RNA_types.hh:251
#define UI_ITEM_NONE
BMesh const char void * data
long long int int64_t
void set_signature(const Signature *signature)
void set_matching_fn(const mf::MultiFunction *fn)
std::optional< std::string > translation_context
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
void operator()(LinkSearchOpParams &params)
#define in
#define out
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:4739
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5414
QuaternionBase< float > Quaternion
T clamp(const T &a, const T &min, const T &max)
T interpolate(const T &a, const T &b, const FactorT &t)
static const char * gpu_shader_get_name(eNodeSocketDatatype data_type, const bool non_uniform, const int blend_type)
static void node_mix_init(bNodeTree *, bNode *node)
static int sh_node_mix_ui_class(const bNode *node)
static void node_mix_gather_link_searches(GatherLinkSearchOpParams &params)
static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder)
static void sh_node_mix_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static const mf::MultiFunction * get_multi_function(const bNode &node)
static int gpu_shader_mix(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void sh_node_mix_declare(NodeDeclarationBuilder &b)
static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
static void sh_node_mix_label(const bNodeTree *, const bNode *node, char *label, int label_maxncpy)
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
#define NODE_SHADER_MATERIALX_BEGIN
#define NODE_SHADER_MATERIALX_END
void register_node_type_sh_mix()
void common_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
const char * name
return ret
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
const EnumPropertyItem rna_enum_ramp_blend_items[]
#define min(a, b)
Definition sort.cc:36
void * first
struct bNodeSocket * next
ListBase inputs
void * storage
ListBase outputs
Defines a node type.
Definition BKE_node.hh:238
NodeMaterialXFunction materialx_fn
Definition BKE_node.hh:344
std::string ui_description
Definition BKE_node.hh:244
int(* ui_class)(const bNode *node)
Definition BKE_node.hh:276
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
void(* labelfunc)(const bNodeTree *ntree, const bNode *node, char *label, int label_maxncpy)
Definition BKE_node.hh:270
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:342
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:351
const char * enum_name_legacy
Definition BKE_node.hh:247
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:378
NodeDeclareFunction declare
Definition BKE_node.hh:362
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:281
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238