Blender V4.5
drawnode.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
9
10#include "BLI_color.hh"
11#include "BLI_listbase.h"
12#include "BLI_string.h"
13#include "BLI_threads.h"
14
15#include "DNA_node_types.h"
16#include "DNA_screen_types.h"
17#include "DNA_space_types.h"
18#include "DNA_userdef_types.h"
19
20#include "BKE_context.hh"
21#include "BKE_curve.hh"
22#include "BKE_image.hh"
23#include "BKE_main.hh"
25#include "BKE_node.hh"
26#include "BKE_node_enum.hh"
28#include "BKE_node_runtime.hh"
30#include "BKE_scene.hh"
31#include "BKE_tracking.h"
32
33#include "BLT_translation.hh"
34
35#include "BIF_glutil.hh"
36
37#include "GPU_batch.hh"
38#include "GPU_batch_presets.hh"
39#include "GPU_capabilities.hh"
40#include "GPU_framebuffer.hh"
41#include "GPU_immediate.hh"
42#include "GPU_matrix.hh"
43#include "GPU_shader_shared.hh"
44#include "GPU_state.hh"
45#include "GPU_uniform_buffer.hh"
46
47#include "DRW_engine.hh"
48
49#include "RNA_access.hh"
50#include "RNA_define.hh"
51#include "RNA_prototypes.hh"
52
53#include "ED_node.hh"
54#include "ED_space_api.hh"
55
56#include "WM_api.hh"
57#include "WM_types.hh"
58
59#include "UI_resources.hh"
60#include "UI_view2d.hh"
61
63#include "IMB_imbuf_types.hh"
64
65#include "NOD_composite.hh"
66#include "NOD_geometry.hh"
69#include "NOD_partial_eval.hh"
70#include "NOD_socket.hh"
72#include "node_intern.hh" /* own include */
73
75
76/* Default flags for uiLayout::prop(). Name is kept short since this is used a lot in this file. */
77#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME
78
79/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
80
82 uiLayout *layout,
83 PointerRNA * /*ptr*/,
84 PointerRNA * /*node_ptr*/,
85 const StringRefNull text)
86{
87 layout->label(text, ICON_NONE);
88}
89
90/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
91
92static void node_buts_mix_rgb(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
93{
94 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
95
96 uiLayout *col = &layout->column(false);
97 uiLayout *row = &col->row(true);
98 row->prop(ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE);
99 if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) {
100 row->prop(ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA);
101 }
102
103 col->prop(ptr, "use_clamp", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
104}
105
106static void node_buts_time(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
107{
108 uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false);
109}
110
111static void node_buts_colorramp(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
112{
113 uiTemplateColorRamp(layout, ptr, "color_ramp", false);
114}
115
116static void node_buts_curvevec(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
117{
118 uiTemplateCurveMapping(layout, ptr, "mapping", 'v', false, false, false, false);
119}
120
121static void node_buts_curvefloat(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
122{
123 uiTemplateCurveMapping(layout, ptr, "mapping", 0, false, false, false, false);
124}
125
126} // namespace blender::ed::space_node
127
128#define SAMPLE_FLT_ISNONE FLT_MAX
129/* Bad! 2.5 will do better? ... no it won't! */
130static float _sample_col[4] = {SAMPLE_FLT_ISNONE};
131void ED_node_sample_set(const float col[4])
132{
133 if (col) {
135 }
136 else {
138 }
139}
140
141namespace blender::ed::space_node {
142
143static void node_buts_curvecol(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
144{
145 bNode *node = (bNode *)ptr->data;
146 CurveMapping *cumap = (CurveMapping *)node->storage;
147
148 if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
149 cumap->flag |= CUMA_DRAW_SAMPLE;
151 }
152 else {
153 cumap->flag &= ~CUMA_DRAW_SAMPLE;
154 }
155
156 /* "Tone" (Standard/Film-like) only used in the Compositor. */
157 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
159 layout, ptr, "mapping", 'c', false, false, false, (ntree->type == NTREE_COMPOSIT));
160}
161
162static void node_buts_normal(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
163{
164 bNode *node = (bNode *)ptr->data;
165 /* first output stores normal */
167 PointerRNA sockptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_NodeSocket, output);
168
169 layout->prop(&sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
170}
171
173{
174 bNode *node = (bNode *)ptr->data;
175
176 short multi = (node->id && ((Tex *)node->id)->use_nodes &&
177 (node->type_legacy != CMP_NODE_TEXTURE) &&
178 (node->type_legacy != TEX_NODE_TEXTURE));
179
180 uiTemplateID(layout, C, ptr, "texture", "texture.new", nullptr, nullptr);
181
182 if (multi) {
183 /* Number Drawing not optimal here, better have a list. */
184 layout->prop(ptr, "node_output", DEFAULT_FLAGS, "", ICON_NONE);
185 }
186}
187
188static void node_buts_math(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
189{
190 layout->prop(ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
191 layout->prop(ptr, "use_clamp", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
192}
193
195{
196 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
197}
198
200 const bNode *node,
201 const int x,
202 const int y)
203{
204 const float size = NODE_RESIZE_MARGIN * math::max(snode.runtime->aspect, 1.0f);
205
206 if (node->is_frame()) {
207 NodeFrame *data = (NodeFrame *)node->storage;
208
209 /* shrinking frame size is determined by child nodes */
210 if (!(data->flag & NODE_FRAME_RESIZEABLE)) {
211 return NODE_RESIZE_NONE;
212 }
213
215
216 const rctf &bounds = node->runtime->draw_bounds;
217
218 if (x > bounds.xmax - size && x <= bounds.xmax && y >= bounds.ymin && y < bounds.ymax) {
219 dir |= NODE_RESIZE_RIGHT;
220 }
221 if (x >= bounds.xmin && x < bounds.xmin + size && y >= bounds.ymin && y < bounds.ymax) {
222 dir |= NODE_RESIZE_LEFT;
223 }
224 if (x >= bounds.xmin && x < bounds.xmax && y >= bounds.ymax - size && y < bounds.ymax) {
225 dir |= NODE_RESIZE_TOP;
226 }
227 if (x >= bounds.xmin && x < bounds.xmax && y >= bounds.ymin && y < bounds.ymin + size) {
228 dir |= NODE_RESIZE_BOTTOM;
229 }
230
231 return dir;
232 }
233
234 if (node->flag & NODE_HIDDEN) {
235 /* right part of node */
236 rctf bounds = node->runtime->draw_bounds;
237 bounds.xmin = node->runtime->draw_bounds.xmax - 1.0f * U.widget_unit;
238 if (BLI_rctf_isect_pt(&bounds, x, y)) {
239 return NODE_RESIZE_RIGHT;
240 }
241
242 return NODE_RESIZE_NONE;
243 }
244
245 const rctf &bounds = node->runtime->draw_bounds;
247
248 if (x >= bounds.xmax - size && x < bounds.xmax && y >= bounds.ymin && y < bounds.ymax) {
249 dir |= NODE_RESIZE_RIGHT;
250 }
251 if (x >= bounds.xmin && x < bounds.xmin + size && y >= bounds.ymin && y < bounds.ymax) {
252 dir |= NODE_RESIZE_LEFT;
253 }
254 return dir;
255}
256
257/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
258
260{
261 uiTemplateIDBrowse(layout, C, ptr, "node_tree", nullptr, nullptr, nullptr);
262}
263
264static void node_buts_frame_ex(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
265{
266 layout->prop(ptr, "label_size", DEFAULT_FLAGS, IFACE_("Label Size"), ICON_NONE);
267 layout->prop(ptr, "shrink", DEFAULT_FLAGS, IFACE_("Shrink"), ICON_NONE);
268 layout->prop(ptr, "text", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
269}
270
272{
273 switch (ntype->type_legacy) {
274 case NODE_GROUP:
276 break;
277 case NODE_FRAME:
279 break;
280 }
281}
282
283/* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
284
285static void node_buts_image_user(uiLayout *layout,
286 bContext *C,
288 PointerRNA *imaptr,
289 PointerRNA *iuserptr,
290 const bool show_layer_selection,
291 const bool show_color_management)
292{
293 Image *image = (Image *)imaptr->data;
294 if (!image) {
295 return;
296 }
297 ImageUser *iuser = (ImageUser *)iuserptr->data;
298
299 uiLayout *col = &layout->column(false);
300
301 col->prop(imaptr, "source", DEFAULT_FLAGS, "", ICON_NONE);
302
303 const int source = RNA_enum_get(imaptr, "source");
304
305 if (source == IMA_SRC_SEQUENCE) {
306 /* don't use iuser->framenr directly
307 * because it may not be updated if auto-refresh is off */
308 Scene *scene = CTX_data_scene(C);
309
310 char numstr[32];
311 const int framenr = BKE_image_user_frame_get(iuser, scene->r.cfra, nullptr);
312 SNPRINTF(numstr, IFACE_("Frame: %d"), framenr);
313 layout->label(numstr, ICON_NONE);
314 }
315
316 if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
317 col = &layout->column(true);
318 col->prop(ptr, "frame_duration", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
319 col->prop(ptr, "frame_start", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
320 col->prop(ptr, "frame_offset", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
321 col->prop(ptr, "use_cyclic", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
322 col->prop(ptr, "use_auto_refresh", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
323 }
324
325 if (show_layer_selection && RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER &&
326 RNA_boolean_get(ptr, "has_layers"))
327 {
328 col = &layout->column(false);
329 col->prop(ptr, "layer", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
330 }
331
332 if (show_color_management) {
333 uiLayout *split = &layout->split(0.33f, true);
334 PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings");
335 split->label(IFACE_("Color Space"), ICON_NONE);
336 split->prop(&colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE);
337
338 if (image->source != IMA_SRC_GENERATED) {
339 split = &layout->split(0.33f, true);
340 split->label(IFACE_("Alpha"), ICON_NONE);
341 split->prop(imaptr, "alpha_mode", DEFAULT_FLAGS, "", ICON_NONE);
342
344 uiLayoutSetActive(split, !is_data);
345 }
346
347 /* Avoid losing changes image is painted. */
348 if (BKE_image_is_dirty((Image *)imaptr->data)) {
350 }
351 }
352}
353
355{
356 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
357 PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
358
359 uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
360 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
361 layout->prop(ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE);
362 layout->prop(ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE);
363
364 if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
365 layout->prop(ptr, "projection_blend", DEFAULT_FLAGS, IFACE_("Blend"), ICON_NONE);
366 }
367
368 layout->prop(ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE);
369
370 /* NOTE: image user properties used directly here, unlike compositor image node,
371 * which redefines them in the node struct RNA to get proper updates.
372 */
373 node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true);
374}
375
377{
378 PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
379 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false);
380}
381
383{
384 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
385 PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
386
387 uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
388 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
389
390 layout->prop(ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE);
391 layout->prop(ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE);
392
393 node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true);
394}
395
397{
398 PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
399 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false);
400
401 layout->prop(ptr, "interpolation", DEFAULT_FLAGS, IFACE_("Interpolation"), ICON_NONE);
402 layout->prop(ptr, "projection", DEFAULT_FLAGS, IFACE_("Projection"), ICON_NONE);
403}
404
406{
407 layout->prop(ptr, "space", DEFAULT_FLAGS, "", ICON_NONE);
408}
409
411{
412 layout->prop(ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE);
413}
414
416{
417 layout->prop(ptr, "target", DEFAULT_FLAGS, "", ICON_NONE);
418}
419
421{
422 layout->prop(ptr, "phase", DEFAULT_FLAGS, "", ICON_NONE);
423}
424
425/* only once called */
427{
428 switch (ntype->type_legacy) {
429 case SH_NODE_NORMAL:
431 break;
434 break;
437 break;
440 break;
443 break;
444 case SH_NODE_VALTORGB:
446 break;
447 case SH_NODE_MATH:
449 break;
453 break;
457 break;
461 break;
465 break;
469 break;
474 break;
477 break;
478 }
479}
480
481/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
482
483static void node_buts_image_views(uiLayout *layout,
484 bContext * /*C*/,
486 PointerRNA *imaptr)
487{
488 uiLayout *col;
489
490 if (!imaptr->data) {
491 return;
492 }
493
494 col = &layout->column(false);
495
496 if (RNA_boolean_get(ptr, "has_views")) {
497 if (RNA_enum_get(ptr, "view") == 0) {
498 col->prop(ptr, "view", DEFAULT_FLAGS, std::nullopt, ICON_CAMERA_STEREO);
499 }
500 else {
501 col->prop(ptr, "view", DEFAULT_FLAGS, std::nullopt, ICON_SCENE);
502 }
503 }
504}
505
507{
508 bNode *node = (bNode *)ptr->data;
509
510 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
511 uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
512 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
513 if (!node->id) {
514 return;
515 }
516
517 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
518
519 node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true, true);
520
521 node_buts_image_views(layout, C, ptr, &imaptr);
522}
523
525{
526 bNode *node = (bNode *)ptr->data;
527
528 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
529 uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
530 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, true);
531}
532
534{
535 bNode *node = (bNode *)ptr->data;
536 CurveMapping *cumap = (CurveMapping *)node->storage;
537
538 if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
539 cumap->flag |= CUMA_DRAW_SAMPLE;
541 }
542 else {
543 cumap->flag &= ~CUMA_DRAW_SAMPLE;
544 }
545
546 uiTemplateCurveMapping(layout, ptr, "mapping", 'h', false, false, false, false);
547}
548
550{
551 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
552}
553
555{
556 bNode *node = (bNode *)ptr->data;
558
559 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
560 if (storage->mode == CMP_NODE_COMBSEP_COLOR_YCC) {
561 layout->prop(ptr, "ycc_mode", DEFAULT_FLAGS, "", ICON_NONE);
562 }
563}
564
566 bContext * /*C*/,
568{
569 uiLayout *col = &layout->column(true);
570
571 col->label(IFACE_("Matte Objects:"), ICON_NONE);
572
573 uiLayout *row = &col->row(true);
574 uiTemplateCryptoPicker(row, ptr, "add", ICON_ADD);
575 uiTemplateCryptoPicker(row, ptr, "remove", ICON_REMOVE);
576
577 col->prop(ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE);
578}
579
581 bContext * /*C*/,
582 PointerRNA * /*ptr*/)
583{
584 layout->op("NODE_OT_cryptomatte_layer_add", IFACE_("Add Crypto Layer"), ICON_ADD);
585 layout->op("NODE_OT_cryptomatte_layer_remove", IFACE_("Remove Crypto Layer"), ICON_REMOVE);
586}
587
589{
590 bNode *node = (bNode *)ptr->data;
591
592 uiLayout *row = &layout->row(true);
593 row->prop(ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
594
595 uiLayout *col = &layout->column(false);
597 uiTemplateID(col, C, ptr, "scene", nullptr, nullptr, nullptr);
598 }
599 else {
600 uiTemplateID(col, C, ptr, "image", nullptr, "IMAGE_OT_open", nullptr);
601
602 NodeCryptomatte *crypto = (NodeCryptomatte *)node->storage;
603 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
605 ptr->owner_id, &RNA_ImageUser, &crypto->iuser);
606 uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
607
608 node_buts_image_user(col, C, ptr, &imaptr, &iuserptr, false, false);
609 node_buts_image_views(col, C, ptr, &imaptr);
610 }
611
612 col = &layout->column(true);
613 col->prop(ptr, "layer_name", UI_ITEM_NONE, "", ICON_NONE);
614 col->label(IFACE_("Matte ID:"), ICON_NONE);
615
616 row = &col->row(true);
617 row->prop(ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE);
618 uiTemplateCryptoPicker(row, ptr, "add", ICON_ADD);
619 uiTemplateCryptoPicker(row, ptr, "remove", ICON_REMOVE);
620}
621
622/* only once called */
624{
625 switch (ntype->type_legacy) {
626 case CMP_NODE_IMAGE:
629 break;
630 case CMP_NODE_NORMAL:
632 break;
635 break;
636 case CMP_NODE_MIX_RGB:
638 break;
641 break;
642 case CMP_NODE_TIME:
644 break;
645 case CMP_NODE_TEXTURE:
647 break;
648 case CMP_NODE_MATH:
650 break;
653 break;
657 break;
661 break;
664 break;
668 break;
669 }
670}
671
672/* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
673
675{
676 uiLayout *col;
677
678 col = &layout->column(true);
679 col->prop(ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
680 col->prop(ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
681
682 col = &layout->column(true);
683 col->prop(ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE);
684 col->prop(ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
685}
686
688{
689 bNode *node = (bNode *)ptr->data;
690 ID *id = ptr->owner_id;
691 Tex *tex = (Tex *)node->storage;
692 uiLayout *col, *row;
693
694 PointerRNA tex_ptr = RNA_pointer_create_discrete(id, &RNA_Texture, tex);
695
696 col = &layout->column(false);
697
698 switch (tex->type) {
699 case TEX_BLEND:
700 col->prop(&tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE);
701 row = &col->row(false);
702 row->prop(
703 &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
704 break;
705
706 case TEX_MARBLE:
707 row = &col->row(false);
708 row->prop(
709 &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
710 row = &col->row(false);
711 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
712 row = &col->row(false);
713 row->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
714 row = &col->row(false);
715 row->prop(
716 &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
717 break;
718
719 case TEX_MAGIC:
720 col->prop(&tex_ptr, "noise_depth", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
721 break;
722
723 case TEX_STUCCI:
724 row = &col->row(false);
725 row->prop(
726 &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
727 row = &col->row(false);
728 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
729 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
730 break;
731
732 case TEX_WOOD:
733 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
734 col->prop(&tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE);
735 row = &col->row(false);
736 row->prop(
737 &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
738 row = &col->row(false);
740 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
741 break;
742
743 case TEX_CLOUDS:
744 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
745 row = &col->row(false);
746 row->prop(&tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
747 row = &col->row(false);
748 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
749 col->prop(
750 &tex_ptr, "noise_depth", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
751 break;
752
753 case TEX_DISTNOISE:
754 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
755 col->prop(&tex_ptr, "noise_distortion", DEFAULT_FLAGS, "", ICON_NONE);
756 break;
757
758 case TEX_MUSGRAVE:
759 col->prop(&tex_ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE);
760 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
761 break;
762 case TEX_VORONOI:
763 col->prop(&tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE);
764 if (tex->vn_distm == TEX_MINKOVSKY) {
765 col->prop(&tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
766 }
767 col->prop(&tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE);
768 break;
769 }
770}
771
773{
774 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
775}
776
778{
779 bNode *node = (bNode *)ptr->data;
780 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
781 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false);
782}
783
785{
786 layout->prop(ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
787}
788
790{
791 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
792}
793
794/* only once called */
796{
797 if (ntype->type_legacy >= TEX_NODE_PROC && ntype->type_legacy < TEX_NODE_PROC_MAX) {
799 }
800 else {
801 switch (ntype->type_legacy) {
802
803 case TEX_NODE_MATH:
805 break;
806
807 case TEX_NODE_MIX_RGB:
809 break;
810
813 break;
814
817 break;
818
821 break;
822
823 case TEX_NODE_TEXTURE:
825 break;
826
827 case TEX_NODE_BRICKS:
829 break;
830
831 case TEX_NODE_IMAGE:
834 break;
835
836 case TEX_NODE_OUTPUT:
838 break;
839
843 break;
844 }
845 }
846}
847
848/* -------------------------------------------------------------------- */
853
854static void node_property_update_default(Main *bmain, Scene * /*scene*/, PointerRNA *ptr)
855{
856 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
857 bNode *node = (bNode *)ptr->data;
860}
861
872
874{
876
877 if (ntype->inputs) {
878 for (stemp = ntype->inputs; stemp->type >= 0; stemp++) {
880 }
881 }
882 if (ntype->outputs) {
883 for (stemp = ntype->outputs; stemp->type >= 0; stemp++) {
885 }
886 }
887}
888
890 uiLayout *layout,
891 PointerRNA * /*ptr*/,
892 PointerRNA * /*node_ptr*/,
893 StringRefNull /*text*/)
894{
895 layout->label(IFACE_("Undefined Socket Type"), ICON_ERROR);
896}
897
899 PointerRNA * /*ptr*/,
900 PointerRNA * /*node_ptr*/,
901 float *r_color)
902{
903 r_color[0] = 1.0f;
904 r_color[1] = 0.0f;
905 r_color[2] = 0.0f;
906 r_color[3] = 1.0f;
907}
908
910 float *r_color)
911{
912 r_color[0] = 1.0f;
913 r_color[1] = 0.0f;
914 r_color[2] = 0.0f;
915 r_color[3] = 1.0f;
916}
917
919 bNodeTreeInterfaceSocket * /*interface_socket*/,
920 bContext * /*C*/,
921 uiLayout *layout)
922{
923 layout->label(IFACE_("Undefined Socket Type"), ICON_ERROR);
924}
925
927
928} // namespace blender::ed::space_node
929
931{
932 using namespace blender::ed::space_node;
933
934 /* Fallback types for undefined tree, nodes, sockets
935 * Defined in blenkernel, but not registered in type hashes.
936 */
937
940
941 NodeTypeUndefined.draw_buttons = nullptr;
942 NodeTypeUndefined.draw_buttons_ex = nullptr;
943
944 NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
945 NodeSocketTypeUndefined.draw_color = node_socket_undefined_draw_color;
948
949 /* node type ui functions */
952
956
957 /* define update callbacks for socket properties */
959 }
960}
961
963
968
969namespace blender::ed::space_node {
970
971static const float virtual_node_socket_color[4] = {0.2, 0.2, 0.2, 1.0};
972
973/* maps standard socket integer type to a color */
974static const float std_node_socket_colors[][4] = {
975 {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
976 {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
977 {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
978 {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
979 {0.80, 0.65, 0.84, 1.0}, /* SOCK_BOOLEAN */
980 {0.0, 0.0, 0.0, 0.0}, /* UNUSED */
981 {0.35, 0.55, 0.36, 1.0}, /* SOCK_INT */
982 {0.44, 0.70, 1.00, 1.0}, /* SOCK_STRING */
983 {0.93, 0.62, 0.36, 1.0}, /* SOCK_OBJECT */
984 {0.39, 0.22, 0.39, 1.0}, /* SOCK_IMAGE */
985 {0.00, 0.84, 0.64, 1.0}, /* SOCK_GEOMETRY */
986 {0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
987 {0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
988 {0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
989 {0.65, 0.39, 0.78, 1.0}, /* SOCK_ROTATION */
990 {0.40, 0.40, 0.40, 1.0}, /* SOCK_MENU */
991 {0.72, 0.20, 0.52, 1.0}, /* SOCK_MATRIX */
992 {0.30, 0.50, 0.50, 1.0}, /* SOCK_BUNDLE */
993 {0.50, 0.60, 0.40, 1.0}, /* SOCK_CLOSURE */
994};
995
996void std_node_socket_colors_get(int socket_type, float *r_color)
997{
998 BLI_assert(socket_type >= 0);
999 BLI_assert(socket_type < std::size(std_node_socket_colors));
1000
1001 copy_v4_v4(r_color, std_node_socket_colors[socket_type]);
1002}
1003
1004/* Callback for colors that does not depend on the socket pointer argument to get the type. */
1005template<int socket_type>
1007 PointerRNA * /*ptr*/,
1008 PointerRNA * /*node_ptr*/,
1009 float *r_color)
1010{
1011 copy_v4_v4(r_color, std_node_socket_colors[socket_type]);
1012};
1013static void std_node_socket_color_simple_fn(const bke::bNodeSocketType *type, float *r_color)
1014{
1015 copy_v4_v4(r_color, std_node_socket_colors[type->type]);
1016};
1017
1018using SocketColorFn = void (*)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color);
1019/* Callbacks for all built-in socket types. */
1032
1033/* draw function for file output node sockets,
1034 * displays only sub-path and format, no value button */
1036 uiLayout *layout,
1037 PointerRNA *ptr,
1038 PointerRNA *node_ptr)
1039{
1040 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
1041 bNodeSocket *sock = (bNodeSocket *)ptr->data;
1042 uiLayout *row;
1043 PointerRNA inputptr;
1044
1045 row = &layout->row(false);
1046
1047 PointerRNA imfptr = RNA_pointer_get(node_ptr, "format");
1048 int imtype = RNA_enum_get(&imfptr, "file_format");
1049
1050 if (imtype == R_IMF_IMTYPE_MULTILAYER) {
1052 inputptr = RNA_pointer_create_discrete(&ntree->id, &RNA_NodeOutputFileSlotLayer, input);
1053
1054 row->label(input->layer, ICON_NONE);
1055 }
1056 else {
1058 uiBlock *block;
1059 inputptr = RNA_pointer_create_discrete(&ntree->id, &RNA_NodeOutputFileSlotFile, input);
1060
1061 row->label(input->path, ICON_NONE);
1062
1063 if (!RNA_boolean_get(&inputptr, "use_node_format")) {
1064 imfptr = RNA_pointer_get(&inputptr, "format");
1065 }
1066
1067 const char *imtype_name;
1068 PropertyRNA *imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
1070 C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
1071 block = uiLayoutGetBlock(row);
1073 row->label(imtype_name, ICON_NONE);
1075 }
1076}
1077
1079{
1080 const nodes::NodeDeclaration *node_decl = node.declaration();
1081 if (node_decl == nullptr) {
1082 return false;
1083 }
1084 if (node_decl->skip_updating_sockets) {
1085 return false;
1086 }
1087 if (socket.in_out == SOCK_OUT) {
1088 return false;
1089 }
1090 const int socket_index = BLI_findindex(&node.inputs, &socket);
1091 return node_decl->inputs[socket_index]->is_attribute_name;
1092}
1093
1094static bool socket_needs_layer_search(const bNode &node, const bNodeSocket &socket)
1095{
1096 const nodes::NodeDeclaration *node_decl = node.declaration();
1097 if (node_decl == nullptr) {
1098 return false;
1099 }
1100 if (node_decl->skip_updating_sockets) {
1101 return false;
1102 }
1103 if (socket.in_out == SOCK_OUT) {
1104 return false;
1105 }
1106 const int socket_index = BLI_findindex(&node.inputs, &socket);
1107 return node_decl->inputs[socket_index]->is_layer_name;
1108}
1109
1110static void draw_gizmo_pin_icon(uiLayout *layout, PointerRNA *socket_ptr)
1111{
1112 layout->prop(socket_ptr, "pin_gizmo", UI_ITEM_NONE, "", ICON_GIZMO);
1113}
1114
1116 bNodeSocket *sock,
1117 const StringRef text)
1118{
1119 if (sock->runtime->declaration) {
1120 if (sock->runtime->declaration->socket_name_rna) {
1122 layout->prop((&sock->runtime->declaration->socket_name_rna->owner),
1123 sock->runtime->declaration->socket_name_rna->property_name,
1125 "",
1126 ICON_NONE);
1127 return;
1128 }
1129 }
1130 layout->label(text, ICON_NONE);
1131}
1132
1134 bNodeSocket *sock,
1135 const StringRef text)
1136{
1137 draw_node_socket_name_editable(layout, sock, text);
1138}
1139
1140/* Menu sockets hide the socket name by default to save space. Some nodes have multiple menu
1141 * sockets which requires showing the name anyway to avoid ambiguity. */
1142static bool show_menu_socket_name(const bNode *node, const bNodeSocket *sock)
1143{
1144 BLI_assert(sock->type == SOCK_MENU);
1145 if (node->is_type("GeometryNodeMenuSwitch") && sock->index() > 0) {
1146 return true;
1147 }
1148 if (node->is_type("GeometryNodeSwitch")) {
1149 return true;
1150 }
1151 return false;
1152}
1153
1155 bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRefNull text)
1156{
1157 bNode *node = (bNode *)node_ptr->data;
1158 bNodeSocket *sock = (bNodeSocket *)ptr->data;
1159 bNodeTree *tree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
1160 int type = sock->typeinfo->type;
1161 // int subtype = sock->typeinfo->subtype;
1162
1163 const nodes::SocketDeclaration *socket_decl = sock->runtime->declaration;
1164 if (socket_decl) {
1165 if (socket_decl->custom_draw_fn) {
1166 nodes::CustomSocketDrawParams params{*C, *layout, *tree, *node, *sock, *node_ptr, *ptr};
1167 (*socket_decl->custom_draw_fn)(params);
1168 return;
1169 }
1170 }
1171
1172 if (sock->is_inactive()) {
1173 uiLayoutSetActive(layout, false);
1174 }
1175
1176 /* XXX not nice, eventually give this node its own socket type ... */
1177 if (node->type_legacy == CMP_NODE_OUTPUT_FILE) {
1178 node_file_output_socket_draw(C, layout, ptr, node_ptr);
1179 return;
1180 }
1181
1182 const bool has_gizmo = tree->runtime->gizmo_propagation ?
1183 tree->runtime->gizmo_propagation->gizmo_endpoint_sockets.contains(
1184 sock) :
1185 false;
1186
1187 if (has_gizmo) {
1188 if (sock->in_out == SOCK_OUT && node->is_group_input()) {
1189 uiLayout *row = &layout->row(false);
1191 node_socket_button_label(C, row, ptr, node_ptr, text);
1192 row->label("", ICON_GIZMO);
1193 return;
1194 }
1195 if (sock->in_out == SOCK_IN && sock->index() == 0 &&
1197 {
1198 uiLayout *row = &layout->row(false);
1199 node_socket_button_label(C, row, ptr, node_ptr, text);
1201 return;
1202 }
1203 }
1204
1205 if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_HIDE_VALUE) || sock->is_logically_linked())
1206 {
1207 draw_node_socket_without_value(layout, sock, text);
1208 return;
1209 }
1210
1211 const StringRefNull label = text;
1212 text = (sock->flag & SOCK_HIDE_LABEL) ? "" : text;
1213
1214 /* Some socket types draw the gizmo icon in a special way to look better. All others use a
1215 * fallback default code path. */
1216 bool gizmo_handled = false;
1217
1218 switch (type) {
1219 case SOCK_FLOAT:
1220 case SOCK_INT:
1221 case SOCK_BOOLEAN:
1222 layout->prop(ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
1223 break;
1224 case SOCK_VECTOR:
1225 if (sock->flag & SOCK_COMPACT) {
1226 uiTemplateComponentMenu(layout, ptr, "default_value", text);
1227 }
1228 else {
1229 if (sock->typeinfo->subtype == PROP_DIRECTION) {
1230 layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1231 }
1232 else {
1233 uiLayout *column = &layout->column(false);
1234 {
1235 uiLayout *row = &column->row(true);
1237 if (has_gizmo) {
1239 gizmo_handled = true;
1240 }
1241 }
1242 column->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1243 }
1244 }
1245 break;
1246 case SOCK_ROTATION: {
1247 uiLayout *column = &layout->column(false);
1248 {
1249 uiLayout *row = &column->row(true);
1251 if (has_gizmo) {
1253 gizmo_handled = true;
1254 }
1255 }
1256 column->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1257 break;
1258 }
1259 case SOCK_MATRIX: {
1260 draw_node_socket_name_editable(layout, sock, text);
1261 break;
1262 }
1263 case SOCK_RGBA: {
1264 if (text.is_empty()) {
1265 layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1266 }
1267 else {
1268 uiLayout *row = &layout->split(0.4f, false);
1269 row->label(text, ICON_NONE);
1270 row->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1271 }
1272 break;
1273 }
1274 case SOCK_STRING: {
1275 if (socket_needs_attribute_search(*node, *sock)) {
1276 if (text.is_empty()) {
1277 node_geometry_add_attribute_search_button(*C, *node, *ptr, *layout, label);
1278 }
1279 else {
1280 uiLayout *row = &layout->split(0.4f, false);
1281 row->label(text, ICON_NONE);
1283 }
1284 }
1285 else if (socket_needs_layer_search(*node, *sock)) {
1286 if (text.is_empty()) {
1287 node_geometry_add_layer_search_button(*C, *node, *ptr, *layout, label);
1288 }
1289 else {
1290 uiLayout *row = &layout->split(0.4f, false);
1291 row->label(text, ICON_NONE);
1293 }
1294 }
1295 else {
1296 if (text.is_empty()) {
1297 layout->prop(ptr,
1298 RNA_struct_find_property(ptr, "default_value"),
1299 -1,
1300 0,
1302 "",
1303 ICON_NONE,
1304 label);
1305 }
1306 else {
1307 uiLayout *row = &layout->split(0.4f, false);
1308 row->label(text, ICON_NONE);
1309 row->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1310 }
1311 }
1312 break;
1313 }
1314 case SOCK_MENU: {
1315 const bNodeSocketValueMenu *default_value =
1316 sock->default_value_typed<bNodeSocketValueMenu>();
1317 if (default_value->enum_items) {
1318 if (default_value->enum_items->items.is_empty()) {
1319 uiLayout *row = &layout->split(0.4f, false);
1320 row->label(text, ICON_NONE);
1321 row->label(IFACE_("No Items"), ICON_NONE);
1322 }
1323 else {
1324 if (const auto *menu_decl = dynamic_cast<const nodes::decl::Menu *>(socket_decl)) {
1325 if (menu_decl->is_expanded) {
1326 layout->prop(ptr, "default_value", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
1327 break;
1328 }
1329 }
1330 const char *name = show_menu_socket_name(node, sock) ? sock->name : "";
1331 layout->prop(ptr, "default_value", DEFAULT_FLAGS, name, ICON_NONE);
1332 }
1333 }
1334 else if (default_value->has_conflict()) {
1335 layout->label(IFACE_("Menu Error"), ICON_ERROR);
1336 }
1337 else {
1338 layout->label(IFACE_("Menu Undefined"), ICON_QUESTION);
1339 }
1340 break;
1341 }
1342 case SOCK_COLLECTION:
1343 case SOCK_OBJECT:
1344 case SOCK_MATERIAL: {
1345 layout->prop(ptr,
1346 RNA_struct_find_property(ptr, "default_value"),
1347 -1,
1348 0,
1350 text,
1351 ICON_NONE,
1352 text.is_empty() ? std::optional(label) : std::nullopt);
1353 break;
1354 }
1355 case SOCK_IMAGE: {
1356 const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
1357 if (node_tree->type == NTREE_GEOMETRY) {
1358 if (text.is_empty()) {
1359 uiTemplateID(layout, C, ptr, "default_value", "image.new", "image.open", nullptr);
1360 }
1361 else {
1362 /* 0.3 split ratio is inconsistent, but use it here because the "New" button is large. */
1363 uiLayout *row = &layout->split(0.3f, false);
1364 row->label(text, ICON_NONE);
1365 uiTemplateID(row, C, ptr, "default_value", "image.new", "image.open", nullptr);
1366 }
1367 }
1368 else {
1369 layout->prop(ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE);
1370 }
1371 break;
1372 }
1373 case SOCK_TEXTURE: {
1374 if (text.is_empty()) {
1375 uiTemplateID(layout, C, ptr, "default_value", "texture.new", nullptr, nullptr);
1376 }
1377 else {
1378 /* 0.3 split ratio is inconsistent, but use it here because the "New" button is large. */
1379 uiLayout *row = &layout->split(0.3f, false);
1380 row->label(text, ICON_NONE);
1381 uiTemplateID(row, C, ptr, "default_value", "texture.new", nullptr, nullptr);
1382 }
1383
1384 break;
1385 }
1386 default:
1387 draw_node_socket_without_value(layout, sock, text);
1388 break;
1389 }
1390
1391 if (has_gizmo && !gizmo_handled) {
1392 draw_gizmo_pin_icon(layout, ptr);
1393 }
1394}
1395
1397 bNodeTreeInterfaceSocket *interface_socket,
1398 bContext * /*C*/,
1399 uiLayout *layout)
1400{
1401 PointerRNA ptr = RNA_pointer_create_discrete(id, &RNA_NodeTreeInterfaceSocket, interface_socket);
1402
1403 const bke::bNodeSocketType *typeinfo = interface_socket->socket_typeinfo();
1404 BLI_assert(typeinfo != nullptr);
1406
1407 uiLayout *col = &layout->column(false);
1408
1409 switch (type) {
1410 case SOCK_FLOAT: {
1411 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1412 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1413 uiLayout *sub = &col->column(true);
1414 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1415 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1416 break;
1417 }
1418 case SOCK_INT: {
1419 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1420 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1421 uiLayout *sub = &col->column(true);
1422 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1423 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1424 break;
1425 }
1426 case SOCK_VECTOR: {
1427 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1428 col->prop(&ptr,
1429 "dimensions",
1432 ICON_NONE);
1433 col->prop(&ptr, "default_value", UI_ITEM_R_EXPAND, IFACE_("Default"), ICON_NONE);
1434 uiLayout *sub = &col->column(true);
1435 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1436 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1437 break;
1438 }
1439 case SOCK_STRING: {
1440 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1441 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1442 break;
1443 }
1444 case SOCK_BOOLEAN:
1445 case SOCK_ROTATION:
1446 case SOCK_RGBA:
1447 case SOCK_OBJECT:
1448 case SOCK_COLLECTION:
1449 case SOCK_IMAGE:
1450 case SOCK_TEXTURE:
1451 case SOCK_MATERIAL: {
1452 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1453 break;
1454 }
1455 case SOCK_MENU: {
1456 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1457 col->prop(&ptr, "menu_expanded", DEFAULT_FLAGS, IFACE_("Expanded"), ICON_NONE);
1458 break;
1459 }
1460 case SOCK_SHADER:
1461 case SOCK_GEOMETRY:
1462 case SOCK_MATRIX:
1463 case SOCK_BUNDLE:
1464 case SOCK_CLOSURE:
1465 break;
1466
1467 case SOCK_CUSTOM:
1469 break;
1470 }
1471
1472 col = &layout->column(false);
1473
1474 const bNodeTree *node_tree = reinterpret_cast<const bNodeTree *>(id);
1475 if (interface_socket->flag & NODE_INTERFACE_SOCKET_INPUT && node_tree->type == NTREE_GEOMETRY) {
1476 if (ELEM(type, SOCK_INT, SOCK_VECTOR, SOCK_MATRIX)) {
1477 col->prop(&ptr, "default_input", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1478 }
1479 }
1480
1481 {
1482 uiLayout *sub = &col->column(false);
1483 uiLayoutSetActive(sub, interface_socket->default_input == NODE_DEFAULT_INPUT_VALUE);
1484 sub->prop(&ptr, "hide_value", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1485 }
1486
1487 if (interface_socket->flag & NODE_INTERFACE_SOCKET_INPUT && node_tree->type == NTREE_GEOMETRY) {
1488 if (type == SOCK_BOOLEAN) {
1489 col->prop(&ptr, "layer_selection_field", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1490 }
1491 uiLayout *sub = &col->column(false);
1492 uiLayoutSetActive(sub, !is_layer_selection_field(*interface_socket));
1493 sub->prop(&ptr, "hide_in_modifier", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1495 sub->prop(&ptr, "structure_type", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1496 }
1497 }
1498}
1499
1501 PointerRNA * /*ptr*/,
1502 PointerRNA * /*node_ptr*/,
1503 float *r_color)
1504{
1506}
1507
1509 float *r_color)
1510{
1512}
1513
1514} // namespace blender::ed::space_node
1515
1524
1532
1533void ED_node_type_draw_color(const char *idname, float *r_color)
1534{
1535 using namespace blender::ed::space_node;
1536
1538 if (!typeinfo || typeinfo->type == SOCK_CUSTOM) {
1539 r_color[0] = 0.0f;
1540 r_color[1] = 0.0f;
1541 r_color[2] = 0.0f;
1542 r_color[3] = 0.0f;
1543 return;
1544 }
1545
1547 copy_v4_v4(r_color, std_node_socket_colors[typeinfo->type]);
1548}
1549
1550namespace blender::ed::space_node {
1551
1552/* ************** Generic drawing ************** */
1553
1555 ARegion &region,
1556 SpaceNode &snode,
1557 bNodeInstanceKey parent_key)
1558{
1559 Main *bmain = CTX_data_main(&C);
1560 bNodeInstanceKey active_viewer_key = (snode.nodetree ? snode.nodetree->active_viewer_key :
1569
1570 if (!(snode.flag & SNODE_BACKDRAW) || !ED_node_is_compositor(&snode)) {
1571 return;
1572 }
1573
1574 if (parent_key.value != active_viewer_key.value) {
1575 return;
1576 }
1577
1580
1581 /* The draw manager is used to draw the backdrop image. */
1582 GPUFrameBuffer *old_fb = GPU_framebuffer_active_get();
1585 DRW_draw_view(&C);
1588 /* Draw manager changes the depth state. Set it back to NONE. Without this the
1589 * node preview images aren't drawn correctly. */
1591
1592 void *lock;
1593 Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
1594 ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
1595 if (ibuf) {
1596 /* somehow the offset has to be calculated inverse */
1598 const float offset_x = snode.xof + ima->runtime->backdrop_offset[0] * snode.zoom;
1599 const float offset_y = snode.yof + ima->runtime->backdrop_offset[1] * snode.zoom;
1600 const float x = (region.winx - snode.zoom * ibuf->x) / 2 + offset_x;
1601 const float y = (region.winy - snode.zoom * ibuf->y) / 2 + offset_y;
1602
1605 if (snode.edittree) {
1606 bNode *node = (bNode *)snode.edittree->nodes.first;
1607 const rctf *viewer_border = &snode.nodetree->viewer_border;
1608 while (node) {
1609 if (node->flag & NODE_SELECT) {
1610 if (node->typeinfo->draw_backdrop) {
1611 node->typeinfo->draw_backdrop(&snode, ibuf, node, x, y);
1612 }
1613 }
1614 node = node->next;
1615 }
1616
1617 if ((snode.nodetree->flag & NTREE_VIEWER_BORDER) &&
1618 viewer_border->xmin < viewer_border->xmax && viewer_border->ymin < viewer_border->ymax)
1619 {
1620 rcti pixel_border;
1621 BLI_rcti_init(&pixel_border,
1622 x + snode.zoom * viewer_border->xmin * ibuf->x,
1623 x + snode.zoom * viewer_border->xmax * ibuf->x,
1624 y + snode.zoom * viewer_border->ymin * ibuf->y,
1625 y + snode.zoom * viewer_border->ymax * ibuf->y);
1626
1631
1632 immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
1633
1635 }
1636 }
1637 }
1638
1639 BKE_image_release_ibuf(ima, ibuf, lock);
1642}
1643
1645 const bNodeSocket &socket,
1646 const bNodeLink &link)
1647{
1648 const float2 socket_location = socket.runtime->location;
1649 if (socket.is_multi_input() && socket.is_input() && !(node.flag & NODE_HIDDEN)) {
1650 /* For internal link case, handle number of links as at least 1. */
1651 const int clamped_total_inputs = math::max<int>(1, socket.runtime->total_inputs);
1653 socket_location, link.multi_input_sort_id, clamped_total_inputs);
1654 }
1655 return socket_location;
1656}
1657
1658static void calculate_inner_link_bezier_points(std::array<float2, 4> &points)
1659{
1660 const int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE);
1661 if (curving == 0) {
1662 /* Straight line: align all points. */
1663 points[1] = math::interpolate(points[0], points[3], 1.0f / 3.0f);
1664 points[2] = math::interpolate(points[0], points[3], 2.0f / 3.0f);
1665 }
1666 else {
1667 const float dist_x = math::distance(points[0].x, points[3].x);
1668 const float dist_y = math::distance(points[0].y, points[3].y);
1669
1670 /* Reduce the handle offset when the link endpoints are close to horizontal. */
1671 const float slope = math::safe_divide(dist_y, dist_x);
1672 const float clamp_factor = math::min(1.0f, slope * (4.5f - 0.25f * float(curving)));
1673
1674 const float handle_offset = curving * 0.1f * dist_x * clamp_factor;
1675
1676 points[1].x = points[0].x + handle_offset;
1677 points[1].y = points[0].y;
1678
1679 points[2].x = points[3].x - handle_offset;
1680 points[2].y = points[3].y;
1681 }
1682}
1683
1684static std::array<float2, 4> node_link_bezier_points(const bNodeLink &link)
1685{
1686 std::array<float2, 4> points;
1687 points[0] = socket_link_connection_location(*link.fromnode, *link.fromsock, link);
1688 points[3] = socket_link_connection_location(*link.tonode, *link.tosock, link);
1690 return points;
1691}
1692
1693static bool node_link_draw_is_visible(const View2D &v2d, const std::array<float2, 4> &points)
1694{
1695 if (min_ffff(points[0].x, points[1].x, points[2].x, points[3].x) > v2d.cur.xmax) {
1696 return false;
1697 }
1698 if (max_ffff(points[0].x, points[1].x, points[2].x, points[3].x) < v2d.cur.xmin) {
1699 return false;
1700 }
1701 return true;
1702}
1703
1705 std::array<float2, NODE_LINK_RESOL + 1> &coords)
1706{
1707 const std::array<float2, 4> points = node_link_bezier_points(link);
1708
1709 /* The extra +1 in size is required by these functions and would be removed ideally. */
1711 points[1].x,
1712 points[2].x,
1713 points[3].x,
1714 &coords[0].x,
1716 sizeof(float2));
1718 points[1].y,
1719 points[2].y,
1720 points[3].y,
1721 &coords[0].y,
1723 sizeof(float2));
1724}
1725
1726/* -------------------------------------------------------------------- */
1729
1730/* Keep in sync with node socket shader. */
1731#define MAX_SOCKET_PARAMETERS 4
1732#define MAX_SOCKET_INSTANCE 32
1733
1739
1741{
1742 static GBatchNodesocket nodesocket_batch;
1743 return nodesocket_batch;
1744}
1745
1746static gpu::Batch *nodesocket_batch_init()
1747{
1748 if (g_batch_nodesocket().batch == nullptr) {
1749 GPUIndexBufBuilder ibuf;
1750 GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 2, 4);
1751 /* Quad to draw the node socket in. */
1752 GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2);
1753 GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3);
1754
1758 }
1759 return g_batch_nodesocket().batch;
1760}
1761
1763{
1764 if (g_batch_nodesocket().params.is_empty()) {
1765 return;
1766 }
1767
1768 gpu::Batch *batch = nodesocket_batch_init();
1769 if (g_batch_nodesocket().params.size() == 1) {
1770 /* draw single */
1773 batch,
1774 "parameters",
1775 4,
1776 reinterpret_cast<const float(*)[4]>(g_batch_nodesocket().params.data()));
1778 }
1779 else {
1782 batch,
1783 "parameters",
1785 reinterpret_cast<const float(*)[4]>(g_batch_nodesocket().params.data()));
1787 }
1789}
1790
1792{
1794 g_batch_nodesocket().enabled = true;
1795}
1796
1806
1808{
1810 g_batch_nodesocket().params.append(socket_params);
1811
1814 }
1815 }
1816 else {
1817 /* Draw single instead of batch. */
1818 gpu::Batch *batch = nodesocket_batch_init();
1821 batch, "parameters", MAX_SOCKET_PARAMETERS, (const float(*)[4])(&socket_params));
1823 }
1824}
1825
1827 const float color_inner[4],
1828 const float color_outline[4],
1829 const float outline_thickness,
1830 const int shape,
1831 const float aspect)
1832{
1833 /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
1834 * If it has been scaled, then it's no longer valid. */
1835 BLI_assert((color_inner != nullptr) && (color_outline != nullptr));
1836
1837 NodeSocketShaderParameters socket_params = {};
1838 socket_params.rect[0] = rect->xmin;
1839 socket_params.rect[1] = rect->xmax;
1840 socket_params.rect[2] = rect->ymin;
1841 socket_params.rect[3] = rect->ymax;
1842 socket_params.color_inner[0] = color_inner[0];
1843 socket_params.color_inner[1] = color_inner[1];
1844 socket_params.color_inner[2] = color_inner[2];
1845 socket_params.color_inner[3] = color_inner[3];
1846 socket_params.color_outline[0] = color_outline[0];
1847 socket_params.color_outline[1] = color_outline[1];
1848 socket_params.color_outline[2] = color_outline[2];
1849 socket_params.color_outline[3] = color_outline[3];
1850 socket_params.outline_thickness = outline_thickness;
1851 socket_params.outline_offset = 0.0;
1852 socket_params.shape = float(shape) + 0.1f;
1853 socket_params.aspect = aspect;
1854
1856 draw_node_socket_batch(socket_params);
1858}
1859
1861
1862/* -------------------------------------------------------------------- */
1865
1866#define NODELINK_GROUP_SIZE 256
1867#define LINK_RESOL 24
1868#define LINK_WIDTH 2.5f
1869#define ARROW_SIZE (7 * UI_SCALE_FAC)
1870
1871/* Reroute arrow shape and mute bar. These are expanded here and shrunk in the GLSL code.
1872 * See: `gpu_shader_2D_nodelink_vert.glsl`. */
1873static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
1874static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
1875static float mute_verts[3][2] = {{0.7071f, 1.0f}, {0.7071f, 0.0f}, {0.7071f, -1.0f}};
1876static float mute_expand_axis[3][2] = {{1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, -0.0f}};
1877
1878/* Is zero initialized because it is static data. */
1879static struct {
1880 gpu::Batch *batch; /* for batching line together */
1881 gpu::Batch *batch_single; /* for single line */
1898
1900{
1906 g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
1908 g_batch_link.inst_vbo, g_batch_link.muted_id, &g_batch_link.muted_step);
1910 g_batch_link.inst_vbo, g_batch_link.dim_factor_id, &g_batch_link.dim_factor_step);
1912 g_batch_link.inst_vbo, g_batch_link.thickness_id, &g_batch_link.thickness_step);
1914 g_batch_link.inst_vbo, g_batch_link.dash_params_id, &g_batch_link.dash_params_step);
1916 g_batch_link.inst_vbo, g_batch_link.has_back_link_id, &g_batch_link.has_back_link_step);
1918 g_batch_link.inst_vbo, g_batch_link.start_color_id, &g_batch_link.start_color_step);
1920 g_batch_link.inst_vbo, g_batch_link.end_color_id, &g_batch_link.end_color_step);
1921 g_batch_link.count = 0;
1922}
1923
1925 uint uv_id,
1926 uint pos_id,
1927 uint exp_id,
1928 uint v,
1929 const float uv[2],
1930 const float pos[2],
1931 const float exp[2])
1932{
1933 GPU_vertbuf_attr_set(vbo, uv_id, v, uv);
1934 GPU_vertbuf_attr_set(vbo, pos_id, v, pos);
1935 GPU_vertbuf_attr_set(vbo, exp_id, v, exp);
1936}
1937
1939{
1940 GPUVertFormat format = {0};
1943 uint expand_id = GPU_vertformat_attr_add(&format, "expand", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1945 int vcount = LINK_RESOL * 2; /* curve */
1946 vcount += 2; /* restart strip */
1947 vcount += 3 * 2; /* arrow */
1948 vcount += 2; /* restart strip */
1949 vcount += 3 * 2; /* mute */
1950 vcount *= 2; /* shadow */
1951 vcount += 2; /* restart strip */
1952 GPU_vertbuf_data_alloc(*vbo, vcount);
1953 int v = 0;
1954
1955 for (int k = 0; k < 2; k++) {
1956 float uv[2] = {0.0f, 0.0f};
1957 float pos[2] = {0.0f, 0.0f};
1958 float exp[2] = {0.0f, 1.0f};
1959
1960 /* restart */
1961 if (k == 1) {
1962 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1963 }
1964
1965 /* curve strip */
1966 for (int i = 0; i < LINK_RESOL; i++) {
1967 uv[0] = (i / float(LINK_RESOL - 1));
1968 uv[1] = 0.0f;
1969 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1970 uv[1] = 1.0f;
1971 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1972 }
1973 /* restart */
1974 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1975
1976 uv[0] = 0.5f;
1977 uv[1] = 0.0f;
1980 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1981 /* arrow */
1982 for (int i = 0; i < 3; i++) {
1983 uv[1] = 0.0f;
1986 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1987
1988 uv[1] = 1.0f;
1989 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1990 }
1991
1992 /* restart */
1993 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1994
1995 uv[0] = 0.5f;
1996 uv[1] = 0.0f;
1999 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
2000 /* bar */
2001 for (int i = 0; i < 3; ++i) {
2002 uv[1] = 0.0f;
2005 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
2006
2007 uv[1] = 1.0f;
2008 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
2009 }
2010
2011 /* restart */
2012 if (k == 0) {
2013 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
2014 }
2015 }
2016
2019
2020 g_batch_link.batch_single = GPU_batch_create_ex(
2021 GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_INVALID);
2023
2024 /* Instances data */
2025 GPUVertFormat format_inst = {0};
2027 &format_inst, "P0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2029 &format_inst, "P1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2031 &format_inst, "P2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2033 &format_inst, "P3", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
2035 &format_inst, "colid_doarrow", GPU_COMP_U8, 4, GPU_FETCH_INT);
2036 g_batch_link.start_color_id = GPU_vertformat_attr_add(
2037 &format_inst, "start_color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2039 &format_inst, "end_color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
2041 &format_inst, "domuted", GPU_COMP_U32, 1, GPU_FETCH_INT);
2042 g_batch_link.dim_factor_id = GPU_vertformat_attr_add(
2043 &format_inst, "dim_factor", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2045 &format_inst, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
2046 g_batch_link.dash_params_id = GPU_vertformat_attr_add(
2047 &format_inst, "dash_params", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
2048 g_batch_link.has_back_link_id = GPU_vertformat_attr_add(
2049 &format_inst, "has_back_link", GPU_COMP_I32, 1, GPU_FETCH_INT);
2051 /* Alloc max count but only draw the range we need. */
2053
2054 GPU_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
2055
2057}
2058
2059static char nodelink_get_color_id(int th_col)
2060{
2061 switch (th_col) {
2062 case TH_WIRE:
2063 return 1;
2064 case TH_WIRE_INNER:
2065 return 2;
2066 case TH_ACTIVE:
2067 return 3;
2068 case TH_EDGE_SELECT:
2069 return 4;
2070 case TH_REDALERT:
2071 return 5;
2072 }
2073 return 0;
2074}
2075
2076static void nodelink_batch_draw(const SpaceNode &snode)
2077{
2078 if (g_batch_link.count == 0) {
2079 return;
2080 }
2081
2083 NodeLinkInstanceData node_link_data;
2084
2091 node_link_data.aspect = snode.runtime->aspect;
2092 node_link_data.arrowSize = ARROW_SIZE;
2093
2094 GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(sizeof(node_link_data), &node_link_data, __func__);
2095
2097 GPU_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
2098
2100 GPU_batch_uniformbuf_bind(g_batch_link.batch, "node_link_data", ubo);
2102
2105
2107
2109}
2110
2112{
2113 g_batch_link.enabled = true;
2114}
2115
2117{
2118 nodelink_batch_draw(snode);
2119 g_batch_link.enabled = false;
2120}
2121
2142
2143static void nodelink_batch_add_link(const SpaceNode &snode,
2144 const std::array<float2, 4> &points,
2145 const NodeLinkDrawConfig &draw_config)
2146{
2147 /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
2148 BLI_assert(
2150 BLI_assert(
2152 BLI_assert(ELEM(draw_config.th_col3, TH_WIRE, TH_REDALERT, -1));
2153
2154 g_batch_link.count++;
2155 copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p0_step), points[0]);
2156 copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p1_step), points[1]);
2157 copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p2_step), points[2]);
2158 copy_v2_v2((float *)GPU_vertbuf_raw_step(&g_batch_link.p3_step), points[3]);
2159 char *colid = (char *)GPU_vertbuf_raw_step(&g_batch_link.colid_step);
2160 colid[0] = nodelink_get_color_id(draw_config.th_col1);
2161 colid[1] = nodelink_get_color_id(draw_config.th_col2);
2162 colid[2] = nodelink_get_color_id(draw_config.th_col3);
2163 colid[3] = draw_config.drawarrow;
2164 copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.start_color_step),
2165 draw_config.start_color);
2166 copy_v4_v4((float *)GPU_vertbuf_raw_step(&g_batch_link.end_color_step), draw_config.end_color);
2167 uint32_t *muted = (uint32_t *)GPU_vertbuf_raw_step(&g_batch_link.muted_step);
2168 muted[0] = draw_config.drawmuted;
2169 *(float *)GPU_vertbuf_raw_step(&g_batch_link.dim_factor_step) = draw_config.dim_factor;
2170 *(float *)GPU_vertbuf_raw_step(&g_batch_link.thickness_step) = draw_config.thickness;
2171 float3 dash_params(draw_config.dash_length, draw_config.dash_factor, draw_config.dash_alpha);
2172 copy_v3_v3((float *)GPU_vertbuf_raw_step(&g_batch_link.dash_params_step), dash_params);
2173 *(int *)GPU_vertbuf_raw_step(&g_batch_link.has_back_link_step) = draw_config.has_back_link;
2174
2175 if (g_batch_link.count == NODELINK_GROUP_SIZE) {
2176 nodelink_batch_draw(snode);
2177 }
2178}
2179
2180static void node_draw_link_end_marker(const float2 center,
2181 const float radius,
2182 const ColorTheme4f &color)
2183{
2184 rctf rect;
2185 BLI_rctf_init(&rect, center.x - radius, center.x + radius, center.y - radius, center.y + radius);
2186
2188 UI_draw_roundbox_4fv(&rect, true, radius, color);
2189 /* Round-box disables alpha. Re-enable it for node links that are drawn after this one. */
2191}
2192
2194 const NodeLinkDrawConfig &draw_config,
2195 const std::array<float2, 4> &points,
2196 const bool outline)
2197{
2198 const float radius = (outline ? 0.65f : 0.45f) * NODE_SOCKSIZE;
2199 if (link.fromsock) {
2201 points[0], radius, outline ? draw_config.outline_color : draw_config.start_color);
2202 }
2203 if (link.tosock) {
2205 points[3], radius, outline ? draw_config.outline_color : draw_config.end_color);
2206 }
2207}
2208
2209static bool node_link_is_field_link(const SpaceNode &snode, const bNodeLink &link)
2210{
2211 const bNodeTree &tree = *snode.edittree;
2212 if (tree.type != NTREE_GEOMETRY) {
2213 return false;
2214 }
2215 const Span<bke::FieldSocketState> field_states = tree.runtime->field_states;
2216 if (link.fromsock &&
2217 field_states[link.fromsock->index_in_tree()] == bke::FieldSocketState::IsField)
2218 {
2219 return true;
2220 }
2221 return false;
2222}
2223
2224static bool node_link_is_gizmo_link(const SpaceNode &snode, const bNodeLink &link)
2225{
2226 if (snode.edittree->type != NTREE_GEOMETRY) {
2227 return false;
2228 }
2229 if (!link.fromsock || !link.tosock) {
2230 return false;
2231 }
2232 const bNodeTree &tree = *snode.edittree;
2233 return tree.runtime->sockets_on_active_gizmo_paths.contains(link.fromsock) &&
2234 tree.runtime->sockets_on_active_gizmo_paths.contains(link.tosock);
2235}
2236
2238 const View2D &v2d,
2239 const SpaceNode &snode,
2240 const bNodeLink &link,
2241 const int th_col1,
2242 const int th_col2,
2243 const int th_col3,
2244 const bool selected)
2245{
2246 NodeLinkDrawConfig draw_config;
2247
2248 draw_config.th_col1 = th_col1;
2249 draw_config.th_col2 = th_col2;
2250 draw_config.th_col3 = th_col3;
2251
2252 draw_config.dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link);
2253
2254 bTheme *btheme = UI_GetTheme();
2255 draw_config.dash_alpha = btheme->space_node.dash_alpha;
2256
2257 const bool field_link = node_link_is_field_link(snode, link);
2258 const bool gizmo_link = node_link_is_gizmo_link(snode, link);
2259
2260 draw_config.dash_factor = field_link ? 0.75f : 1.0f;
2261 draw_config.dash_length = 10.0f * UI_SCALE_FAC;
2262
2263 const float scale = UI_view2d_scale_get_x(&v2d);
2264 /* Clamp the thickness to make the links more readable when zooming out. */
2265 draw_config.thickness = LINK_WIDTH * max_ff(UI_SCALE_FAC * scale, 1.0f) *
2266 (field_link ? 0.7f : 1.0f);
2267 draw_config.has_back_link = gizmo_link;
2268 draw_config.highlighted = link.flag & NODE_LINK_TEMP_HIGHLIGHT;
2269 draw_config.drawarrow = ((link.tonode && link.tonode->is_reroute()) &&
2270 (link.fromnode && link.fromnode->is_reroute()));
2271 draw_config.drawmuted = (link.flag & NODE_LINK_MUTED);
2272
2273 UI_GetThemeColor4fv(th_col3, draw_config.outline_color);
2274
2277 {
2278 const bNodeTree &node_tree = *snode.edittree;
2280 &const_cast<ID &>(node_tree.id), &RNA_Node, link.fromnode);
2282 &const_cast<ID &>(node_tree.id), &RNA_Node, link.tonode);
2283
2284 if (link.fromsock) {
2285 node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.start_color);
2286 }
2287 else {
2288 node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.start_color);
2289 }
2290
2291 if (link.tosock) {
2292 node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.end_color);
2293 }
2294 else {
2295 node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.end_color);
2296 }
2297 }
2298 else {
2299 UI_GetThemeColor4fv(th_col1, draw_config.start_color);
2300 UI_GetThemeColor4fv(th_col2, draw_config.end_color);
2301 }
2302
2303 /* Highlight links connected to selected nodes. */
2304 if (selected) {
2305 ColorTheme4f color_selected;
2306 UI_GetThemeColor4fv(TH_EDGE_SELECT, color_selected);
2307 const float alpha = color_selected.a;
2308
2309 /* Interpolate color if highlight color is not fully transparent. */
2310 if (alpha != 0.0) {
2311 if (link.fromsock) {
2312 interp_v3_v3v3(draw_config.start_color, draw_config.start_color, color_selected, alpha);
2313 }
2314 if (link.tosock) {
2315 interp_v3_v3v3(draw_config.end_color, draw_config.end_color, color_selected, alpha);
2316 }
2317 }
2318 }
2319
2320 if (draw_config.highlighted) {
2321 ColorTheme4f link_preselection_highlight_color;
2322 UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color);
2323 /* Multi sockets can only be inputs. So we only have to highlight the end of the link. */
2324 copy_v4_v4(draw_config.end_color, link_preselection_highlight_color);
2325 }
2326
2327 return draw_config;
2328}
2329
2330static void node_draw_link_bezier_ex(const SpaceNode &snode,
2331 const NodeLinkDrawConfig &draw_config,
2332 const std::array<float2, 4> &points)
2333{
2334 if (g_batch_link.batch == nullptr) {
2336 }
2337
2338 if (g_batch_link.enabled && !draw_config.highlighted && !GPU_node_link_instancing_workaround()) {
2339 /* Add link to batch. */
2340 nodelink_batch_add_link(snode, points, draw_config);
2341 }
2342 else {
2343 NodeLinkData node_link_data;
2344 for (const int i : IndexRange(points.size())) {
2345 copy_v2_v2(node_link_data.bezierPts[i], points[i]);
2346 }
2347
2348 copy_v4_v4(node_link_data.colors[0], draw_config.outline_color);
2349 copy_v4_v4(node_link_data.colors[1], draw_config.start_color);
2350 copy_v4_v4(node_link_data.colors[2], draw_config.end_color);
2351
2352 node_link_data.doArrow = draw_config.drawarrow;
2353 node_link_data.doMuted = draw_config.drawmuted;
2354 node_link_data.dim_factor = draw_config.dim_factor;
2355 node_link_data.thickness = draw_config.thickness;
2356 node_link_data.dash_params[0] = draw_config.dash_length;
2357 node_link_data.dash_params[1] = draw_config.dash_factor;
2358 node_link_data.dash_params[2] = draw_config.dash_alpha;
2359 node_link_data.has_back_link = draw_config.has_back_link;
2360 node_link_data.aspect = snode.runtime->aspect;
2361 node_link_data.arrowSize = ARROW_SIZE;
2362
2363 gpu::Batch *batch = g_batch_link.batch_single;
2364 GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(sizeof(NodeLinkData), &node_link_data, __func__);
2365
2367 GPU_batch_uniformbuf_bind(batch, "node_link_data", ubo);
2369
2372 }
2373}
2374
2376 const View2D &v2d,
2377 const SpaceNode &snode,
2378 const bNodeLink &link,
2379 const int th_col1,
2380 const int th_col2,
2381 const int th_col3,
2382 const bool selected)
2383{
2384 const std::array<float2, 4> points = node_link_bezier_points(link);
2385 if (!node_link_draw_is_visible(v2d, points)) {
2386 return;
2387 }
2388 const NodeLinkDrawConfig draw_config = nodelink_get_draw_config(
2389 C, v2d, snode, link, th_col1, th_col2, th_col3, selected);
2390
2391 node_draw_link_bezier_ex(snode, draw_config, points);
2392}
2393
2395 const View2D &v2d,
2396 const SpaceNode &snode,
2397 const bNodeLink &link,
2398 const bool selected)
2399{
2400 int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
2401
2402 if (link.fromsock == nullptr && link.tosock == nullptr) {
2403 return;
2404 }
2405
2406 /* going to give issues once... */
2407 if (link.tosock->flag & SOCK_UNAVAIL) {
2408 return;
2409 }
2410 if (link.fromsock->flag & SOCK_UNAVAIL) {
2411 return;
2412 }
2413
2414 if (link.flag & NODE_LINK_VALID) {
2415 /* special indicated link, on drop-node */
2417 th_col1 = th_col2 = TH_ACTIVE;
2418 }
2419 else if (link.flag & NODE_LINK_MUTED) {
2420 th_col1 = th_col2 = TH_REDALERT;
2421 }
2422 }
2423 else {
2424 /* Invalid link. */
2425 th_col1 = th_col2 = th_col3 = TH_REDALERT;
2426 // th_col3 = -1; /* no shadow */
2427 }
2428
2429 node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3, selected);
2430}
2431
2432std::array<float2, 4> node_link_bezier_points_dragged(const SpaceNode &snode,
2433 const bNodeLink &link)
2434{
2435 const float2 cursor = snode.runtime->cursor * UI_SCALE_FAC;
2436 std::array<float2, 4> points;
2437 points[0] = link.fromsock ?
2439 cursor;
2440 points[3] = link.tosock ? socket_link_connection_location(*link.tonode, *link.tosock, link) :
2441 cursor;
2443 return points;
2444}
2445
2447 const View2D &v2d,
2448 const SpaceNode &snode,
2449 const bNodeLink &link)
2450{
2451 if (link.fromsock == nullptr && link.tosock == nullptr) {
2452 return;
2453 }
2454
2455 const std::array<float2, 4> points = node_link_bezier_points_dragged(snode, link);
2456
2457 const NodeLinkDrawConfig draw_config = nodelink_get_draw_config(
2458 C, v2d, snode, link, TH_ACTIVE, TH_ACTIVE, TH_WIRE, true);
2459 /* End marker outline. */
2460 node_draw_link_end_markers(link, draw_config, points, true);
2461 /* Link. */
2462 node_draw_link_bezier_ex(snode, draw_config, points);
2463 /* End marker fill. */
2464 node_draw_link_end_markers(link, draw_config, points, false);
2465}
2466
2467} // namespace blender::ed::space_node
void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
Definition glutil.cc:618
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition curve.cc:1673
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
Image * BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
bool BKE_image_is_dirty(Image *image)
int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, bool *r_is_in_range)
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
#define NODE_GROUP
Definition BKE_node.hh:796
#define NODE_FRAME
Definition BKE_node.hh:797
#define CMP_NODE_VALTORGB
#define SH_NODE_COMBINE_COLOR
#define SH_NODE_MIX_RGB_LEGACY
#define SH_NODE_CURVE_FLOAT
#define CMP_NODE_MIX_RGB
#define CMP_NODE_TIME
#define SH_NODE_OUTPUT_WORLD
#define SH_NODE_NORMAL
#define SH_NODE_TEX_IMAGE
#define TEX_NODE_PROC_MAX
#define CMP_NODE_COMBYCCA_LEGACY
#define CMP_NODE_SEPARATE_COLOR
#define CMP_NODE_CRYPTOMATTE
#define SH_NODE_SEPARATE_COLOR
#define TEX_NODE_BRICKS
#define SH_NODE_TEX_ENVIRONMENT
#define SH_NODE_CURVE_VEC
#define CMP_NODE_TEXTURE
#define CMP_NODE_HUECORRECT
#define TEX_NODE_COMBINE_COLOR
#define SH_NODE_MATH
#define TEX_NODE_TEXTURE
#define TEX_NODE_SEPARATE_COLOR
#define CMP_NODE_MATH
#define CMP_NODE_CRYPTOMATTE_LEGACY
#define SH_NODE_OUTPUT_MATERIAL
#define TEX_NODE_IMAGE
#define CMP_NODE_OUTPUT_FILE
#define CMP_NODE_CURVE_RGB
#define CMP_NODE_COMBINE_COLOR
#define SH_NODE_VECTOR_DISPLACEMENT
#define SH_NODE_VALTORGB
#define SH_NODE_CURVE_RGB
#define TEX_NODE_OUTPUT
#define TEX_NODE_CURVE_TIME
#define SH_NODE_BSDF_GLASS
#define SH_NODE_DISPLACEMENT
#define CMP_NODE_SEPYCCA_LEGACY
#define TEX_NODE_MATH
#define SH_NODE_BSDF_REFRACTION
#define CMP_NODE_IMAGE
#define TEX_NODE_PROC
#define CMP_NODE_NORMAL
#define SH_NODE_OUTPUT_LIGHT
#define SH_NODE_VOLUME_SCATTER
#define TEX_NODE_MIX_RGB
#define TEX_NODE_VALTORGB
#define TEX_NODE_CURVE_RGB
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
MINLINE float max_ffff(float a, float b, float c, float d)
MINLINE float max_ff(float a, float b)
MINLINE float min_ffff(float a, float b, float c, float d)
#define M_SQRT2
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE void copy_v4_fl(float r[4], float f)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.cc:404
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
unsigned int uint
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_thread_lock(int type)
Definition threads.cc:328
@ LOCK_DRAW_IMAGE
Definition BLI_threads.h:64
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_ID_TEXTURE
@ CUMA_DRAW_SAMPLE
@ IMA_SRC_MOVIE
@ IMA_SRC_GENERATED
@ IMA_SRC_SEQUENCE
@ IMA_TYPE_MULTILAYER
@ IMA_TYPE_COMPOSITE
@ NODE_HIDDEN
@ NODE_SELECT
@ CMP_NODE_COMBSEP_COLOR_YCC
@ NTREE_TEXTURE
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ NTREE_VIEWER_BORDER
@ NODE_LINK_TEMP_HIGHLIGHT
@ NODE_LINK_MUTED
@ NODE_LINK_INSERT_TARGET
@ NODE_LINK_INSERT_TARGET_INVALID
@ NODE_LINK_VALID
@ NODE_FRAME_RESIZEABLE
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ SOCK_OUT
@ SOCK_IN
@ SOCK_HIDE_LABEL
@ SOCK_HIDE_VALUE
@ SOCK_COMPACT
@ SOCK_UNAVAIL
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_CLOSURE
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ SOCK_BUNDLE
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
@ SHD_PROJ_BOX
@ R_IMF_IMTYPE_MULTILAYER
@ SN_OVERLAY_SHOW_WIRE_COLORS
@ SN_OVERLAY_SHOW_OVERLAYS
@ SNODE_BACKDRAW
@ SPACE_NODE
@ TEX_RING
@ TEX_BAND
@ TEX_MINKOVSKY
@ TEX_BLEND
@ TEX_MARBLE
@ TEX_WOOD
@ TEX_CLOUDS
@ TEX_DISTNOISE
@ TEX_VORONOI
@ TEX_STUCCI
@ TEX_MAGIC
@ TEX_MUSGRAVE
#define UI_SCALE_FAC
void DRW_draw_view(const bContext *C)
bool ED_node_is_compositor(const SpaceNode *snode)
Definition node_edit.cc:548
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_BACKDROP
static void split(const char *text, const char *seps, char ***str, int *count)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
void GPU_batch_instbuf_set(blender::gpu::Batch *batch, blender::gpu::VertBuf *vertex_buf, bool own_vbo)
void GPU_batch_draw_instance_range(blender::gpu::Batch *batch, int instance_first, int instance_count)
#define GPU_batch_uniformbuf_bind(batch, name, ubo)
Definition GPU_batch.hh:316
#define GPU_batch_uniform_4fv_array(batch, name, len, val)
Definition GPU_batch.hh:312
void GPU_batch_program_set_builtin(blender::gpu::Batch *batch, eGPUBuiltinShader shader_id)
void GPU_batch_draw(blender::gpu::Batch *batch)
@ GPU_BATCH_INVALID
Definition GPU_batch.hh:38
@ GPU_BATCH_OWNS_INDEX
Definition GPU_batch.hh:50
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:41
void gpu_batch_presets_register(blender::gpu::Batch *preset_batch)
bool GPU_node_link_instancing_workaround()
void GPU_framebuffer_bind_no_srgb(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_restore()
void immUnbindProgram()
void immUniformThemeColor(int color_id)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
GPUVertFormat * immVertexFormat()
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
blender::gpu::IndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *, uint v1, uint v2, uint v3)
void GPU_matrix_identity_set()
void GPU_matrix_push()
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
void GPU_matrix_pop()
@ GPU_PRIM_TRI_STRIP
@ GPU_PRIM_TRIS
@ GPU_SHADER_2D_NODELINK_INST
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_2D_NODE_SOCKET
@ GPU_SHADER_2D_NODE_SOCKET_INST
@ GPU_SHADER_2D_NODELINK
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
void GPU_depth_test(eGPUDepthTest test)
Definition gpu_state.cc:68
GPUUniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
void GPU_uniformbuf_unbind(GPUUniformBuf *ubo)
void GPU_uniformbuf_free(GPUUniformBuf *ubo)
void GPU_vertbuf_attr_get_raw_data(blender::gpu::VertBuf *, uint a_idx, GPUVertBufRaw *access)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
void GPU_vertbuf_use(blender::gpu::VertBuf *)
blender::gpu::VertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat &format, GPUUsageType usage)
void GPU_vertbuf_data_len_set(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertbuf_attr_set(blender::gpu::VertBuf *, uint a_idx, uint v_idx, const void *data)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_USAGE_STATIC
@ GPU_USAGE_STREAM
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U32
@ GPU_COMP_U8
bool IMB_colormanagement_space_name_is_data(const char *name)
@ PROP_DIRECTION
Definition RNA_types.hh:250
#define C
Definition RandGen.cpp:29
void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4])
void UI_block_emboss_set(uiBlock *block, blender::ui::EmbossType emboss)
@ UI_CNR_ALL
void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, blender::StringRef name)
void UI_draw_roundbox_corner_set(int type)
void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, bool expand)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, const char *text=nullptr)
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, blender::StringRefNull propname, PointerRNA *userptr, bool compact, bool multiview)
void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int type, bool levels, bool brush, bool neg_slope, bool tone)
void uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int icon)
void uiLayoutSetContextPointer(uiLayout *layout, blender::StringRef name, PointerRNA *ptr)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
@ UI_LAYOUT_ALIGN_RIGHT
uiBlock * uiLayoutGetBlock(uiLayout *layout)
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
#define UI_ITEM_NONE
void uiLayoutSetEmboss(uiLayout *layout, blender::ui::EmbossType emboss)
int UI_GetThemeValueType(int colorid, int spacetype)
@ TH_WIRE
@ TH_EDGE_SELECT
@ TH_REDALERT
@ TH_NODE_CURVING
@ TH_SELECT
@ TH_WIRE_INNER
@ TH_ACTIVE
void UI_GetThemeColor4fv(int colorid, float col[4])
bTheme * UI_GetTheme()
float UI_view2d_scale_get_x(const View2D *v2d)
Definition view2d.cc:1920
volatile int lock
#define U
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void append(const T &value)
void clear()
ChannelStorageType a
Definition BLI_color.hh:93
Vector< SocketDeclaration * > inputs
std::unique_ptr< CustomSocketDrawFn > custom_draw_fn
#define LINK_RESOL
Definition drawnode.cc:1867
void ED_node_sample_set(const float col[4])
Definition drawnode.cc:131
#define ARROW_SIZE
Definition drawnode.cc:1869
#define MAX_SOCKET_PARAMETERS
Definition drawnode.cc:1731
#define NODELINK_GROUP_SIZE
Definition drawnode.cc:1866
void ED_init_standard_node_socket_type(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:1516
#define MAX_SOCKET_INSTANCE
Definition drawnode.cc:1732
static float _sample_col[4]
Definition drawnode.cc:130
void ED_init_custom_node_socket_type(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:964
void ED_init_node_socket_type_virtual(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:1525
void ED_node_type_draw_color(const char *idname, float *r_color)
Definition drawnode.cc:1533
void ED_init_custom_node_type(blender::bke::bNodeType *)
Definition drawnode.cc:962
#define DEFAULT_FLAGS
Definition drawnode.cc:77
void ED_node_init_butfuncs()
Definition drawnode.cc:930
#define SAMPLE_FLT_ISNONE
Definition drawnode.cc:128
#define LINK_WIDTH
Definition drawnode.cc:1868
KDTree_3d * tree
uint pos
uint col
#define input
#define exp
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
bNodeSocketType NodeSocketTypeUndefined
Definition node.cc:123
Span< bNodeType * > node_types_get()
Definition node.cc:2779
bNodeType NodeTypeUndefined
Definition node.cc:122
bNodeSocketType * node_socket_type_find(StringRef idname)
Definition node.cc:2794
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
Definition node.cc:5119
static void node_texture_buts_bricks(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:674
static const float virtual_node_socket_color[4]
Definition drawnode.cc:971
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:396
static void node_composit_buts_cryptomatte_legacy_ex(uiLayout *layout, bContext *, PointerRNA *)
Definition drawnode.cc:580
static void node_shader_buts_scatter(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:420
static void node_socket_template_properties_update(blender::bke::bNodeType *ntype, blender::bke::bNodeSocketTemplate *stemp)
Definition drawnode.cc:862
static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:506
static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:524
void nodelink_batch_start(SpaceNode &)
Definition drawnode.cc:2111
static const float std_node_socket_colors[][4]
Definition drawnode.cc:974
static void node_shader_buts_displacement(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:405
static void node_socket_button_label(bContext *, uiLayout *layout, PointerRNA *, PointerRNA *, const StringRefNull text)
Definition drawnode.cc:81
static void node_buts_frame_ex(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:264
static void node_buts_time(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:106
static void node_buts_curvevec(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:116
static void std_node_socket_interface_draw(ID *id, bNodeTreeInterfaceSocket *interface_socket, bContext *, uiLayout *layout)
Definition drawnode.cc:1396
GPUVertBufRaw dash_params_step
Definition drawnode.cc:1893
static float mute_expand_axis[3][2]
Definition drawnode.cc:1876
static void node_buts_math(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:188
static void calculate_inner_link_bezier_points(std::array< float2, 4 > &points)
Definition drawnode.cc:1658
static void node_texture_buts_proc(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:687
static void node_buts_combsep_color(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:194
static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:777
void node_draw_link_bezier(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const int th_col1, const int th_col2, const int th_col3, const bool selected)
Definition drawnode.cc:2375
static void node_composit_buts_ycc(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:549
void nodelink_batch_end(SpaceNode &snode)
Definition drawnode.cc:2116
static bool node_link_is_gizmo_link(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2224
std::array< float2, 4 > node_link_bezier_points_dragged(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2432
GPUVertBufRaw p1_step
Definition drawnode.cc:1889
static bool show_menu_socket_name(const bNode *node, const bNodeSocket *sock)
Definition drawnode.cc:1142
static float arrow_expand_axis[3][2]
Definition drawnode.cc:1874
GPUVertBufRaw has_back_link_step
Definition drawnode.cc:1894
void node_geometry_add_layer_search_button(const bContext &, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout, const StringRef placeholder)
void node_socket_color_get(const bContext &C, const bNodeTree &ntree, PointerRNA &node_ptr, const bNodeSocket &sock, float r_color[4])
static NodeLinkDrawConfig nodelink_get_draw_config(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const int th_col1, const int th_col2, const int th_col3, const bool selected)
Definition drawnode.cc:2237
void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const bool selected)
Definition drawnode.cc:2394
static void nodelink_batch_reset()
Definition drawnode.cc:1899
static void draw_node_socket_batch(const NodeSocketShaderParameters &socket_params)
Definition drawnode.cc:1807
static void draw_gizmo_pin_icon(uiLayout *layout, PointerRNA *socket_ptr)
Definition drawnode.cc:1110
gpu::Batch * batch_single
Definition drawnode.cc:1881
float2 node_link_calculate_multi_input_position(const float2 &socket_position, const int index, const int total_inputs)
Definition node_edit.cc:128
static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:259
static void nodelink_batch_init()
Definition drawnode.cc:1938
static bool socket_needs_layer_search(const bNode &node, const bNodeSocket &socket)
Definition drawnode.cc:1094
static void node_buts_colorramp(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:111
void std_node_socket_colors_get(int socket_type, float *r_color)
Definition drawnode.cc:996
static GBatchNodesocket & g_batch_nodesocket()
Definition drawnode.cc:1740
void node_draw_link_dragged(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2446
static char nodelink_get_color_id(int th_col)
Definition drawnode.cc:2059
static void draw_node_socket_without_value(uiLayout *layout, bNodeSocket *sock, const StringRef text)
Definition drawnode.cc:1133
GPUVertBufRaw p2_step
Definition drawnode.cc:1889
static void nodelink_batch_add_link(const SpaceNode &snode, const std::array< float2, 4 > &points, const NodeLinkDrawConfig &draw_config)
Definition drawnode.cc:2143
static void node_buts_output_shader(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:415
GPUVertBufRaw end_color_step
Definition drawnode.cc:1890
static void node_buts_curvefloat(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:121
static void node_buts_texture(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:172
static void node_composit_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:623
GPUVertBufRaw dim_factor_step
Definition drawnode.cc:1891
void draw_nodespace_back_pix(const bContext &C, ARegion &region, SpaceNode &snode, bNodeInstanceKey parent_key)
Definition drawnode.cc:1554
static void node_socket_undefined_draw_color_simple(const bke::bNodeSocketType *, float *r_color)
Definition drawnode.cc:909
float node_link_dim_factor(const View2D &v2d, const bNodeLink &link)
static void node_texture_buts_output(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:784
GPUVertBufRaw thickness_step
Definition drawnode.cc:1892
static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:376
static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRefNull text)
Definition drawnode.cc:1154
static bool node_link_is_field_link(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2209
void node_geometry_add_attribute_search_button(const bContext &, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout, const StringRef placeholder)
static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:772
static const SocketColorFn std_node_socket_color_funcs[]
Definition drawnode.cc:1020
static float arrow_verts[3][2]
Definition drawnode.cc:1873
static std::array< float2, 4 > node_link_bezier_points(const bNodeLink &link)
Definition drawnode.cc:1684
static void node_buts_mix_rgb(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:92
static void node_shader_buts_glossy(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:410
static void node_socket_undefined_interface_draw(ID *, bNodeTreeInterfaceSocket *, bContext *, uiLayout *layout)
Definition drawnode.cc:918
GPUVertBufRaw muted_step
Definition drawnode.cc:1890
static void std_node_socket_color_simple_fn(const bke::bNodeSocketType *type, float *r_color)
Definition drawnode.cc:1013
static bool node_link_draw_is_visible(const View2D &v2d, const std::array< float2, 4 > &points)
Definition drawnode.cc:1693
static void nodesocket_cache_flush()
Definition drawnode.cc:1762
static void node_buts_image_views(uiLayout *layout, bContext *, PointerRNA *ptr, PointerRNA *imaptr)
Definition drawnode.cc:483
void node_link_bezier_points_evaluated(const bNodeLink &link, std::array< float2, NODE_LINK_RESOL+1 > &coords)
Definition drawnode.cc:1704
static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:588
static void node_texture_buts_combsep_color(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:789
static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr)
Definition drawnode.cc:1035
static struct blender::ed::space_node::@115050225201365207313130011241223120045130311177 g_batch_link
static void node_socket_virtual_draw_color(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:1500
static void nodelink_batch_draw(const SpaceNode &snode)
Definition drawnode.cc:2076
float2 socket_link_connection_location(const bNode &node, const bNodeSocket &socket, const bNodeLink &link)
Definition drawnode.cc:1644
static void node_draw_link_bezier_ex(const SpaceNode &snode, const NodeLinkDrawConfig &draw_config, const std::array< float2, 4 > &points)
Definition drawnode.cc:2330
static void node_texture_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:795
static void node_socket_undefined_draw_color(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:898
static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr, PointerRNA *imaptr, PointerRNA *iuserptr, const bool show_layer_selection, const bool show_color_management)
Definition drawnode.cc:285
NodeResizeDirection node_get_resize_direction(const SpaceNode &snode, const bNode *node, const int x, const int y)
Definition drawnode.cc:199
void std_node_socket_color_fn(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:1006
static void node_composit_buts_huecorrect(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:533
static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:382
static void node_buts_curvecol(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:143
GPUVertBufRaw p3_step
Definition drawnode.cc:1889
static void node_common_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:271
static void node_draw_link_end_marker(const float2 center, const float radius, const ColorTheme4f &color)
Definition drawnode.cc:2180
static void node_template_properties_update(blender::bke::bNodeType *ntype)
Definition drawnode.cc:873
void(*)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color) SocketColorFn
Definition drawnode.cc:1018
GPUVertBufRaw colid_step
Definition drawnode.cc:1890
GPUVertBufRaw start_color_step
Definition drawnode.cc:1890
static void node_composit_buts_cryptomatte_legacy(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:565
static void node_socket_virtual_draw_color_simple(const bke::bNodeSocketType *, float *r_color)
Definition drawnode.cc:1508
static void node_composit_buts_combsep_color(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:554
gpu::VertBuf * inst_vbo
Definition drawnode.cc:1882
static float mute_verts[3][2]
Definition drawnode.cc:1875
static void draw_node_socket_name_editable(uiLayout *layout, bNodeSocket *sock, const StringRef text)
Definition drawnode.cc:1115
void node_draw_nodesocket(const rctf *rect, const float color_inner[4], const float color_outline[4], float outline_thickness, int shape, float aspect)
Definition drawnode.cc:1826
static void node_draw_link_end_markers(const bNodeLink &link, const NodeLinkDrawConfig &draw_config, const std::array< float2, 4 > &points, const bool outline)
Definition drawnode.cc:2193
static void node_socket_undefined_draw(bContext *, uiLayout *layout, PointerRNA *, PointerRNA *, StringRefNull)
Definition drawnode.cc:889
GPUVertBufRaw p0_step
Definition drawnode.cc:1889
static void node_buts_normal(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:162
static gpu::Batch * nodesocket_batch_init()
Definition drawnode.cc:1746
static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:354
static void node_property_update_default(Main *bmain, Scene *, PointerRNA *ptr)
Definition drawnode.cc:854
static void node_shader_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:426
static void set_nodelink_vertex(gpu::VertBuf *vbo, uint uv_id, uint pos_id, uint exp_id, uint v, const float uv[2], const float pos[2], const float exp[2])
Definition drawnode.cc:1924
static bool socket_needs_attribute_search(bNode &node, bNodeSocket &socket)
Definition drawnode.cc:1078
T safe_divide(const T &a, const T &b)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T max(const T &a, const T &b)
bool is_builtin_gizmo_node(const bNode &node)
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
bool socket_type_supports_grids(const eNodeSocketDatatype socket_type)
VecBase< float, 2 > float2
ColorTheme4< float > ColorTheme4f
Definition BLI_color.hh:292
VecBase< float, 3 > float3
bool is_layer_selection_field(const bNodeTreeInterfaceSocket &socket)
#define NODE_LINK_RESOL
#define NODE_RESIZE_MARGIN
#define NODE_SOCKSIZE
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
void RNA_def_property_update_runtime(PropertyRNA *prop, RNAPropertyUpdateFunc func)
StructRNA * srna
Definition RNA_types.hh:909
Definition DNA_ID.h:404
ColorManagedColorspaceSettings colorspace_settings
short source
ImageRuntimeHandle * runtime
void * first
ID * owner_id
Definition RNA_types.hh:51
void * data
Definition RNA_types.hh:53
struct RenderData r
SpaceNode_Runtime * runtime
struct bNodeTree * edittree
SpaceNodeOverlay overlay
struct bNodeTree * nodetree
short stype
short vn_distm
unsigned int value
const RuntimeNodeEnumItemsHandle * enum_items
bNodeSocketRuntimeHandle * runtime
bNodeSocketTypeHandle * typeinfo
ListBase nodes
bNodeInstanceKey active_viewer_key
bNodeTypeHandle * typeinfo
int16_t custom1
ListBase inputs
struct ID * id
int16_t type_legacy
struct bNode * next
bNodeRuntimeHandle * runtime
void * storage
ListBase outputs
ThemeSpace space_node
Compact definition of a node socket.
Definition BKE_node.hh:98
Defines a socket type.
Definition BKE_node.hh:152
void(* draw_color)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color)
Definition BKE_node.hh:165
void(* draw_color_simple)(const bNodeSocketType *socket_type, float *r_color)
Definition BKE_node.hh:166
void(* interface_draw)(ID *id, bNodeTreeInterfaceSocket *socket, bContext *C, uiLayout *layout)
Definition BKE_node.hh:168
eNodeSocketDatatype type
Definition BKE_node.hh:187
void(* draw)(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRefNull text)
Definition BKE_node.hh:160
Defines a node type.
Definition BKE_node.hh:226
bNodeSocketTemplate * inputs
Definition BKE_node.hh:242
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:249
bNodeSocketTemplate * outputs
Definition BKE_node.hh:242
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
Vector< NodeSocketShaderParameters, MAX_SOCKET_INSTANCE > params
Definition drawnode.cc:1736
float xmax
float xmin
float ymax
float ymin
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
uiLayout & row(bool align)
uiLayout & split(float percentage, bool align)
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
PointerRNA * ptr
Definition wm_files.cc:4226
void wmOrtho2_region_pixelspace(const ARegion *region)