Blender V5.0
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_utf8.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_interface.hh"
60#include "UI_resources.hh"
61#include "UI_view2d.hh"
62
64#include "IMB_imbuf_types.hh"
65
66#include "NOD_composite.hh"
67#include "NOD_geometry.hh"
70#include "NOD_partial_eval.hh"
71#include "NOD_socket.hh"
73#include "node_intern.hh" /* own include */
74
76
77/* Default flags for uiLayout::prop(). Name is kept short since this is used a lot in this file. */
78#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME
79
80/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
81
83 uiLayout *layout,
84 PointerRNA * /*ptr*/,
85 PointerRNA * /*node_ptr*/,
86 const StringRef text)
87{
88 layout->label(text, ICON_NONE);
89}
90
91/* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
92
93static void node_buts_mix_rgb(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
94{
95 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
96
97 uiLayout *col = &layout->column(false);
98 uiLayout *row = &col->row(true);
99 row->prop(ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE);
100 if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) {
101 row->prop(ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA);
102 }
103
104 col->prop(ptr, "use_clamp", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
105}
106
107static void node_buts_time(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
108{
109 uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false, false);
110}
111
112static void node_buts_colorramp(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
113{
114 uiTemplateColorRamp(layout, ptr, "color_ramp", false);
115}
116
117static void node_buts_curvevec(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
118{
119 uiTemplateCurveMapping(layout, ptr, "mapping", 'v', false, false, false, false, false);
120}
121
122static void node_buts_curvefloat(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
123{
124 uiTemplateCurveMapping(layout, ptr, "mapping", 0, false, false, false, false, false);
125}
126
127} // namespace blender::ed::space_node
128
129#define SAMPLE_FLT_ISNONE FLT_MAX
130/* Bad! 2.5 will do better? ... no it won't! */
131static float _sample_col[4] = {SAMPLE_FLT_ISNONE};
132void ED_node_sample_set(const float col[4])
133{
134 if (col) {
136 }
137 else {
139 }
140}
141
142namespace blender::ed::space_node {
143
144static void node_buts_curvecol(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
145{
146 bNode *node = (bNode *)ptr->data;
147 CurveMapping *cumap = (CurveMapping *)node->storage;
148
149 if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
150 cumap->flag |= CUMA_DRAW_SAMPLE;
152 }
153 else {
154 cumap->flag &= ~CUMA_DRAW_SAMPLE;
155 }
156
157 /* "Tone" (Standard/Film-like) only used in the Compositor. */
158 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
160 layout, ptr, "mapping", 'c', false, false, false, (ntree->type == NTREE_COMPOSIT), false);
161}
162
163static void node_buts_normal(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
164{
165 bNode *node = (bNode *)ptr->data;
166 /* first output stores normal */
168 PointerRNA sockptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_NodeSocket, output);
169
170 layout->prop(&sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
171}
172
174{
175 bNode *node = (bNode *)ptr->data;
176
177 short multi = (node->id && ((Tex *)node->id)->use_nodes &&
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_COLLAPSED) {
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_UTF8(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 split->active_set(!is_data);
345 }
346
347 /* Avoid losing changes image is painted. */
348 if (BKE_image_is_dirty((Image *)imaptr->data)) {
349 split->enabled_set(false);
350 }
351 }
352}
353
355{
356 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
357 PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
358
359 layout->context_ptr_set("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 layout->context_ptr_set("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;
468 break;
473 break;
476 break;
477 }
478}
479
480/* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
481
482static void node_buts_image_views(uiLayout *layout,
483 bContext * /*C*/,
485 PointerRNA *imaptr)
486{
487 uiLayout *col;
488
489 if (!imaptr->data) {
490 return;
491 }
492
493 col = &layout->column(false);
494
495 if (RNA_boolean_get(ptr, "has_views")) {
496 if (RNA_enum_get(ptr, "view") == 0) {
497 col->prop(ptr, "view", DEFAULT_FLAGS, std::nullopt, ICON_CAMERA_STEREO);
498 }
499 else {
500 col->prop(ptr, "view", DEFAULT_FLAGS, std::nullopt, ICON_SCENE);
501 }
502 }
503}
504
506{
507 bNode *node = (bNode *)ptr->data;
508
509 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
510 layout->context_ptr_set("image_user", &iuserptr);
511 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
512 if (!node->id) {
513 return;
514 }
515
516 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
517
518 node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true, true);
519
520 node_buts_image_views(layout, C, ptr, &imaptr);
521}
522
524{
525 bNode *node = (bNode *)ptr->data;
526
527 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
528 layout->context_ptr_set("image_user", &iuserptr);
529 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, true);
530}
531
533{
534 bNode *node = (bNode *)ptr->data;
535 CurveMapping *cumap = (CurveMapping *)node->storage;
536
537 if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
538 cumap->flag |= CUMA_DRAW_SAMPLE;
540 }
541 else {
542 cumap->flag &= ~CUMA_DRAW_SAMPLE;
543 }
544
545 uiTemplateCurveMapping(layout, ptr, "mapping", 'h', false, false, false, false, false);
546}
547
549{
550 bNode *node = (bNode *)ptr->data;
552
553 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
554 if (storage->mode == CMP_NODE_COMBSEP_COLOR_YCC) {
555 layout->prop(ptr, "ycc_mode", DEFAULT_FLAGS, "", ICON_NONE);
556 }
557}
558
560 bContext * /*C*/,
562{
563 uiLayout *col = &layout->column(true);
564
565 col->label(IFACE_("Matte Objects:"), ICON_NONE);
566
567 uiLayout *row = &col->row(true);
568 uiTemplateCryptoPicker(row, ptr, "add", ICON_ADD);
569 uiTemplateCryptoPicker(row, ptr, "remove", ICON_REMOVE);
570
571 col->prop(ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE);
572}
573
575 bContext * /*C*/,
576 PointerRNA * /*ptr*/)
577{
578 layout->op("NODE_OT_cryptomatte_layer_add", IFACE_("Add Crypto Layer"), ICON_ADD);
579 layout->op("NODE_OT_cryptomatte_layer_remove", IFACE_("Remove Crypto Layer"), ICON_REMOVE);
580}
581
583{
584 bNode *node = (bNode *)ptr->data;
585
586 uiLayout *row = &layout->row(true);
587 row->prop(ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
588
589 uiLayout *col = &layout->column(false);
591 uiTemplateID(col, C, ptr, "scene", nullptr, nullptr, nullptr);
592 }
593 else {
594 uiTemplateID(col, C, ptr, "image", nullptr, "IMAGE_OT_open", nullptr);
595
596 NodeCryptomatte *crypto = (NodeCryptomatte *)node->storage;
597 PointerRNA imaptr = RNA_pointer_get(ptr, "image");
599 ptr->owner_id, &RNA_ImageUser, &crypto->iuser);
600 layout->context_ptr_set("image_user", &iuserptr);
601
602 node_buts_image_user(col, C, ptr, &imaptr, &iuserptr, false, false);
603 node_buts_image_views(col, C, ptr, &imaptr);
604 }
605
606 col = &layout->column(true);
607 col->prop(ptr, "layer_name", UI_ITEM_NONE, "", ICON_NONE);
608 col->label(IFACE_("Matte ID:"), ICON_NONE);
609
610 row = &col->row(true);
611 row->prop(ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE);
612 uiTemplateCryptoPicker(row, ptr, "add", ICON_ADD);
613 uiTemplateCryptoPicker(row, ptr, "remove", ICON_REMOVE);
614}
615
616/* only once called */
649
650/* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
651
653{
654 uiLayout *col;
655
656 col = &layout->column(true);
657 col->prop(ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE);
658 col->prop(ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
659
660 col = &layout->column(true);
661 col->prop(ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE);
662 col->prop(ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE);
663}
664
666{
667 bNode *node = (bNode *)ptr->data;
668 ID *id = ptr->owner_id;
669 Tex *tex = (Tex *)node->storage;
670 uiLayout *col, *row;
671
672 PointerRNA tex_ptr = RNA_pointer_create_discrete(id, &RNA_Texture, tex);
673
674 col = &layout->column(false);
675
676 switch (tex->type) {
677 case TEX_BLEND:
678 col->prop(&tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE);
679 row = &col->row(false);
680 row->prop(
681 &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
682 break;
683
684 case TEX_MARBLE:
685 row = &col->row(false);
686 row->prop(
687 &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
688 row = &col->row(false);
689 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
690 row = &col->row(false);
691 row->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
692 row = &col->row(false);
693 row->prop(
694 &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
695 break;
696
697 case TEX_MAGIC:
698 col->prop(&tex_ptr, "noise_depth", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
699 break;
700
701 case TEX_STUCCI:
702 row = &col->row(false);
703 row->prop(
704 &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
705 row = &col->row(false);
706 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
707 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
708 break;
709
710 case TEX_WOOD:
711 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
712 col->prop(&tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE);
713 row = &col->row(false);
714 row->prop(
715 &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
716 row = &col->row(false);
717 row->active_set(!ELEM(tex->stype, TEX_BAND, TEX_RING));
718 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
719 break;
720
721 case TEX_CLOUDS:
722 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
723 row = &col->row(false);
724 row->prop(&tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
725 row = &col->row(false);
726 row->prop(&tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
727 col->prop(
728 &tex_ptr, "noise_depth", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
729 break;
730
731 case TEX_DISTNOISE:
732 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
733 col->prop(&tex_ptr, "noise_distortion", DEFAULT_FLAGS, "", ICON_NONE);
734 break;
735
736 case TEX_MUSGRAVE:
737 col->prop(&tex_ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE);
738 col->prop(&tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE);
739 break;
740 case TEX_VORONOI:
741 col->prop(&tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE);
742 if (tex->vn_distm == TEX_MINKOVSKY) {
743 col->prop(&tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
744 }
745 col->prop(&tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE);
746 break;
747 }
748}
749
751{
752 uiTemplateID(layout, C, ptr, "image", "IMAGE_OT_new", "IMAGE_OT_open", nullptr);
753}
754
756{
757 bNode *node = (bNode *)ptr->data;
758 PointerRNA iuserptr = RNA_pointer_create_discrete(ptr->owner_id, &RNA_ImageUser, node->storage);
759 uiTemplateImage(layout, C, ptr, "image", &iuserptr, false, false);
760}
761
763{
764 layout->prop(ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE);
765}
766
768{
769 layout->prop(ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE);
770}
771
772/* only once called */
774{
775 if (ntype->type_legacy >= TEX_NODE_PROC && ntype->type_legacy < TEX_NODE_PROC_MAX) {
777 }
778 else {
779 switch (ntype->type_legacy) {
780
781 case TEX_NODE_MATH:
783 break;
784
785 case TEX_NODE_MIX_RGB:
787 break;
788
791 break;
792
795 break;
796
799 break;
800
801 case TEX_NODE_TEXTURE:
803 break;
804
805 case TEX_NODE_BRICKS:
807 break;
808
809 case TEX_NODE_IMAGE:
812 break;
813
814 case TEX_NODE_OUTPUT:
816 break;
817
821 break;
822 }
823 }
824}
825
826/* -------------------------------------------------------------------- */
831
832static void node_property_update_default(Main *bmain, Scene * /*scene*/, PointerRNA *ptr)
833{
834 bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
835 bNode *node = (bNode *)ptr->data;
838}
839
850
852{
854
855 if (ntype->inputs) {
856 for (stemp = ntype->inputs; stemp->type >= 0; stemp++) {
858 }
859 }
860 if (ntype->outputs) {
861 for (stemp = ntype->outputs; stemp->type >= 0; stemp++) {
863 }
864 }
865}
866
868 uiLayout *layout,
869 PointerRNA * /*ptr*/,
870 PointerRNA * /*node_ptr*/,
871 StringRef /*text*/)
872{
873 layout->label(IFACE_("Undefined Socket Type"), ICON_ERROR);
874}
875
877 PointerRNA * /*ptr*/,
878 PointerRNA * /*node_ptr*/,
879 float *r_color)
880{
881 r_color[0] = 1.0f;
882 r_color[1] = 0.0f;
883 r_color[2] = 0.0f;
884 r_color[3] = 1.0f;
885}
886
888 float *r_color)
889{
890 r_color[0] = 1.0f;
891 r_color[1] = 0.0f;
892 r_color[2] = 0.0f;
893 r_color[3] = 1.0f;
894}
895
897 bNodeTreeInterfaceSocket * /*interface_socket*/,
898 bContext * /*C*/,
899 uiLayout *layout)
900{
901 layout->label(IFACE_("Undefined Socket Type"), ICON_ERROR);
902}
903
905
906} // namespace blender::ed::space_node
907
909{
910 using namespace blender::ed::space_node;
911
912 /* Fallback types for undefined tree, nodes, sockets
913 * Defined in blenkernel, but not registered in type hashes.
914 */
915
918
919 NodeTypeUndefined.draw_buttons = nullptr;
920 NodeTypeUndefined.draw_buttons_ex = nullptr;
921
922 NodeSocketTypeUndefined.draw = node_socket_undefined_draw;
923 NodeSocketTypeUndefined.draw_color = node_socket_undefined_draw_color;
926
927 /* node type ui functions */
930
934
935 /* define update callbacks for socket properties */
937 }
938}
939
941
946
947namespace blender::ed::space_node {
948
949static const float virtual_node_socket_color[4] = {0.2, 0.2, 0.2, 1.0};
950
951/* maps standard socket integer type to a color */
952static const float std_node_socket_colors[][4] = {
953 {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
954 {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
955 {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
956 {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
957 {0.80, 0.65, 0.84, 1.0}, /* SOCK_BOOLEAN */
958 {0.0, 0.0, 0.0, 0.0}, /* UNUSED */
959 {0.35, 0.55, 0.36, 1.0}, /* SOCK_INT */
960 {0.44, 0.70, 1.00, 1.0}, /* SOCK_STRING */
961 {0.93, 0.62, 0.36, 1.0}, /* SOCK_OBJECT */
962 {0.39, 0.22, 0.39, 1.0}, /* SOCK_IMAGE */
963 {0.00, 0.84, 0.64, 1.0}, /* SOCK_GEOMETRY */
964 {0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
965 {0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
966 {0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
967 {0.65, 0.39, 0.78, 1.0}, /* SOCK_ROTATION */
968 {0.40, 0.40, 0.40, 1.0}, /* SOCK_MENU */
969 {0.72, 0.20, 0.52, 1.0}, /* SOCK_MATRIX */
970 {0.30, 0.50, 0.50, 1.0}, /* SOCK_BUNDLE */
971 {0.49, 0.49, 0.23, 1.0}, /* SOCK_CLOSURE */
972};
973
974void std_node_socket_colors_get(int socket_type, float *r_color)
975{
976 BLI_assert(socket_type >= 0);
977 BLI_assert(socket_type < std::size(std_node_socket_colors));
978
979 copy_v4_v4(r_color, std_node_socket_colors[socket_type]);
980}
981
982/* Callback for colors that does not depend on the socket pointer argument to get the type. */
983template<int socket_type>
985 PointerRNA * /*ptr*/,
986 PointerRNA * /*node_ptr*/,
987 float *r_color)
988{
989 copy_v4_v4(r_color, std_node_socket_colors[socket_type]);
990};
991static void std_node_socket_color_simple_fn(const bke::bNodeSocketType *type, float *r_color)
992{
993 copy_v4_v4(r_color, std_node_socket_colors[type->type]);
994};
995
996using SocketColorFn = void (*)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color);
997/* Callbacks for all built-in socket types. */
1010
1012{
1013 const nodes::NodeDeclaration *node_decl = node.declaration();
1014 if (node_decl == nullptr) {
1015 return false;
1016 }
1017 if (node_decl->skip_updating_sockets) {
1018 return false;
1019 }
1020 if (socket.in_out == SOCK_OUT) {
1021 return false;
1022 }
1023 return socket.runtime->declaration->is_attribute_name;
1024}
1025
1026static bool socket_needs_layer_search(const bNode &node, const bNodeSocket &socket)
1027{
1028 const nodes::NodeDeclaration *node_decl = node.declaration();
1029 if (node_decl == nullptr) {
1030 return false;
1031 }
1032 if (node_decl->skip_updating_sockets) {
1033 return false;
1034 }
1035 if (socket.in_out == SOCK_OUT) {
1036 return false;
1037 }
1038 return socket.runtime->declaration->is_layer_name;
1039}
1040
1041static bool socket_needs_volume_grid_search(const bNode &node, const bNodeSocket &socket)
1042{
1043 const nodes::NodeDeclaration *node_decl = node.declaration();
1044 if (node_decl == nullptr) {
1045 return false;
1046 }
1047 if (node_decl->skip_updating_sockets) {
1048 return false;
1049 }
1050 if (socket.in_out == SOCK_OUT) {
1051 return false;
1052 }
1053 return socket.runtime->declaration->is_volume_grid_name;
1054}
1055
1056static void draw_gizmo_pin_icon(uiLayout *layout, PointerRNA *socket_ptr)
1057{
1058 layout->prop(socket_ptr, "pin_gizmo", UI_ITEM_NONE, "", ICON_GIZMO);
1059}
1060
1062 bNodeSocket *sock,
1063 const StringRef text)
1064{
1065 if (sock->runtime->declaration) {
1066 if (sock->runtime->declaration->socket_name_rna) {
1069 layout->prop((&sock->runtime->declaration->socket_name_rna->owner),
1070 sock->runtime->declaration->socket_name_rna->property_name,
1072 "",
1073 ICON_NONE);
1074 return;
1075 }
1076 }
1077 layout->label(text, ICON_NONE);
1078}
1079
1081 bNodeSocket *sock,
1082 const StringRef text)
1083{
1084 draw_node_socket_name_editable(layout, sock, text);
1085}
1086
1088 bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRef label)
1089{
1090 bNode *node = (bNode *)node_ptr->data;
1091 bNodeSocket *sock = (bNodeSocket *)ptr->data;
1092 bNodeTree *tree = reinterpret_cast<bNodeTree *>(ptr->owner_id);
1093 int type = sock->typeinfo->type;
1094 // int subtype = sock->typeinfo->subtype;
1095
1096 const nodes::SocketDeclaration *socket_decl = sock->runtime->declaration;
1097
1098 if (sock->is_inactive()) {
1099 layout->active_set(false);
1100 }
1101
1102 const bool optional_label = (socket_decl && socket_decl->optional_label) || label.is_empty();
1103 const StringRef label_or_empty = optional_label ? "" : label;
1104
1105 const bool has_gizmo = tree->runtime->gizmo_propagation ?
1106 tree->runtime->gizmo_propagation->gizmo_endpoint_sockets.contains(
1107 sock) :
1108 false;
1109
1110 if (has_gizmo) {
1111 if (sock->in_out == SOCK_OUT && node->is_group_input()) {
1112 uiLayout *row = &layout->row(false);
1114 node_socket_button_label(C, row, ptr, node_ptr, label);
1115 row->label("", ICON_GIZMO);
1116 return;
1117 }
1118 if (sock->in_out == SOCK_IN && sock->index() == 0 &&
1120 {
1121 uiLayout *row = &layout->row(false);
1122 node_socket_button_label(C, row, ptr, node_ptr, label);
1124 return;
1125 }
1126 }
1127
1128 if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_HIDE_VALUE) || sock->is_logically_linked())
1129 {
1130 draw_node_socket_without_value(layout, sock, label);
1131 return;
1132 }
1133 if (tree->type == NTREE_GEOMETRY &&
1135 {
1136 draw_node_socket_without_value(layout, sock, label);
1137 return;
1138 }
1139
1140 /* Some socket types draw the gizmo icon in a special way to look better. All others use a
1141 * fallback default code path. */
1142 bool gizmo_handled = false;
1143
1144 switch (type) {
1145 case SOCK_FLOAT:
1146 case SOCK_INT:
1147 case SOCK_BOOLEAN:
1148 layout->prop(ptr, "default_value", DEFAULT_FLAGS, label_or_empty, ICON_NONE);
1149 break;
1150 case SOCK_VECTOR:
1151 if (socket_decl && socket_decl->compact) {
1152 uiTemplateComponentMenu(layout, ptr, "default_value", label_or_empty);
1153 }
1154 else {
1155 if (sock->typeinfo->subtype == PROP_DIRECTION) {
1156 layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1157 }
1158 else {
1159 uiLayout *column = &layout->column(false);
1160 {
1161 uiLayout *row = &column->row(true);
1162 draw_node_socket_name_editable(row, sock, label_or_empty);
1163 if (has_gizmo) {
1165 gizmo_handled = true;
1166 }
1167 }
1168 column->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1169 }
1170 }
1171 break;
1172 case SOCK_ROTATION: {
1173 uiLayout *column = &layout->column(false);
1174 {
1175 uiLayout *row = &column->row(true);
1176 draw_node_socket_name_editable(row, sock, label_or_empty);
1177 if (has_gizmo) {
1179 gizmo_handled = true;
1180 }
1181 }
1182 column->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1183 break;
1184 }
1185 case SOCK_MATRIX: {
1186 draw_node_socket_name_editable(layout, sock, label);
1187 break;
1188 }
1189 case SOCK_RGBA: {
1190 if (optional_label) {
1191 layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1192 }
1193 else {
1194 uiLayout *row = &layout->split(0.4f, false);
1195 uiLayout *label_layout = &row->column(true);
1196 label_layout->label(label, ICON_NONE);
1197 uiLayout *color_layout = &row->column(true);
1198 color_layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1199 /* Keep color layout active to avoid darkened color appearance when inactive. */
1200 if (sock->is_inactive()) {
1201 layout->active_set(true);
1202 label_layout->active_set(false);
1203 color_layout->active_set(true);
1204 }
1205 }
1206 break;
1207 }
1208 case SOCK_STRING: {
1209 if (socket_needs_attribute_search(*node, *sock)) {
1210 if (optional_label) {
1211 node_geometry_add_attribute_search_button(*C, *node, *ptr, *layout, label);
1212 }
1213 else {
1214 uiLayout *row = &layout->split(0.4f, false);
1215 row->label(label, ICON_NONE);
1217 }
1218 }
1219 else if (socket_needs_layer_search(*node, *sock)) {
1220 if (optional_label) {
1221 node_geometry_add_layer_search_button(*C, *node, *ptr, *layout, label);
1222 }
1223 else {
1224 uiLayout *row = &layout->split(0.4f, false);
1225 row->label(label, ICON_NONE);
1227 }
1228 }
1229 else if (socket_needs_volume_grid_search(*node, *sock)) {
1230 if (optional_label) {
1231 node_geometry_add_volume_grid_search_button(*C, *node, *ptr, *layout, label);
1232 }
1233 else {
1234 uiLayout *row = &layout->split(0.4f, false);
1235 row->label(label, ICON_NONE);
1237 }
1238 }
1239 else {
1240 if (optional_label) {
1241 layout->prop(ptr,
1242 RNA_struct_find_property(ptr, "default_value"),
1243 -1,
1244 0,
1246 "",
1247 ICON_NONE,
1248 label);
1249 }
1250 else {
1251 uiLayout *row = &layout->split(0.4f, false);
1252 row->label(label, ICON_NONE);
1253 row->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1254 }
1255 }
1256 break;
1257 }
1258 case SOCK_MENU: {
1259 const bNodeSocketValueMenu *default_value =
1260 sock->default_value_typed<bNodeSocketValueMenu>();
1261 if (default_value->enum_items) {
1262 if (default_value->enum_items->items.is_empty()) {
1263 uiLayout *row = &layout->split(0.4f, false);
1264 row->label(label, ICON_NONE);
1265 row->label(IFACE_("No Items"), ICON_NONE);
1266 }
1267 else {
1268 bool expanded = false;
1269 if (const auto *menu_decl = dynamic_cast<const nodes::decl::Menu *>(socket_decl)) {
1270 expanded = menu_decl->is_expanded;
1271 }
1272 if (optional_label) {
1273 if (expanded) {
1274 /* Use a single space for the name to work around a bug. Also see
1275 * #ui_item_enum_expand_exec. */
1276 layout->prop(ptr, "default_value", UI_ITEM_R_EXPAND, " ", ICON_NONE);
1277 }
1278 else {
1279 layout->prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1280 }
1281 }
1282 else {
1283 uiLayout &row = layout->split(0.4f, false);
1284 row.label(label, ICON_NONE);
1285 if (expanded) {
1286 /* Use a single space for the name to work around a bug. Also see
1287 * #ui_item_enum_expand_exec. */
1288 row.row(true).prop(ptr, "default_value", UI_ITEM_R_EXPAND, " ", ICON_NONE);
1289 }
1290 else {
1291 row.prop(ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE);
1292 }
1293 }
1294 }
1295 }
1296 else if (default_value->has_conflict()) {
1297 layout->label(IFACE_("Menu Error"), ICON_ERROR);
1298 }
1299 else {
1300 layout->label(IFACE_("Menu Undefined"), ICON_QUESTION);
1301 }
1302 break;
1303 }
1304 case SOCK_COLLECTION:
1305 case SOCK_OBJECT:
1306 case SOCK_MATERIAL: {
1307 if (optional_label) {
1308 layout->prop(ptr,
1309 RNA_struct_find_property(ptr, "default_value"),
1310 -1,
1311 0,
1313 "",
1314 ICON_NONE,
1315 std::optional(label));
1316 }
1317 else {
1318 layout->prop(ptr,
1319 RNA_struct_find_property(ptr, "default_value"),
1320 -1,
1321 0,
1323 label,
1324 ICON_NONE);
1325 }
1326
1327 break;
1328 }
1329 case SOCK_IMAGE: {
1330 const bNodeTree *node_tree = (const bNodeTree *)node_ptr->owner_id;
1331 if (node_tree->type == NTREE_GEOMETRY) {
1332 if (optional_label) {
1333 uiTemplateID(layout, C, ptr, "default_value", "image.new", "image.open", nullptr);
1334 }
1335 else {
1336 /* 0.3 split ratio is inconsistent, but use it here because the "New" button is large. */
1337 uiLayout *row = &layout->split(0.3f, false);
1338 row->label(label, ICON_NONE);
1339 uiTemplateID(row, C, ptr, "default_value", "image.new", "image.open", nullptr);
1340 }
1341 }
1342 else {
1343 layout->prop(ptr, "default_value", DEFAULT_FLAGS, label_or_empty, ICON_NONE);
1344 }
1345 break;
1346 }
1347 case SOCK_TEXTURE: {
1348 if (optional_label) {
1349 uiTemplateID(layout, C, ptr, "default_value", "texture.new", nullptr, nullptr);
1350 }
1351 else {
1352 /* 0.3 split ratio is inconsistent, but use it here because the "New" button is large. */
1353 uiLayout *row = &layout->split(0.3f, false);
1354 row->label(label, ICON_NONE);
1355 uiTemplateID(row, C, ptr, "default_value", "texture.new", nullptr, nullptr);
1356 }
1357
1358 break;
1359 }
1360 default:
1361 draw_node_socket_without_value(layout, sock, label_or_empty);
1362 break;
1363 }
1364
1365 if (has_gizmo && !gizmo_handled) {
1366 draw_gizmo_pin_icon(layout, ptr);
1367 }
1368}
1369
1371 bNodeTreeInterfaceSocket *interface_socket,
1372 bContext * /*C*/,
1373 uiLayout *layout)
1374{
1375 PointerRNA ptr = RNA_pointer_create_discrete(id, &RNA_NodeTreeInterfaceSocket, interface_socket);
1376
1377 const bke::bNodeSocketType *typeinfo = interface_socket->socket_typeinfo();
1378 BLI_assert(typeinfo != nullptr);
1380
1381 uiLayout *col = &layout->column(false);
1382
1383 switch (type) {
1384 case SOCK_FLOAT: {
1385 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1386 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1387 uiLayout *sub = &col->column(true);
1388 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1389 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1390 break;
1391 }
1392 case SOCK_INT: {
1393 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1394 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1395 uiLayout *sub = &col->column(true);
1396 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1397 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1398 break;
1399 }
1400 case SOCK_VECTOR: {
1401 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1402 col->prop(&ptr,
1403 "dimensions",
1406 ICON_NONE);
1407 col->prop(&ptr, "default_value", UI_ITEM_R_EXPAND, IFACE_("Default"), ICON_NONE);
1408 uiLayout *sub = &col->column(true);
1409 sub->prop(&ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE);
1410 sub->prop(&ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE);
1411 break;
1412 }
1413 case SOCK_STRING: {
1414 col->prop(&ptr, "subtype", DEFAULT_FLAGS, IFACE_("Subtype"), ICON_NONE);
1415 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1416 break;
1417 }
1418 case SOCK_BOOLEAN:
1419 case SOCK_ROTATION:
1420 case SOCK_RGBA:
1421 case SOCK_OBJECT:
1422 case SOCK_COLLECTION:
1423 case SOCK_IMAGE:
1424 case SOCK_TEXTURE:
1425 case SOCK_MATERIAL: {
1426 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1427 break;
1428 }
1429 case SOCK_MENU: {
1430 col->prop(&ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), ICON_NONE);
1431 col->prop(&ptr, "menu_expanded", DEFAULT_FLAGS, IFACE_("Expanded"), ICON_NONE);
1432 break;
1433 }
1434 case SOCK_SHADER:
1435 case SOCK_GEOMETRY:
1436 case SOCK_MATRIX:
1437 case SOCK_BUNDLE:
1438 case SOCK_CLOSURE:
1439 break;
1440
1441 case SOCK_CUSTOM:
1443 break;
1444 }
1445
1446 col = &layout->column(false);
1447
1448 const bNodeTree *node_tree = reinterpret_cast<const bNodeTree *>(id);
1449 if (interface_socket->flag & NODE_INTERFACE_SOCKET_INPUT && node_tree->type == NTREE_GEOMETRY) {
1450 if (ELEM(type, SOCK_INT, SOCK_VECTOR, SOCK_MATRIX)) {
1451 col->prop(&ptr, "default_input", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1452 }
1453 }
1454
1455 if (interface_socket->flag & NODE_INTERFACE_SOCKET_INPUT) {
1456 col->prop(&ptr, "optional_label", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1457 }
1458 {
1459 uiLayout *sub = &col->column(false);
1460 sub->active_set(interface_socket->default_input == NODE_DEFAULT_INPUT_VALUE);
1461 sub->prop(&ptr, "hide_value", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1462 }
1463
1464 if (interface_socket->flag & NODE_INTERFACE_SOCKET_INPUT && node_tree->type == NTREE_GEOMETRY) {
1465 if (type == SOCK_BOOLEAN) {
1466 col->prop(&ptr, "layer_selection_field", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1467 }
1468 uiLayout *sub = &col->column(false);
1469 sub->active_set(!is_layer_selection_field(*interface_socket));
1470 sub->prop(&ptr, "hide_in_modifier", DEFAULT_FLAGS, std::nullopt, ICON_NONE);
1472 sub->prop(&ptr, "structure_type", DEFAULT_FLAGS, IFACE_("Shape"), ICON_NONE);
1473 }
1474 }
1475}
1476
1478 PointerRNA * /*ptr*/,
1479 PointerRNA * /*node_ptr*/,
1480 float *r_color)
1481{
1483}
1484
1486 float *r_color)
1487{
1489}
1490
1491} // namespace blender::ed::space_node
1492
1501
1509
1510void ED_node_type_draw_color(const char *idname, float *r_color)
1511{
1512 using namespace blender::ed::space_node;
1513
1515 if (!typeinfo || typeinfo->type == SOCK_CUSTOM) {
1516 r_color[0] = 0.0f;
1517 r_color[1] = 0.0f;
1518 r_color[2] = 0.0f;
1519 r_color[3] = 0.0f;
1520 return;
1521 }
1522
1524 copy_v4_v4(r_color, std_node_socket_colors[typeinfo->type]);
1525}
1526
1527namespace blender::ed::space_node {
1528
1529/* ************** Generic drawing ************** */
1530
1532 ARegion &region,
1533 SpaceNode &snode,
1534 bNodeInstanceKey parent_key)
1535{
1536 Main *bmain = CTX_data_main(&C);
1537 bNodeInstanceKey active_viewer_key = (snode.nodetree ? snode.nodetree->active_viewer_key :
1546
1547 if (!(snode.flag & SNODE_BACKDRAW) || !ED_node_is_compositor(&snode) ||
1549 {
1550 return;
1551 }
1552
1553 if (parent_key.value != active_viewer_key.value) {
1554 return;
1555 }
1556
1559
1560 /* The draw manager is used to draw the backdrop image. */
1564 DRW_draw_view(&C);
1567 /* Draw manager changes the depth state. Set it back to NONE. Without this the
1568 * node preview images aren't drawn correctly. */
1570
1571 void *lock;
1572 Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
1573 ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
1574 if (ibuf) {
1575 /* somehow the offset has to be calculated inverse */
1577 const float offset_x = snode.xof + ima->runtime->backdrop_offset[0] * snode.zoom;
1578 const float offset_y = snode.yof + ima->runtime->backdrop_offset[1] * snode.zoom;
1579 const float x = (region.winx - snode.zoom * ibuf->x) / 2 + offset_x;
1580 const float y = (region.winy - snode.zoom * ibuf->y) / 2 + offset_y;
1581
1584 if (snode.edittree) {
1585 bNode *node = (bNode *)snode.edittree->nodes.first;
1586 const rctf *viewer_border = &snode.nodetree->viewer_border;
1587 while (node) {
1588 if (node->flag & NODE_SELECT) {
1589 if (node->typeinfo->draw_backdrop) {
1590 node->typeinfo->draw_backdrop(&snode, ibuf, node, x, y);
1591 }
1592 }
1593 node = node->next;
1594 }
1595
1596 if ((snode.nodetree->flag & NTREE_VIEWER_BORDER) &&
1597 viewer_border->xmin < viewer_border->xmax && viewer_border->ymin < viewer_border->ymax)
1598 {
1599 rcti pixel_border;
1600 BLI_rcti_init(&pixel_border,
1601 x + snode.zoom * viewer_border->xmin * ibuf->x,
1602 x + snode.zoom * viewer_border->xmax * ibuf->x,
1603 y + snode.zoom * viewer_border->ymin * ibuf->y,
1604 y + snode.zoom * viewer_border->ymax * ibuf->y);
1605
1607 immVertexFormat(), "pos", blender::gpu::VertAttrType::SFLOAT_32_32);
1610
1611 immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
1612
1614 }
1615 }
1616 }
1617
1618 BKE_image_release_ibuf(ima, ibuf, lock);
1621}
1622
1624 const bNodeSocket &socket,
1625 const bNodeLink &link)
1626{
1627 const float2 socket_location = socket.runtime->location;
1628 if (socket.is_multi_input() && socket.is_input() && !(node.flag & NODE_COLLAPSED)) {
1629 /* For internal link case, handle number of links as at least 1. */
1630 const int clamped_total_inputs = math::max<int>(1, socket.runtime->total_inputs);
1632 socket_location, link.multi_input_sort_id, clamped_total_inputs);
1633 }
1634 return socket_location;
1635}
1636
1637static void calculate_inner_link_bezier_points(std::array<float2, 4> &points)
1638{
1639 const int curving = UI_GetThemeValueType(TH_NODE_CURVING, SPACE_NODE);
1640 if (curving == 0) {
1641 /* Straight line: align all points. */
1642 points[1] = math::interpolate(points[0], points[3], 1.0f / 3.0f);
1643 points[2] = math::interpolate(points[0], points[3], 2.0f / 3.0f);
1644 }
1645 else {
1646 const float dist_x = math::distance(points[0].x, points[3].x);
1647 const float dist_y = math::distance(points[0].y, points[3].y);
1648
1649 /* Reduce the handle offset when the link endpoints are close to horizontal. */
1650 const float slope = math::safe_divide(dist_y, dist_x);
1651 const float clamp_factor = math::min(1.0f, slope * (4.5f - 0.25f * float(curving)));
1652
1653 const float handle_offset = curving * 0.1f * dist_x * clamp_factor;
1654
1655 points[1].x = points[0].x + handle_offset;
1656 points[1].y = points[0].y;
1657
1658 points[2].x = points[3].x - handle_offset;
1659 points[2].y = points[3].y;
1660 }
1661}
1662
1663static std::array<float2, 4> node_link_bezier_points(const bNodeLink &link)
1664{
1665 std::array<float2, 4> points;
1666 points[0] = socket_link_connection_location(*link.fromnode, *link.fromsock, link);
1667 points[3] = socket_link_connection_location(*link.tonode, *link.tosock, link);
1669 return points;
1670}
1671
1672static bool node_link_draw_is_visible(const View2D &v2d, const std::array<float2, 4> &points)
1673{
1674 if (min_ffff(points[0].x, points[1].x, points[2].x, points[3].x) > v2d.cur.xmax) {
1675 return false;
1676 }
1677 if (max_ffff(points[0].x, points[1].x, points[2].x, points[3].x) < v2d.cur.xmin) {
1678 return false;
1679 }
1680 return true;
1681}
1682
1684 std::array<float2, NODE_LINK_RESOL + 1> &coords)
1685{
1686 const std::array<float2, 4> points = node_link_bezier_points(link);
1687
1688 /* The extra +1 in size is required by these functions and would be removed ideally. */
1690 points[1].x,
1691 points[2].x,
1692 points[3].x,
1693 &coords[0].x,
1695 sizeof(float2));
1697 points[1].y,
1698 points[2].y,
1699 points[3].y,
1700 &coords[0].y,
1702 sizeof(float2));
1703}
1704
1705/* -------------------------------------------------------------------- */
1708
1709/* Keep in sync with node socket shader. */
1710#define MAX_SOCKET_PARAMETERS 4
1711#define MAX_SOCKET_INSTANCE 32
1712
1718
1720{
1721 static GBatchNodesocket nodesocket_batch;
1722 return nodesocket_batch;
1723}
1724
1725static gpu::Batch *nodesocket_batch_init()
1726{
1727 if (g_batch_nodesocket().batch == nullptr) {
1728 GPUIndexBufBuilder ibuf;
1729 GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 2, 4);
1730 /* Quad to draw the node socket in. */
1731 GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2);
1732 GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3);
1733
1737 }
1738 return g_batch_nodesocket().batch;
1739}
1740
1742{
1743 if (g_batch_nodesocket().params.is_empty()) {
1744 return;
1745 }
1746
1747 gpu::Batch *batch = nodesocket_batch_init();
1748 if (g_batch_nodesocket().params.size() == 1) {
1749 /* draw single */
1752 batch,
1753 "parameters",
1754 4,
1755 reinterpret_cast<const float (*)[4]>(g_batch_nodesocket().params.data()));
1757 }
1758 else {
1761 batch,
1762 "parameters",
1764 reinterpret_cast<const float (*)[4]>(g_batch_nodesocket().params.data()));
1766 }
1768}
1769
1771{
1773 g_batch_nodesocket().enabled = true;
1774}
1775
1785
1787{
1789 g_batch_nodesocket().params.append(socket_params);
1790
1793 }
1794 }
1795 else {
1796 /* Draw single instead of batch. */
1797 gpu::Batch *batch = nodesocket_batch_init();
1800 batch, "parameters", MAX_SOCKET_PARAMETERS, (const float (*)[4])(&socket_params));
1802 }
1803}
1804
1806 const float color_inner[4],
1807 const float color_outline[4],
1808 const float outline_thickness,
1809 const int shape,
1810 const float aspect)
1811{
1812 /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space.
1813 * If it has been scaled, then it's no longer valid. */
1814 BLI_assert((color_inner != nullptr) && (color_outline != nullptr));
1815
1816 NodeSocketShaderParameters socket_params = {};
1817 socket_params.rect[0] = rect->xmin;
1818 socket_params.rect[1] = rect->xmax;
1819 socket_params.rect[2] = rect->ymin;
1820 socket_params.rect[3] = rect->ymax;
1821 socket_params.color_inner[0] = color_inner[0];
1822 socket_params.color_inner[1] = color_inner[1];
1823 socket_params.color_inner[2] = color_inner[2];
1824 socket_params.color_inner[3] = color_inner[3];
1825 socket_params.color_outline[0] = color_outline[0];
1826 socket_params.color_outline[1] = color_outline[1];
1827 socket_params.color_outline[2] = color_outline[2];
1828 socket_params.color_outline[3] = color_outline[3];
1829 socket_params.outline_thickness = outline_thickness;
1830 socket_params.outline_offset = 0.0;
1831 socket_params.shape = float(shape) + 0.1f;
1832 socket_params.aspect = aspect;
1833
1835 draw_node_socket_batch(socket_params);
1837}
1838
1840
1841/* -------------------------------------------------------------------- */
1844
1845#define NODELINK_GROUP_SIZE 256
1846#define LINK_RESOL 24
1847#define LINK_WIDTH 2.5f
1848#define ARROW_SIZE (7 * UI_SCALE_FAC)
1849
1850/* Reroute arrow shape and mute bar. These are expanded here and shrunk in the GLSL code.
1851 * See: `gpu_shader_2D_nodelink_vert.glsl`. */
1852static float arrow_verts[3][2] = {{-1.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, -1.0f}};
1853static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
1854static float mute_verts[3][2] = {{0.7071f, 1.0f}, {0.7071f, 0.0f}, {0.7071f, -1.0f}};
1855static float mute_expand_axis[3][2] = {{1.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, -0.0f}};
1856
1857/* Is zero initialized because it is static data. */
1858static struct {
1859 gpu::Batch *batch;
1865
1867{
1868 g_batch_link.count = 0;
1869}
1870
1872 uint uv_id,
1873 uint pos_id,
1874 uint exp_id,
1875 uint v,
1876 const float uv[2],
1877 const float pos[2],
1878 const float exp[2])
1879{
1880 GPU_vertbuf_attr_set(vbo, uv_id, v, uv);
1881 GPU_vertbuf_attr_set(vbo, pos_id, v, pos);
1882 GPU_vertbuf_attr_set(vbo, exp_id, v, exp);
1883}
1884
1886{
1887 GPUVertFormat format = {0};
1888 uint uv_id = GPU_vertformat_attr_add(&format, "uv", gpu::VertAttrType::SFLOAT_32_32);
1889 uint pos_id = GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32);
1890 uint expand_id = GPU_vertformat_attr_add(&format, "expand", gpu::VertAttrType::SFLOAT_32_32);
1892 int vcount = LINK_RESOL * 2; /* curve */
1893 vcount += 2; /* restart strip */
1894 vcount += 3 * 2; /* arrow */
1895 vcount += 2; /* restart strip */
1896 vcount += 3 * 2; /* mute */
1897 vcount *= 2; /* shadow */
1898 vcount += 2; /* restart strip */
1899 GPU_vertbuf_data_alloc(*vbo, vcount);
1900 int v = 0;
1901
1902 for (int k = 0; k < 2; k++) {
1903 float uv[2] = {0.0f, 0.0f};
1904 float pos[2] = {0.0f, 0.0f};
1905 float exp[2] = {0.0f, 1.0f};
1906
1907 /* restart */
1908 if (k == 1) {
1909 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1910 }
1911
1912 /* curve strip */
1913 for (int i = 0; i < LINK_RESOL; i++) {
1914 uv[0] = (i / float(LINK_RESOL - 1));
1915 uv[1] = 0.0f;
1916 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1917 uv[1] = 1.0f;
1918 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1919 }
1920 /* restart */
1921 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1922
1923 uv[0] = 0.5f;
1924 uv[1] = 0.0f;
1927 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1928 /* arrow */
1929 for (int i = 0; i < 3; i++) {
1930 uv[1] = 0.0f;
1933 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1934
1935 uv[1] = 1.0f;
1936 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1937 }
1938
1939 /* restart */
1940 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1941
1942 uv[0] = 0.5f;
1943 uv[1] = 0.0f;
1946 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1947 /* bar */
1948 for (int i = 0; i < 3; ++i) {
1949 uv[1] = 0.0f;
1952 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1953
1954 uv[1] = 1.0f;
1955 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1956 }
1957
1958 /* restart */
1959 if (k == 0) {
1960 set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
1961 }
1962 }
1963
1966
1967 /* Instances data */
1970
1972}
1973
1974static char nodelink_get_color_id(int th_col)
1975{
1976 switch (th_col) {
1977 case TH_WIRE:
1978 return 1;
1979 case TH_WIRE_INNER:
1980 return 2;
1981 case TH_ACTIVE:
1982 return 3;
1983 case TH_EDGE_SELECT:
1984 return 4;
1985 case TH_REDALERT:
1986 return 5;
1987 }
1988 return 0;
1989}
1990
1991static void nodelink_batch_draw(const SpaceNode &snode)
1992{
1993 if (g_batch_link.count == 0) {
1994 return;
1995 }
1996
1998 NodeLinkUniformData node_link_data;
1999
2006 node_link_data.aspect = snode.runtime->aspect;
2007 node_link_data.arrow_size = ARROW_SIZE;
2008
2010 sizeof(node_link_data), &node_link_data, __func__);
2011
2012 /* TODO(fclem): Update sub. */
2014
2016 GPU_batch_uniformbuf_bind(g_batch_link.batch, "link_uniforms", ubo);
2017 GPU_storagebuf_bind(g_batch_link.link_buf, 0);
2019
2022
2024
2026}
2027
2028void nodelink_batch_start(const SpaceNode & /*snode*/)
2029{
2030 g_batch_link.enabled = true;
2031}
2032
2034{
2035 nodelink_batch_draw(snode);
2036 g_batch_link.enabled = false;
2037}
2038
2059
2060static void nodelink_batch_add_link(const SpaceNode &snode,
2061 const std::array<float2, 4> &points,
2062 const NodeLinkDrawConfig &draw_config)
2063{
2064 /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
2065 BLI_assert(
2067 BLI_assert(
2069 BLI_assert(ELEM(draw_config.th_col3, TH_WIRE, TH_REDALERT, -1));
2070
2071 NodeLinkData &data = g_batch_link.data[g_batch_link.count++];
2072 data.bezier_P0 = points[0];
2073 data.bezier_P1 = points[1];
2074 data.bezier_P2 = points[2];
2075 data.bezier_P3 = points[3];
2076
2077 char *colid = reinterpret_cast<char *>(&data.color_ids);
2078 colid[0] = nodelink_get_color_id(draw_config.th_col1);
2079 colid[1] = nodelink_get_color_id(draw_config.th_col2);
2080 colid[2] = nodelink_get_color_id(draw_config.th_col3);
2081
2082 data.do_muted = draw_config.draw_muted;
2083 data.do_arrow = draw_config.draw_arrow;
2084 data.start_color = float4(draw_config.start_color);
2085 data.end_color = float4(draw_config.end_color);
2086 data.dim_factor = draw_config.dim_factor;
2087 data.thickness = draw_config.thickness;
2088 data.dash_length = draw_config.dash_length;
2089 data.dash_factor = draw_config.dash_factor;
2090 data.dash_alpha = draw_config.dash_alpha;
2091 data.has_back_link = draw_config.has_back_link;
2092
2093 if (g_batch_link.count == NODELINK_GROUP_SIZE) {
2094 nodelink_batch_draw(snode);
2095 }
2096}
2097
2098static void node_draw_link_end_marker(const float2 center,
2099 const float radius,
2100 const ColorTheme4f &color)
2101{
2102 rctf rect;
2103 BLI_rctf_init(&rect, center.x - radius, center.x + radius, center.y - radius, center.y + radius);
2104
2106 UI_draw_roundbox_4fv(&rect, true, radius, color);
2107 /* Round-box disables alpha. Re-enable it for node links that are drawn after this one. */
2109}
2110
2112 const NodeLinkDrawConfig &draw_config,
2113 const std::array<float2, 4> &points,
2114 const bool outline)
2115{
2116 const float radius = (outline ? 0.65f : 0.45f) * NODE_SOCKSIZE;
2117 if (link.fromsock) {
2119 points[0], radius, outline ? draw_config.outline_color : draw_config.start_color);
2120 }
2121 if (link.tosock) {
2123 points[3], radius, outline ? draw_config.outline_color : draw_config.end_color);
2124 }
2125}
2126
2127static bool node_link_is_field_link(const SpaceNode &snode, const bNodeLink &link)
2128{
2129 const bNodeTree &tree = *snode.edittree;
2130 if (tree.type != NTREE_GEOMETRY) {
2131 return false;
2132 }
2133 if (link.fromsock && link.fromsock->may_be_field()) {
2134 return true;
2135 }
2136 return false;
2137}
2138
2139static bool node_link_is_gizmo_link(const SpaceNode &snode, const bNodeLink &link)
2140{
2141 if (snode.edittree->type != NTREE_GEOMETRY) {
2142 return false;
2143 }
2144 if (!link.fromsock || !link.tosock) {
2145 return false;
2146 }
2147 const bNodeTree &tree = *snode.edittree;
2148 return tree.runtime->sockets_on_active_gizmo_paths.contains(link.fromsock) &&
2149 tree.runtime->sockets_on_active_gizmo_paths.contains(link.tosock);
2150}
2151
2153 const View2D &v2d,
2154 const SpaceNode &snode,
2155 const bNodeLink &link,
2156 const int th_col1,
2157 const int th_col2,
2158 const int th_col3,
2159 const bool selected)
2160{
2161 NodeLinkDrawConfig draw_config;
2162
2163 draw_config.th_col1 = th_col1;
2164 draw_config.th_col2 = th_col2;
2165 draw_config.th_col3 = th_col3;
2166
2167 draw_config.dim_factor = selected ? 1.0f : node_link_dim_factor(v2d, link);
2168
2169 bTheme *btheme = UI_GetTheme();
2170 draw_config.dash_alpha = btheme->space_node.dash_alpha;
2171
2172 const bool field_link = node_link_is_field_link(snode, link);
2173 const bool gizmo_link = node_link_is_gizmo_link(snode, link);
2174
2175 draw_config.dash_factor = field_link ? 0.75f : 1.0f;
2176 draw_config.dash_length = 10.0f * UI_SCALE_FAC;
2177
2178 const float scale = UI_view2d_scale_get_x(&v2d);
2179 /* Clamp the thickness to make the links more readable when zooming out. */
2180 draw_config.thickness = LINK_WIDTH * max_ff(UI_SCALE_FAC * scale, 1.0f) *
2181 (field_link ? 0.7f : 1.0f);
2182 draw_config.has_back_link = gizmo_link;
2183 draw_config.highlighted = link.flag & NODE_LINK_TEMP_HIGHLIGHT;
2184 draw_config.draw_arrow = ((link.tonode && link.tonode->is_reroute()) &&
2185 (link.fromnode && link.fromnode->is_reroute()));
2186 draw_config.draw_muted = (link.flag & NODE_LINK_MUTED);
2187
2188 UI_GetThemeColor4fv(th_col3, draw_config.outline_color);
2189
2192 {
2193 const bNodeTree &node_tree = *snode.edittree;
2195 &const_cast<ID &>(node_tree.id), &RNA_Node, link.fromnode);
2197 &const_cast<ID &>(node_tree.id), &RNA_Node, link.tonode);
2198
2199 if (link.fromsock) {
2200 node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.start_color);
2201 }
2202 else {
2203 node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.start_color);
2204 }
2205
2206 if (link.tosock) {
2207 node_socket_color_get(C, node_tree, to_node_ptr, *link.tosock, draw_config.end_color);
2208 }
2209 else {
2210 node_socket_color_get(C, node_tree, from_node_ptr, *link.fromsock, draw_config.end_color);
2211 }
2212 }
2213 else {
2214 UI_GetThemeColor4fv(th_col1, draw_config.start_color);
2215 UI_GetThemeColor4fv(th_col2, draw_config.end_color);
2216 }
2217
2218 /* Highlight links connected to selected nodes. */
2219 if (selected) {
2220 ColorTheme4f color_selected;
2221 UI_GetThemeColor4fv(TH_EDGE_SELECT, color_selected);
2222 const float alpha = color_selected.a;
2223
2224 /* Interpolate color if highlight color is not fully transparent. */
2225 if (alpha != 0.0) {
2226 if (link.fromsock) {
2227 interp_v3_v3v3(draw_config.start_color, draw_config.start_color, color_selected, alpha);
2228 }
2229 if (link.tosock) {
2230 interp_v3_v3v3(draw_config.end_color, draw_config.end_color, color_selected, alpha);
2231 }
2232 }
2233 }
2234
2235 if (draw_config.highlighted) {
2236 ColorTheme4f link_preselection_highlight_color;
2237 UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color);
2238 /* Multi sockets can only be inputs. So we only have to highlight the end of the link. */
2239 copy_v4_v4(draw_config.end_color, link_preselection_highlight_color);
2240 }
2241
2242 return draw_config;
2243}
2244
2245static void node_draw_link_bezier_ex(const SpaceNode &snode,
2246 const NodeLinkDrawConfig &draw_config,
2247 const std::array<float2, 4> &points)
2248{
2249 if (g_batch_link.batch == nullptr) {
2251 }
2252
2253 if (g_batch_link.enabled && !draw_config.highlighted) {
2254 /* Add link to batch. */
2255 nodelink_batch_add_link(snode, points, draw_config);
2256 }
2257 else {
2258 /* Slow path but should eventually not be the majority of them. */
2259 nodelink_batch_start(snode);
2260 nodelink_batch_add_link(snode, points, draw_config);
2261 nodelink_batch_end(snode);
2262 }
2263}
2264
2266 const View2D &v2d,
2267 const SpaceNode &snode,
2268 const bNodeLink &link,
2269 const int th_col1,
2270 const int th_col2,
2271 const int th_col3,
2272 const bool selected)
2273{
2274 const std::array<float2, 4> points = node_link_bezier_points(link);
2275 if (!node_link_draw_is_visible(v2d, points)) {
2276 return;
2277 }
2278 const NodeLinkDrawConfig draw_config = nodelink_get_draw_config(
2279 C, v2d, snode, link, th_col1, th_col2, th_col3, selected);
2280
2281 node_draw_link_bezier_ex(snode, draw_config, points);
2282}
2283
2285 const View2D &v2d,
2286 const SpaceNode &snode,
2287 const bNodeLink &link,
2288 const bool selected)
2289{
2290 int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
2291
2292 if (link.fromsock == nullptr && link.tosock == nullptr) {
2293 return;
2294 }
2295
2296 /* going to give issues once... */
2297 if (link.tosock->flag & SOCK_UNAVAIL) {
2298 return;
2299 }
2300 if (link.fromsock->flag & SOCK_UNAVAIL) {
2301 return;
2302 }
2303
2304 if (link.flag & NODE_LINK_VALID) {
2305 /* special indicated link, on drop-node */
2307 th_col1 = th_col2 = TH_ACTIVE;
2308 }
2309 else if (link.flag & NODE_LINK_MUTED) {
2310 th_col1 = th_col2 = TH_REDALERT;
2311 }
2312 }
2313 else {
2314 /* Invalid link. */
2315 th_col1 = th_col2 = th_col3 = TH_REDALERT;
2316 // th_col3 = -1; /* no shadow */
2317 }
2318
2319 node_draw_link_bezier(C, v2d, snode, link, th_col1, th_col2, th_col3, selected);
2320}
2321
2322std::array<float2, 4> node_link_bezier_points_dragged(const SpaceNode &snode,
2323 const bNodeLink &link)
2324{
2325 const float2 cursor = snode.runtime->cursor * UI_SCALE_FAC;
2326 std::array<float2, 4> points;
2327 points[0] = link.fromsock ?
2329 cursor;
2330 points[3] = link.tosock ? socket_link_connection_location(*link.tonode, *link.tosock, link) :
2331 cursor;
2333 return points;
2334}
2335
2337 const View2D &v2d,
2338 const SpaceNode &snode,
2339 const bNodeLink &link)
2340{
2341 if (link.fromsock == nullptr && link.tosock == nullptr) {
2342 return;
2343 }
2344
2345 const std::array<float2, 4> points = node_link_bezier_points_dragged(snode, link);
2346
2347 const NodeLinkDrawConfig draw_config = nodelink_get_draw_config(
2348 C, v2d, snode, link, TH_WIRE_INNER, TH_WIRE_INNER, TH_WIRE, true);
2349 /* End marker outline. */
2350 node_draw_link_end_markers(link, draw_config, points, true);
2351 /* Link. */
2352 node_draw_link_bezier_ex(snode, draw_config, points);
2353 /* End marker fill. */
2354 node_draw_link_end_markers(link, draw_config, points, false);
2355}
2356
2357} // namespace blender::ed::space_node
void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
Definition glutil.cc:633
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:1669
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:811
#define NODE_FRAME
Definition BKE_node.hh:812
#define SH_NODE_COMBINE_COLOR
#define SH_NODE_MIX_RGB_LEGACY
#define SH_NODE_CURVE_FLOAT
#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_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_HUECORRECT
#define TEX_NODE_COMBINE_COLOR
#define SH_NODE_MATH
#define TEX_NODE_TEXTURE
#define TEX_NODE_SEPARATE_COLOR
#define CMP_NODE_CRYPTOMATTE_LEGACY
#define SH_NODE_OUTPUT_MATERIAL
#define TEX_NODE_IMAGE
#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_DISPLACEMENT
#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
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_UTF8(dst, format,...)
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
@ CMP_NODE_COMBSEP_COLOR_YCC
@ CMP_NODE_CRYPTOMATTE_SOURCE_RENDER
@ NTREE_VIEWER_BORDER
@ SHD_PROJ_BOX
@ NODE_COLLAPSED
@ NODE_SELECT
@ NTREE_TEXTURE
@ NTREE_GEOMETRY
@ NTREE_COMPOSIT
@ SOCK_OUT
@ SOCK_IN
@ NODE_LINK_TEMP_HIGHLIGHT
@ NODE_LINK_MUTED
@ NODE_LINK_INSERT_TARGET
@ NODE_LINK_INSERT_TARGET_INVALID
@ NODE_LINK_VALID
@ SOCK_HIDE_VALUE
@ SOCK_UNAVAIL
@ SOCK_DISPLAY_SHAPE_LIST
@ SOCK_DISPLAY_SHAPE_VOLUME_GRID
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
@ NODE_FRAME_RESIZEABLE
@ SN_OVERLAY_SHOW_WIRE_COLORS
@ SN_OVERLAY_SHOW_OVERLAYS
@ SNODE_BACKDRAW
@ SPACE_NODE
@ SNODE_COMPOSITOR_SCENE
@ TEX_RING
@ TEX_BAND
@ TEX_BLEND
@ TEX_MARBLE
@ TEX_WOOD
@ TEX_CLOUDS
@ TEX_DISTNOISE
@ TEX_VORONOI
@ TEX_STUCCI
@ TEX_MAGIC
@ TEX_MUSGRAVE
@ TEX_MINKOVSKY
#define UI_SCALE_FAC
void DRW_draw_view(const bContext *C)
bool ED_node_is_compositor(const SpaceNode *snode)
Definition node_edit.cc:487
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)
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:286
void GPU_batch_program_set_builtin(blender::gpu::Batch *batch, GPUBuiltinShader shader_id)
#define GPU_batch_uniform_4fv_array(batch, name, len, val)
Definition GPU_batch.hh:282
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, GPUBatchFlag owns_flag)
Definition gpu_batch.cc:51
@ GPU_BATCH_OWNS_INDEX
Definition GPU_batch.hh:46
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
void GPU_batch_draw(blender::gpu::Batch *batch)
void gpu_batch_presets_register(blender::gpu::Batch *preset_batch)
void gpu_batch_storage_buffer_register(blender::gpu::StorageBuf *preset_buffer)
void GPU_framebuffer_restore()
void GPU_framebuffer_bind_no_srgb(blender::gpu::FrameBuffer *fb)
blender::gpu::FrameBuffer * GPU_framebuffer_active_get()
void immUnbindProgram()
void immBindBuiltinProgram(GPUBuiltinShader shader_id)
void immUniformThemeColor(int color_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_3D_UNIFORM_COLOR
@ GPU_SHADER_2D_NODE_SOCKET
@ GPU_SHADER_2D_NODE_SOCKET_INST
@ GPU_SHADER_2D_NODELINK
@ GPU_DEPTH_NONE
Definition GPU_state.hh:111
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(GPUBlend blend)
Definition gpu_state.cc:42
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_storagebuf_update(blender::gpu::StorageBuf *ssbo, const void *data)
void GPU_storagebuf_bind(blender::gpu::StorageBuf *ssbo, int slot)
#define GPU_storagebuf_create(size)
void GPU_uniformbuf_free(blender::gpu::UniformBuf *ubo)
void GPU_uniformbuf_unbind(blender::gpu::UniformBuf *ubo)
blender::gpu::UniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
blender::gpu::VertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat &format, GPUUsageType usage)
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
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
bool IMB_colormanagement_space_name_is_data(const char *name)
@ PROP_DIRECTION
Definition RNA_types.hh:262
#define C
Definition RandGen.cpp:29
void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4])
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 uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int type, bool levels, bool brush, bool neg_slope, bool tone, bool presets)
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)
@ UI_CNR_ALL
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 uiTemplateCryptoPicker(uiLayout *layout, PointerRNA *ptr, blender::StringRefNull propname, int icon)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
#define UI_ITEM_NONE
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:1921
volatile int lock
#define U
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
constexpr bool is_empty() const
nullptr float
#define LINK_RESOL
Definition drawnode.cc:1846
void ED_node_sample_set(const float col[4])
Definition drawnode.cc:132
#define ARROW_SIZE
Definition drawnode.cc:1848
#define MAX_SOCKET_PARAMETERS
Definition drawnode.cc:1710
#define NODELINK_GROUP_SIZE
Definition drawnode.cc:1845
void ED_init_standard_node_socket_type(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:1493
#define MAX_SOCKET_INSTANCE
Definition drawnode.cc:1711
static float _sample_col[4]
Definition drawnode.cc:131
void ED_init_custom_node_socket_type(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:942
void ED_init_node_socket_type_virtual(blender::bke::bNodeSocketType *stype)
Definition drawnode.cc:1502
void ED_node_type_draw_color(const char *idname, float *r_color)
Definition drawnode.cc:1510
void ED_init_custom_node_type(blender::bke::bNodeType *)
Definition drawnode.cc:940
#define DEFAULT_FLAGS
Definition drawnode.cc:78
void ED_node_init_butfuncs()
Definition drawnode.cc:908
#define SAMPLE_FLT_ISNONE
Definition drawnode.cc:129
#define LINK_WIDTH
Definition drawnode.cc:1847
KDTree_3d * tree
uint pos
uint col
#define output
#define exp
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
bNodeSocketType NodeSocketTypeUndefined
Definition node.cc:127
Span< bNodeType * > node_types_get()
Definition node.cc:2447
bNodeType NodeTypeUndefined
Definition node.cc:126
bNodeSocketType * node_socket_type_find(StringRef idname)
Definition node.cc:2462
const bNodeInstanceKey NODE_INSTANCE_KEY_NONE
Definition node.cc:4847
static void node_texture_buts_bricks(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:652
static const float virtual_node_socket_color[4]
Definition drawnode.cc:949
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:574
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:840
static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:505
NodeLinkData data[NODELINK_GROUP_SIZE]
Definition drawnode.cc:1863
static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:523
static const float std_node_socket_colors[][4]
Definition drawnode.cc:952
static void node_shader_buts_displacement(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:405
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:107
static void node_buts_curvevec(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:117
static void std_node_socket_interface_draw(ID *id, bNodeTreeInterfaceSocket *interface_socket, bContext *, uiLayout *layout)
Definition drawnode.cc:1370
static bool socket_needs_volume_grid_search(const bNode &node, const bNodeSocket &socket)
Definition drawnode.cc:1041
static float mute_expand_axis[3][2]
Definition drawnode.cc:1855
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:1637
static void node_texture_buts_proc(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:665
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:755
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:2265
gpu::StorageBuf * link_buf
Definition drawnode.cc:1860
static bool node_link_is_gizmo_link(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2139
std::array< float2, 4 > node_link_bezier_points_dragged(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2322
static float arrow_expand_axis[3][2]
Definition drawnode.cc:1853
static struct blender::ed::space_node::@355314271107322122265366121241003211321003121362 g_batch_link
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:2152
void node_draw_link(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link, const bool selected)
Definition drawnode.cc:2284
static void nodelink_batch_reset()
Definition drawnode.cc:1866
static void draw_node_socket_batch(const NodeSocketShaderParameters &socket_params)
Definition drawnode.cc:1786
static void draw_gizmo_pin_icon(uiLayout *layout, PointerRNA *socket_ptr)
Definition drawnode.cc:1056
float2 node_link_calculate_multi_input_position(const float2 &socket_position, const int index, const int total_inputs)
Definition node_edit.cc:124
static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:259
static void nodelink_batch_init()
Definition drawnode.cc:1885
static void node_socket_undefined_draw(bContext *, uiLayout *layout, PointerRNA *, PointerRNA *, StringRef)
Definition drawnode.cc:867
static bool socket_needs_layer_search(const bNode &node, const bNodeSocket &socket)
Definition drawnode.cc:1026
static void node_buts_colorramp(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:112
void std_node_socket_colors_get(int socket_type, float *r_color)
Definition drawnode.cc:974
static GBatchNodesocket & g_batch_nodesocket()
Definition drawnode.cc:1719
void node_draw_link_dragged(const bContext &C, const View2D &v2d, const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2336
static char nodelink_get_color_id(int th_col)
Definition drawnode.cc:1974
static void draw_node_socket_without_value(uiLayout *layout, bNodeSocket *sock, const StringRef text)
Definition drawnode.cc:1080
static void nodelink_batch_add_link(const SpaceNode &snode, const std::array< float2, 4 > &points, const NodeLinkDrawConfig &draw_config)
Definition drawnode.cc:2060
static void node_socket_button_label(bContext *, uiLayout *layout, PointerRNA *, PointerRNA *, const StringRef text)
Definition drawnode.cc:82
static void node_buts_output_shader(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:415
static void node_buts_curvefloat(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:122
static void node_buts_texture(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:173
static void node_composit_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:617
void draw_nodespace_back_pix(const bContext &C, ARegion &region, SpaceNode &snode, bNodeInstanceKey parent_key)
Definition drawnode.cc:1531
static void node_socket_undefined_draw_color_simple(const bke::bNodeSocketType *, float *r_color)
Definition drawnode.cc:887
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:762
static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:376
static bool node_link_is_field_link(const SpaceNode &snode, const bNodeLink &link)
Definition drawnode.cc:2127
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:750
static const SocketColorFn std_node_socket_color_funcs[]
Definition drawnode.cc:998
static float arrow_verts[3][2]
Definition drawnode.cc:1852
static std::array< float2, 4 > node_link_bezier_points(const bNodeLink &link)
Definition drawnode.cc:1663
static void node_buts_mix_rgb(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:93
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:896
static void std_node_socket_color_simple_fn(const bke::bNodeSocketType *type, float *r_color)
Definition drawnode.cc:991
static bool node_link_draw_is_visible(const View2D &v2d, const std::array< float2, 4 > &points)
Definition drawnode.cc:1672
static void nodesocket_cache_flush()
Definition drawnode.cc:1741
static void node_buts_image_views(uiLayout *layout, bContext *, PointerRNA *ptr, PointerRNA *imaptr)
Definition drawnode.cc:482
void node_link_bezier_points_evaluated(const bNodeLink &link, std::array< float2, NODE_LINK_RESOL+1 > &coords)
Definition drawnode.cc:1683
static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *C, PointerRNA *ptr)
Definition drawnode.cc:582
static void node_texture_buts_combsep_color(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:767
static void node_socket_virtual_draw_color(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:1477
static void nodelink_batch_draw(const SpaceNode &snode)
Definition drawnode.cc:1991
float2 socket_link_connection_location(const bNode &node, const bNodeSocket &socket, const bNodeLink &link)
Definition drawnode.cc:1623
static void node_draw_link_bezier_ex(const SpaceNode &snode, const NodeLinkDrawConfig &draw_config, const std::array< float2, 4 > &points)
Definition drawnode.cc:2245
static void node_texture_set_butfunc(blender::bke::bNodeType *ntype)
Definition drawnode.cc:773
static void node_socket_undefined_draw_color(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:876
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
static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRef label)
Definition drawnode.cc:1087
NodeResizeDirection node_get_resize_direction(const SpaceNode &snode, const bNode *node, const int x, const int y)
Definition drawnode.cc:199
void nodelink_batch_end(const SpaceNode &snode)
Definition drawnode.cc:2033
void nodelink_batch_start(const SpaceNode &)
Definition drawnode.cc:2028
void std_node_socket_color_fn(bContext *, PointerRNA *, PointerRNA *, float *r_color)
Definition drawnode.cc:984
static void node_composit_buts_huecorrect(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:532
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:144
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:2098
static void node_template_properties_update(blender::bke::bNodeType *ntype)
Definition drawnode.cc:851
void(*)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color) SocketColorFn
Definition drawnode.cc:996
static void node_composit_buts_cryptomatte_legacy(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:559
static void node_socket_virtual_draw_color_simple(const bke::bNodeSocketType *, float *r_color)
Definition drawnode.cc:1485
void node_geometry_add_volume_grid_search_button(const bContext &, const bNode &node, PointerRNA &socket_ptr, uiLayout &layout, const StringRef placeholder)
static void node_composit_buts_combsep_color(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:548
static float mute_verts[3][2]
Definition drawnode.cc:1854
static void draw_node_socket_name_editable(uiLayout *layout, bNodeSocket *sock, const StringRef text)
Definition drawnode.cc:1061
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:1805
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:2111
static void node_buts_normal(uiLayout *layout, bContext *, PointerRNA *ptr)
Definition drawnode.cc:163
static gpu::Batch * nodesocket_batch_init()
Definition drawnode.cc:1725
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:832
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:1871
static bool socket_needs_attribute_search(bNode &node, bNodeSocket &socket)
Definition drawnode.cc:1011
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, 4 > float4
VecBase< float, 2 > float2
ColorTheme4< float > ColorTheme4f
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_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 DNA_ID.h:414
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
char node_tree_sub_type
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
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:99
Defines a socket type.
Definition BKE_node.hh:158
void(* draw_color)(bContext *C, PointerRNA *ptr, PointerRNA *node_ptr, float *r_color)
Definition BKE_node.hh:171
void(* draw_color_simple)(const bNodeSocketType *socket_type, float *r_color)
Definition BKE_node.hh:172
void(* interface_draw)(ID *id, bNodeTreeInterfaceSocket *socket, bContext *C, uiLayout *layout)
Definition BKE_node.hh:174
void(* draw)(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, StringRef text)
Definition BKE_node.hh:166
eNodeSocketDatatype type
Definition BKE_node.hh:193
Defines a node type.
Definition BKE_node.hh:238
bNodeSocketTemplate * inputs
Definition BKE_node.hh:254
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:261
bNodeSocketTemplate * outputs
Definition BKE_node.hh:254
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
Vector< NodeSocketShaderParameters, MAX_SOCKET_INSTANCE > params
Definition drawnode.cc:1715
float xmax
float xmin
float ymax
float ymin
void alignment_set(blender::ui::LayoutAlign alignment)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void active_set(bool active)
void context_ptr_set(blender::StringRef name, const PointerRNA *ptr)
uiLayout & row(bool align)
uiLayout & split(float percentage, bool align)
void emboss_set(blender::ui::EmbossType emboss)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
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:4238
void wmOrtho2_region_pixelspace(const ARegion *region)