Blender V5.0
node_composite_colorbalance.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_math_base.hh"
11#include "BLI_math_vector.hh"
13
14#include "BKE_node.hh"
15#include "BKE_node_runtime.hh"
16
17#include "NOD_multi_function.hh"
18
19#include "RNA_access.hh"
20
21#include "UI_interface.hh"
23#include "UI_resources.hh"
24
25#include "GPU_material.hh"
26
28
29#include "BLI_math_color.hh"
30
32
34
35static const EnumPropertyItem type_items[] = {
36 {CMP_NODE_COLOR_BALANCE_LGG, "LIFT_GAMMA_GAIN", 0, N_("Lift/Gamma/Gain"), ""},
38 "OFFSET_POWER_SLOPE",
39 0,
40 N_("Offset/Power/Slope (ASC-CDL)"),
41 N_("ASC-CDL standard color correction")},
43 "WHITEPOINT",
44 0,
45 N_("White Point"),
46 N_("Chromatic adaption from a different white point")},
47 {0, nullptr, 0, nullptr, nullptr},
48};
49
51{
52 b.is_function_node();
53 b.use_custom_socket_order();
54 b.allow_any_socket_order();
55
56 b.add_input<decl::Color>("Image").default_value({1.0f, 1.0f, 1.0f, 1.0f}).hide_value();
57 b.add_output<decl::Color>("Image").align_with_previous();
58
59 b.add_input<decl::Float>("Factor", "Fac")
60 .default_value(1.0f)
61 .min(0.0f)
62 .max(1.0f)
64
65 b.add_input<decl::Menu>("Type")
66 .default_value(CMP_NODE_COLOR_BALANCE_LGG)
67 .static_items(type_items)
69
70 b.add_input<decl::Float>("Lift", "Base Lift")
71 .default_value(0.0f)
72 .min(-1.0f)
73 .max(1.0f)
75 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
76 .description("Correction for shadows");
77 b.add_input<decl::Color>("Lift", "Color Lift")
78 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
79 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
80 .description("Correction for shadows");
81 b.add_input<decl::Float>("Gamma", "Base Gamma")
82 .default_value(1.0f)
83 .min(0.0f)
84 .max(2.0f)
86 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
87 .description("Correction for midtones");
88 b.add_input<decl::Color>("Gamma", "Color Gamma")
89 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
90 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
91 .description("Correction for midtones");
92 b.add_input<decl::Float>("Gain", "Base Gain")
93 .default_value(1.0f)
94 .min(0.0f)
95 .max(2.0f)
97 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
98 .description("Correction for highlights");
99 b.add_input<decl::Color>("Gain", "Color Gain")
100 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
101 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_LGG)
102 .description("Correction for highlights");
103
104 b.add_input<decl::Float>("Offset", "Base Offset")
105 .default_value(0.0f)
106 .min(-1.0f)
107 .max(1.0f)
109 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
110 .description("Correction for shadows");
111 b.add_input<decl::Color>("Offset", "Color Offset")
112 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
113 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
114 .description("Correction for shadows");
115 b.add_input<decl::Float>("Power", "Base Power")
116 .default_value(1.0f)
117 .min(0.0f)
118 .max(2.0f)
120 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
121 .description("Correction for midtones");
122 b.add_input<decl::Color>("Power", "Color Power")
123 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
124 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
125 .description("Correction for midtones");
126 b.add_input<decl::Float>("Slope", "Base Slope")
127 .default_value(1.0f)
128 .min(0.0f)
129 .max(2.0f)
131 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
132 .description("Correction for highlights");
133 b.add_input<decl::Color>("Slope", "Color Slope")
134 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
135 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_ASC_CDL)
136 .description("Correction for highlights");
137
138 PanelDeclarationBuilder &input_panel = b.add_panel("Input");
139 input_panel.add_input<decl::Float>("Temperature", "Input Temperature")
140 .default_value(6500.0f)
142 .min(1800.0f)
143 .max(100000.0f)
144 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_WHITEPOINT)
145 .description("Color temperature of the input's white point");
146 input_panel.add_input<decl::Float>("Tint", "Input Tint")
147 .default_value(10.0f)
149 .min(-150.0f)
150 .max(150.0f)
151 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_WHITEPOINT)
152 .description("Color tint of the input's white point (the default of 10 matches daylight)");
153 input_panel.add_layout([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
154 uiLayout *split = &layout->split(0.2f, false);
155 uiTemplateCryptoPicker(split, ptr, "input_whitepoint", ICON_EYEDROPPER);
156 });
157
158 PanelDeclarationBuilder &output_panel = b.add_panel("Output");
159 output_panel.add_input<decl::Float>("Temperature", "Output Temperature")
160 .default_value(6500.0f)
162 .min(1800.0f)
163 .max(100000.0f)
164 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_WHITEPOINT)
165 .description("Color temperature of the output's white point");
166 output_panel.add_input<decl::Float>("Tint", "Output Tint")
167 .default_value(10.0f)
169 .min(-150.0f)
170 .max(150.0f)
171 .usage_by_menu("Type", CMP_NODE_COLOR_BALANCE_WHITEPOINT)
172 .description("Color tint of the output's white point (the default of 10 matches daylight)");
173 output_panel.add_layout([](uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) {
174 uiLayout *split = &layout->split(0.2f, false);
175 uiTemplateCryptoPicker(split, ptr, "output_whitepoint", ICON_EYEDROPPER);
176 });
177}
178
179static float3x3 get_white_point_matrix(const float input_temperature,
180 const float input_tint,
181 const float output_temperature,
182 const float output_tint)
183{
186 const float3 input = blender::math::whitepoint_from_temp_tint(input_temperature, input_tint);
187 const float3 output = blender::math::whitepoint_from_temp_tint(output_temperature, output_tint);
189 return xyz_to_scene * adaption * scene_to_xyz;
190}
191
192static int node_gpu_material(GPUMaterial *material,
193 bNode *node,
194 bNodeExecData * /*execdata*/,
197{
198 const bNodeSocket &type = *node->input_by_identifier("Type");
199 const bool is_white_point = !type.is_directly_linked() &&
200 type.default_value_typed<bNodeSocketValueMenu>()->value ==
202
203 const bNodeSocket &input_temperature = *node->input_by_identifier("Input Temperature");
204 const bNodeSocket &input_tint = *node->input_by_identifier("Input Tint");
205 const bNodeSocket &output_temperature = *node->input_by_identifier("Output Temperature");
206 const bNodeSocket &output_tint = *node->input_by_identifier("Output Tint");
207
208 /* As an optimization for white point balancing, if all inputs are constant, compute the white
209 * point matrix on the host and pass it to the shader. */
210 if (is_white_point && !input_temperature.is_directly_linked() &&
211 !input_tint.is_directly_linked() && !output_temperature.is_directly_linked() &&
212 !output_tint.is_directly_linked())
213 {
214 const float4x4 white_point_matrix = float4x4(get_white_point_matrix(
215 input_temperature.default_value_typed<bNodeSocketValueFloat>()->value,
216 input_tint.default_value_typed<bNodeSocketValueFloat>()->value,
217 output_temperature.default_value_typed<bNodeSocketValueFloat>()->value,
218 output_tint.default_value_typed<bNodeSocketValueFloat>()->value));
219
220 return GPU_stack_link(material,
221 node,
222 "node_composite_color_balance_white_point_constant",
223 inputs,
224 outputs,
225 GPU_uniform(white_point_matrix.base_ptr()));
226 }
227
230 return GPU_stack_link(material,
231 node,
232 "node_composite_color_balance",
233 inputs,
234 outputs,
235 GPU_uniform(scene_to_xyz.base_ptr()),
236 GPU_uniform(xyz_to_scene.base_ptr()));
237}
238
240 const float base_lift,
241 const float4 color_lift,
242 const float base_gamma,
243 const float4 color_gamma,
244 const float base_gain,
245 const float4 color_gain)
246{
247 const float3 lift = base_lift + color_lift.xyz();
248 const float3 lift_balanced = ((color.xyz() - 1.0f) * (2.0f - lift)) + 1.0f;
249
250 const float3 gain = base_gain * color_gain.xyz();
251 const float3 gain_balanced = math::max(float3(0.0f), lift_balanced * gain);
252
253 const float3 gamma = base_gamma * color_gamma.xyz();
254 const float3 gamma_balanced = math::pow(gain_balanced, 1.0f / math::max(gamma, float3(1e-6f)));
255
256 return float4(gamma_balanced, color.w);
257}
258
260 const float base_offset,
261 const float4 color_offset,
262 const float base_power,
263 const float4 color_power,
264 const float base_slope,
265 const float4 color_slope)
266{
267 const float3 slope = base_slope * color_slope.xyz();
268 const float3 slope_balanced = color.xyz() * slope;
269
270 const float3 offset = base_offset + color_offset.xyz();
271 const float3 offset_balanced = slope_balanced + offset;
272
273 const float3 power = base_power * color_power.xyz();
274 const float3 power_balanced = math::pow(math::max(offset_balanced, float3(0.0f)), power);
275
276 return float4(power_balanced, color.w);
277}
278
280 const float factor,
281 const float3x3 white_point_matrix)
282{
283 const float3 balanced = white_point_matrix * color.xyz();
284 return float4(math::interpolate(color.xyz(), balanced, math::min(factor, 1.0f)), color.w);
285}
286
288 const float input_temperature,
289 const float input_tint,
290 const float output_temperature,
291 const float output_tint,
292 const float3x3 &scene_to_xyz,
293 const float3x3 &xyz_to_scene)
294{
295 const float3 input = blender::math::whitepoint_from_temp_tint(input_temperature, input_tint);
296 const float3 output = blender::math::whitepoint_from_temp_tint(output_temperature, output_tint);
298 const float3x3 white_point_matrix = xyz_to_scene * adaption * scene_to_xyz;
299
300 const float3 balanced = white_point_matrix * color.xyz();
301 return float4(balanced, color.w);
302}
303
305 const float factor,
306 const CMPNodeColorBalanceMethod type,
307 const float base_lift,
308 const float4 color_lift,
309 const float base_gamma,
310 const float4 color_gamma,
311 const float base_gain,
312 const float4 color_gain,
313 const float base_offset,
314 const float4 color_offset,
315 const float base_power,
316 const float4 color_power,
317 const float base_slope,
318 const float4 color_slope,
319 const float input_temperature,
320 const float input_tint,
321 const float output_temperature,
322 const float output_tint,
323 const float3x3 scene_to_xyz,
324 const float3x3 xyz_to_scene)
325{
326 float4 result = float4(0.0f);
327 switch (type) {
330 color, base_lift, color_lift, base_gamma, color_gamma, base_gain, color_gain);
331 break;
334 color, base_offset, color_offset, base_power, color_power, base_slope, color_slope);
335 break;
338 input_temperature,
339 input_tint,
340 output_temperature,
341 output_tint,
342 scene_to_xyz,
343 xyz_to_scene);
344 break;
345 }
346
347 return float4(math::interpolate(color.xyz(), result.xyz(), math::min(factor, 1.0f)), color.w);
348}
349
350class ColorBalanceFunction : public mf::MultiFunction {
351 public:
353 {
354 static const mf::Signature signature = []() {
355 mf::Signature signature;
356 mf::SignatureBuilder builder{"Color Balance", signature};
357 builder.single_input<float4>("Color");
358 builder.single_input<float>("Factor");
359 builder.single_input<MenuValue>("Type");
360
361 builder.single_input<float>("Base Lift");
362 builder.single_input<float4>("Color Lift");
363 builder.single_input<float>("Base Gamma");
364 builder.single_input<float4>("Color Gamma");
365 builder.single_input<float>("Base Gain");
366 builder.single_input<float4>("Color Gain");
367
368 builder.single_input<float>("Base Offset");
369 builder.single_input<float4>("Color Offset");
370 builder.single_input<float>("Base Power");
371 builder.single_input<float4>("Color Power");
372 builder.single_input<float>("Base Slope");
373 builder.single_input<float4>("Color Slope");
374
375 builder.single_input<float>("Input Temperature");
376 builder.single_input<float>("Input Tint");
377 builder.single_input<float>("Output Temperature");
378 builder.single_input<float>("Output Tint");
379
380 builder.single_output<float4>("Result");
381 return signature;
382 }();
383 this->set_signature(&signature);
384 }
385
386 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
387 {
388 const VArray<float4> color_array = params.readonly_single_input<float4>(0, "Color");
389 const VArray<float> factor_array = params.readonly_single_input<float>(1, "Factor");
390 const VArray<MenuValue> type_array = params.readonly_single_input<MenuValue>(2, "Type");
391
392 const VArray<float> base_lift_array = params.readonly_single_input<float>(3, "Base Lift");
393 const VArray<float4> color_lift_array = params.readonly_single_input<float4>(4, "Color Lift");
394 const VArray<float> base_gamma_array = params.readonly_single_input<float>(5, "Base Gamma");
395 const VArray<float4> color_gamma_array = params.readonly_single_input<float4>(6,
396 "Color Gamma");
397 const VArray<float> base_gain_array = params.readonly_single_input<float>(7, "Base Gain");
398 const VArray<float4> color_gain_array = params.readonly_single_input<float4>(8, "Color Gain");
399
400 const VArray<float> base_offset_array = params.readonly_single_input<float>(9, "Base Offset");
401 const VArray<float4> color_offset_array = params.readonly_single_input<float4>(10,
402 "Color Offset");
403 const VArray<float> base_power_array = params.readonly_single_input<float>(11, "Base Power");
404 const VArray<float4> color_power_array = params.readonly_single_input<float4>(12,
405 "Color Power");
406 const VArray<float> base_slope_array = params.readonly_single_input<float>(13, "Base Slope");
407 const VArray<float4> color_slope_array = params.readonly_single_input<float4>(14,
408 "Color Slope");
409
410 const VArray<float> input_temperature_array = params.readonly_single_input<float>(
411 15, "Input Temperature");
412 const VArray<float> input_tint_array = params.readonly_single_input<float>(16, "Input Tint");
413 const VArray<float> output_temperature_array = params.readonly_single_input<float>(
414 17, "Output Temperature");
415 const VArray<float> output_tint_array = params.readonly_single_input<float>(18, "Output Tint");
416
417 MutableSpan<float4> result = params.uninitialized_single_output<float4>(19, "Result");
418
419 const std::optional<MenuValue> type_single = type_array.get_if_single();
420 const std::optional<float> input_temperature_single = input_temperature_array.get_if_single();
421 const std::optional<float> input_tint_single = input_tint_array.get_if_single();
422 const std::optional<float> output_temperature_single =
423 output_temperature_array.get_if_single();
424 const std::optional<float> output_tint_single = output_tint_array.get_if_single();
425
426 const bool is_white_point = type_single.has_value() &&
427 type_single.value().value == CMP_NODE_COLOR_BALANCE_WHITEPOINT;
428
429 /* As an optimization for white point balancing, if all inputs are single, compute the white
430 * point matrix outside of the loop. */
431 if (is_white_point && input_temperature_single.has_value() && input_tint_single.has_value() &&
432 output_temperature_single.has_value() && output_tint_single.has_value())
433 {
434 const float3x3 white_point_matrix = get_white_point_matrix(input_temperature_single.value(),
435 input_tint_single.value(),
436 output_temperature_single.value(),
437 output_tint_single.value());
438 mask.foreach_index([&](const int64_t i) {
439 result[i] = white_point_constant(color_array[i], factor_array[i], white_point_matrix);
440 });
441 }
442 else {
445
446 bool all_but_color_single_value = true;
447 for (int i = 0; i < 19; i++) {
448 if (i == 1) {
449 continue;
450 }
451 if (!params.readonly_single_input(i).is_single()) {
452 all_but_color_single_value = false;
453 break;
454 }
455 }
456
457 if (all_but_color_single_value) {
458 const float factor = factor_array.get_internal_single();
459 const float type = CMPNodeColorBalanceMethod(type_array.get_internal_single().value);
460 const float base_lift = base_lift_array.get_internal_single();
461 const float4 color_lift = color_lift_array.get_internal_single();
462 const float base_gamma = base_gamma_array.get_internal_single();
463 const float4 color_gamma = color_gamma_array.get_internal_single();
464 const float base_gain = base_gain_array.get_internal_single();
465 const float4 color_gain = color_gain_array.get_internal_single();
466 const float base_offset = base_offset_array.get_internal_single();
467 const float4 color_offset = color_offset_array.get_internal_single();
468 const float base_power = base_power_array.get_internal_single();
469 const float4 color_power = color_power_array.get_internal_single();
470 const float base_slope = base_slope_array.get_internal_single();
471 const float4 color_slope = color_slope_array.get_internal_single();
472 const float input_temperature = input_temperature_array.get_internal_single();
473 const float input_tint = input_tint_array.get_internal_single();
474 const float output_temperature = output_temperature_array.get_internal_single();
475 const float output_tint = output_tint_array.get_internal_single();
476
477 mask.foreach_index([&](const int64_t i) {
478 result[i] = color_balance(color_array[i],
479 factor,
481 base_lift,
482 color_lift,
483 base_gamma,
484 color_gamma,
485 base_gain,
486 color_gain,
487 base_offset,
488 color_offset,
489 base_power,
490 color_power,
491 base_slope,
492 color_slope,
493 input_temperature,
494 input_tint,
495 output_temperature,
496 output_tint,
497 scene_to_xyz,
498 xyz_to_scene);
499 });
500 }
501 else {
502 mask.foreach_index([&](const int64_t i) {
503 result[i] = color_balance(color_array[i],
504 factor_array[i],
505 CMPNodeColorBalanceMethod(type_array[i].value),
506 base_lift_array[i],
507 color_lift_array[i],
508 base_gamma_array[i],
509 color_gamma_array[i],
510 base_gain_array[i],
511 color_gain_array[i],
512 base_offset_array[i],
513 color_offset_array[i],
514 base_power_array[i],
515 color_power_array[i],
516 base_slope_array[i],
517 color_slope_array[i],
518 input_temperature_array[i],
519 input_tint_array[i],
520 output_temperature_array[i],
521 output_tint_array[i],
522 scene_to_xyz,
523 xyz_to_scene);
524 });
525 }
526 }
527 }
528};
529
531{
532 const static ColorBalanceFunction function;
533 builder.set_matching_fn(function);
534}
535
536} // namespace blender::nodes::node_composite_colorbalance_cc
537
539{
541
542 static blender::bke::bNodeType ntype;
543
544 cmp_node_type_base(&ntype, "CompositorNodeColorBalance", CMP_NODE_COLORBALANCE);
545 ntype.ui_name = "Color Balance";
546 ntype.ui_description = "Adjust color and values";
547 ntype.enum_name_legacy = "COLORBALANCE";
549 ntype.declare = file_ns::cmp_node_colorbalance_declare;
550 ntype.gpu_fn = file_ns::node_gpu_material;
551 ntype.build_multi_function = file_ns::node_build_multi_function;
552
554}
#define NODE_CLASS_OP_COLOR
Definition BKE_node.hh:449
#define CMP_NODE_COLORBALANCE
CMPNodeColorBalanceMethod
@ CMP_NODE_COLOR_BALANCE_LGG
@ CMP_NODE_COLOR_BALANCE_ASC_CDL
@ CMP_NODE_COLOR_BALANCE_WHITEPOINT
static void split(const char *text, const char *seps, char ***str, int *count)
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_uniform(const float *num)
blender::float3x3 IMB_colormanagement_get_scene_linear_to_xyz()
blender::float3x3 IMB_colormanagement_get_xyz_to_scene_linear()
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ PROP_COLOR_TEMPERATURE
Definition RNA_types.hh:290
@ PROP_FACTOR
Definition RNA_types.hh:251
void uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int icon)
long long int int64_t
void set_signature(const Signature *signature)
void add_layout(std::function< void(uiLayout *, bContext *, PointerRNA *)> draw)
DeclType::Builder & add_input(StringRef name, StringRef identifier="")
void set_matching_fn(const mf::MultiFunction *fn)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
#define input
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 power(const float2 v, const float e)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
T pow(const T &x, const T &power)
float3 whitepoint_from_temp_tint(float temperature, float tint)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
float3x3 chromatic_adaption_matrix(const float3 &from_XYZ, const float3 &to_XYZ)
T max(const T &a, const T &b)
static float4 lift_gamma_gain(const float4 color, const float base_lift, const float4 color_lift, const float base_gamma, const float4 color_gamma, const float base_gain, const float4 color_gain)
static float4 offset_power_slope(const float4 color, const float base_offset, const float4 color_offset, const float base_power, const float4 color_power, const float base_slope, const float4 color_slope)
static void cmp_node_colorbalance_declare(NodeDeclarationBuilder &b)
static float4 white_point_constant(const float4 color, const float factor, const float3x3 white_point_matrix)
static float4 white_point_variable(const float4 color, const float input_temperature, const float input_tint, const float output_temperature, const float output_tint, const float3x3 &scene_to_xyz, const float3x3 &xyz_to_scene)
static float4 color_balance(const float4 color, const float factor, const CMPNodeColorBalanceMethod type, const float base_lift, const float4 color_lift, const float base_gamma, const float4 color_gamma, const float base_gain, const float4 color_gain, const float base_offset, const float4 color_offset, const float base_power, const float4 color_power, const float base_slope, const float4 color_slope, const float input_temperature, const float input_tint, const float output_temperature, const float output_tint, const float3x3 scene_to_xyz, const float3x3 xyz_to_scene)
static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder)
static float3x3 get_white_point_matrix(const float input_temperature, const float input_tint, const float output_temperature, const float output_tint)
static int node_gpu_material(GPUMaterial *material, bNode *node, bNodeExecData *, GPUNodeStack *inputs, GPUNodeStack *outputs)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
static void register_node_type_cmp_colorbalance()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
const T * base_ptr() const
VecBase< T, 3 > xyz() const
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
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
NodeDeclareFunction declare
Definition BKE_node.hh:362
uiLayout & split(float percentage, bool align)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238