Blender  V3.3
node_edit.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include <algorithm>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_light_types.h"
13 #include "DNA_material_types.h"
14 #include "DNA_node_types.h"
15 #include "DNA_text_types.h"
16 #include "DNA_world_types.h"
17 
18 #include "BKE_callbacks.h"
19 #include "BKE_context.h"
20 #include "BKE_global.h"
21 #include "BKE_image.h"
22 #include "BKE_image_format.h"
23 #include "BKE_lib_id.h"
24 #include "BKE_main.h"
25 #include "BKE_material.h"
26 #include "BKE_node.h"
27 #include "BKE_node_tree_update.h"
28 #include "BKE_report.h"
29 #include "BKE_scene.h"
30 #include "BKE_workspace.h"
31 
32 #include "DEG_depsgraph.h"
33 #include "DEG_depsgraph_build.h"
34 #include "DEG_depsgraph_query.h"
35 
36 #include "RE_engine.h"
37 #include "RE_pipeline.h"
38 
39 #include "ED_image.h"
40 #include "ED_node.h" /* own include */
41 #include "ED_render.h"
42 #include "ED_screen.h"
43 #include "ED_select_utils.h"
44 #include "ED_spreadsheet.h"
45 
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 #include "RNA_enum_types.h"
49 #include "RNA_prototypes.h"
50 
51 #include "WM_api.h"
52 #include "WM_types.h"
53 
54 #include "UI_view2d.h"
55 
56 #include "GPU_material.h"
57 
58 #include "IMB_imbuf_types.h"
59 
60 #include "NOD_composite.h"
61 #include "NOD_geometry.h"
62 #include "NOD_shader.h"
63 #include "NOD_texture.h"
64 #include "node_intern.hh" /* own include */
65 
66 namespace blender::ed::space_node {
67 
68 #define USE_ESC_COMPO
69 
70 /* -------------------------------------------------------------------- */
74 enum {
77 };
78 
79 struct CompoJob {
80  /* Input parameters. */
86  /* Evaluated state/ */
89  /* Jon system integration. */
90  const short *stop;
91  short *do_update;
92  float *progress;
93 };
94 
96 {
97  float sock_height = NODE_SOCKSIZE * NODE_SOCKSIZE_DRAW_MULIPLIER;
98  if (socket.flag & SOCK_MULTI_INPUT) {
99  sock_height += max_ii(NODE_MULTI_INPUT_LINK_GAP * 0.5f * socket.total_inputs, NODE_SOCKSIZE);
100  }
101  return sock_height;
102 }
103 
105  const int index,
106  const int total_inputs)
107 {
108  const float offset = (total_inputs * NODE_MULTI_INPUT_LINK_GAP - NODE_MULTI_INPUT_LINK_GAP) *
109  0.5f;
110  return {socket_position.x - NODE_SOCKSIZE * 0.5f,
111  socket_position.y - offset + index * NODE_MULTI_INPUT_LINK_GAP};
112 }
113 
114 static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
115 {
116  LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) {
117  if (node->type == CMP_NODE_COMPOSITE) {
118  if (recalc_flags & COM_RECALC_COMPOSITE) {
119  node->flag |= NODE_DO_OUTPUT_RECALC;
120  }
121  }
122  else if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
123  if (recalc_flags & COM_RECALC_VIEWER) {
124  node->flag |= NODE_DO_OUTPUT_RECALC;
125  }
126  }
127  else if (node->type == NODE_GROUP) {
128  if (node->id) {
129  compo_tag_output_nodes((bNodeTree *)node->id, recalc_flags);
130  }
131  }
132  }
133 }
134 
135 static int compo_get_recalc_flags(const bContext *C)
136 {
138  int recalc_flags = 0;
139 
140  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
141  const bScreen *screen = WM_window_get_active_screen(win);
142 
143  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
144  if (area->spacetype == SPACE_IMAGE) {
145  SpaceImage *sima = (SpaceImage *)area->spacedata.first;
146  if (sima->image) {
147  if (sima->image->type == IMA_TYPE_R_RESULT) {
148  recalc_flags |= COM_RECALC_COMPOSITE;
149  }
150  else if (sima->image->type == IMA_TYPE_COMPOSITE) {
151  recalc_flags |= COM_RECALC_VIEWER;
152  }
153  }
154  }
155  else if (area->spacetype == SPACE_NODE) {
156  SpaceNode *snode = (SpaceNode *)area->spacedata.first;
157  if (snode->flag & SNODE_BACKDRAW) {
158  recalc_flags |= COM_RECALC_VIEWER;
159  }
160  }
161  }
162  }
163 
164  return recalc_flags;
165 }
166 
167 /* called by compo, only to check job 'stop' value */
168 static int compo_breakjob(void *cjv)
169 {
170  CompoJob *cj = (CompoJob *)cjv;
171 
172  /* without G.is_break 'ESC' won't quit - which annoys users */
173  return (*(cj->stop)
174 #ifdef USE_ESC_COMPO
175  || G.is_break
176 #endif
177  );
178 }
179 
180 /* called by compo, wmJob sends notifier */
181 static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
182 {
183  CompoJob *cj = (CompoJob *)cjv;
184 
185  *(cj->do_update) = true;
186 }
187 
188 /* called by compo, wmJob sends notifier */
189 static void compo_redrawjob(void *cjv)
190 {
191  CompoJob *cj = (CompoJob *)cjv;
192 
193  *(cj->do_update) = true;
194 }
195 
196 static void compo_freejob(void *cjv)
197 {
198  CompoJob *cj = (CompoJob *)cjv;
199 
200  if (cj->localtree) {
201  ntreeLocalMerge(cj->bmain, cj->localtree, cj->ntree);
202  }
203  if (cj->compositor_depsgraph != nullptr) {
205  }
206  MEM_freeN(cj);
207 }
208 
209 /* only now we copy the nodetree, so adding many jobs while
210  * sliding buttons doesn't frustrate */
211 static void compo_initjob(void *cjv)
212 {
213  CompoJob *cj = (CompoJob *)cjv;
214  Main *bmain = cj->bmain;
215  Scene *scene = cj->scene;
216  ViewLayer *view_layer = cj->view_layer;
217 
218  cj->compositor_depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
220 
221  /* NOTE: Don't update animation to preserve unkeyed changes, this means can not use
222  * evaluate_on_framechange. */
224 
226  &cj->ntree->id);
227 
228  cj->localtree = ntreeLocalize(ntree_eval);
229 
230  if (cj->recalc_flags) {
232  }
233 }
234 
235 /* called before redraw notifiers, it moves finished previews over */
236 static void compo_updatejob(void *UNUSED(cjv))
237 {
239 }
240 
241 static void compo_progressjob(void *cjv, float progress)
242 {
243  CompoJob *cj = (CompoJob *)cjv;
244 
245  *(cj->progress) = progress;
246 }
247 
248 /* only this runs inside thread */
249 static void compo_startjob(void *cjv,
250  /* Cannot be const, this function implements wm_jobs_start_callback.
251  * NOLINTNEXTLINE: readability-non-const-parameter. */
252  short *stop,
253  short *do_update,
254  float *progress)
255 {
256  CompoJob *cj = (CompoJob *)cjv;
257  bNodeTree *ntree = cj->localtree;
258  Scene *scene = cj->scene;
259 
260  if (scene->use_nodes == false) {
261  return;
262  }
263 
264  cj->stop = stop;
265  cj->do_update = do_update;
266  cj->progress = progress;
267 
269  ntree->tbh = cj;
271  ntree->sdh = cj;
273  ntree->prh = cj;
275  ntree->udh = cj;
276 
277  // XXX BIF_store_spare();
278  /* 1 is do_previews */
280 
281  if ((cj->scene->r.scemode & R_MULTIVIEW) == 0) {
282  ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, "");
283  }
284  else {
286  if (BKE_scene_multiview_is_render_view_active(&scene->r, srv) == false) {
287  continue;
288  }
289  ntreeCompositExecTree(cj->scene, ntree, &cj->scene->r, false, true, srv->name);
290  }
291  }
292 
293  ntree->test_break = nullptr;
294  ntree->stats_draw = nullptr;
295  ntree->progress = nullptr;
296 }
297 
298 static void compo_canceljob(void *cjv)
299 {
300  CompoJob *cj = (CompoJob *)cjv;
301  Main *bmain = cj->bmain;
302  Scene *scene = cj->scene;
304 }
305 
306 static void compo_completejob(void *cjv)
307 {
308  CompoJob *cj = (CompoJob *)cjv;
309  Main *bmain = cj->bmain;
310  Scene *scene = cj->scene;
312 }
313 
316 } // namespace blender::ed::space_node
317 
318 /* -------------------------------------------------------------------- */
322 void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
323 {
324  using namespace blender::ed::space_node;
325 
326  Main *bmain = CTX_data_main(C);
328  ViewLayer *view_layer = CTX_data_view_layer(C);
329 
330  /* to fix bug: T32272. */
331  if (G.is_rendering) {
332  return;
333  }
334 
335 #ifdef USE_ESC_COMPO
336  G.is_break = false;
337 #endif
338 
340  scene, BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"), false);
341 
342  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
343  CTX_wm_window(C),
344  scene_owner,
345  "Compositing",
348  CompoJob *cj = MEM_cnew<CompoJob>("compo job");
349 
350  /* customdata for preview thread */
351  cj->bmain = bmain;
352  cj->scene = scene;
353  cj->view_layer = view_layer;
354  cj->ntree = nodetree;
356 
357  /* setup job */
360  WM_jobs_callbacks_ex(wm_job,
364  nullptr,
367 
368  WM_jobs_start(CTX_wm_manager(C), wm_job);
369 }
370 
373 namespace blender::ed::space_node {
374 
375 /* -------------------------------------------------------------------- */
380 {
381  if (ED_operator_node_active(C)) {
382  SpaceNode *snode = CTX_wm_space_node(C);
383  if (ED_node_is_compositor(snode)) {
384  return true;
385  }
386  }
387  return false;
388 }
389 
391 {
393  SpaceNode *snode = CTX_wm_space_node(C);
394  if (ED_node_is_compositor(snode)) {
395  return true;
396  }
397  }
398  return false;
399 }
400 
402 {
404 
405  if (ntree->type == NTREE_SHADER && id != nullptr) {
406  if (GS(id->name) == ID_MA) {
408  }
409  else if (GS(id->name) == ID_LA) {
411  }
412  else if (GS(id->name) == ID_WO) {
414  }
415  }
416  else if (ntree->type == NTREE_COMPOSIT) {
418  }
419  else if (ntree->type == NTREE_TEXTURE) {
421  }
422  else if (ntree->type == NTREE_GEOMETRY) {
424  }
425 }
426 
429 } // namespace blender::ed::space_node
430 
431 /* -------------------------------------------------------------------- */
435 void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *root_ntree)
436 {
437  if (C != nullptr) {
438  SpaceNode *snode = CTX_wm_space_node(C);
439  if (snode != nullptr && root_ntree != nullptr) {
441  }
442  }
443 
444  NodeTreeUpdateExtraParams params = {nullptr};
445  params.tree_changed_fn = [](ID *id, bNodeTree *ntree, void *UNUSED(user_data)) {
448  };
449  params.tree_output_changed_fn = [](ID *UNUSED(id), bNodeTree *ntree, void *UNUSED(user_data)) {
451  };
452 
453  BKE_ntree_update_main_tree(bmain, root_ntree, &params);
454 }
455 
457 {
458  if (typeinfo) {
459  BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
460  }
461  else {
462  snode->tree_idname[0] = '\0';
463  }
464 }
465 
466 bool ED_node_is_compositor(struct SpaceNode *snode)
467 {
468  return STREQ(snode->tree_idname, ntreeType_Composite->idname);
469 }
470 
471 bool ED_node_is_shader(struct SpaceNode *snode)
472 {
473  return STREQ(snode->tree_idname, ntreeType_Shader->idname);
474 }
475 
476 bool ED_node_is_texture(struct SpaceNode *snode)
477 {
478  return STREQ(snode->tree_idname, ntreeType_Texture->idname);
479 }
480 
481 bool ED_node_is_geometry(struct SpaceNode *snode)
482 {
483  return STREQ(snode->tree_idname, ntreeType_Geometry->idname);
484 }
485 
487 {
488  Main *bmain = CTX_data_main(C);
489 
490  if (GS(id->name) == ID_MA) {
491  /* Materials */
493  Material *ma = (Material *)id;
494  Material *ma_default;
495 
496  if (ob && ob->type == OB_VOLUME) {
497  ma_default = BKE_material_default_volume();
498  }
499  else {
500  ma_default = BKE_material_default_surface();
501  }
502 
503  ma->nodetree = ntreeCopyTree(bmain, ma_default->nodetree);
504  BKE_ntree_update_main_tree(bmain, ma->nodetree, nullptr);
505  }
506  else if (ELEM(GS(id->name), ID_WO, ID_LA)) {
507  /* Emission */
508  bNodeTree *ntree = ntreeAddTree(nullptr, "Shader Nodetree", ntreeType_Shader->idname);
509  bNode *shader, *output;
510 
511  if (GS(id->name) == ID_WO) {
512  World *world = (World *)id;
513  world->nodetree = ntree;
514 
515  shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_BACKGROUND);
518  shader,
519  nodeFindSocket(shader, SOCK_OUT, "Background"),
520  output,
521  nodeFindSocket(output, SOCK_IN, "Surface"));
522 
523  bNodeSocket *color_sock = nodeFindSocket(shader, SOCK_IN, "Color");
524  copy_v3_v3(((bNodeSocketValueRGBA *)color_sock->default_value)->value, &world->horr);
525  }
526  else {
527  Light *light = (Light *)id;
528  light->nodetree = ntree;
529 
530  shader = nodeAddStaticNode(nullptr, ntree, SH_NODE_EMISSION);
533  shader,
534  nodeFindSocket(shader, SOCK_OUT, "Emission"),
535  output,
536  nodeFindSocket(output, SOCK_IN, "Surface"));
537  }
538 
539  shader->locx = 10.0f;
540  shader->locy = 300.0f;
541  output->locx = 300.0f;
542  output->locy = 300.0f;
544  BKE_ntree_update_main_tree(bmain, ntree, nullptr);
545  }
546  else {
547  printf("ED_node_shader_default called on wrong ID type.\n");
548  return;
549  }
550 }
551 
552 void ED_node_composit_default(const bContext *C, struct Scene *sce)
553 {
554  /* but lets check it anyway */
555  if (sce->nodetree) {
556  if (G.debug & G_DEBUG) {
557  printf("error in composite initialize\n");
558  }
559  return;
560  }
561 
562  sce->nodetree = ntreeAddTree(nullptr, "Compositing Nodetree", ntreeType_Composite->idname);
563 
564  sce->nodetree->chunksize = 256;
567 
569  out->locx = 300.0f;
570  out->locy = 400.0f;
571 
573  in->locx = 10.0f;
574  in->locy = 400.0f;
575  nodeSetActive(sce->nodetree, in);
576 
577  /* links from color to color */
578  bNodeSocket *fromsock = (bNodeSocket *)in->outputs.first;
579  bNodeSocket *tosock = (bNodeSocket *)out->inputs.first;
580  nodeAddLink(sce->nodetree, in, fromsock, out, tosock);
581 
583 }
584 
586 {
587  /* but lets check it anyway */
588  if (tex->nodetree) {
589  if (G.debug & G_DEBUG) {
590  printf("error in texture initialize\n");
591  }
592  return;
593  }
594 
595  tex->nodetree = ntreeAddTree(nullptr, "Texture Nodetree", ntreeType_Texture->idname);
596 
598  out->locx = 300.0f;
599  out->locy = 300.0f;
600 
602  in->locx = 10.0f;
603  in->locy = 300.0f;
604  nodeSetActive(tex->nodetree, in);
605 
606  bNodeSocket *fromsock = (bNodeSocket *)in->outputs.first;
607  bNodeSocket *tosock = (bNodeSocket *)out->inputs.first;
608  nodeAddLink(tex->nodetree, in, fromsock, out, tosock);
609 
611 }
612 
613 namespace blender::ed::space_node {
614 
619 {
620  SpaceNode *snode = CTX_wm_space_node(&C);
621  bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
622  bNodeTree *ntree = snode->nodetree;
623  ID *id = snode->id, *from = snode->from;
624 
625  /* check the tree type */
626  if (!treetype || (treetype->poll && !treetype->poll(&C, treetype))) {
627  /* invalid tree type, skip
628  * NOTE: not resetting the node path here, invalid #bNodeTreeType
629  * may still be registered at a later point. */
630  return;
631  }
632 
633  if (snode->nodetree && !STREQ(snode->nodetree->idname, snode->tree_idname)) {
634  /* current tree does not match selected type, clear tree path */
635  ntree = nullptr;
636  id = nullptr;
637  from = nullptr;
638  }
639 
640  if (!(snode->flag & SNODE_PIN) || ntree == nullptr) {
641  if (treetype->get_from_context) {
642  /* reset and update from context */
643  ntree = nullptr;
644  id = nullptr;
645  from = nullptr;
646 
647  treetype->get_from_context(&C, treetype, &ntree, &id, &from);
648  }
649  }
650 
651  if (snode->nodetree != ntree || snode->id != id || snode->from != from ||
652  (snode->treepath.last == nullptr && ntree)) {
653  ED_node_tree_start(snode, ntree, id, from);
654  }
655 }
656 
657 } // namespace blender::ed::space_node
658 
660  Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
661 {
662  const bool was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE) != 0;
663  if (r_active_texture_changed) {
664  *r_active_texture_changed = false;
665  }
666 
668 
669  if (node->type != NODE_GROUP) {
670  const bool was_output = (node->flag & NODE_DO_OUTPUT) != 0;
671  bool do_update = false;
672 
673  /* generic node group output: set node as active output */
674  if (node->type == NODE_GROUP_OUTPUT) {
675  LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
676  if (node_iter->type == NODE_GROUP_OUTPUT) {
677  node_iter->flag &= ~NODE_DO_OUTPUT;
678  }
679  }
680 
681  node->flag |= NODE_DO_OUTPUT;
682  if (!was_output) {
683  do_update = true;
685  }
686  }
687 
688  /* tree specific activate calls */
689  if (ntree->type == NTREE_SHADER) {
690  if (ELEM(node->type,
695  LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
696  if (node_iter->type == node->type) {
697  node_iter->flag &= ~NODE_DO_OUTPUT;
698  }
699  }
700 
701  node->flag |= NODE_DO_OUTPUT;
703  }
704 
705  ED_node_tree_propagate_change(nullptr, bmain, ntree);
706 
707  if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
708  /* If active texture changed, free glsl materials. */
709  LISTBASE_FOREACH (Material *, ma, &bmain->materials) {
710  if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) {
711  GPU_material_free(&ma->gpumaterial);
712 
713  /* Sync to active texpaint slot, otherwise we can end up painting on a different slot
714  * than we are looking at. */
715  if (ma->texpaintslot) {
716  if (node->id != nullptr && GS(node->id->name) == ID_IM) {
717  Image *image = (Image *)node->id;
718  for (int i = 0; i < ma->tot_slots; i++) {
719  if (ma->texpaintslot[i].ima == image) {
720  ma->paint_active_slot = i;
721  }
722  }
723  }
724  }
725  }
726  }
727 
728  LISTBASE_FOREACH (World *, wo, &bmain->worlds) {
729  if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) {
730  GPU_material_free(&wo->gpumaterial);
731  }
732  }
733 
734  /* Sync to Image Editor under the following conditions:
735  * - current image is not pinned
736  * - current image is not a Render Result or ViewerNode (want to keep looking at these) */
737  if (node->id != nullptr && GS(node->id->name) == ID_IM) {
738  Image *image = (Image *)node->id;
739  wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
740  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
741  const bScreen *screen = WM_window_get_active_screen(win);
742  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
743  LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
744  if (sl->spacetype != SPACE_IMAGE) {
745  continue;
746  }
747  SpaceImage *sima = (SpaceImage *)sl;
748  if (sima->pin) {
749  continue;
750  }
751  if (sima->image &&
753  continue;
754  }
755  ED_space_image_set(bmain, sima, image, true);
756  }
757  }
758  }
759  }
760 
761  if (r_active_texture_changed) {
762  *r_active_texture_changed = true;
763  }
764  ED_node_tree_propagate_change(nullptr, bmain, ntree);
765  WM_main_add_notifier(NC_IMAGE, nullptr);
766  }
767 
769  }
770  else if (ntree->type == NTREE_COMPOSIT) {
771  /* make active viewer, currently only 1 supported... */
773  LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
774  if (ELEM(node_iter->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
775  node_iter->flag &= ~NODE_DO_OUTPUT;
776  }
777  }
778 
779  node->flag |= NODE_DO_OUTPUT;
780  if (was_output == 0) {
782  ED_node_tree_propagate_change(nullptr, bmain, ntree);
783  }
784 
785  /* Adding a node doesn't link this yet. */
786  node->id = (ID *)BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
787  }
788  else if (node->type == CMP_NODE_COMPOSITE) {
789  if (was_output == 0) {
790  LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
791  if (node_iter->type == CMP_NODE_COMPOSITE) {
792  node_iter->flag &= ~NODE_DO_OUTPUT;
793  }
794  }
795 
796  node->flag |= NODE_DO_OUTPUT;
798  ED_node_tree_propagate_change(nullptr, bmain, ntree);
799  }
800  }
801  else if (do_update) {
802  ED_node_tree_propagate_change(nullptr, bmain, ntree);
803  }
804  }
805  else if (ntree->type == NTREE_TEXTURE) {
806  /* XXX */
807 #if 0
808  if (node->id) {
809  BIF_preview_changed(-1);
810  allqueue(REDRAWBUTSSHADING, 1);
811  allqueue(REDRAWIPO, 0);
812  }
813 #endif
814  }
815  else if (ntree->type == NTREE_GEOMETRY) {
816  if (node->type == GEO_NODE_VIEWER) {
817  if ((node->flag & NODE_DO_OUTPUT) == 0) {
818  LISTBASE_FOREACH (bNode *, node_iter, &ntree->nodes) {
819  if (node_iter->type == GEO_NODE_VIEWER) {
820  node_iter->flag &= ~NODE_DO_OUTPUT;
821  }
822  }
823  node->flag |= NODE_DO_OUTPUT;
825  }
826  }
827  }
828  }
829 }
830 
832 {
833  /* XXX This does not work due to layout functions relying on node->block,
834  * which only exists during actual drawing. Can we rely on valid totr rects?
835  */
836  /* make sure nodes have correct bounding boxes after transform */
837  // node_update_nodetree(C, ntree, 0.0f, 0.0f);
838 }
839 
842 namespace blender::ed::space_node {
843 
844 /* -------------------------------------------------------------------- */
848 #if 0 /* UNUSED */
849 
850 static bool edit_node_poll(bContext *C)
851 {
852  return ED_operator_node_active(C);
853 }
854 
855 static void edit_node_properties(wmOperatorType *ot)
856 {
857  /* XXX could node be a context pointer? */
858  RNA_def_string(ot->srna, "node", nullptr, MAX_NAME, "Node", "");
859  RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
860  RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Side", "");
861 }
862 
863 static int edit_node_invoke_properties(bContext *C, wmOperator *op)
864 {
865  if (!RNA_struct_property_is_set(op->ptr, "node")) {
866  bNode *node = CTX_data_pointer_get_type(C, "node", &RNA_Node).data;
867  if (!node) {
868  return 0;
869  }
870  else {
871  RNA_string_set(op->ptr, "node", node->name);
872  }
873  }
874 
875  if (!RNA_struct_property_is_set(op->ptr, "in_out")) {
876  RNA_enum_set(op->ptr, "in_out", SOCK_IN);
877  }
878 
879  if (!RNA_struct_property_is_set(op->ptr, "socket")) {
880  RNA_int_set(op->ptr, "socket", 0);
881  }
882 
883  return 1;
884 }
885 
886 static void edit_node_properties_get(
887  wmOperator *op, bNodeTree *ntree, bNode **r_node, bNodeSocket **r_sock, int *r_in_out)
888 {
889  bNode *node;
890  bNodeSocket *sock = nullptr;
891  char nodename[MAX_NAME];
892  int sockindex;
893  int in_out;
894 
895  RNA_string_get(op->ptr, "node", nodename);
896  node = nodeFindNodebyName(ntree, nodename);
897 
898  in_out = RNA_enum_get(op->ptr, "in_out");
899 
900  sockindex = RNA_int_get(op->ptr, "socket");
901  switch (in_out) {
902  case SOCK_IN:
903  sock = BLI_findlink(&node->inputs, sockindex);
904  break;
905  case SOCK_OUT:
906  sock = BLI_findlink(&node->outputs, sockindex);
907  break;
908  }
909 
910  if (r_node) {
911  *r_node = node;
912  }
913  if (r_sock) {
914  *r_sock = sock;
915  }
916  if (r_in_out) {
917  *r_in_out = in_out;
918  }
919 }
920 #endif
921 
924 /* -------------------------------------------------------------------- */
928 static bool socket_is_occluded(const bNodeSocket &sock,
929  const bNode &node_the_socket_belongs_to,
930  const SpaceNode &snode)
931 {
933  if (node == &node_the_socket_belongs_to) {
934  /* Nodes after this one are underneath and can't occlude the socket. */
935  return false;
936  }
937 
938  rctf socket_hitbox;
939  const float socket_hitbox_radius = NODE_SOCKSIZE - 0.1f * U.widget_unit;
940  BLI_rctf_init_pt_radius(&socket_hitbox, float2(sock.locx, sock.locy), socket_hitbox_radius);
941  if (BLI_rctf_inside_rctf(&node->totr, &socket_hitbox)) {
942  return true;
943  }
944  }
945  return false;
946 }
947 
950 /* -------------------------------------------------------------------- */
955  float mxstart, mystart;
956  float oldlocx, oldlocy;
960 };
961 
962 static void node_resize_init(
963  bContext *C, wmOperator *op, const float cursor[2], const bNode *node, NodeResizeDirection dir)
964 {
965  NodeSizeWidget *nsw = MEM_cnew<NodeSizeWidget>(__func__);
966 
967  op->customdata = nsw;
968 
969  nsw->mxstart = cursor[0];
970  nsw->mystart = cursor[1];
971 
972  /* store old */
973  nsw->oldlocx = node->locx;
974  nsw->oldlocy = node->locy;
975  nsw->oldoffsetx = node->offsetx;
976  nsw->oldoffsety = node->offsety;
977  nsw->oldwidth = node->width;
978  nsw->oldheight = node->height;
979  nsw->directions = dir;
980 
982  /* add modal handler */
984 }
985 
986 static void node_resize_exit(bContext *C, wmOperator *op, bool cancel)
987 {
989 
990  /* Restore old data on cancel. */
991  if (cancel) {
992  SpaceNode *snode = CTX_wm_space_node(C);
993  bNode *node = nodeGetActive(snode->edittree);
995 
996  node->locx = nsw->oldlocx;
997  node->locy = nsw->oldlocy;
998  node->offsetx = nsw->oldoffsetx;
999  node->offsety = nsw->oldoffsety;
1000  node->width = nsw->oldwidth;
1001  node->height = nsw->oldheight;
1002  }
1003 
1004  MEM_freeN(op->customdata);
1005  op->customdata = nullptr;
1006 }
1007 
1008 static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
1009 {
1010  SpaceNode *snode = CTX_wm_space_node(C);
1011  ARegion *region = CTX_wm_region(C);
1012  bNode *node = nodeGetActive(snode->edittree);
1014 
1015  switch (event->type) {
1016  case MOUSEMOVE: {
1017  int mval[2];
1018  WM_event_drag_start_mval(event, region, mval);
1019  float mx, my;
1020  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &mx, &my);
1021  float dx = (mx - nsw->mxstart) / UI_DPI_FAC;
1022  float dy = (my - nsw->mystart) / UI_DPI_FAC;
1023 
1024  if (node) {
1025  float *pwidth = &node->width;
1026  float oldwidth = nsw->oldwidth;
1027  float widthmin = node->typeinfo->minwidth;
1028  float widthmax = node->typeinfo->maxwidth;
1029 
1030  {
1031  if (nsw->directions & NODE_RESIZE_RIGHT) {
1032  *pwidth = oldwidth + dx;
1033  CLAMP(*pwidth, widthmin, widthmax);
1034  }
1035  if (nsw->directions & NODE_RESIZE_LEFT) {
1036  float locmax = nsw->oldlocx + oldwidth;
1037 
1038  node->locx = nsw->oldlocx + dx;
1039  CLAMP(node->locx, locmax - widthmax, locmax - widthmin);
1040  *pwidth = locmax - node->locx;
1041  }
1042  }
1043 
1044  /* height works the other way round ... */
1045  {
1046  float heightmin = UI_DPI_FAC * node->typeinfo->minheight;
1047  float heightmax = UI_DPI_FAC * node->typeinfo->maxheight;
1048  if (nsw->directions & NODE_RESIZE_TOP) {
1049  float locmin = nsw->oldlocy - nsw->oldheight;
1050 
1051  node->locy = nsw->oldlocy + dy;
1052  CLAMP(node->locy, locmin + heightmin, locmin + heightmax);
1053  node->height = node->locy - locmin;
1054  }
1055  if (nsw->directions & NODE_RESIZE_BOTTOM) {
1056  node->height = nsw->oldheight - dy;
1057  CLAMP(node->height, heightmin, heightmax);
1058  }
1059  }
1060 
1061  /* XXX make callback? */
1062  if (node->type == NODE_FRAME) {
1063  /* keep the offset symmetric around center point */
1064  if (nsw->directions & NODE_RESIZE_LEFT) {
1065  node->locx = nsw->oldlocx + 0.5f * dx;
1066  node->offsetx = nsw->oldoffsetx + 0.5f * dx;
1067  }
1068  if (nsw->directions & NODE_RESIZE_RIGHT) {
1069  node->locx = nsw->oldlocx + 0.5f * dx;
1070  node->offsetx = nsw->oldoffsetx - 0.5f * dx;
1071  }
1072  if (nsw->directions & NODE_RESIZE_TOP) {
1073  node->locy = nsw->oldlocy + 0.5f * dy;
1074  node->offsety = nsw->oldoffsety + 0.5f * dy;
1075  }
1076  if (nsw->directions & NODE_RESIZE_BOTTOM) {
1077  node->locy = nsw->oldlocy + 0.5f * dy;
1078  node->offsety = nsw->oldoffsety - 0.5f * dy;
1079  }
1080  }
1081  }
1082 
1083  ED_region_tag_redraw(region);
1084 
1085  break;
1086  }
1087  case LEFTMOUSE:
1088  case MIDDLEMOUSE:
1089  case RIGHTMOUSE: {
1090  if (event->val == KM_RELEASE) {
1091  node_resize_exit(C, op, false);
1093 
1094  return OPERATOR_FINISHED;
1095  }
1096  if (event->val == KM_PRESS) {
1097  node_resize_exit(C, op, true);
1098  ED_region_tag_redraw(region);
1099 
1100  return OPERATOR_CANCELLED;
1101  }
1102  break;
1103  }
1104  case EVT_ESCKEY:
1105  node_resize_exit(C, op, true);
1106  ED_region_tag_redraw(region);
1107  return OPERATOR_CANCELLED;
1108  }
1109 
1110  return OPERATOR_RUNNING_MODAL;
1111 }
1112 
1113 static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1114 {
1115  SpaceNode *snode = CTX_wm_space_node(C);
1116  ARegion *region = CTX_wm_region(C);
1117  const bNode *node = nodeGetActive(snode->edittree);
1118 
1119  if (node == nullptr) {
1121  }
1122 
1123  /* convert mouse coordinates to v2d space */
1124  float cursor[2];
1125  int mval[2];
1126  WM_event_drag_start_mval(event, region, mval);
1127  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
1128  const NodeResizeDirection dir = node_get_resize_direction(node, cursor[0], cursor[1]);
1129  if (dir == NODE_RESIZE_NONE) {
1131  }
1132 
1133  node_resize_init(C, op, cursor, node, dir);
1134  return OPERATOR_RUNNING_MODAL;
1135 }
1136 
1138 {
1139  node_resize_exit(C, op, true);
1140 }
1141 
1143 {
1144  /* identifiers */
1145  ot->name = "Resize Node";
1146  ot->idname = "NODE_OT_resize";
1147  ot->description = "Resize a node";
1148 
1149  /* api callbacks */
1154 
1155  /* flags */
1156  ot->flag = OPTYPE_BLOCKING;
1157 }
1158 
1161 /* -------------------------------------------------------------------- */
1166 {
1167  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1168  if (sock->flag & SOCK_HIDDEN) {
1169  return true;
1170  }
1171  }
1172  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1173  if (sock->flag & SOCK_HIDDEN) {
1174  return true;
1175  }
1176  }
1177  return false;
1178 }
1179 
1181 {
1182  if (set == 0) {
1183  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1184  sock->flag &= ~SOCK_HIDDEN;
1185  }
1186  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1187  sock->flag &= ~SOCK_HIDDEN;
1188  }
1189  }
1190  else {
1191  /* hide unused sockets */
1192  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1193  if (sock->link == nullptr) {
1194  sock->flag |= SOCK_HIDDEN;
1195  }
1196  }
1197  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1198  if (nodeCountSocketLinks(snode->edittree, sock) == 0) {
1199  sock->flag |= SOCK_HIDDEN;
1200  }
1201  }
1202  }
1203 }
1204 
1205 /* checks snode->mouse position, and returns found node/socket */
1206 static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSocket &socket)
1207 {
1208  const float node_socket_height = node_socket_calculate_height(socket);
1209  rctf multi_socket_rect;
1210  /* `.xmax = socket->locx + NODE_SOCKSIZE * 5.5f`
1211  * would be the same behavior as for regular sockets.
1212  * But keep it smaller because for multi-input socket you
1213  * sometimes want to drag the link to the other side, if you may
1214  * accidentally pick the wrong link otherwise. */
1215  BLI_rctf_init(&multi_socket_rect,
1216  socket.locx - NODE_SOCKSIZE * 4.0f,
1217  socket.locx + NODE_SOCKSIZE * 2.0f,
1218  socket.locy - node_socket_height,
1219  socket.locy + node_socket_height);
1220  if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) {
1221  return true;
1222  }
1223  return false;
1224 }
1225 
1227  bNode **nodep,
1228  bNodeSocket **sockp,
1229  const float2 &cursor,
1230  const eNodeSocketInOut in_out)
1231 {
1232  rctf rect;
1233 
1234  const float size_sock_padded = NODE_SOCKSIZE + 4;
1235 
1236  *nodep = nullptr;
1237  *sockp = nullptr;
1238 
1239  /* check if we click in a socket */
1241  BLI_rctf_init_pt_radius(&rect, cursor, size_sock_padded);
1242 
1243  if (!(node->flag & NODE_HIDDEN)) {
1244  /* extra padding inside and out - allow dragging on the text areas too */
1245  if (in_out == SOCK_IN) {
1246  rect.xmax += NODE_SOCKSIZE;
1247  rect.xmin -= NODE_SOCKSIZE * 4;
1248  }
1249  else if (in_out == SOCK_OUT) {
1250  rect.xmax += NODE_SOCKSIZE * 4;
1251  rect.xmin -= NODE_SOCKSIZE;
1252  }
1253  }
1254 
1255  if (in_out & SOCK_IN) {
1256  LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
1257  if (!nodeSocketIsHidden(sock)) {
1258  if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) {
1259  if (cursor_isect_multi_input_socket(cursor, *sock)) {
1260  if (!socket_is_occluded(*sock, *node, snode)) {
1261  *nodep = node;
1262  *sockp = sock;
1263  return true;
1264  }
1265  }
1266  }
1267  else if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1268  if (!socket_is_occluded(*sock, *node, snode)) {
1269  *nodep = node;
1270  *sockp = sock;
1271  return true;
1272  }
1273  }
1274  }
1275  }
1276  }
1277  if (in_out & SOCK_OUT) {
1278  LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
1279  if (!nodeSocketIsHidden(sock)) {
1280  if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
1281  if (!socket_is_occluded(*sock, *node, snode)) {
1282  *nodep = node;
1283  *sockp = sock;
1284  return true;
1285  }
1286  }
1287  }
1288  }
1289  }
1290  }
1291 
1292  return false;
1293 }
1294 
1297 /* -------------------------------------------------------------------- */
1301 float node_link_dim_factor(const View2D &v2d, const bNodeLink &link)
1302 {
1303  if (link.fromsock == nullptr || link.tosock == nullptr) {
1304  return 1.0f;
1305  }
1306 
1307  const float min_endpoint_distance = std::min(
1309  BLI_rctf_length_y(&v2d.cur, link.fromsock->locy)),
1310  std::max(BLI_rctf_length_x(&v2d.cur, link.tosock->locx),
1311  BLI_rctf_length_y(&v2d.cur, link.tosock->locy)));
1312 
1313  if (min_endpoint_distance == 0.0f) {
1314  return 1.0f;
1315  }
1316  const float viewport_width = BLI_rctf_size_x(&v2d.cur);
1317  return std::clamp(1.0f - min_endpoint_distance / viewport_width * 10.0f, 0.05f, 1.0f);
1318 }
1319 
1320 bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
1321 {
1322  return nodeLinkIsHidden(&link) || node_link_dim_factor(v2d, link) < 0.5f;
1323 }
1324 
1327 /* -------------------------------------------------------------------- */
1332  bNode *node)
1333 {
1334  bNode *parent;
1335 
1336  node->flag |= NODE_TEST;
1337 
1338  /* find first selected parent */
1339  for (parent = node->parent; parent; parent = parent->parent) {
1340  if (parent->flag & SELECT) {
1341  if (!(parent->flag & NODE_TEST)) {
1342  node_duplicate_reparent_recursive(node_map, parent);
1343  }
1344  break;
1345  }
1346  }
1347  /* reparent node copy to parent copy */
1348  if (parent) {
1349  nodeDetachNode(node_map.lookup(node));
1350  nodeAttachNode(node_map.lookup(node), node_map.lookup(parent));
1351  }
1352 }
1353 
1355 {
1356  Main *bmain = CTX_data_main(C);
1357  SpaceNode *snode = CTX_wm_space_node(C);
1358  bNodeTree *ntree = snode->edittree;
1359  const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
1360  bool changed = false;
1361 
1363 
1364  Map<const bNode *, bNode *> node_map;
1366 
1367  bNode *lastnode = (bNode *)ntree->nodes.last;
1369  if (node->flag & SELECT) {
1371  ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map);
1372  node_map.add_new(node, new_node);
1373  changed = true;
1374  }
1375 
1376  /* make sure we don't copy new nodes again! */
1377  if (node == lastnode) {
1378  break;
1379  }
1380  }
1381 
1382  if (!changed) {
1383  return OPERATOR_CANCELLED;
1384  }
1385 
1386  /* Copy links between selected nodes. */
1387  bNodeLink *lastlink = (bNodeLink *)ntree->links.last;
1388  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
1389  /* This creates new links between copied nodes.
1390  * If keep_inputs is set, also copies input links from unselected (when fromnode==nullptr)!
1391  */
1392  if (link->tonode && (link->tonode->flag & NODE_SELECT) &&
1393  (keep_inputs || (link->fromnode && (link->fromnode->flag & NODE_SELECT)))) {
1394  bNodeLink *newlink = MEM_cnew<bNodeLink>("bNodeLink");
1395  newlink->flag = link->flag;
1396  newlink->tonode = node_map.lookup(link->tonode);
1397  newlink->tosock = socket_map.lookup(link->tosock);
1398 
1399  if (link->tosock->flag & SOCK_MULTI_INPUT) {
1400  newlink->multi_input_socket_index = link->multi_input_socket_index;
1401  }
1402 
1403  if (link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
1404  newlink->fromnode = node_map.lookup(link->fromnode);
1405  newlink->fromsock = socket_map.lookup(link->fromsock);
1406  }
1407  else {
1408  /* input node not copied, this keeps the original input linked */
1409  newlink->fromnode = link->fromnode;
1410  newlink->fromsock = link->fromsock;
1411  }
1412 
1413  BLI_addtail(&ntree->links, newlink);
1414  }
1415 
1416  /* make sure we don't copy new links again! */
1417  if (link == lastlink) {
1418  break;
1419  }
1420  }
1421 
1422  /* clear flags for recursive depth-first iteration */
1424  node->flag &= ~NODE_TEST;
1425  }
1426  /* reparent copied nodes */
1428  if ((node->flag & SELECT) && !(node->flag & NODE_TEST)) {
1430  }
1431 
1432  /* only has to check old nodes */
1433  if (node == lastnode) {
1434  break;
1435  }
1436  }
1437 
1438  /* deselect old nodes, select the copies instead */
1440  if (node->flag & SELECT) {
1441  /* has been set during copy above */
1442  bNode *newnode = node_map.lookup(node);
1443 
1444  nodeSetSelected(node, false);
1445  node->flag &= ~(NODE_ACTIVE | NODE_ACTIVE_TEXTURE);
1446  nodeSetSelected(newnode, true);
1447  }
1448 
1449  /* make sure we don't copy new nodes again! */
1450  if (node == lastnode) {
1451  break;
1452  }
1453  }
1454 
1455  ED_node_tree_propagate_change(C, bmain, snode->edittree);
1456  return OPERATOR_FINISHED;
1457 }
1458 
1460 {
1461  /* identifiers */
1462  ot->name = "Duplicate Nodes";
1463  ot->description = "Duplicate selected nodes";
1464  ot->idname = "NODE_OT_duplicate";
1465 
1466  /* api callbacks */
1469 
1470  /* flags */
1472 
1474  ot->srna, "keep_inputs", false, "Keep Inputs", "Keep the input links to duplicated nodes");
1475 }
1476 
1477 static bool node_select_check(const ListBase *lb)
1478 {
1479  LISTBASE_FOREACH (const bNode *, node, lb) {
1480  if (node->flag & NODE_SELECT) {
1481  return true;
1482  }
1483  }
1484 
1485  return false;
1486 }
1487 
1488 void node_select_all(ListBase *lb, int action)
1489 {
1490  if (action == SEL_TOGGLE) {
1491  if (node_select_check(lb)) {
1492  action = SEL_DESELECT;
1493  }
1494  else {
1495  action = SEL_SELECT;
1496  }
1497  }
1498 
1499  LISTBASE_FOREACH (bNode *, node, lb) {
1500  switch (action) {
1501  case SEL_SELECT:
1502  nodeSetSelected(node, true);
1503  break;
1504  case SEL_DESELECT:
1505  nodeSetSelected(node, false);
1506  break;
1507  case SEL_INVERT:
1508  nodeSetSelected(node, !(node->flag & SELECT));
1509  break;
1510  }
1511  }
1512 }
1513 
1514 /* XXX: some code needing updating to operators. */
1515 
1516 /* goes over all scenes, reads render layers */
1518 {
1519  Main *bmain = CTX_data_main(C);
1520  SpaceNode *snode = CTX_wm_space_node(C);
1521  Scene *curscene = CTX_data_scene(C);
1522 
1524 
1525  /* first tag scenes unread */
1526  LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1527  scene->id.tag |= LIB_TAG_DOIT;
1528  }
1529 
1530  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1531  if ((node->type == CMP_NODE_R_LAYERS) ||
1532  (node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER)) {
1533  ID *id = node->id;
1534  if (id == nullptr) {
1535  continue;
1536  }
1537  if (id->tag & LIB_TAG_DOIT) {
1538  RE_ReadRenderResult(curscene, (Scene *)id);
1540  id->tag &= ~LIB_TAG_DOIT;
1541  }
1542  }
1543  }
1544 
1545  ED_node_tree_propagate_change(C, bmain, snode->edittree);
1546 
1547  return OPERATOR_FINISHED;
1548 }
1549 
1551 {
1552 
1553  ot->name = "Read View Layers";
1554  ot->idname = "NODE_OT_read_viewlayers";
1555  ot->description = "Read all render layers of all used scenes";
1556 
1558 
1560 
1561  /* flags */
1562  ot->flag = 0;
1563 }
1564 
1566 {
1567  Scene *sce = CTX_data_scene(C);
1568 
1569  /* This is actually a test whether scene is used by the compositor or not.
1570  * All the nodes are using same render result, so there is no need to do
1571  * anything smart about check how exactly scene is used. */
1572  bNode *node = nullptr;
1573  LISTBASE_FOREACH (bNode *, node_iter, &sce->nodetree->nodes) {
1574  if (node_iter->id == (ID *)sce) {
1575  node = node_iter;
1576  break;
1577  }
1578  }
1579 
1580  if (node) {
1581  ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, node->custom1);
1582 
1583  if (view_layer) {
1584  PointerRNA op_ptr;
1585 
1586  WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
1587  RNA_string_set(&op_ptr, "layer", view_layer->name);
1588  RNA_string_set(&op_ptr, "scene", sce->id.name + 2);
1589 
1590  /* To keep keyframe positions. */
1591  sce->r.scemode |= R_NO_FRAME_UPDATE;
1592 
1593  WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr, nullptr);
1594 
1595  WM_operator_properties_free(&op_ptr);
1596 
1597  return OPERATOR_FINISHED;
1598  }
1599  }
1600  return OPERATOR_CANCELLED;
1601 }
1602 
1604 {
1605  ot->name = "Render Changed Layer";
1606  ot->idname = "NODE_OT_render_changed";
1607  ot->description = "Render current scene, when input node's layer has been changed";
1608 
1610 
1612 
1613  /* flags */
1614  ot->flag = 0;
1615 }
1616 
1619 /* -------------------------------------------------------------------- */
1623 static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
1624 {
1625  int tot_eq = 0, tot_neq = 0;
1626 
1627  /* Toggles the flag on all selected nodes.
1628  * If the flag is set on all nodes it is unset.
1629  * If the flag is not set on all nodes, it is set.
1630  */
1631 
1632  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1633  if (node->flag & SELECT) {
1634 
1635  if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
1636  continue;
1637  }
1638  if (toggle_flag == NODE_OPTIONS &&
1639  !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
1640  continue;
1641  }
1642 
1643  if (node->flag & toggle_flag) {
1644  tot_eq++;
1645  }
1646  else {
1647  tot_neq++;
1648  }
1649  }
1650  }
1651  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1652  if (node->flag & SELECT) {
1653 
1654  if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) {
1655  continue;
1656  }
1657  if (toggle_flag == NODE_OPTIONS &&
1658  !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) {
1659  continue;
1660  }
1661 
1662  if ((tot_eq && tot_neq) || tot_eq == 0) {
1663  node->flag |= toggle_flag;
1664  }
1665  else {
1666  node->flag &= ~toggle_flag;
1667  }
1668  }
1669  }
1670 }
1671 
1673 {
1674  SpaceNode *snode = CTX_wm_space_node(C);
1675 
1676  /* sanity checking (poll callback checks this already) */
1677  if ((snode == nullptr) || (snode->edittree == nullptr)) {
1678  return OPERATOR_CANCELLED;
1679  }
1680 
1682 
1684 
1685  return OPERATOR_FINISHED;
1686 }
1687 
1689 {
1690  /* identifiers */
1691  ot->name = "Hide";
1692  ot->description = "Toggle hiding of selected nodes";
1693  ot->idname = "NODE_OT_hide_toggle";
1694 
1695  /* callbacks */
1698 
1699  /* flags */
1701 }
1702 
1704 {
1705  SpaceNode *snode = CTX_wm_space_node(C);
1706 
1707  /* sanity checking (poll callback checks this already) */
1708  if ((snode == nullptr) || (snode->edittree == nullptr)) {
1709  return OPERATOR_CANCELLED;
1710  }
1711 
1713 
1715 
1717 
1718  return OPERATOR_FINISHED;
1719 }
1720 
1722 {
1723  /* identifiers */
1724  ot->name = "Toggle Node Preview";
1725  ot->description = "Toggle preview display for selected nodes";
1726  ot->idname = "NODE_OT_preview_toggle";
1727 
1728  /* callbacks */
1731 
1732  /* flags */
1734 }
1735 
1737 {
1738  SpaceNode *snode = CTX_wm_space_node(C);
1739 
1740  /* sanity checking (poll callback checks this already) */
1741  if ((snode == nullptr) || (snode->edittree == nullptr)) {
1742  return OPERATOR_CANCELLED;
1743  }
1744 
1746 
1748 
1749  return OPERATOR_FINISHED;
1750 }
1751 
1753 {
1754  /* identifiers */
1755  ot->name = "Toggle Node Options";
1756  ot->description = "Toggle option buttons display for selected nodes";
1757  ot->idname = "NODE_OT_options_toggle";
1758 
1759  /* callbacks */
1762 
1763  /* flags */
1765 }
1766 
1768 {
1769  SpaceNode *snode = CTX_wm_space_node(C);
1770 
1771  /* sanity checking (poll callback checks this already) */
1772  if ((snode == nullptr) || (snode->edittree == nullptr)) {
1773  return OPERATOR_CANCELLED;
1774  }
1775 
1777 
1778  /* Toggle for all selected nodes */
1779  bool hidden = false;
1780  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1781  if (node->flag & SELECT) {
1783  hidden = true;
1784  break;
1785  }
1786  }
1787  }
1788 
1789  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1790  if (node->flag & SELECT) {
1791  node_set_hidden_sockets(snode, node, !hidden);
1792  }
1793  }
1794 
1796 
1798 
1799  return OPERATOR_FINISHED;
1800 }
1801 
1803 {
1804  /* identifiers */
1805  ot->name = "Toggle Hidden Node Sockets";
1806  ot->description = "Toggle unused node socket display";
1807  ot->idname = "NODE_OT_hide_socket_toggle";
1808 
1809  /* callbacks */
1812 
1813  /* flags */
1815 }
1816 
1819 /* -------------------------------------------------------------------- */
1824 {
1825  Main *bmain = CTX_data_main(C);
1826  SpaceNode *snode = CTX_wm_space_node(C);
1827 
1829 
1830  LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
1831  if ((node->flag & SELECT) && !node->typeinfo->no_muting) {
1832  node->flag ^= NODE_MUTED;
1834  }
1835  }
1836 
1837  ED_node_tree_propagate_change(C, bmain, snode->edittree);
1838 
1839  return OPERATOR_FINISHED;
1840 }
1841 
1843 {
1844  /* identifiers */
1845  ot->name = "Toggle Node Mute";
1846  ot->description = "Toggle muting of the nodes";
1847  ot->idname = "NODE_OT_mute_toggle";
1848 
1849  /* callbacks */
1850  ot->exec = node_mute_exec;
1852 
1853  /* flags */
1855 }
1856 
1859 /* -------------------------------------------------------------------- */
1864 {
1865  Main *bmain = CTX_data_main(C);
1866  SpaceNode *snode = CTX_wm_space_node(C);
1867 
1869 
1871  if (node->flag & SELECT) {
1872  nodeRemoveNode(bmain, snode->edittree, node, true);
1873  }
1874  }
1875 
1876  ED_node_tree_propagate_change(C, bmain, snode->edittree);
1877 
1878  return OPERATOR_FINISHED;
1879 }
1880 
1882 {
1883  /* identifiers */
1884  ot->name = "Delete";
1885  ot->description = "Delete selected nodes";
1886  ot->idname = "NODE_OT_delete";
1887 
1888  /* api callbacks */
1891 
1892  /* flags */
1894 }
1895 
1898 /* -------------------------------------------------------------------- */
1903 {
1904  SpaceNode *snode = CTX_wm_space_node(C);
1905 
1906  if (snode && snode->edittree) {
1907  return true;
1908  }
1909 
1910  return false;
1911 }
1912 
1914 {
1915  SpaceNode *snode = CTX_wm_space_node(C);
1916 
1918  if (node->flag & SELECT) {
1919  /* call the update function from the Switch View node */
1920  node->update = NODE_UPDATE_OPERATOR;
1921  }
1922  }
1923 
1925 
1926  return OPERATOR_FINISHED;
1927 }
1928 
1930 {
1931  /* identifiers */
1932  ot->name = "Update Views";
1933  ot->description = "Update views of selected node";
1934  ot->idname = "NODE_OT_switch_view_update";
1935 
1936  /* api callbacks */
1939 
1940  /* flags */
1942 }
1943 
1946 /* -------------------------------------------------------------------- */
1951 {
1952  Main *bmain = CTX_data_main(C);
1953  SpaceNode *snode = CTX_wm_space_node(C);
1954 
1956 
1958  if (node->flag & SELECT) {
1959  nodeInternalRelink(snode->edittree, node);
1960  nodeRemoveNode(bmain, snode->edittree, node, true);
1961  }
1962  }
1963 
1964  ED_node_tree_propagate_change(C, bmain, snode->edittree);
1965 
1966  return OPERATOR_FINISHED;
1967 }
1968 
1970 {
1971  /* identifiers */
1972  ot->name = "Delete with Reconnect";
1973  ot->description = "Delete nodes; will reconnect nodes as if deletion was muted";
1974  ot->idname = "NODE_OT_delete_reconnect";
1975 
1976  /* api callbacks */
1979 
1980  /* flags */
1982 }
1983 
1986 /* -------------------------------------------------------------------- */
1991 {
1993  SpaceNode *snode = CTX_wm_space_node(C);
1994  PointerRNA ptr = CTX_data_pointer_get(C, "node");
1995  bNodeTree *ntree = nullptr;
1996  bNode *node = nullptr;
1997  char file_path[MAX_NAME];
1998 
1999  if (ptr.data) {
2000  node = (bNode *)ptr.data;
2001  ntree = (bNodeTree *)ptr.owner_id;
2002  }
2003  else if (snode && snode->edittree) {
2004  ntree = snode->edittree;
2005  node = nodeGetActive(snode->edittree);
2006  }
2007 
2008  if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
2009  return OPERATOR_CANCELLED;
2010  }
2011 
2012  RNA_string_get(op->ptr, "file_path", file_path);
2014 
2016 
2017  return OPERATOR_FINISHED;
2018 }
2019 
2021 {
2022  /* identifiers */
2023  ot->name = "Add File Node Socket";
2024  ot->description = "Add a new input to a file output node";
2025  ot->idname = "NODE_OT_output_file_add_socket";
2026 
2027  /* callbacks */
2030 
2031  /* flags */
2033 
2035  ot->srna, "file_path", "Image", MAX_NAME, "File Path", "Subpath of the output file");
2036 }
2037 
2040 /* -------------------------------------------------------------------- */
2045 {
2046  SpaceNode *snode = CTX_wm_space_node(C);
2047  PointerRNA ptr = CTX_data_pointer_get(C, "node");
2048  bNodeTree *ntree = nullptr;
2049  bNode *node = nullptr;
2050 
2051  if (ptr.data) {
2052  node = (bNode *)ptr.data;
2053  ntree = (bNodeTree *)ptr.owner_id;
2054  }
2055  else if (snode && snode->edittree) {
2056  ntree = snode->edittree;
2057  node = nodeGetActive(snode->edittree);
2058  }
2059 
2060  if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
2061  return OPERATOR_CANCELLED;
2062  }
2063 
2065  return OPERATOR_CANCELLED;
2066  }
2067 
2069 
2070  return OPERATOR_FINISHED;
2071 }
2072 
2074 {
2075  /* identifiers */
2076  ot->name = "Remove File Node Socket";
2077  ot->description = "Remove active input from a file output node";
2078  ot->idname = "NODE_OT_output_file_remove_active_socket";
2079 
2080  /* callbacks */
2083 
2084  /* flags */
2086 }
2087 
2090 /* -------------------------------------------------------------------- */
2095 {
2096  SpaceNode *snode = CTX_wm_space_node(C);
2097  PointerRNA ptr = CTX_data_pointer_get(C, "node");
2098  bNode *node = nullptr;
2099 
2100  if (ptr.data) {
2101  node = (bNode *)ptr.data;
2102  }
2103  else if (snode && snode->edittree) {
2104  node = nodeGetActive(snode->edittree);
2105  }
2106 
2107  if (!node || node->type != CMP_NODE_OUTPUT_FILE) {
2108  return OPERATOR_CANCELLED;
2109  }
2110 
2111  NodeImageMultiFile *nimf = (NodeImageMultiFile *)node->storage;
2112 
2113  bNodeSocket *sock = (bNodeSocket *)BLI_findlink(&node->inputs, nimf->active_input);
2114  if (!sock) {
2115  return OPERATOR_CANCELLED;
2116  }
2117 
2118  int direction = RNA_enum_get(op->ptr, "direction");
2119 
2120  if (direction == 1) {
2121  bNodeSocket *before = sock->prev;
2122  if (!before) {
2123  return OPERATOR_CANCELLED;
2124  }
2125  BLI_remlink(&node->inputs, sock);
2126  BLI_insertlinkbefore(&node->inputs, before, sock);
2127  nimf->active_input--;
2128  }
2129  else {
2130  bNodeSocket *after = sock->next;
2131  if (!after) {
2132  return OPERATOR_CANCELLED;
2133  }
2134  BLI_remlink(&node->inputs, sock);
2135  BLI_insertlinkafter(&node->inputs, after, sock);
2136  nimf->active_input++;
2137  }
2138 
2140 
2141  return OPERATOR_FINISHED;
2142 }
2143 
2145 {
2146  static const EnumPropertyItem direction_items[] = {
2147  {1, "UP", 0, "Up", ""}, {2, "DOWN", 0, "Down", ""}, {0, nullptr, 0, nullptr, nullptr}};
2148 
2149  /* identifiers */
2150  ot->name = "Move File Node Socket";
2151  ot->description = "Move the active input of a file output node up or down the list";
2152  ot->idname = "NODE_OT_output_file_move_active_socket";
2153 
2154  /* callbacks */
2157 
2158  /* flags */
2160 
2161  RNA_def_enum(ot->srna, "direction", direction_items, 2, "Direction", "");
2162 }
2163 
2166 /* -------------------------------------------------------------------- */
2171 {
2172  SpaceNode &snode = *CTX_wm_space_node(C);
2173  bNodeTree &ntree = *snode.edittree;
2174 
2176  if (!node) {
2177  return OPERATOR_CANCELLED;
2178  }
2179 
2180  LISTBASE_FOREACH (bNode *, node_iter, &ntree.nodes) {
2181  if (node_iter->flag & NODE_SELECT && node_iter != node) {
2182  if (node->flag & NODE_CUSTOM_COLOR) {
2183  node_iter->flag |= NODE_CUSTOM_COLOR;
2184  copy_v3_v3(node_iter->color, node->color);
2185  }
2186  else {
2187  node_iter->flag &= ~NODE_CUSTOM_COLOR;
2188  }
2189  }
2190  }
2191 
2192  node_sort(ntree);
2194 
2195  return OPERATOR_FINISHED;
2196 }
2197 
2199 {
2200  /* identifiers */
2201  ot->name = "Copy Color";
2202  ot->description = "Copy color to all selected nodes";
2203  ot->idname = "NODE_OT_node_copy_color";
2204 
2205  /* api callbacks */
2208 
2209  /* flags */
2211 }
2212 
2215 /* -------------------------------------------------------------------- */
2220 {
2221  SpaceNode *snode = CTX_wm_space_node(C);
2222  bNodeTree *ntree = snode->edittree;
2223 
2225 
2226  /* clear current clipboard */
2229 
2230  Map<const bNode *, bNode *> node_map;
2232 
2234  if (node->flag & SELECT) {
2235  /* No ID refcounting, this node is virtual,
2236  * detached from any actual Blender data currently. */
2237  bNode *new_node = blender::bke::node_copy_with_mapping(nullptr,
2238  *node,
2241  false,
2242  socket_map);
2243  node_map.add_new(node, new_node);
2244  }
2245  }
2246 
2247  for (bNode *new_node : node_map.values()) {
2248  BKE_node_clipboard_add_node(new_node);
2249 
2250  /* Parent pointer must be redirected to new node or detached if parent is not copied. */
2251  if (new_node->parent) {
2252  if (node_map.contains(new_node->parent)) {
2253  new_node->parent = node_map.lookup(new_node->parent);
2254  }
2255  else {
2256  nodeDetachNode(new_node);
2257  }
2258  }
2259  }
2260 
2261  /* Copy links between selected nodes. */
2262  LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
2263  BLI_assert(link->tonode);
2264  BLI_assert(link->fromnode);
2265  if (link->tonode->flag & NODE_SELECT && link->fromnode->flag & NODE_SELECT) {
2266  bNodeLink *newlink = MEM_cnew<bNodeLink>(__func__);
2267  newlink->flag = link->flag;
2268  newlink->tonode = node_map.lookup(link->tonode);
2269  newlink->tosock = socket_map.lookup(link->tosock);
2270  newlink->fromnode = node_map.lookup(link->fromnode);
2271  newlink->fromsock = socket_map.lookup(link->fromsock);
2272 
2273  BKE_node_clipboard_add_link(newlink);
2274  }
2275  }
2276 
2277  return OPERATOR_FINISHED;
2278 }
2279 
2281 {
2282  /* identifiers */
2283  ot->name = "Copy to Clipboard";
2284  ot->description = "Copies selected nodes to the clipboard";
2285  ot->idname = "NODE_OT_clipboard_copy";
2286 
2287  /* api callbacks */
2290 
2291  /* flags */
2293 }
2294 
2297 /* -------------------------------------------------------------------- */
2302 {
2303  SpaceNode *snode = CTX_wm_space_node(C);
2304  bNodeTree *ntree = snode->edittree;
2305 
2306  /* validate pointers in the clipboard */
2307  bool is_clipboard_valid = BKE_node_clipboard_validate();
2308  const ListBase *clipboard_nodes_lb = BKE_node_clipboard_get_nodes();
2309  const ListBase *clipboard_links_lb = BKE_node_clipboard_get_links();
2310 
2311  if (BLI_listbase_is_empty(clipboard_nodes_lb)) {
2312  BKE_report(op->reports, RPT_ERROR, "Clipboard is empty");
2313  return OPERATOR_CANCELLED;
2314  }
2315 
2317  BKE_report(op->reports, RPT_ERROR, "Clipboard nodes are an incompatible type");
2318  return OPERATOR_CANCELLED;
2319  }
2320 
2321  /* only warn */
2322  if (is_clipboard_valid == false) {
2323  BKE_report(op->reports,
2324  RPT_WARNING,
2325  "Some nodes references could not be restored, will be left empty");
2326  }
2327 
2328  /* make sure all clipboard nodes would be valid in the target tree */
2329  bool all_nodes_valid = true;
2330  LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) {
2331  const char *disabled_hint = nullptr;
2332  if (!node->typeinfo->poll_instance ||
2333  !node->typeinfo->poll_instance(node, ntree, &disabled_hint)) {
2334  all_nodes_valid = false;
2335  if (disabled_hint) {
2336  BKE_reportf(op->reports,
2337  RPT_ERROR,
2338  "Cannot add node %s into node tree %s:\n %s",
2339  node->name,
2340  ntree->id.name + 2,
2341  disabled_hint);
2342  }
2343  else {
2344  BKE_reportf(op->reports,
2345  RPT_ERROR,
2346  "Cannot add node %s into node tree %s",
2347  node->name,
2348  ntree->id.name + 2);
2349  }
2350  }
2351  }
2352  if (!all_nodes_valid) {
2353  return OPERATOR_CANCELLED;
2354  }
2355 
2357 
2358  /* deselect old nodes */
2359  node_deselect_all(*snode);
2360 
2361  /* calculate "barycenter" for placing on mouse cursor */
2362  float center[2] = {0.0f, 0.0f};
2363  int num_nodes = 0;
2364  LISTBASE_FOREACH_INDEX (bNode *, node, clipboard_nodes_lb, num_nodes) {
2365  center[0] += BLI_rctf_cent_x(&node->totr);
2366  center[1] += BLI_rctf_cent_y(&node->totr);
2367  }
2368  mul_v2_fl(center, 1.0 / num_nodes);
2369 
2370  Map<const bNode *, bNode *> node_map;
2372 
2373  /* copy nodes from clipboard */
2374  LISTBASE_FOREACH (bNode *, node, clipboard_nodes_lb) {
2376  ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map);
2377  node_map.add_new(node, new_node);
2378  }
2379 
2380  for (bNode *new_node : node_map.values()) {
2381  /* pasted nodes are selected */
2382  nodeSetSelected(new_node, true);
2383 
2384  /* The parent pointer must be redirected to new node. */
2385  if (new_node->parent) {
2386  if (node_map.contains(new_node->parent)) {
2387  new_node->parent = node_map.lookup(new_node->parent);
2388  }
2389  }
2390  }
2391 
2392  LISTBASE_FOREACH (bNodeLink *, link, clipboard_links_lb) {
2394  node_map.lookup(link->fromnode),
2395  socket_map.lookup(link->fromsock),
2396  node_map.lookup(link->tonode),
2397  socket_map.lookup(link->tosock));
2398  }
2399 
2400  Main *bmain = CTX_data_main(C);
2401  ED_node_tree_propagate_change(C, bmain, snode->edittree);
2402  /* Pasting nodes can create arbitrary new relations, because nodes can reference IDs. */
2403  DEG_relations_tag_update(bmain);
2404 
2405  return OPERATOR_FINISHED;
2406 }
2407 
2409 {
2410  /* identifiers */
2411  ot->name = "Paste from Clipboard";
2412  ot->description = "Pastes nodes from the clipboard to the active node tree";
2413  ot->idname = "NODE_OT_clipboard_paste";
2414 
2415  /* api callbacks */
2418 
2419  /* flags */
2421 }
2422 
2425 /* -------------------------------------------------------------------- */
2430 {
2431  LISTBASE_FOREACH (bNodeSocket *, socket, lb) {
2432  if (socket->flag & SELECT) {
2433  return socket;
2434  }
2435  }
2436  return nullptr;
2437 }
2438 
2440 {
2441  SpaceNode *snode = CTX_wm_space_node(C);
2442  bNodeTree *ntree = snode->edittree;
2443 
2444  PointerRNA ntree_ptr;
2445  RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
2446 
2447  const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out");
2448  ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
2449 
2450  const char *default_name = (in_out == SOCK_IN) ? "Input" : "Output";
2451  bNodeSocket *active_sock = ntree_get_active_interface_socket(sockets);
2452 
2453  bNodeSocket *sock;
2454  if (active_sock) {
2455  /* insert a copy of the active socket right after it */
2457  ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
2458  /* XXX this only works for actual sockets, not interface templates! */
2459  // nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);
2460  }
2461  else {
2462  /* XXX TODO: define default socket type for a tree! */
2463  sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
2464  }
2465 
2466  /* Deactivate sockets. */
2467  LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) {
2468  socket_iter->flag &= ~SELECT;
2469  }
2470  /* make the new socket active */
2471  sock->flag |= SELECT;
2472 
2474 
2476 
2477  return OPERATOR_FINISHED;
2478 }
2479 
2481 {
2482  /* identifiers */
2483  ot->name = "Add Node Tree Interface Socket";
2484  ot->description = "Add an input or output socket to the current node tree";
2485  ot->idname = "NODE_OT_tree_socket_add";
2486 
2487  /* api callbacks */
2490 
2491  /* flags */
2493 
2494  RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2495 }
2496 
2499 /* -------------------------------------------------------------------- */
2504 {
2505  SpaceNode *snode = CTX_wm_space_node(C);
2506  bNodeTree *ntree = snode->edittree;
2507  const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out");
2508 
2510  &ntree->outputs);
2511  if (iosock == nullptr) {
2512  return OPERATOR_CANCELLED;
2513  }
2514 
2515  /* preferably next socket becomes active, otherwise try previous socket */
2516  bNodeSocket *active_sock = (iosock->next ? iosock->next : iosock->prev);
2518 
2519  /* set active socket */
2520  if (active_sock) {
2521  active_sock->flag |= SELECT;
2522  }
2523 
2525 
2527 
2528  return OPERATOR_FINISHED;
2529 }
2530 
2532 {
2533  /* identifiers */
2534  ot->name = "Remove Node Tree Interface Socket";
2535  ot->description = "Remove an input or output socket to the current node tree";
2536  ot->idname = "NODE_OT_tree_socket_remove";
2537 
2538  /* api callbacks */
2541 
2542  /* flags */
2544  RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2545 }
2546 
2549 /* -------------------------------------------------------------------- */
2554 {
2555  SpaceNode *snode = CTX_wm_space_node(C);
2556  bNodeTree *ntree = snode->edittree;
2557  const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out");
2558  const bNodeSocketType *socket_type = rna_node_socket_type_from_enum(
2559  RNA_enum_get(op->ptr, "socket_type"));
2560  ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
2561 
2562  Main *main = CTX_data_main(C);
2563 
2565  if (iosock == nullptr) {
2566  return OPERATOR_CANCELLED;
2567  }
2568 
2569  /* The type remains the same, so we don't need to change anything. */
2570  if (iosock->typeinfo == socket_type) {
2571  return OPERATOR_FINISHED;
2572  }
2573 
2574  /* Don't handle subtypes for now. */
2575  nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname);
2576 
2577  /* Need the extra update here because the loop above does not check for valid links in the node
2578  * group we're currently editing. */
2580 
2581  /* Deactivate sockets. */
2582  LISTBASE_FOREACH (bNodeSocket *, socket_iter, sockets) {
2583  socket_iter->flag &= ~SELECT;
2584  }
2585  /* Make the new socket active. */
2586  iosock->flag |= SELECT;
2587 
2589 
2591 
2592  return OPERATOR_FINISHED;
2593 }
2594 
2595 static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type)
2596 {
2597  /* Check if the node tree supports the socket type. */
2598  bNodeTreeType *ntreetype = (bNodeTreeType *)userdata;
2599  if (ntreetype->valid_socket_type && !ntreetype->valid_socket_type(ntreetype, socket_type)) {
2600  return false;
2601  }
2602 
2603  /* Only use basic socket types for this enum. */
2604  if (socket_type->subtype != PROP_NONE) {
2605  return false;
2606  }
2607 
2608  return true;
2609 }
2610 
2612  PointerRNA *UNUSED(ptr),
2613  PropertyRNA *UNUSED(prop),
2614  bool *r_free)
2615 {
2616  if (!C) {
2617  return DummyRNA_NULL_items;
2618  }
2619 
2620  SpaceNode *snode = CTX_wm_space_node(C);
2621  if (!snode || !snode->edittree) {
2622  return DummyRNA_NULL_items;
2623  }
2624 
2626 }
2627 
2629 {
2630  PropertyRNA *prop;
2631 
2632  /* identifiers */
2633  ot->name = "Change Node Tree Interface Socket Type";
2634  ot->description = "Change the type of a socket of the current node tree";
2635  ot->idname = "NODE_OT_tree_socket_change_type";
2636 
2637  /* api callbacks */
2641 
2642  /* flags */
2644 
2645  RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2646  prop = RNA_def_enum(ot->srna, "socket_type", DummyRNA_DEFAULT_items, 0, "Socket Type", "");
2648  ot->prop = prop;
2649 }
2650 
2653 /* -------------------------------------------------------------------- */
2658  {1, "UP", 0, "Up", ""},
2659  {2, "DOWN", 0, "Down", ""},
2660  {0, nullptr, 0, nullptr, nullptr},
2661 };
2662 
2664 {
2665  SpaceNode *snode = CTX_wm_space_node(C);
2666  bNodeTree *ntree = snode->edittree;
2667  int direction = RNA_enum_get(op->ptr, "direction");
2668 
2669  const eNodeSocketInOut in_out = (eNodeSocketInOut)RNA_enum_get(op->ptr, "in_out");
2670  ListBase *sockets = in_out == SOCK_IN ? &ntree->inputs : &ntree->outputs;
2671 
2673 
2674  if (iosock == nullptr) {
2675  return OPERATOR_CANCELLED;
2676  }
2677 
2678  switch (direction) {
2679  case 1: { /* up */
2680  bNodeSocket *before = iosock->prev;
2681  BLI_remlink(sockets, iosock);
2682  if (before) {
2683  BLI_insertlinkbefore(sockets, before, iosock);
2684  }
2685  else {
2686  BLI_addhead(sockets, iosock);
2687  }
2688  break;
2689  }
2690  case 2: { /* down */
2691  bNodeSocket *after = iosock->next;
2692  BLI_remlink(sockets, iosock);
2693  if (after) {
2694  BLI_insertlinkafter(sockets, after, iosock);
2695  }
2696  else {
2697  BLI_addtail(sockets, iosock);
2698  }
2699  break;
2700  }
2701  }
2702 
2705 
2707 
2708  return OPERATOR_FINISHED;
2709 }
2710 
2712 {
2713  /* identifiers */
2714  ot->name = "Move Node Tree Socket";
2715  ot->description = "Move a socket up or down in the current node tree's sockets stack";
2716  ot->idname = "NODE_OT_tree_socket_move";
2717 
2718  /* api callbacks */
2721 
2722  /* flags */
2724 
2725  RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
2726  RNA_def_enum(ot->srna, "in_out", rna_enum_node_socket_in_out_items, SOCK_IN, "Socket Type", "");
2727 }
2728 
2731 /* -------------------------------------------------------------------- */
2736 {
2739  SpaceNode *snode = CTX_wm_space_node(C);
2740 
2741  /* test if we have a render engine that supports shaders scripts */
2742  if (!(type && type->update_script_node)) {
2743  return false;
2744  }
2745 
2746  /* see if we have a shader script node in context */
2747  bNode *node = (bNode *)CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data;
2748 
2749  if (!node && snode && snode->edittree) {
2750  node = nodeGetActive(snode->edittree);
2751  }
2752 
2753  if (node && node->type == SH_NODE_SCRIPT) {
2754  NodeShaderScript *nss = (NodeShaderScript *)node->storage;
2755 
2756  if (node->id || nss->filepath[0]) {
2757  return ED_operator_node_editable(C);
2758  }
2759  }
2760 
2761  /* see if we have a text datablock in context */
2762  Text *text = (Text *)CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2763  if (text) {
2764  return true;
2765  }
2766 
2767  /* we don't check if text datablock is actually in use, too slow for poll */
2768 
2769  return false;
2770 }
2771 
2772 /* recursively check for script nodes in groups using this text and update */
2775  bNodeTree *ntree,
2776  Text *text)
2777 {
2778  bool found = false;
2779 
2780  ntree->done = true;
2781 
2782  /* update each script that is using this text datablock */
2784  if (node->type == NODE_GROUP) {
2785  bNodeTree *ngroup = (bNodeTree *)node->id;
2786  if (ngroup && !ngroup->done) {
2787  found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
2788  }
2789  }
2790  else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
2791  type->update_script_node(engine, ntree, node);
2792  found = true;
2793  }
2794  }
2795 
2796  return found;
2797 }
2798 
2800 {
2801  Main *bmain = CTX_data_main(C);
2803  SpaceNode *snode = CTX_wm_space_node(C);
2804  PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
2805  bool found = false;
2806 
2807  /* setup render engine */
2809  RenderEngine *engine = RE_engine_create(type);
2810  engine->reports = op->reports;
2811 
2812  /* get node */
2813  bNodeTree *ntree_base = nullptr;
2814  bNode *node = nullptr;
2815  if (nodeptr.data) {
2816  ntree_base = (bNodeTree *)nodeptr.owner_id;
2817  node = (bNode *)nodeptr.data;
2818  }
2819  else if (snode && snode->edittree) {
2820  ntree_base = snode->edittree;
2821  node = nodeGetActive(snode->edittree);
2822  }
2823 
2824  if (node) {
2825  /* update single node */
2826  type->update_script_node(engine, ntree_base, node);
2827 
2828  found = true;
2829  }
2830  else {
2831  /* update all nodes using text datablock */
2832  Text *text = (Text *)CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
2833 
2834  if (text) {
2835  /* clear flags for recursion check */
2836  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
2837  if (ntree->type == NTREE_SHADER) {
2838  ntree->done = false;
2839  }
2840  }
2842 
2843  FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
2844  if (ntree->type == NTREE_SHADER) {
2845  if (!ntree->done) {
2846  found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
2847  }
2848  }
2849  }
2851 
2852  if (!found) {
2853  BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
2854  }
2855  }
2856  }
2857 
2858  RE_engine_free(engine);
2859 
2860  return (found) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
2861 }
2862 
2864 {
2865  /* identifiers */
2866  ot->name = "Script Node Update";
2867  ot->description = "Update shader script node with new sockets and options from the script";
2868  ot->idname = "NODE_OT_shader_script_update";
2869 
2870  /* api callbacks */
2873 
2874  /* flags */
2876 }
2877 
2880 /* -------------------------------------------------------------------- */
2885  ARegion *region,
2886  int x,
2887  int y,
2888  int backdrop_width,
2889  int backdrop_height,
2890  float *fx,
2891  float *fy)
2892 {
2893  float bufx = backdrop_width * snode->zoom;
2894  float bufy = backdrop_height * snode->zoom;
2895 
2896  *fx = (bufx > 0.0f ? ((float)x - 0.5f * region->winx - snode->xof) / bufx + 0.5f : 0.0f);
2897  *fy = (bufy > 0.0f ? ((float)y - 0.5f * region->winy - snode->yof) / bufy + 0.5f : 0.0f);
2898 }
2899 
2901 {
2902  Main *bmain = CTX_data_main(C);
2903  void *lock;
2904 
2906 
2907  Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
2908  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock);
2909 
2910  if (ibuf) {
2911  ARegion *region = CTX_wm_region(C);
2912  SpaceNode *snode = CTX_wm_space_node(C);
2913  bNodeTree *btree = snode->nodetree;
2914  rcti rect;
2915  rctf rectf;
2916 
2917  /* get border from operator */
2919 
2920  /* convert border to unified space within backdrop image */
2922  snode, region, rect.xmin, rect.ymin, ibuf->x, ibuf->y, &rectf.xmin, &rectf.ymin);
2923 
2925  snode, region, rect.xmax, rect.ymax, ibuf->x, ibuf->y, &rectf.xmax, &rectf.ymax);
2926 
2927  /* clamp coordinates */
2928  rectf.xmin = max_ff(rectf.xmin, 0.0f);
2929  rectf.ymin = max_ff(rectf.ymin, 0.0f);
2930  rectf.xmax = min_ff(rectf.xmax, 1.0f);
2931  rectf.ymax = min_ff(rectf.ymax, 1.0f);
2932 
2933  if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) {
2934  btree->viewer_border = rectf;
2935 
2936  if (rectf.xmin == 0.0f && rectf.ymin == 0.0f && rectf.xmax == 1.0f && rectf.ymax == 1.0f) {
2937  btree->flag &= ~NTREE_VIEWER_BORDER;
2938  }
2939  else {
2940  btree->flag |= NTREE_VIEWER_BORDER;
2941  }
2942 
2943  ED_node_tree_propagate_change(C, bmain, btree);
2945  }
2946  else {
2947  btree->flag &= ~NTREE_VIEWER_BORDER;
2948  }
2949  }
2950 
2951  BKE_image_release_ibuf(ima, ibuf, lock);
2952 
2953  return OPERATOR_FINISHED;
2954 }
2955 
2957 {
2958  /* identifiers */
2959  ot->name = "Viewer Region";
2960  ot->description = "Set the boundaries for viewer operations";
2961  ot->idname = "NODE_OT_viewer_border";
2962 
2963  /* api callbacks */
2969 
2970  /* flags */
2972 
2973  /* properties */
2975 }
2976 
2978 {
2979  SpaceNode *snode = CTX_wm_space_node(C);
2980  bNodeTree *btree = snode->nodetree;
2981 
2982  btree->flag &= ~NTREE_VIEWER_BORDER;
2985 
2986  return OPERATOR_FINISHED;
2987 }
2988 
2990 {
2991  /* identifiers */
2992  ot->name = "Clear Viewer Region";
2993  ot->description = "Clear the boundaries for viewer operations";
2994  ot->idname = "NODE_OT_clear_viewer_border";
2995 
2996  /* api callbacks */
2999 
3000  /* flags */
3002 }
3003 
3006 /* -------------------------------------------------------------------- */
3011 {
3012  SpaceNode *snode = CTX_wm_space_node(C);
3013  PointerRNA ptr = CTX_data_pointer_get(C, "node");
3014  bNodeTree *ntree = nullptr;
3015  bNode *node = nullptr;
3016 
3017  if (ptr.data) {
3018  node = (bNode *)ptr.data;
3019  ntree = (bNodeTree *)ptr.owner_id;
3020  }
3021  else if (snode && snode->edittree) {
3022  ntree = snode->edittree;
3023  node = nodeGetActive(snode->edittree);
3024  }
3025 
3026  if (!node || node->type != CMP_NODE_CRYPTOMATTE_LEGACY) {
3027  return OPERATOR_CANCELLED;
3028  }
3029 
3031 
3033 
3034  return OPERATOR_FINISHED;
3035 }
3036 
3038 {
3039  /* identifiers */
3040  ot->name = "Add Cryptomatte Socket";
3041  ot->description = "Add a new input layer to a Cryptomatte node";
3042  ot->idname = "NODE_OT_cryptomatte_layer_add";
3043 
3044  /* callbacks */
3047 
3048  /* flags */
3050 }
3051 
3054 /* -------------------------------------------------------------------- */
3059 {
3060  SpaceNode *snode = CTX_wm_space_node(C);
3061  PointerRNA ptr = CTX_data_pointer_get(C, "node");
3062  bNodeTree *ntree = nullptr;
3063  bNode *node = nullptr;
3064 
3065  if (ptr.data) {
3066  node = (bNode *)ptr.data;
3067  ntree = (bNodeTree *)ptr.owner_id;
3068  }
3069  else if (snode && snode->edittree) {
3070  ntree = snode->edittree;
3071  node = nodeGetActive(snode->edittree);
3072  }
3073 
3074  if (!node || node->type != CMP_NODE_CRYPTOMATTE_LEGACY) {
3075  return OPERATOR_CANCELLED;
3076  }
3077 
3079  return OPERATOR_CANCELLED;
3080  }
3081 
3083 
3084  return OPERATOR_FINISHED;
3085 }
3086 
3088 {
3089  /* identifiers */
3090  ot->name = "Remove Cryptomatte Socket";
3091  ot->description = "Remove layer from a Cryptomatte node";
3092  ot->idname = "NODE_OT_cryptomatte_layer_remove";
3093 
3094  /* callbacks */
3097 
3098  /* flags */
3100 }
3101 
3104 } // namespace blender::ed::space_node
typedef float(TangentPoint)[2]
@ BKE_CB_EVT_COMPOSITE_PRE
@ BKE_CB_EVT_COMPOSITE_CANCEL
@ BKE_CB_EVT_COMPOSITE_POST
void BKE_callback_exec_id(struct Main *bmain, struct ID *id, eCbEvent evt)
Definition: callbacks.c:46
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
Definition: context.c:462
struct SpaceNode * CTX_wm_space_node(const bContext *C)
Definition: context.c:878
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
@ G_DEBUG
Definition: BKE_global.h:174
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
void BKE_image_backup_render(struct Scene *scene, struct Image *ima, bool free_current_slot)
struct Image * BKE_image_ensure_viewer(struct Main *bmain, int type, const char *name)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:126
@ LIB_ID_CREATE_NO_MAIN
Definition: BKE_lib_id.h:122
@ LIB_ID_COPY_DEFAULT
Definition: BKE_lib_id.h:181
General operations, lookup, etc. for materials.
struct Material * BKE_material_default_surface(void)
Definition: material.c:2051
struct Material * BKE_material_default_volume(void)
Definition: material.c:2056
void BKE_node_clipboard_init(const struct bNodeTree *ntree)
Definition: node.cc:3773
const struct ListBase * BKE_node_clipboard_get_links(void)
Definition: node.cc:3878
#define CMP_NODE_COMPOSITE
Definition: BKE_node.h:1217
void BKE_node_clipboard_add_node(struct bNode *node)
Definition: node.cc:3838
#define CMP_NODE_SPLITVIEWER
Definition: BKE_node.h:1235
bool nodeLinkIsHidden(const struct bNodeLink *link)
#define CMP_NODE_VIEWER
Definition: BKE_node.h:1196
void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:2490
#define SH_NODE_EMISSION
Definition: BKE_node.h:1115
#define CMP_NODE_CRYPTOMATTE
Definition: BKE_node.h:1292
struct bNodeTreeType * ntreeTypeFind(const char *idname)
Definition: node.cc:1280
void nodeModifySocketType(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, const char *idname)
#define GEO_NODE_VIEWER
Definition: BKE_node.h:1413
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup)
const struct ListBase * BKE_node_clipboard_get_nodes(void)
Definition: node.cc:3873
void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock)
Definition: node.cc:3415
void nodeAttachNode(struct bNode *node, struct bNode *parent)
Definition: node.cc:2594
struct bNode * nodeFindNodebyName(struct bNodeTree *ntree, const char *name)
Definition: node.cc:1992
struct bNode * nodeGetActive(struct bNodeTree *ntree)
Definition: node.cc:3601
int nodeSocketIsHidden(const struct bNodeSocket *sock)
void nodeRemoveNode(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node, bool do_id_user)
Definition: node.cc:3011
int BKE_node_clipboard_get_type(void)
Definition: node.cc:3883
void BKE_node_clipboard_add_link(struct bNodeLink *link)
Definition: node.cc:3868
#define TEX_NODE_CHECKER
Definition: BKE_node.h:1348
#define CMP_NODE_CRYPTOMATTE_LEGACY
Definition: BKE_node.h:1289
#define SH_NODE_OUTPUT_MATERIAL
Definition: BKE_node.h:1101
#define CMP_NODE_OUTPUT_FILE
Definition: BKE_node.h:1218
#define FOREACH_NODETREE_END
Definition: BKE_node.h:1058
struct bNodeLink * nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock)
Definition: node.cc:2296
#define SH_NODE_BACKGROUND
Definition: BKE_node.h:1107
struct bNodeSocket * nodeFindSocket(const struct bNode *node, eNodeSocketInOut in_out, const char *identifier)
struct bNodeTree * ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree)
void ntreeLocalMerge(struct Main *bmain, struct bNodeTree *localtree, struct bNodeTree *ntree)
Definition: node.cc:3286
void nodeSetSelected(struct bNode *node, bool select)
Definition: node.cc:3615
#define MAX_SOCKET
Definition: BKE_node.h:30
#define TEX_NODE_OUTPUT
Definition: BKE_node.h:1347
#define FOREACH_NODETREE_BEGIN(bmain, _nodetree, _id)
Definition: BKE_node.h:1048
#define CMP_CRYPTOMATTE_SRC_RENDER
Definition: BKE_node.h:1331
struct bNodeTree * ntreeAddTree(struct Main *bmain, const char *name, const char *idname)
Definition: node.cc:2674
#define NODE_FRAME
Definition: BKE_node.h:985
struct bNodeSocket * ntreeAddSocketInterface(struct bNodeTree *ntree, eNodeSocketInOut in_out, const char *idname, const char *name)
Definition: node.cc:3349
struct bNode * nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type)
Definition: node.cc:2151
#define CMP_NODE_R_LAYERS
Definition: BKE_node.h:1216
bool BKE_node_clipboard_validate(void)
Definition: node.cc:3795
int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock)
void BKE_node_clipboard_clear(void)
Definition: node.cc:3778
struct bNodeSocket * ntreeInsertSocketInterface(struct bNodeTree *ntree, eNodeSocketInOut in_out, const char *idname, struct bNodeSocket *next_sock, const char *name)
Definition: node.cc:3365
void nodeDetachNode(struct bNode *node)
Definition: node.cc:2607
#define SH_NODE_OUTPUT_LIGHT
Definition: BKE_node.h:1103
void nodeSetActive(struct bNodeTree *ntree, struct bNode *node)
Definition: node.cc:3644
#define SH_NODE_OUTPUT_LINESTYLE
Definition: BKE_node.h:1161
void BKE_ntree_update_tag_interface(struct bNodeTree *ntree)
void BKE_ntree_update_main_tree(struct Main *bmain, struct bNodeTree *ntree, struct NodeTreeUpdateExtraParams *params)
void BKE_ntree_update_tag_active_output_changed(struct bNodeTree *ntree)
void BKE_ntree_update_tag_node_mute(struct bNodeTree *ntree, struct bNode *node)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv)
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:348
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:340
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct)
Definition: BLI_rect.h:181
BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct)
Definition: BLI_rect.h:177
float BLI_rctf_length_x(const rctf *rect, float x)
Definition: rct.c:170
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:407
bool BLI_rctf_isect_pt(const struct rctf *rect, float x, float y)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
bool BLI_rctf_inside_rctf(const rctf *rct_a, const rctf *rct_b)
Definition: rct.c:192
void BLI_rctf_init_pt_radius(struct rctf *rect, const float xy[2], float size)
Definition: rct.c:461
float BLI_rctf_length_y(const rctf *rect, float y)
Definition: rct.c:181
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
void DEG_evaluate_on_refresh(Depsgraph *graph)
Depsgraph * DEG_graph_new(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, eEvaluationMode mode)
Definition: depsgraph.cc:267
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
void DEG_graph_free(Depsgraph *graph)
Definition: depsgraph.cc:295
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_graph_build_for_compositor_preview(struct Depsgraph *graph, struct bNodeTree *nodetree)
void DEG_relations_tag_update(struct Main *bmain)
struct ID * DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_NTREE_OUTPUT
Definition: DNA_ID.h:871
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_LA
Definition: DNA_ID_enums.h:55
@ ID_WO
Definition: DNA_ID_enums.h:59
@ ID_MA
Definition: DNA_ID_enums.h:51
#define MAX_NAME
Definition: DNA_defs.h:48
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
#define NODE_OPTIONS
#define NODE_CUSTOM_COLOR
#define NTREE_TEXTURE
#define NODE_TEST
#define NODE_UPDATE_OPERATOR
#define NODE_DO_OUTPUT
#define NTREE_GEOMETRY
#define NODE_MUTED
#define NTREE_COMPOSIT
#define NODE_ACTIVE_TEXTURE
#define NTREE_VIEWER_BORDER
#define NODE_DO_OUTPUT_RECALC
#define NODE_HIDDEN
eNodeSocketInOut
@ SOCK_OUT
@ SOCK_IN
#define NTREE_QUALITY_HIGH
#define NODE_PREVIEW
@ SOCK_MULTI_INPUT
@ SOCK_HIDDEN
#define NODE_SELECT
#define NTREE_SHADER
#define NODE_ACTIVE
@ OB_VOLUME
#define R_MULTIVIEW
#define R_NO_FRAME_UPDATE
@ SNODE_PIN
@ SNODE_BACKDRAW
@ SPACE_NODE
@ SPACE_IMAGE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_space_image_set(struct Main *bmain, struct SpaceImage *sima, struct Image *ima, bool automatic)
Definition: image_edit.c:45
void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from)
Definition: space_node.cc:44
void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain)
bool ED_operator_node_active(struct bContext *C)
Definition: screen_ops.c:307
bool ED_operator_node_editable(struct bContext *C)
Definition: screen_ops.c:318
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
void ED_spreadsheet_context_paths_set_geometry_node(struct Main *bmain, struct SpaceNode *snode, struct bNode *node)
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void GPU_material_free(struct ListBase *gpumaterial)
Definition: gpu_material.c:171
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
struct bNodeTreeType * ntreeType_Shader
NODE_GROUP_OUTPUT
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces SH_NODE_SCRIPT
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of which functions by specifying the so the result may not be physically accurate SH_NODE_OUTPUT_WORLD
NODE_GROUP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
struct bNodeTreeType * ntreeType_Texture
struct bNodeSocketType * rna_node_socket_type_from_enum(int value)
const EnumPropertyItem * rna_node_socket_type_itemf(void *data, bool(*poll)(void *data, struct bNodeSocketType *), bool *r_free)
@ PROP_NONE
Definition: RNA_types.h:126
#define C
Definition: RandGen.cpp:25
#define UI_DPI_FAC
Definition: UI_interface.h:305
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
@ WM_JOB_EXCL_RENDER
Definition: WM_api.h:1338
@ WM_JOB_PROGRESS
Definition: WM_api.h:1339
@ WM_JOB_TYPE_COMPOSITE
Definition: WM_api.h:1348
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
#define NC_WORLD
Definition: WM_types.h:337
#define ND_SHADING
Definition: WM_types.h:425
#define ND_WORLD
Definition: WM_types.h:401
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_NODE
Definition: WM_types.h:344
#define ND_DISPLAY
Definition: WM_types.h:439
#define ND_COMPO_RESULT
Definition: WM_types.h:395
#define NC_SCENE
Definition: WM_types.h:328
#define ND_NODES
Definition: WM_types.h:384
#define ND_MODIFIER
Definition: WM_types.h:411
#define NA_EDITED
Definition: WM_types.h:523
#define NC_MATERIAL
Definition: WM_types.h:330
#define NC_LAMP
Definition: WM_types.h:332
#define NC_IMAGE
Definition: WM_types.h:334
#define NC_TEXTURE
Definition: WM_types.h:331
#define ND_LIGHTING
Definition: WM_types.h:431
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
#define NC_OBJECT
Definition: WM_types.h:329
volatile int lock
int main(int argc, char *argv[])
unsigned int U
Definition: btGjkEpa3.h:78
short type
ValueIterator values() const
Definition: BLI_map.hh:840
const Value & lookup(const Key &key) const
Definition: BLI_map.hh:485
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:220
bool contains(const Key &key) const
Definition: BLI_map.hh:308
#define SELECT
OperationNode * node
StackEntry * from
Scene scene
World world
void * user_data
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
bNodeTree * ntree
RenderEngine * RE_engine_create(RenderEngineType *type)
Definition: engine.c:136
RenderEngineType * RE_engines_find(const char *idname)
Definition: engine.c:98
void RE_engine_free(RenderEngine *engine)
Definition: engine.c:164
#define str(s)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define GS(x)
Definition: iris.c:225
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define G(x, y, z)
bNode * node_copy_with_mapping(bNodeTree *dst_tree, const bNode &node_src, const int flag, const bool unique_name, Map< const bNodeSocket *, bNodeSocket * > &socket_map)
Definition: node.cc:2198
static void area(int d1, int d2, int e1, int e2, float weights[2])
void NODE_OT_delete(wmOperatorType *ot)
Definition: node_edit.cc:1881
static int viewer_border_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2900
void NODE_OT_cryptomatte_layer_add(wmOperatorType *ot)
Definition: node_edit.cc:3037
static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1703
static void send_notifiers_after_tree_change(ID *id, bNodeTree *ntree)
Definition: node_edit.cc:401
float node_socket_calculate_height(const bNodeSocket &socket)
Definition: node_edit.cc:95
void NODE_OT_read_viewlayers(wmOperatorType *ot)
Definition: node_edit.cc:1550
void node_sort(bNodeTree &ntree)
Definition: node_draw.cc:215
static void node_duplicate_reparent_recursive(const Map< const bNode *, bNode * > &node_map, bNode *node)
Definition: node_edit.cc:1331
void NODE_OT_clipboard_copy(wmOperatorType *ot)
Definition: node_edit.cc:2280
int node_get_resize_cursor(NodeResizeDirection directions)
Definition: node_draw.cc:2508
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
Definition: node_edit.cc:1623
void NODE_OT_tree_socket_add(wmOperatorType *ot)
Definition: node_edit.cc:2480
static int node_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:2170
static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:2219
static bool node_shader_script_update_poll(bContext *C)
Definition: node_edit.cc:2735
static void node_resize_exit(bContext *C, wmOperator *op, bool cancel)
Definition: node_edit.cc:986
static void node_resize_cancel(bContext *C, wmOperator *op)
Definition: node_edit.cc:1137
static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2553
static void compo_redrawjob(void *cjv)
Definition: node_edit.cc:189
void NODE_OT_node_copy_color(wmOperatorType *ot)
Definition: node_edit.cc:2198
bool composite_node_editable(bContext *C)
Definition: node_edit.cc:390
void NODE_OT_viewer_border(wmOperatorType *ot)
Definition: node_edit.cc:2956
void NODE_OT_tree_socket_move(wmOperatorType *ot)
Definition: node_edit.cc:2711
static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1767
static int node_duplicate_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:1354
static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1863
void NODE_OT_tree_socket_remove(wmOperatorType *ot)
Definition: node_edit.cc:2531
static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: node_edit.cc:1113
static int ntree_socket_move_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2663
float2 node_link_calculate_multi_input_position(const float2 &socket_position, const int index, const int total_inputs)
Definition: node_edit.cc:104
void NODE_OT_resize(wmOperatorType *ot)
Definition: node_edit.cc:1142
void NODE_OT_clipboard_paste(wmOperatorType *ot)
Definition: node_edit.cc:2408
void NODE_OT_render_changed(wmOperatorType *ot)
Definition: node_edit.cc:1603
static int ntree_socket_add_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2439
static bool socket_change_poll_type(void *userdata, bNodeSocketType *socket_type)
Definition: node_edit.cc:2595
static void compo_freejob(void *cjv)
Definition: node_edit.cc:196
static int node_switch_view_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1913
void NODE_OT_delete_reconnect(wmOperatorType *ot)
Definition: node_edit.cc:1969
void NODE_OT_shader_script_update(wmOperatorType *ot)
Definition: node_edit.cc:2863
void node_select_all(ListBase *lb, int action)
Definition: node_edit.cc:1488
static bool node_switch_view_poll(bContext *C)
Definition: node_edit.cc:1902
void node_deselect_all(SpaceNode &snode)
Definition: node_select.cc:250
void NODE_OT_hide_socket_toggle(wmOperatorType *ot)
Definition: node_edit.cc:1802
static bool node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
Definition: node_edit.cc:2773
static bool node_select_check(const ListBase *lb)
Definition: node_edit.cc:1477
void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
Definition: node_edit.cc:1180
static int clear_viewer_border_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:2977
float node_link_dim_factor(const View2D &v2d, const bNodeLink &link)
Definition: node_edit.cc:1301
static void compo_canceljob(void *cjv)
Definition: node_edit.cc:298
static int compo_breakjob(void *cjv)
Definition: node_edit.cc:168
void NODE_OT_output_file_remove_active_socket(wmOperatorType *ot)
Definition: node_edit.cc:2073
static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2301
static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2094
NodeResizeDirection node_get_resize_direction(const bNode *node, const int x, const int y)
Definition: drawnode.cc:222
static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *region, int x, int y, int backdrop_width, int backdrop_height, float *fx, float *fy)
Definition: node_edit.cc:2884
bool node_link_is_hidden_or_dimmed(const View2D &v2d, const bNodeLink &link)
Definition: node_edit.cc:1320
static void compo_updatejob(void *UNUSED(cjv))
Definition: node_edit.cc:236
static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: node_edit.cc:1008
static void compo_progressjob(void *cjv, float progress)
Definition: node_edit.cc:241
static int compo_get_recalc_flags(const bContext *C)
Definition: node_edit.cc:135
bool node_find_indicated_socket(SpaceNode &snode, bNode **nodep, bNodeSocket **sockp, const float2 &cursor, const eNodeSocketInOut in_out)
Definition: node_edit.cc:1226
static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1736
void NODE_OT_preview_toggle(wmOperatorType *ot)
Definition: node_edit.cc:1721
void NODE_OT_clear_viewer_border(wmOperatorType *ot)
Definition: node_edit.cc:2989
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2799
static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags)
Definition: node_edit.cc:114
static void node_resize_init(bContext *C, wmOperator *op, const float cursor[2], const bNode *node, NodeResizeDirection dir)
Definition: node_edit.cc:962
static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:3010
static const EnumPropertyItem move_direction_items[]
Definition: node_edit.cc:2657
static int ntree_socket_remove_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:2503
static bool socket_is_occluded(const bNodeSocket &sock, const bNode &node_the_socket_belongs_to, const SpaceNode &snode)
Definition: node_edit.cc:928
static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1672
static const EnumPropertyItem * socket_change_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: node_edit.cc:2611
void snode_set_context(const bContext &C)
Definition: node_edit.cc:618
void NODE_OT_duplicate(wmOperatorType *ot)
Definition: node_edit.cc:1459
bool node_has_hidden_sockets(bNode *node)
Definition: node_edit.cc:1165
void NODE_OT_output_file_add_socket(wmOperatorType *ot)
Definition: node_edit.cc:2020
void NODE_OT_options_toggle(wmOperatorType *ot)
Definition: node_edit.cc:1752
static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:3058
static bNodeSocket * ntree_get_active_interface_socket(ListBase *lb)
Definition: node_edit.cc:2429
static void compo_startjob(void *cjv, short *stop, short *do_update, float *progress)
Definition: node_edit.cc:249
static void compo_statsdrawjob(void *cjv, const char *UNUSED(str))
Definition: node_edit.cc:181
bool composite_node_active(bContext *C)
Definition: node_edit.cc:379
static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
Definition: node_edit.cc:1990
void NODE_OT_switch_view_update(wmOperatorType *ot)
Definition: node_edit.cc:1929
static void compo_initjob(void *cjv)
Definition: node_edit.cc:211
static void compo_completejob(void *cjv)
Definition: node_edit.cc:306
int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1565
static int node_delete_reconnect_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1950
static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSocket &socket)
Definition: node_edit.cc:1206
void NODE_OT_hide_toggle(wmOperatorType *ot)
Definition: node_edit.cc:1688
static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:2044
void NODE_OT_cryptomatte_layer_remove(wmOperatorType *ot)
Definition: node_edit.cc:3087
void NODE_OT_tree_socket_change_type(wmOperatorType *ot)
Definition: node_edit.cc:2628
void NODE_OT_output_file_move_active_socket(wmOperatorType *ot)
Definition: node_edit.cc:2144
void NODE_OT_mute_toggle(wmOperatorType *ot)
Definition: node_edit.cc:1842
static int node_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1517
static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
Definition: node_edit.cc:1823
T clamp(const T &a, const T &min, const T &max)
vec_base< float, 2 > float2
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
int ntreeCompositCryptomatteRemoveSocket(bNodeTree *ntree, bNode *node)
bNodeSocket * ntreeCompositCryptomatteAddSocket(bNodeTree *ntree, bNode *node)
int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node)
bNodeSocket * ntreeCompositOutputFileAddSocket(bNodeTree *ntree, bNode *node, const char *name, const ImageFormatData *im_format)
void ntreeCompositTagRender(Scene *scene)
bNodeTreeType * ntreeType_Composite
void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int rendering, int do_preview, const char *view_name)
bool ED_node_is_compositor(struct SpaceNode *snode)
Definition: node_edit.cc:466
void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
Definition: node_edit.cc:831
void ED_node_texture_default(const bContext *C, Tex *tex)
Definition: node_edit.cc:585
bool ED_node_is_texture(struct SpaceNode *snode)
Definition: node_edit.cc:476
bool ED_node_is_geometry(struct SpaceNode *snode)
Definition: node_edit.cc:481
void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
Definition: node_edit.cc:456
void ED_node_set_active(Main *bmain, SpaceNode *snode, bNodeTree *ntree, bNode *node, bool *r_active_texture_changed)
Definition: node_edit.cc:659
bool ED_node_is_shader(struct SpaceNode *snode)
Definition: node_edit.cc:471
void ED_node_composite_job(const bContext *C, struct bNodeTree *nodetree, Scene *scene_owner)
Definition: node_edit.cc:322
void ED_node_composit_default(const bContext *C, struct Scene *sce)
Definition: node_edit.cc:552
void ED_node_shader_default(const bContext *C, ID *id)
Definition: node_edit.cc:486
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *root_ntree)
Definition: node_edit.cc:435
bNodeTreeType * ntreeType_Geometry
#define NODE_MULTI_INPUT_LINK_GAP
Definition: node_intern.hh:121
#define NODE_SOCKSIZE
Definition: node_intern.hh:118
#define NODE_SOCKSIZE_DRAW_MULIPLIER
Definition: node_intern.hh:119
bool RE_ReadRenderResult(Scene *scene, Scene *scenode)
Definition: pipeline.c:2447
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
const EnumPropertyItem rna_enum_node_socket_in_out_items[]
Definition: rna_nodetree.c:54
const EnumPropertyItem DummyRNA_DEFAULT_items[]
Definition: rna_rna.c:31
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
#define min(a, b)
Definition: sort.c:35
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
char name[66]
Definition: DNA_ID.h:378
struct bNodeTree * nodetree
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase scenes
Definition: BKE_main.h:168
ListBase wm
Definition: BKE_main.h:197
ListBase materials
Definition: BKE_main.h:174
ListBase worlds
Definition: BKE_main.h:182
struct bNodeTree * nodetree
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
char engine[32]
struct ImageFormatData im_format
ListBase views
struct ReportList * reports
Definition: RE_engine.h:141
struct bNodeTree * nodetree
struct RenderData r
ListBase view_layers
char use_nodes
struct Image * image
char tree_idname[64]
struct ID * from
ListBase treepath
struct bNodeTree * edittree
struct ID * id
struct bNodeTree * nodetree
struct bNodeTree * nodetree
char name[64]
struct bNodeTree * nodetree
float horr
Defines a socket type.
Definition: BKE_node.h:143
char idname[64]
Definition: BKE_node.h:145
char name[64]
struct bNodeLink * link
struct bNodeSocket * next
struct bNodeSocket * prev
void * default_value
struct bNodeSocketType * typeinfo
short total_inputs
char idname[64]
bool(* poll)(const struct bContext *C, struct bNodeTreeType *ntreetype)
Definition: BKE_node.h:387
char idname[64]
Definition: BKE_node.h:375
void(* get_from_context)(const struct bContext *C, struct bNodeTreeType *ntreetype, struct bNodeTree **r_ntree, struct ID **r_id, struct ID **r_from)
Definition: BKE_node.h:389
bool(* valid_socket_type)(struct bNodeTreeType *ntreetype, struct bNodeSocketType *socket_type)
Definition: BKE_node.h:407
void(* progress)(void *, float progress)
char idname[64]
short render_quality
int(* test_break)(void *)
void(* update_draw)(void *)
struct bNodeTreeType * typeinfo
short edit_quality
void(* stats_draw)(void *, const char *str)
ListBase nodes
ListBase inputs
ListBase links
rctf viewer_border
ListBase outputs
float locy
struct bNode * parent
float locx
ListBase outputs
ListBase areabase
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
Definition: wm_jobs.c:57
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
float max
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:191
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:200
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ RIGHTMOUSE
@ MOUSEMOVE
@ LEFTMOUSE
@ MIDDLEMOUSE
@ EVT_ESCKEY
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:437
void WM_jobs_callbacks_ex(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *), void(*completed)(void *), void(*canceled)(void *))
Definition: wm_jobs.c:360
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:323
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:339
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:184
void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
void WM_operator_properties_gesture_box(wmOperatorType *ot)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
Definition: wm_operators.c:667
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783
bScreen * WM_window_get_active_screen(const wmWindow *win)
Definition: wm_window.c:2300