From cbca71a7cff394b0c5d670f87f2b480f526ba6dd Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 12 Nov 2021 12:12:27 -0600 Subject: Cleanup: Move remaning node editor files to C++ Differential Revision: https://developer.blender.org/D13200 --- source/blender/editors/space_node/CMakeLists.txt | 8 +- source/blender/editors/space_node/drawnode.cc | 2 +- source/blender/editors/space_node/node_add.cc | 2 +- .../editors/space_node/node_context_path.cc | 2 +- source/blender/editors/space_node/node_draw.cc | 2 +- source/blender/editors/space_node/node_edit.cc | 2 +- .../space_node/node_geometry_attribute_search.cc | 2 +- source/blender/editors/space_node/node_gizmo.c | 645 ------------ source/blender/editors/space_node/node_gizmo.cc | 634 ++++++++++++ source/blender/editors/space_node/node_group.cc | 2 +- source/blender/editors/space_node/node_intern.h | 355 ------- source/blender/editors/space_node/node_intern.hh | 347 +++++++ source/blender/editors/space_node/node_ops.c | 214 ---- source/blender/editors/space_node/node_ops.cc | 214 ++++ .../editors/space_node/node_relationships.cc | 2 +- source/blender/editors/space_node/node_select.cc | 2 +- .../blender/editors/space_node/node_templates.cc | 2 +- source/blender/editors/space_node/node_toolbar.cc | 2 +- source/blender/editors/space_node/node_view.cc | 2 +- source/blender/editors/space_node/space_node.c | 1088 -------------------- source/blender/editors/space_node/space_node.cc | 1081 +++++++++++++++++++ 21 files changed, 2292 insertions(+), 2318 deletions(-) delete mode 100644 source/blender/editors/space_node/node_gizmo.c create mode 100644 source/blender/editors/space_node/node_gizmo.cc delete mode 100644 source/blender/editors/space_node/node_intern.h create mode 100644 source/blender/editors/space_node/node_intern.hh delete mode 100644 source/blender/editors/space_node/node_ops.c create mode 100644 source/blender/editors/space_node/node_ops.cc delete mode 100644 source/blender/editors/space_node/space_node.c create mode 100644 source/blender/editors/space_node/space_node.cc (limited to 'source/blender/editors') diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index 600309c2c86..e88d61fe880 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -44,17 +44,17 @@ set(SRC node_draw.cc node_edit.cc node_geometry_attribute_search.cc - node_gizmo.c + node_gizmo.cc node_group.cc - node_ops.c + node_ops.cc node_relationships.cc node_select.cc node_templates.cc node_toolbar.cc node_view.cc - space_node.c + space_node.cc - node_intern.h + node_intern.hh ) set(LIB diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index d903e9ee984..57c0f4b0ad4 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -77,7 +77,7 @@ #include "NOD_node_declaration.hh" #include "NOD_shader.h" #include "NOD_texture.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ /* Default flags for uiItemR(). Name is kept short since this is used a lot in this file. */ #define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME diff --git a/source/blender/editors/space_node/node_add.cc b/source/blender/editors/space_node/node_add.cc index cb66d0dbd2b..ea78ff36ab6 100644 --- a/source/blender/editors/space_node/node_add.cc +++ b/source/blender/editors/space_node/node_add.cc @@ -56,7 +56,7 @@ #include "UI_view2d.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ /* -------------------------------------------------------------------- */ /** \name Utilities diff --git a/source/blender/editors/space_node/node_context_path.cc b/source/blender/editors/space_node/node_context_path.cc index a0ff7f3ce25..2f3855fd654 100644 --- a/source/blender/editors/space_node/node_context_path.cc +++ b/source/blender/editors/space_node/node_context_path.cc @@ -43,7 +43,7 @@ #include "UI_interface.hh" -#include "node_intern.h" +#include "node_intern.hh" struct Mesh; struct Curve; diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 5fdf816339b..b2c16280c58 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -85,7 +85,7 @@ #include "FN_field_cpp_type.hh" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ #ifdef WITH_COMPOSITOR # include "COM_compositor.h" diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 030d1672a08..3d44d893b88 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -76,7 +76,7 @@ #include "NOD_geometry.h" #include "NOD_shader.h" #include "NOD_texture.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ #define USE_ESC_COMPO diff --git a/source/blender/editors/space_node/node_geometry_attribute_search.cc b/source/blender/editors/space_node/node_geometry_attribute_search.cc index 063e6348123..79ba9b8d2d9 100644 --- a/source/blender/editors/space_node/node_geometry_attribute_search.cc +++ b/source/blender/editors/space_node/node_geometry_attribute_search.cc @@ -44,7 +44,7 @@ #include "NOD_geometry_nodes_eval_log.hh" -#include "node_intern.h" +#include "node_intern.hh" using blender::IndexRange; using blender::Map; diff --git a/source/blender/editors/space_node/node_gizmo.c b/source/blender/editors/space_node/node_gizmo.c deleted file mode 100644 index e1deca54890..00000000000 --- a/source/blender/editors/space_node/node_gizmo.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** \file - * \ingroup spnode - */ - -#include - -#include "BLI_math_matrix.h" -#include "BLI_math_vector.h" -#include "BLI_rect.h" -#include "BLI_utildefines.h" - -#include "BKE_context.h" -#include "BKE_image.h" -#include "BKE_main.h" - -#include "ED_gizmo_library.h" -#include "ED_screen.h" - -#include "IMB_imbuf_types.h" - -#include "MEM_guardedalloc.h" - -#include "RNA_access.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "node_intern.h" - -/* -------------------------------------------------------------------- */ -/** \name Local Utilities - * \{ */ - -static void node_gizmo_calc_matrix_space(const SpaceNode *snode, - const ARegion *region, - float matrix_space[4][4]) -{ - unit_m4(matrix_space); - mul_v3_fl(matrix_space[0], snode->zoom); - mul_v3_fl(matrix_space[1], snode->zoom); - matrix_space[3][0] = (region->winx / 2) + snode->xof; - matrix_space[3][1] = (region->winy / 2) + snode->yof; -} - -static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode, - const ARegion *region, - const float image_dims[2], - float matrix_space[4][4]) -{ - unit_m4(matrix_space); - mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]); - mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]); - matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom); - matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Backdrop Gizmo - * \{ */ - -static void gizmo_node_backdrop_prop_matrix_get(const wmGizmo *UNUSED(gz), - wmGizmoProperty *gz_prop, - void *value_p) -{ - float(*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - const SpaceNode *snode = gz_prop->custom_func.user_data; - matrix[0][0] = snode->zoom; - matrix[1][1] = snode->zoom; - matrix[3][0] = snode->xof; - matrix[3][1] = snode->yof; -} - -static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz), - wmGizmoProperty *gz_prop, - const void *value_p) -{ - const float(*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - SpaceNode *snode = gz_prop->custom_func.user_data; - snode->zoom = matrix[0][0]; - snode->xof = matrix[3][0]; - snode->yof = matrix[3][1]; -} - -static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - if ((snode->flag & SNODE_BACKDRAW) == 0) { - return false; - } - - if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { - bNode *node = nodeGetActive(snode->edittree); - - if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { - return true; - } - } - - return false; -} - -static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) -{ - wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); - - wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); - - RNA_enum_set(wwrapper->gizmo->ptr, - "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); - - gzgroup->customdata = wwrapper; -} - -static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *gzgroup) -{ - Main *bmain = CTX_data_main(C); - wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo; - const ARegion *region = CTX_wm_region(C); - /* center is always at the origin */ - const float origin[3] = {region->winx / 2, region->winy / 2}; - - void *lock; - Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - - if (ibuf) { - const float dims[2] = { - (ibuf->x > 0) ? ibuf->x : 64.0f, - (ibuf->y > 0) ? ibuf->y : 64.0f, - }; - - RNA_float_set_array(cage->ptr, "dimensions", dims); - WM_gizmo_set_matrix_location(cage, origin); - WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false); - - /* Need to set property here for undo. TODO: would prefer to do this in _init. */ - SpaceNode *snode = CTX_wm_space_node(C); -#if 0 - PointerRNA nodeptr; - RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr); - WM_gizmo_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1); - WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1); -#endif - - WM_gizmo_target_property_def_func(cage, - "matrix", - &(const struct wmGizmoPropertyFnParams){ - .value_get_fn = gizmo_node_backdrop_prop_matrix_get, - .value_set_fn = gizmo_node_backdrop_prop_matrix_set, - .range_get_fn = NULL, - .user_data = snode, - }); - } - else { - WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true); - } - - BKE_image_release_ibuf(ima, ibuf, lock); -} - -void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt) -{ - gzgt->name = "Backdrop Transform Widget"; - gzgt->idname = "NODE_GGT_backdrop_transform"; - - gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; - - gzgt->poll = WIDGETGROUP_node_transform_poll; - gzgt->setup = WIDGETGROUP_node_transform_setup; - gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; - gzgt->refresh = WIDGETGROUP_node_transform_refresh; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Crop Gizmo - * \{ */ - -struct NodeCropWidgetGroup { - wmGizmo *border; - - struct { - float dims[2]; - } state; - - struct { - PointerRNA ptr; - PropertyRNA *prop; - bContext *context; - } update_data; -}; - -static void gizmo_node_crop_update(struct NodeCropWidgetGroup *crop_group) -{ - RNA_property_update( - crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop); -} - -static void two_xy_to_rect(const NodeTwoXYs *nxy, - rctf *rect, - const float dims[2], - bool is_relative) -{ - if (is_relative) { - rect->xmin = nxy->fac_x1; - rect->xmax = nxy->fac_x2; - rect->ymin = nxy->fac_y1; - rect->ymax = nxy->fac_y2; - } - else { - rect->xmin = nxy->x1 / dims[0]; - rect->xmax = nxy->x2 / dims[0]; - rect->ymin = nxy->y1 / dims[1]; - rect->ymax = nxy->y2 / dims[1]; - } -} - -static void two_xy_from_rect(NodeTwoXYs *nxy, - const rctf *rect, - const float dims[2], - bool is_relative) -{ - if (is_relative) { - nxy->fac_x1 = rect->xmin; - nxy->fac_x2 = rect->xmax; - nxy->fac_y1 = rect->ymin; - nxy->fac_y2 = rect->ymax; - } - else { - nxy->x1 = rect->xmin * dims[0]; - nxy->x2 = rect->xmax * dims[0]; - nxy->y1 = rect->ymin * dims[1]; - nxy->y2 = rect->ymax * dims[1]; - } -} - -/* scale callbacks */ -static void gizmo_node_crop_prop_matrix_get(const wmGizmo *gz, - wmGizmoProperty *gz_prop, - void *value_p) -{ - float(*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata; - const float *dims = crop_group->state.dims; - const bNode *node = gz_prop->custom_func.user_data; - const NodeTwoXYs *nxy = node->storage; - bool is_relative = (bool)node->custom2; - rctf rct; - two_xy_to_rect(nxy, &rct, dims, is_relative); - matrix[0][0] = fabsf(BLI_rctf_size_x(&rct)); - matrix[1][1] = fabsf(BLI_rctf_size_y(&rct)); - matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0]; - matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1]; -} - -static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz, - wmGizmoProperty *gz_prop, - const void *value_p) -{ - const float(*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata; - const float *dims = crop_group->state.dims; - bNode *node = gz_prop->custom_func.user_data; - NodeTwoXYs *nxy = node->storage; - bool is_relative = (bool)node->custom2; - rctf rct; - two_xy_to_rect(nxy, &rct, dims, is_relative); - const bool nx = rct.xmin > rct.xmax; - const bool ny = rct.ymin > rct.ymax; - BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1])); - BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f); - BLI_rctf_isect( - &(rctf){ - .xmin = 0, - .ymin = 0, - .xmax = 1, - .ymax = 1, - }, - &rct, - &rct); - if (nx) { - SWAP(float, rct.xmin, rct.xmax); - } - if (ny) { - SWAP(float, rct.ymin, rct.ymax); - } - two_xy_from_rect(nxy, &rct, dims, is_relative); - gizmo_node_crop_update(crop_group); -} - -static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - if ((snode->flag & SNODE_BACKDRAW) == 0) { - return false; - } - - if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { - bNode *node = nodeGetActive(snode->edittree); - - if (node && ELEM(node->type, CMP_NODE_CROP)) { - /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */ - if ((node->custom1 & (1 << 0)) == 0) { - return true; - } - } - } - - return false; -} - -static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) -{ - struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), - __func__); - - crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); - - RNA_enum_set(crop_group->border->ptr, - "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); - - gzgroup->customdata = crop_group; -} - -static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) -{ - ARegion *region = CTX_wm_region(C); - wmGizmo *gz = gzgroup->gizmos.first; - - SpaceNode *snode = CTX_wm_space_node(C); - - node_gizmo_calc_matrix_space(snode, region, gz->matrix_space); -} - -static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup) -{ - Main *bmain = CTX_data_main(C); - struct NodeCropWidgetGroup *crop_group = gzgroup->customdata; - wmGizmo *gz = crop_group->border; - - void *lock; - Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - - if (ibuf) { - crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; - crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; - - RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims); - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - - SpaceNode *snode = CTX_wm_space_node(C); - bNode *node = nodeGetActive(snode->edittree); - - crop_group->update_data.context = (bContext *)C; - RNA_pointer_create( - (ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr); - crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, - "relative"); - - WM_gizmo_target_property_def_func(gz, - "matrix", - &(const struct wmGizmoPropertyFnParams){ - .value_get_fn = gizmo_node_crop_prop_matrix_get, - .value_set_fn = gizmo_node_crop_prop_matrix_set, - .range_get_fn = NULL, - .user_data = node, - }); - } - else { - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); - } - - BKE_image_release_ibuf(ima, ibuf, lock); -} - -void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt) -{ - gzgt->name = "Backdrop Crop Widget"; - gzgt->idname = "NODE_GGT_backdrop_crop"; - - gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; - - gzgt->poll = WIDGETGROUP_node_crop_poll; - gzgt->setup = WIDGETGROUP_node_crop_setup; - gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; - gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare; - gzgt->refresh = WIDGETGROUP_node_crop_refresh; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Sun Beams - * \{ */ - -struct NodeSunBeamsWidgetGroup { - wmGizmo *gizmo; - - struct { - float dims[2]; - } state; -}; - -static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - if ((snode->flag & SNODE_BACKDRAW) == 0) { - return false; - } - - if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { - bNode *node = nodeGetActive(snode->edittree); - - if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) { - return true; - } - } - - return false; -} - -static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) -{ - struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup), - __func__); - - sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL); - wmGizmo *gz = sbeam_group->gizmo; - - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D); - - gz->scale_basis = 0.05f / 75.0f; - - gzgroup->customdata = sbeam_group; -} - -static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) -{ - struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata; - ARegion *region = CTX_wm_region(C); - wmGizmo *gz = gzgroup->gizmos.first; - - SpaceNode *snode = CTX_wm_space_node(C); - - node_gizmo_calc_matrix_space_with_image_dims( - snode, region, sbeam_group->state.dims, gz->matrix_space); -} - -static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup) -{ - Main *bmain = CTX_data_main(C); - struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata; - wmGizmo *gz = sbeam_group->gizmo; - - void *lock; - Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - - if (ibuf) { - sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; - sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; - - SpaceNode *snode = CTX_wm_space_node(C); - bNode *node = nodeGetActive(snode->edittree); - - /* Need to set property here for undo. TODO: would prefer to do this in _init. */ - PointerRNA nodeptr; - RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); - WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1); - - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true); - } - else { - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); - } - - BKE_image_release_ibuf(ima, ibuf, lock); -} - -void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt) -{ - gzgt->name = "Sun Beams Widget"; - gzgt->idname = "NODE_GGT_sbeam"; - - gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; - - gzgt->poll = WIDGETGROUP_node_sbeam_poll; - gzgt->setup = WIDGETGROUP_node_sbeam_setup; - gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; - gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare; - gzgt->refresh = WIDGETGROUP_node_sbeam_refresh; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Corner Pin - * \{ */ - -struct NodeCornerPinWidgetGroup { - wmGizmo *gizmos[4]; - - struct { - float dims[2]; - } state; -}; - -static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - if ((snode->flag & SNODE_BACKDRAW) == 0) { - return false; - } - - if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { - bNode *node = nodeGetActive(snode->edittree); - - if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) { - return true; - } - } - - return false; -} - -static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) -{ - struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN( - sizeof(struct NodeCornerPinWidgetGroup), __func__); - const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false); - - for (int i = 0; i < 4; i++) { - cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, NULL); - wmGizmo *gz = cpin_group->gizmos[i]; - - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D); - - gz->scale_basis = 0.01f / 75.0; - } - - gzgroup->customdata = cpin_group; -} - -static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) -{ - struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata; - ARegion *region = CTX_wm_region(C); - - SpaceNode *snode = CTX_wm_space_node(C); - - float matrix_space[4][4]; - node_gizmo_calc_matrix_space_with_image_dims( - snode, region, cpin_group->state.dims, matrix_space); - - for (int i = 0; i < 4; i++) { - wmGizmo *gz = cpin_group->gizmos[i]; - copy_m4_m4(gz->matrix_space, matrix_space); - } -} - -static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup) -{ - Main *bmain = CTX_data_main(C); - struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata; - - void *lock; - Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - - if (ibuf) { - cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; - cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; - - SpaceNode *snode = CTX_wm_space_node(C); - bNode *node = nodeGetActive(snode->edittree); - - /* need to set property here for undo. TODO: would prefer to do this in _init. */ - int i = 0; - for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) { - if (sock->type == SOCK_VECTOR) { - wmGizmo *gz = cpin_group->gizmos[i++]; - - PointerRNA sockptr; - RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr); - WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1); - - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true); - } - } - } - else { - for (int i = 0; i < 4; i++) { - wmGizmo *gz = cpin_group->gizmos[i]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); - } - } - - BKE_image_release_ibuf(ima, ibuf, lock); -} - -void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt) -{ - gzgt->name = "Corner Pin Widget"; - gzgt->idname = "NODE_GGT_backdrop_corner_pin"; - - gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; - - gzgt->poll = WIDGETGROUP_node_corner_pin_poll; - gzgt->setup = WIDGETGROUP_node_corner_pin_setup; - gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; - gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare; - gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh; -} - -/** \} */ diff --git a/source/blender/editors/space_node/node_gizmo.cc b/source/blender/editors/space_node/node_gizmo.cc new file mode 100644 index 00000000000..717f4d2f4f9 --- /dev/null +++ b/source/blender/editors/space_node/node_gizmo.cc @@ -0,0 +1,634 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spnode + */ + +#include + +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" +#include "BLI_rect.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_image.h" +#include "BKE_main.h" + +#include "ED_gizmo_library.h" +#include "ED_screen.h" + +#include "IMB_imbuf_types.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "node_intern.hh" + +/* -------------------------------------------------------------------- */ +/** \name Local Utilities + * \{ */ + +static void node_gizmo_calc_matrix_space(const SpaceNode *snode, + const ARegion *region, + float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom); + mul_v3_fl(matrix_space[1], snode->zoom); + matrix_space[3][0] = (region->winx / 2) + snode->xof; + matrix_space[3][1] = (region->winy / 2) + snode->yof; +} + +static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode, + const ARegion *region, + const float image_dims[2], + float matrix_space[4][4]) +{ + unit_m4(matrix_space); + mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]); + mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]); + matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom); + matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Backdrop Gizmo + * \{ */ + +static void gizmo_node_backdrop_prop_matrix_get(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) +{ + float(*matrix)[4] = (float(*)[4])value_p; + BLI_assert(gz_prop->type->array_length == 16); + const SpaceNode *snode = (const SpaceNode *)gz_prop->custom_func.user_data; + matrix[0][0] = snode->zoom; + matrix[1][1] = snode->zoom; + matrix[3][0] = snode->xof; + matrix[3][1] = snode->yof; +} + +static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) +{ + const float(*matrix)[4] = (const float(*)[4])value_p; + BLI_assert(gz_prop->type->array_length == 16); + SpaceNode *snode = (SpaceNode *)gz_prop->custom_func.user_data; + snode->zoom = matrix[0][0]; + snode->xof = matrix[3][0]; + snode->yof = matrix[3][1]; +} + +static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + wmGizmoWrapper *wwrapper = (wmGizmoWrapper *)MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, nullptr); + + RNA_enum_set(wwrapper->gizmo->ptr, + "transform", + ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + gzgroup->customdata = wwrapper; +} + +static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *gzgroup) +{ + Main *bmain = CTX_data_main(C); + wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo; + const ARegion *region = CTX_wm_region(C); + /* center is always at the origin */ + const float origin[3] = {float(region->winx / 2), float(region->winy / 2), 0.0f}; + + void *lock; + Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); + + if (ibuf) { + const float dims[2] = { + (ibuf->x > 0) ? ibuf->x : 64.0f, + (ibuf->y > 0) ? ibuf->y : 64.0f, + }; + + RNA_float_set_array(cage->ptr, "dimensions", dims); + WM_gizmo_set_matrix_location(cage, origin); + WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false); + + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ + SpaceNode *snode = CTX_wm_space_node(C); +#if 0 + PointerRNA nodeptr; + RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr); + WM_gizmo_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1); + WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1); +#endif + + wmGizmoPropertyFnParams params{}; + params.value_get_fn = gizmo_node_backdrop_prop_matrix_get; + params.value_set_fn = gizmo_node_backdrop_prop_matrix_set; + params.range_get_fn = nullptr; + params.user_data = snode; + WM_gizmo_target_property_def_func(cage, "matrix", ¶ms); + } + else { + WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Backdrop Transform Widget"; + gzgt->idname = "NODE_GGT_backdrop_transform"; + + gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; + + gzgt->poll = WIDGETGROUP_node_transform_poll; + gzgt->setup = WIDGETGROUP_node_transform_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->refresh = WIDGETGROUP_node_transform_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Crop Gizmo + * \{ */ + +struct NodeCropWidgetGroup { + wmGizmo *border; + + struct { + float dims[2]; + } state; + + struct { + PointerRNA ptr; + PropertyRNA *prop; + bContext *context; + } update_data; +}; + +static void gizmo_node_crop_update(struct NodeCropWidgetGroup *crop_group) +{ + RNA_property_update( + crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop); +} + +static void two_xy_to_rect(const NodeTwoXYs *nxy, + rctf *rect, + const float dims[2], + bool is_relative) +{ + if (is_relative) { + rect->xmin = nxy->fac_x1; + rect->xmax = nxy->fac_x2; + rect->ymin = nxy->fac_y1; + rect->ymax = nxy->fac_y2; + } + else { + rect->xmin = nxy->x1 / dims[0]; + rect->xmax = nxy->x2 / dims[0]; + rect->ymin = nxy->y1 / dims[1]; + rect->ymax = nxy->y2 / dims[1]; + } +} + +static void two_xy_from_rect(NodeTwoXYs *nxy, + const rctf *rect, + const float dims[2], + bool is_relative) +{ + if (is_relative) { + nxy->fac_x1 = rect->xmin; + nxy->fac_x2 = rect->xmax; + nxy->fac_y1 = rect->ymin; + nxy->fac_y2 = rect->ymax; + } + else { + nxy->x1 = rect->xmin * dims[0]; + nxy->x2 = rect->xmax * dims[0]; + nxy->y1 = rect->ymin * dims[1]; + nxy->y2 = rect->ymax * dims[1]; + } +} + +/* scale callbacks */ +static void gizmo_node_crop_prop_matrix_get(const wmGizmo *gz, + wmGizmoProperty *gz_prop, + void *value_p) +{ + float(*matrix)[4] = (float(*)[4])value_p; + BLI_assert(gz_prop->type->array_length == 16); + NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gz->parent_gzgroup->customdata; + const float *dims = crop_group->state.dims; + const bNode *node = (const bNode *)gz_prop->custom_func.user_data; + const NodeTwoXYs *nxy = (const NodeTwoXYs *)node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + matrix[0][0] = fabsf(BLI_rctf_size_x(&rct)); + matrix[1][1] = fabsf(BLI_rctf_size_y(&rct)); + matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0]; + matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1]; +} + +static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz, + wmGizmoProperty *gz_prop, + const void *value_p) +{ + const float(*matrix)[4] = (const float(*)[4])value_p; + BLI_assert(gz_prop->type->array_length == 16); + NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gz->parent_gzgroup->customdata; + const float *dims = crop_group->state.dims; + bNode *node = (bNode *)gz_prop->custom_func.user_data; + NodeTwoXYs *nxy = (NodeTwoXYs *)node->storage; + bool is_relative = (bool)node->custom2; + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + const bool nx = rct.xmin > rct.xmax; + const bool ny = rct.ymin > rct.ymax; + BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1])); + BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f); + const rctf rct_isect{0, 0, 1, 1}; + BLI_rctf_isect(&rct_isect, &rct, &rct); + if (nx) { + SWAP(float, rct.xmin, rct.xmax); + } + if (ny) { + SWAP(float, rct.ymin, rct.ymax); + } + two_xy_from_rect(nxy, &rct, dims, is_relative); + gizmo_node_crop_update(crop_group); +} + +static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CROP)) { + /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */ + if ((node->custom1 & (1 << 0)) == 0) { + return true; + } + } + } + + return false; +} + +static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + struct NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)MEM_mallocN( + sizeof(struct NodeCropWidgetGroup), __func__); + + crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, nullptr); + + RNA_enum_set(crop_group->border->ptr, + "transform", + ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); + + gzgroup->customdata = crop_group; +} + +static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +{ + ARegion *region = CTX_wm_region(C); + wmGizmo *gz = (wmGizmo *)gzgroup->gizmos.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_gizmo_calc_matrix_space(snode, region, gz->matrix_space); +} + +static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup) +{ + Main *bmain = CTX_data_main(C); + NodeCropWidgetGroup *crop_group = (NodeCropWidgetGroup *)gzgroup->customdata; + wmGizmo *gz = crop_group->border; + + void *lock; + Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); + + if (ibuf) { + crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims); + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + crop_group->update_data.context = (bContext *)C; + RNA_pointer_create( + (ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr); + crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr, + "relative"); + + wmGizmoPropertyFnParams params{}; + params.value_get_fn = gizmo_node_crop_prop_matrix_get; + params.value_set_fn = gizmo_node_crop_prop_matrix_set; + params.range_get_fn = nullptr; + params.user_data = snode; + WM_gizmo_target_property_def_func(gz, "matrix", ¶ms); + } + else { + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Backdrop Crop Widget"; + gzgt->idname = "NODE_GGT_backdrop_crop"; + + gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; + + gzgt->poll = WIDGETGROUP_node_crop_poll; + gzgt->setup = WIDGETGROUP_node_crop_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare; + gzgt->refresh = WIDGETGROUP_node_crop_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sun Beams + * \{ */ + +struct NodeSunBeamsWidgetGroup { + wmGizmo *gizmo; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)MEM_mallocN( + sizeof(NodeSunBeamsWidgetGroup), __func__); + + sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, nullptr); + wmGizmo *gz = sbeam_group->gizmo; + + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D); + + gz->scale_basis = 0.05f / 75.0f; + + gzgroup->customdata = sbeam_group; +} + +static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +{ + NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)gzgroup->customdata; + ARegion *region = CTX_wm_region(C); + wmGizmo *gz = (wmGizmo *)gzgroup->gizmos.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + node_gizmo_calc_matrix_space_with_image_dims( + snode, region, sbeam_group->state.dims, gz->matrix_space); +} + +static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup) +{ + Main *bmain = CTX_data_main(C); + NodeSunBeamsWidgetGroup *sbeam_group = (NodeSunBeamsWidgetGroup *)gzgroup->customdata; + wmGizmo *gz = sbeam_group->gizmo; + + void *lock; + Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); + + if (ibuf) { + sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* Need to set property here for undo. TODO: would prefer to do this in _init. */ + PointerRNA nodeptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr); + WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1); + + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true); + } + else { + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Sun Beams Widget"; + gzgt->idname = "NODE_GGT_sbeam"; + + gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; + + gzgt->poll = WIDGETGROUP_node_sbeam_poll; + gzgt->setup = WIDGETGROUP_node_sbeam_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare; + gzgt->refresh = WIDGETGROUP_node_sbeam_refresh; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Corner Pin + * \{ */ + +struct NodeCornerPinWidgetGroup { + wmGizmo *gizmos[4]; + + struct { + float dims[2]; + } state; +}; + +static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if ((snode->flag & SNODE_BACKDRAW) == 0) { + return false; + } + + if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { + bNode *node = nodeGetActive(snode->edittree); + + if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) { + return true; + } + } + + return false; +} + +static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +{ + NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)MEM_mallocN( + sizeof(NodeCornerPinWidgetGroup), __func__); + const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false); + + for (int i = 0; i < 4; i++) { + cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, nullptr); + wmGizmo *gz = cpin_group->gizmos[i]; + + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D); + + gz->scale_basis = 0.01f / 75.0; + } + + gzgroup->customdata = cpin_group; +} + +static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +{ + NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)gzgroup->customdata; + ARegion *region = CTX_wm_region(C); + + SpaceNode *snode = CTX_wm_space_node(C); + + float matrix_space[4][4]; + node_gizmo_calc_matrix_space_with_image_dims( + snode, region, cpin_group->state.dims, matrix_space); + + for (int i = 0; i < 4; i++) { + wmGizmo *gz = cpin_group->gizmos[i]; + copy_m4_m4(gz->matrix_space, matrix_space); + } +} + +static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup) +{ + Main *bmain = CTX_data_main(C); + NodeCornerPinWidgetGroup *cpin_group = (NodeCornerPinWidgetGroup *)gzgroup->customdata; + + void *lock; + Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node"); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, nullptr, &lock); + + if (ibuf) { + cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f; + cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f; + + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node = nodeGetActive(snode->edittree); + + /* need to set property here for undo. TODO: would prefer to do this in _init. */ + int i = 0; + for (bNodeSocket *sock = (bNodeSocket *)node->inputs.first; sock && i < 4; sock = sock->next) { + if (sock->type == SOCK_VECTOR) { + wmGizmo *gz = cpin_group->gizmos[i++]; + + PointerRNA sockptr; + RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr); + WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1); + + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true); + } + } + } + else { + for (int i = 0; i < 4; i++) { + wmGizmo *gz = cpin_group->gizmos[i]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); + } + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Corner Pin Widget"; + gzgt->idname = "NODE_GGT_backdrop_corner_pin"; + + gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT; + + gzgt->poll = WIDGETGROUP_node_corner_pin_poll; + gzgt->setup = WIDGETGROUP_node_corner_pin_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare; + gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh; +} + +/** \} */ diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index d7541d8f512..d9fbbc81a8f 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -58,7 +58,7 @@ #include "NOD_common.h" #include "NOD_socket.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ /* -------------------------------------------------------------------- */ /** \name Local Utilities diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h deleted file mode 100644 index 383fe5afdf9..00000000000 --- a/source/blender/editors/space_node/node_intern.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#pragma once - -#include "BKE_node.h" -#include "UI_interface.h" -#include "UI_view2d.h" -#include /* for size_t */ - -/* internal exports only */ - -struct ARegion; -struct ARegionType; -struct Main; -struct NodeInsertOfsData; -struct View2D; -struct bContext; -struct bNode; -struct bNodeLink; -struct bNodeSocket; -struct wmGizmoGroupType; -struct wmKeyConfig; -struct wmWindow; - -#ifdef __cplusplus -extern "C" { -#endif - -/* temp data to pass on to modal */ -typedef struct bNodeLinkDrag { - struct bNodeLinkDrag *next, *prev; - - /* List of links dragged by the operator. - * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks. - * This way the links can be added to the node tree while being stored in this list. - */ - ListBase links; - bool from_multi_input_socket; - int in_out; - - /** Temporarily stores the last picked link from multi-input socket operator. */ - struct bNodeLink *last_picked_multi_input_socket_link; - - /** Temporarily stores the last hovered socket for multi-input socket operator. - * Store it to recalculate sorting after it is no longer hovered. */ - struct bNode *last_node_hovered_while_dragging_a_link; - - /* Data for edge panning */ - View2DEdgePanData pan_data; -} bNodeLinkDrag; - -typedef struct SpaceNode_Runtime { - float aspect; - - /** Mouse position for drawing socket-less links and adding nodes. */ - float cursor[2]; - - /** For auto compositing. */ - bool recalc; - - /** Temporary data for modal linking operator. */ - struct ListBase linkdrag; - - /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ - /** Temporary data for node insert offset (in UI called Auto-offset). */ - struct NodeInsertOfsData *iofsd; -} SpaceNode_Runtime; - -/* space_node.c */ - -/* transform between View2Ds in the tree path */ -void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); - -/* node_draw.cc */ -float node_socket_calculate_height(const bNodeSocket *socket); -void node_link_calculate_multi_input_position(const float socket_x, - const float socket_y, - const int index, - const int total_inputs, - float r[2]); - -int node_get_colorid(struct bNode *node); -int node_get_resize_cursor(int directions); -void node_draw_shadow(const struct SpaceNode *snode, - const struct bNode *node, - float radius, - float alpha); -void node_draw_default(const struct bContext *C, - struct ARegion *region, - struct SpaceNode *snode, - struct bNodeTree *ntree, - struct bNode *node, - bNodeInstanceKey key); -void node_draw_sockets(const struct View2D *v2d, - const struct bContext *C, - struct bNodeTree *ntree, - struct bNode *node, - bool draw_outputs, - bool select_all); -void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); -int node_select_area_default(struct bNode *node, int x, int y); -int node_tweak_area_default(struct bNode *node, int x, int y); -void node_socket_color_get(const struct bContext *C, - struct bNodeTree *ntree, - struct PointerRNA *node_ptr, - struct bNodeSocket *sock, - float r_color[4]); -void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); -void node_draw_nodetree(const struct bContext *C, - struct ARegion *region, - struct SpaceNode *snode, - struct bNodeTree *ntree, - bNodeInstanceKey parent_key); -void node_draw_space(const bContext *C, ARegion *region); - -void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); -/* DPI scaled coords */ -void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry); -void node_to_updated_rect(const struct bNode *node, rctf *r_rect); -void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); - -/* node_toolbar.c */ -void node_toolbar_register(struct ARegionType *art); - -/* node_ops.c */ -void node_operatortypes(void); -void node_keymap(struct wmKeyConfig *keyconf); - -/* node_select.c */ -void node_deselect_all(struct SpaceNode *snode); -void node_socket_select(struct bNode *node, struct bNodeSocket *sock); -void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, const bool deselect_node); -void node_deselect_all_input_sockets(struct SpaceNode *snode, const bool deselect_nodes); -void node_deselect_all_output_sockets(struct SpaceNode *snode, const bool deselect_nodes); -void node_select_single(struct bContext *C, struct bNode *node); - -void NODE_OT_select(struct wmOperatorType *ot); -void NODE_OT_select_all(struct wmOperatorType *ot); -void NODE_OT_select_linked_to(struct wmOperatorType *ot); -void NODE_OT_select_linked_from(struct wmOperatorType *ot); -void NODE_OT_select_box(struct wmOperatorType *ot); -void NODE_OT_select_circle(struct wmOperatorType *ot); -void NODE_OT_select_lasso(struct wmOperatorType *ot); -void NODE_OT_select_grouped(struct wmOperatorType *ot); -void NODE_OT_select_same_type_step(struct wmOperatorType *ot); -void NODE_OT_find_node(struct wmOperatorType *ot); - -/* node_view.c */ -int space_node_view_flag(struct bContext *C, - struct SpaceNode *snode, - ARegion *region, - const int node_flag, - const int smooth_viewtx); - -void NODE_OT_view_all(struct wmOperatorType *ot); -void NODE_OT_view_selected(struct wmOperatorType *ot); -void NODE_OT_geometry_node_view_legacy(struct wmOperatorType *ot); - -void NODE_OT_backimage_move(struct wmOperatorType *ot); -void NODE_OT_backimage_zoom(struct wmOperatorType *ot); -void NODE_OT_backimage_fit(struct wmOperatorType *ot); -void NODE_OT_backimage_sample(struct wmOperatorType *ot); - -/* drawnode.c */ -void nodelink_batch_start(struct SpaceNode *snode); -void nodelink_batch_end(struct SpaceNode *snode); - -void node_draw_link(const struct bContext *C, - struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link); -void node_draw_link_bezier(const struct bContext *C, - const struct View2D *v2d, - const struct SpaceNode *snode, - const struct bNodeLink *link, - int th_col1, - int th_col2, - int th_col3); -bool node_link_bezier_points(const struct View2D *v2d, - const struct SpaceNode *snode, - const struct bNodeLink *link, - float coord_array[][2], - const int resol); -bool node_link_bezier_handles(const struct View2D *v2d, - const struct SpaceNode *snode, - const struct bNodeLink *link, - float vec[4][2]); -void draw_nodespace_back_pix(const struct bContext *C, - struct ARegion *region, - struct SpaceNode *snode, - bNodeInstanceKey parent_key); - -/* node_add.c */ -bNode *node_add_node( - const struct bContext *C, const char *idname, int type, float locx, float locy); -void NODE_OT_add_reroute(struct wmOperatorType *ot); -void NODE_OT_add_group(struct wmOperatorType *ot); -void NODE_OT_add_object(struct wmOperatorType *ot); -void NODE_OT_add_collection(struct wmOperatorType *ot); -void NODE_OT_add_texture(struct wmOperatorType *ot); -void NODE_OT_add_file(struct wmOperatorType *ot); -void NODE_OT_add_mask(struct wmOperatorType *ot); -void NODE_OT_new_node_tree(struct wmOperatorType *ot); - -/* node_group.c */ -const char *node_group_idname(struct bContext *C); -void NODE_OT_group_make(struct wmOperatorType *ot); -void NODE_OT_group_insert(struct wmOperatorType *ot); -void NODE_OT_group_ungroup(struct wmOperatorType *ot); -void NODE_OT_group_separate(struct wmOperatorType *ot); -void NODE_OT_group_edit(struct wmOperatorType *ot); - -/* node_relationships.c */ -void sort_multi_input_socket_links(struct SpaceNode *snode, - struct bNode *node, - struct bNodeLink *drag_link, - float cursor[2]); -bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); - -void NODE_OT_link(struct wmOperatorType *ot); -void NODE_OT_link_make(struct wmOperatorType *ot); -void NODE_OT_links_cut(struct wmOperatorType *ot); -void NODE_OT_links_detach(struct wmOperatorType *ot); -void NODE_OT_links_mute(struct wmOperatorType *ot); - -void NODE_OT_parent_set(struct wmOperatorType *ot); -void NODE_OT_join(struct wmOperatorType *ot); -void NODE_OT_attach(struct wmOperatorType *ot); -void NODE_OT_detach(struct wmOperatorType *ot); - -void NODE_OT_link_viewer(struct wmOperatorType *ot); - -void NODE_OT_insert_offset(struct wmOperatorType *ot); - -/* node_edit.c */ -void snode_notify(struct bContext *C, struct SpaceNode *snode); -void snode_dag_update(struct bContext *C, struct SpaceNode *snode); -void snode_set_context(const struct bContext *C); - -void snode_update(struct SpaceNode *snode, struct bNode *node); -bool composite_node_active(struct bContext *C); -bool composite_node_editable(struct bContext *C); - -bool node_has_hidden_sockets(struct bNode *node); -void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set); -int node_render_changed_exec(bContext *, struct wmOperator *); -int node_find_indicated_socket(struct SpaceNode *snode, - struct bNode **nodep, - struct bNodeSocket **sockp, - const float cursor[2], - int in_out); -float node_link_dim_factor(const struct View2D *v2d, const struct bNodeLink *link); -bool node_link_is_hidden_or_dimmed(const struct View2D *v2d, const struct bNodeLink *link); - -void NODE_OT_duplicate(struct wmOperatorType *ot); -void NODE_OT_delete(struct wmOperatorType *ot); -void NODE_OT_delete_reconnect(struct wmOperatorType *ot); -void NODE_OT_resize(struct wmOperatorType *ot); - -void NODE_OT_mute_toggle(struct wmOperatorType *ot); -void NODE_OT_hide_toggle(struct wmOperatorType *ot); -void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); -void NODE_OT_preview_toggle(struct wmOperatorType *ot); -void NODE_OT_options_toggle(struct wmOperatorType *ot); -void NODE_OT_node_copy_color(struct wmOperatorType *ot); - -void NODE_OT_read_viewlayers(struct wmOperatorType *ot); -void NODE_OT_render_changed(struct wmOperatorType *ot); - -void NODE_OT_output_file_add_socket(struct wmOperatorType *ot); -void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot); -void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); - -void NODE_OT_switch_view_update(struct wmOperatorType *ot); - -/* NOTE: clipboard_cut is a simple macro of copy + delete. */ -void NODE_OT_clipboard_copy(struct wmOperatorType *ot); -void NODE_OT_clipboard_paste(struct wmOperatorType *ot); - -void NODE_OT_tree_socket_add(struct wmOperatorType *ot); -void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); -void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot); -void NODE_OT_tree_socket_move(struct wmOperatorType *ot); - -void NODE_OT_shader_script_update(struct wmOperatorType *ot); - -void NODE_OT_viewer_border(struct wmOperatorType *ot); -void NODE_OT_clear_viewer_border(struct wmOperatorType *ot); - -/* node_widgets.c */ -void NODE_GGT_backdrop_transform(struct wmGizmoGroupType *gzgt); -void NODE_GGT_backdrop_crop(struct wmGizmoGroupType *gzgt); -void NODE_GGT_backdrop_sun_beams(struct wmGizmoGroupType *gzgt); -void NODE_GGT_backdrop_corner_pin(struct wmGizmoGroupType *gzgt); - -void NODE_OT_cryptomatte_layer_add(struct wmOperatorType *ot); -void NODE_OT_cryptomatte_layer_remove(struct wmOperatorType *ot); - -/* node_geometry_attribute_search.cc */ -void node_geometry_add_attribute_search_button(const struct bContext *C, - const struct bNodeTree *node_tree, - const struct bNode *node, - struct PointerRNA *socket_ptr, - struct uiLayout *layout); - -extern const char *node_context_dir[]; - -/* XXXXXX */ - -/* Nodes draw without dpi - the view zoom is flexible. */ -#define HIDDEN_RAD (0.75f * U.widget_unit) -#define BASIS_RAD (0.2f * U.widget_unit) -#define NODE_DYS (U.widget_unit / 2) -#define NODE_DY U.widget_unit -#define NODE_SOCKDY (0.1f * U.widget_unit) -#define NODE_WIDTH(node) (node->width * UI_DPI_FAC) -#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) -#define NODE_MARGIN_X (1.2f * U.widget_unit) -#define NODE_SOCKSIZE (0.25f * U.widget_unit) -#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit) -#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) -#define NODE_LINK_RESOL 12 - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -# include "BLI_vector.hh" -# include "UI_interface.hh" -namespace blender::ed::space_node { -Vector context_path_for_space_node(const bContext &C); -} -#endif diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh new file mode 100644 index 00000000000..cb2980b7db5 --- /dev/null +++ b/source/blender/editors/space_node/node_intern.hh @@ -0,0 +1,347 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spnode + */ + +#pragma once + +#include "BKE_node.h" +#include "UI_interface.h" +#include "UI_view2d.h" + +#include "BLI_vector.hh" +#include "UI_interface.hh" + +#include /* for size_t */ + +/* internal exports only */ + +struct ARegion; +struct ARegionType; +struct Main; +struct NodeInsertOfsData; +struct View2D; +struct bContext; +struct bNode; +struct bNodeLink; +struct bNodeSocket; +struct wmGizmoGroupType; +struct wmKeyConfig; +struct wmWindow; + +/* temp data to pass on to modal */ +typedef struct bNodeLinkDrag { + struct bNodeLinkDrag *next, *prev; + + /* List of links dragged by the operator. + * NOTE: This is a list of LinkData structs on top of the actual bNodeLinks. + * This way the links can be added to the node tree while being stored in this list. + */ + ListBase links; + bool from_multi_input_socket; + int in_out; + + /** Temporarily stores the last picked link from multi-input socket operator. */ + struct bNodeLink *last_picked_multi_input_socket_link; + + /** Temporarily stores the last hovered socket for multi-input socket operator. + * Store it to recalculate sorting after it is no longer hovered. */ + struct bNode *last_node_hovered_while_dragging_a_link; + + /* Data for edge panning */ + View2DEdgePanData pan_data; +} bNodeLinkDrag; + +typedef struct SpaceNode_Runtime { + float aspect; + + /** Mouse position for drawing socket-less links and adding nodes. */ + float cursor[2]; + + /** For auto compositing. */ + bool recalc; + + /** Temporary data for modal linking operator. */ + struct ListBase linkdrag; + + /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ + /** Temporary data for node insert offset (in UI called Auto-offset). */ + struct NodeInsertOfsData *iofsd; +} SpaceNode_Runtime; + +/* space_node.c */ + +/* transform between View2Ds in the tree path */ +void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); + +/* node_draw.cc */ +float node_socket_calculate_height(const bNodeSocket *socket); +void node_link_calculate_multi_input_position(const float socket_x, + const float socket_y, + const int index, + const int total_inputs, + float r[2]); + +int node_get_colorid(struct bNode *node); +int node_get_resize_cursor(int directions); +void node_draw_shadow(const struct SpaceNode *snode, + const struct bNode *node, + float radius, + float alpha); +void node_draw_default(const struct bContext *C, + struct ARegion *region, + struct SpaceNode *snode, + struct bNodeTree *ntree, + struct bNode *node, + bNodeInstanceKey key); +void node_draw_sockets(const struct View2D *v2d, + const struct bContext *C, + struct bNodeTree *ntree, + struct bNode *node, + bool draw_outputs, + bool select_all); +void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); +int node_select_area_default(struct bNode *node, int x, int y); +int node_tweak_area_default(struct bNode *node, int x, int y); +void node_socket_color_get(const struct bContext *C, + struct bNodeTree *ntree, + struct PointerRNA *node_ptr, + struct bNodeSocket *sock, + float r_color[4]); +void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); +void node_draw_nodetree(const struct bContext *C, + struct ARegion *region, + struct SpaceNode *snode, + struct bNodeTree *ntree, + bNodeInstanceKey parent_key); +void node_draw_space(const bContext *C, ARegion *region); + +void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); +/* DPI scaled coords */ +void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_updated_rect(const struct bNode *node, rctf *r_rect); +void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); + +/* node_toolbar.c */ +void node_toolbar_register(struct ARegionType *art); + +/* node_ops.c */ +void node_operatortypes(void); +void node_keymap(struct wmKeyConfig *keyconf); + +/* node_select.c */ +void node_deselect_all(struct SpaceNode *snode); +void node_socket_select(struct bNode *node, struct bNodeSocket *sock); +void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, const bool deselect_node); +void node_deselect_all_input_sockets(struct SpaceNode *snode, const bool deselect_nodes); +void node_deselect_all_output_sockets(struct SpaceNode *snode, const bool deselect_nodes); +void node_select_single(struct bContext *C, struct bNode *node); + +void NODE_OT_select(struct wmOperatorType *ot); +void NODE_OT_select_all(struct wmOperatorType *ot); +void NODE_OT_select_linked_to(struct wmOperatorType *ot); +void NODE_OT_select_linked_from(struct wmOperatorType *ot); +void NODE_OT_select_box(struct wmOperatorType *ot); +void NODE_OT_select_circle(struct wmOperatorType *ot); +void NODE_OT_select_lasso(struct wmOperatorType *ot); +void NODE_OT_select_grouped(struct wmOperatorType *ot); +void NODE_OT_select_same_type_step(struct wmOperatorType *ot); +void NODE_OT_find_node(struct wmOperatorType *ot); + +/* node_view.c */ +int space_node_view_flag(struct bContext *C, + struct SpaceNode *snode, + ARegion *region, + const int node_flag, + const int smooth_viewtx); + +void NODE_OT_view_all(struct wmOperatorType *ot); +void NODE_OT_view_selected(struct wmOperatorType *ot); +void NODE_OT_geometry_node_view_legacy(struct wmOperatorType *ot); + +void NODE_OT_backimage_move(struct wmOperatorType *ot); +void NODE_OT_backimage_zoom(struct wmOperatorType *ot); +void NODE_OT_backimage_fit(struct wmOperatorType *ot); +void NODE_OT_backimage_sample(struct wmOperatorType *ot); + +/* drawnode.c */ +void nodelink_batch_start(struct SpaceNode *snode); +void nodelink_batch_end(struct SpaceNode *snode); + +void node_draw_link(const struct bContext *C, + struct View2D *v2d, + struct SpaceNode *snode, + struct bNodeLink *link); +void node_draw_link_bezier(const struct bContext *C, + const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, + int th_col1, + int th_col2, + int th_col3); +bool node_link_bezier_points(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, + float coord_array[][2], + const int resol); +bool node_link_bezier_handles(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, + float vec[4][2]); +void draw_nodespace_back_pix(const struct bContext *C, + struct ARegion *region, + struct SpaceNode *snode, + bNodeInstanceKey parent_key); + +/* node_add.c */ +bNode *node_add_node( + const struct bContext *C, const char *idname, int type, float locx, float locy); +void NODE_OT_add_reroute(struct wmOperatorType *ot); +void NODE_OT_add_group(struct wmOperatorType *ot); +void NODE_OT_add_object(struct wmOperatorType *ot); +void NODE_OT_add_collection(struct wmOperatorType *ot); +void NODE_OT_add_texture(struct wmOperatorType *ot); +void NODE_OT_add_file(struct wmOperatorType *ot); +void NODE_OT_add_mask(struct wmOperatorType *ot); +void NODE_OT_new_node_tree(struct wmOperatorType *ot); + +/* node_group.c */ +const char *node_group_idname(struct bContext *C); +void NODE_OT_group_make(struct wmOperatorType *ot); +void NODE_OT_group_insert(struct wmOperatorType *ot); +void NODE_OT_group_ungroup(struct wmOperatorType *ot); +void NODE_OT_group_separate(struct wmOperatorType *ot); +void NODE_OT_group_edit(struct wmOperatorType *ot); + +/* node_relationships.c */ +void sort_multi_input_socket_links(struct SpaceNode *snode, + struct bNode *node, + struct bNodeLink *drag_link, + float cursor[2]); +bool node_connected_to_output(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); + +void NODE_OT_link(struct wmOperatorType *ot); +void NODE_OT_link_make(struct wmOperatorType *ot); +void NODE_OT_links_cut(struct wmOperatorType *ot); +void NODE_OT_links_detach(struct wmOperatorType *ot); +void NODE_OT_links_mute(struct wmOperatorType *ot); + +void NODE_OT_parent_set(struct wmOperatorType *ot); +void NODE_OT_join(struct wmOperatorType *ot); +void NODE_OT_attach(struct wmOperatorType *ot); +void NODE_OT_detach(struct wmOperatorType *ot); + +void NODE_OT_link_viewer(struct wmOperatorType *ot); + +void NODE_OT_insert_offset(struct wmOperatorType *ot); + +/* node_edit.c */ +void snode_notify(struct bContext *C, struct SpaceNode *snode); +void snode_dag_update(struct bContext *C, struct SpaceNode *snode); +void snode_set_context(const struct bContext *C); + +void snode_update(struct SpaceNode *snode, struct bNode *node); +bool composite_node_active(struct bContext *C); +bool composite_node_editable(struct bContext *C); + +bool node_has_hidden_sockets(struct bNode *node); +void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set); +int node_render_changed_exec(bContext *, struct wmOperator *); +int node_find_indicated_socket(struct SpaceNode *snode, + struct bNode **nodep, + struct bNodeSocket **sockp, + const float cursor[2], + int in_out); +float node_link_dim_factor(const struct View2D *v2d, const struct bNodeLink *link); +bool node_link_is_hidden_or_dimmed(const struct View2D *v2d, const struct bNodeLink *link); + +void NODE_OT_duplicate(struct wmOperatorType *ot); +void NODE_OT_delete(struct wmOperatorType *ot); +void NODE_OT_delete_reconnect(struct wmOperatorType *ot); +void NODE_OT_resize(struct wmOperatorType *ot); + +void NODE_OT_mute_toggle(struct wmOperatorType *ot); +void NODE_OT_hide_toggle(struct wmOperatorType *ot); +void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); +void NODE_OT_preview_toggle(struct wmOperatorType *ot); +void NODE_OT_options_toggle(struct wmOperatorType *ot); +void NODE_OT_node_copy_color(struct wmOperatorType *ot); + +void NODE_OT_read_viewlayers(struct wmOperatorType *ot); +void NODE_OT_render_changed(struct wmOperatorType *ot); + +void NODE_OT_output_file_add_socket(struct wmOperatorType *ot); +void NODE_OT_output_file_remove_active_socket(struct wmOperatorType *ot); +void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); + +void NODE_OT_switch_view_update(struct wmOperatorType *ot); + +/* NOTE: clipboard_cut is a simple macro of copy + delete. */ +void NODE_OT_clipboard_copy(struct wmOperatorType *ot); +void NODE_OT_clipboard_paste(struct wmOperatorType *ot); + +void NODE_OT_tree_socket_add(struct wmOperatorType *ot); +void NODE_OT_tree_socket_remove(struct wmOperatorType *ot); +void NODE_OT_tree_socket_change_type(struct wmOperatorType *ot); +void NODE_OT_tree_socket_move(struct wmOperatorType *ot); + +void NODE_OT_shader_script_update(struct wmOperatorType *ot); + +void NODE_OT_viewer_border(struct wmOperatorType *ot); +void NODE_OT_clear_viewer_border(struct wmOperatorType *ot); + +/* node_widgets.c */ +void NODE_GGT_backdrop_transform(struct wmGizmoGroupType *gzgt); +void NODE_GGT_backdrop_crop(struct wmGizmoGroupType *gzgt); +void NODE_GGT_backdrop_sun_beams(struct wmGizmoGroupType *gzgt); +void NODE_GGT_backdrop_corner_pin(struct wmGizmoGroupType *gzgt); + +void NODE_OT_cryptomatte_layer_add(struct wmOperatorType *ot); +void NODE_OT_cryptomatte_layer_remove(struct wmOperatorType *ot); + +/* node_geometry_attribute_search.cc */ +void node_geometry_add_attribute_search_button(const struct bContext *C, + const struct bNodeTree *node_tree, + const struct bNode *node, + struct PointerRNA *socket_ptr, + struct uiLayout *layout); + +extern const char *node_context_dir[]; + +/* XXXXXX */ + +/* Nodes draw without dpi - the view zoom is flexible. */ +#define HIDDEN_RAD (0.75f * U.widget_unit) +#define BASIS_RAD (0.2f * U.widget_unit) +#define NODE_DYS (U.widget_unit / 2) +#define NODE_DY U.widget_unit +#define NODE_SOCKDY (0.1f * U.widget_unit) +#define NODE_WIDTH(node) (node->width * UI_DPI_FAC) +#define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) +#define NODE_MARGIN_X (1.2f * U.widget_unit) +#define NODE_SOCKSIZE (0.25f * U.widget_unit) +#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit) +#define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) +#define NODE_LINK_RESOL 12 + +namespace blender::ed::space_node { +Vector context_path_for_space_node(const bContext &C); +} diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c deleted file mode 100644 index 0c54da65e9c..00000000000 --- a/source/blender/editors/space_node/node_ops.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#include "DNA_node_types.h" - -#include "BKE_context.h" - -#include "ED_node.h" /* own include */ -#include "ED_screen.h" - -#include "RNA_access.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "node_intern.h" /* own include */ - -void node_operatortypes(void) -{ - WM_operatortype_append(NODE_OT_select); - WM_operatortype_append(NODE_OT_select_all); - WM_operatortype_append(NODE_OT_select_linked_to); - WM_operatortype_append(NODE_OT_select_linked_from); - WM_operatortype_append(NODE_OT_select_box); - WM_operatortype_append(NODE_OT_select_circle); - WM_operatortype_append(NODE_OT_select_lasso); - WM_operatortype_append(NODE_OT_select_grouped); - WM_operatortype_append(NODE_OT_select_same_type_step); - - WM_operatortype_append(NODE_OT_find_node); - - WM_operatortype_append(NODE_OT_view_all); - WM_operatortype_append(NODE_OT_view_selected); - WM_operatortype_append(NODE_OT_geometry_node_view_legacy); - - WM_operatortype_append(NODE_OT_mute_toggle); - WM_operatortype_append(NODE_OT_hide_toggle); - WM_operatortype_append(NODE_OT_preview_toggle); - WM_operatortype_append(NODE_OT_options_toggle); - WM_operatortype_append(NODE_OT_hide_socket_toggle); - WM_operatortype_append(NODE_OT_node_copy_color); - - WM_operatortype_append(NODE_OT_duplicate); - WM_operatortype_append(NODE_OT_delete); - WM_operatortype_append(NODE_OT_delete_reconnect); - WM_operatortype_append(NODE_OT_resize); - - WM_operatortype_append(NODE_OT_link); - WM_operatortype_append(NODE_OT_link_make); - WM_operatortype_append(NODE_OT_links_cut); - WM_operatortype_append(NODE_OT_links_detach); - WM_operatortype_append(NODE_OT_links_mute); - WM_operatortype_append(NODE_OT_add_reroute); - - WM_operatortype_append(NODE_OT_group_make); - WM_operatortype_append(NODE_OT_group_insert); - WM_operatortype_append(NODE_OT_group_ungroup); - WM_operatortype_append(NODE_OT_group_separate); - WM_operatortype_append(NODE_OT_group_edit); - - WM_operatortype_append(NODE_OT_link_viewer); - - WM_operatortype_append(NODE_OT_insert_offset); - - WM_operatortype_append(NODE_OT_read_viewlayers); - WM_operatortype_append(NODE_OT_render_changed); - - WM_operatortype_append(NODE_OT_backimage_move); - WM_operatortype_append(NODE_OT_backimage_zoom); - WM_operatortype_append(NODE_OT_backimage_fit); - WM_operatortype_append(NODE_OT_backimage_sample); - - WM_operatortype_append(NODE_OT_add_group); - WM_operatortype_append(NODE_OT_add_object); - WM_operatortype_append(NODE_OT_add_collection); - WM_operatortype_append(NODE_OT_add_texture); - WM_operatortype_append(NODE_OT_add_file); - WM_operatortype_append(NODE_OT_add_mask); - - WM_operatortype_append(NODE_OT_new_node_tree); - - WM_operatortype_append(NODE_OT_output_file_add_socket); - WM_operatortype_append(NODE_OT_output_file_remove_active_socket); - WM_operatortype_append(NODE_OT_output_file_move_active_socket); - - WM_operatortype_append(NODE_OT_parent_set); - WM_operatortype_append(NODE_OT_join); - WM_operatortype_append(NODE_OT_attach); - WM_operatortype_append(NODE_OT_detach); - - WM_operatortype_append(NODE_OT_clipboard_copy); - WM_operatortype_append(NODE_OT_clipboard_paste); - - WM_operatortype_append(NODE_OT_shader_script_update); - - WM_operatortype_append(NODE_OT_viewer_border); - WM_operatortype_append(NODE_OT_clear_viewer_border); - - WM_operatortype_append(NODE_OT_switch_view_update); - - WM_operatortype_append(NODE_OT_tree_socket_add); - WM_operatortype_append(NODE_OT_tree_socket_remove); - WM_operatortype_append(NODE_OT_tree_socket_change_type); - WM_operatortype_append(NODE_OT_tree_socket_move); - - WM_operatortype_append(NODE_OT_cryptomatte_layer_add); - WM_operatortype_append(NODE_OT_cryptomatte_layer_remove); -} - -void ED_operatormacros_node(void) -{ - wmOperatorType *ot; - wmOperatorTypeMacro *mot; - - ot = WM_operatortype_append_macro("NODE_OT_select_link_viewer", - "Link Viewer", - "Select node and link it to a viewer node", - OPTYPE_UNDO); - mot = WM_operatortype_macro_define(ot, "NODE_OT_select"); - RNA_boolean_set(mot->ptr, "extend", false); - RNA_boolean_set(mot->ptr, "socket_select", true); - WM_operatortype_macro_define(ot, "NODE_OT_link_viewer"); - - ot = WM_operatortype_append_macro("NODE_OT_translate_attach", - "Move and Attach", - "Move nodes and attach to frame", - OPTYPE_UNDO | OPTYPE_REGISTER); - mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - WM_operatortype_macro_define(ot, "NODE_OT_attach"); - WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - - /* NODE_OT_translate_attach with remove_on_canel set to true */ - ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", - "Move and Attach", - "Move nodes and attach to frame", - OPTYPE_UNDO | OPTYPE_REGISTER); - mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - RNA_boolean_set(mot->ptr, "remove_on_cancel", true); - RNA_boolean_set(mot->ptr, "view2d_edge_pan", true); - WM_operatortype_macro_define(ot, "NODE_OT_attach"); - WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - - /* NOTE: Currently not in a default keymap or menu due to messy keymaps - * and tricky invoke functionality. - * Kept around in case users want to make own shortcuts. - */ - ot = WM_operatortype_append_macro("NODE_OT_detach_translate_attach", - "Detach and Move", - "Detach nodes, move and attach to frame", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "NODE_OT_detach"); - mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - WM_operatortype_macro_define(ot, "NODE_OT_attach"); - - ot = WM_operatortype_append_macro("NODE_OT_duplicate_move", - "Duplicate", - "Duplicate selected nodes and move them", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); - WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); - - /* modified operator call for duplicating with input links */ - ot = WM_operatortype_append_macro("NODE_OT_duplicate_move_keep_inputs", - "Duplicate", - "Duplicate selected nodes keeping input links and move them", - OPTYPE_UNDO | OPTYPE_REGISTER); - mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); - RNA_boolean_set(mot->ptr, "keep_inputs", true); - WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); - - ot = WM_operatortype_append_macro("NODE_OT_move_detach_links", - "Detach", - "Move a node to detach links", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "NODE_OT_links_detach"); - WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); - - ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release", - "Detach", - "Move a node to detach links", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "NODE_OT_links_detach"); - WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); -} - -void node_keymap(struct wmKeyConfig *keyconf) -{ - /* Entire Editor only ----------------- */ - WM_keymap_ensure(keyconf, "Node Generic", SPACE_NODE, 0); - - /* Main Region only ----------------- */ - WM_keymap_ensure(keyconf, "Node Editor", SPACE_NODE, 0); -} diff --git a/source/blender/editors/space_node/node_ops.cc b/source/blender/editors/space_node/node_ops.cc new file mode 100644 index 00000000000..4c08f4d7b47 --- /dev/null +++ b/source/blender/editors/space_node/node_ops.cc @@ -0,0 +1,214 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spnode + */ + +#include "DNA_node_types.h" + +#include "BKE_context.h" + +#include "ED_node.h" /* own include */ +#include "ED_screen.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "node_intern.hh" /* own include */ + +void node_operatortypes() +{ + WM_operatortype_append(NODE_OT_select); + WM_operatortype_append(NODE_OT_select_all); + WM_operatortype_append(NODE_OT_select_linked_to); + WM_operatortype_append(NODE_OT_select_linked_from); + WM_operatortype_append(NODE_OT_select_box); + WM_operatortype_append(NODE_OT_select_circle); + WM_operatortype_append(NODE_OT_select_lasso); + WM_operatortype_append(NODE_OT_select_grouped); + WM_operatortype_append(NODE_OT_select_same_type_step); + + WM_operatortype_append(NODE_OT_find_node); + + WM_operatortype_append(NODE_OT_view_all); + WM_operatortype_append(NODE_OT_view_selected); + WM_operatortype_append(NODE_OT_geometry_node_view_legacy); + + WM_operatortype_append(NODE_OT_mute_toggle); + WM_operatortype_append(NODE_OT_hide_toggle); + WM_operatortype_append(NODE_OT_preview_toggle); + WM_operatortype_append(NODE_OT_options_toggle); + WM_operatortype_append(NODE_OT_hide_socket_toggle); + WM_operatortype_append(NODE_OT_node_copy_color); + + WM_operatortype_append(NODE_OT_duplicate); + WM_operatortype_append(NODE_OT_delete); + WM_operatortype_append(NODE_OT_delete_reconnect); + WM_operatortype_append(NODE_OT_resize); + + WM_operatortype_append(NODE_OT_link); + WM_operatortype_append(NODE_OT_link_make); + WM_operatortype_append(NODE_OT_links_cut); + WM_operatortype_append(NODE_OT_links_detach); + WM_operatortype_append(NODE_OT_links_mute); + WM_operatortype_append(NODE_OT_add_reroute); + + WM_operatortype_append(NODE_OT_group_make); + WM_operatortype_append(NODE_OT_group_insert); + WM_operatortype_append(NODE_OT_group_ungroup); + WM_operatortype_append(NODE_OT_group_separate); + WM_operatortype_append(NODE_OT_group_edit); + + WM_operatortype_append(NODE_OT_link_viewer); + + WM_operatortype_append(NODE_OT_insert_offset); + + WM_operatortype_append(NODE_OT_read_viewlayers); + WM_operatortype_append(NODE_OT_render_changed); + + WM_operatortype_append(NODE_OT_backimage_move); + WM_operatortype_append(NODE_OT_backimage_zoom); + WM_operatortype_append(NODE_OT_backimage_fit); + WM_operatortype_append(NODE_OT_backimage_sample); + + WM_operatortype_append(NODE_OT_add_group); + WM_operatortype_append(NODE_OT_add_object); + WM_operatortype_append(NODE_OT_add_collection); + WM_operatortype_append(NODE_OT_add_texture); + WM_operatortype_append(NODE_OT_add_file); + WM_operatortype_append(NODE_OT_add_mask); + + WM_operatortype_append(NODE_OT_new_node_tree); + + WM_operatortype_append(NODE_OT_output_file_add_socket); + WM_operatortype_append(NODE_OT_output_file_remove_active_socket); + WM_operatortype_append(NODE_OT_output_file_move_active_socket); + + WM_operatortype_append(NODE_OT_parent_set); + WM_operatortype_append(NODE_OT_join); + WM_operatortype_append(NODE_OT_attach); + WM_operatortype_append(NODE_OT_detach); + + WM_operatortype_append(NODE_OT_clipboard_copy); + WM_operatortype_append(NODE_OT_clipboard_paste); + + WM_operatortype_append(NODE_OT_shader_script_update); + + WM_operatortype_append(NODE_OT_viewer_border); + WM_operatortype_append(NODE_OT_clear_viewer_border); + + WM_operatortype_append(NODE_OT_switch_view_update); + + WM_operatortype_append(NODE_OT_tree_socket_add); + WM_operatortype_append(NODE_OT_tree_socket_remove); + WM_operatortype_append(NODE_OT_tree_socket_change_type); + WM_operatortype_append(NODE_OT_tree_socket_move); + + WM_operatortype_append(NODE_OT_cryptomatte_layer_add); + WM_operatortype_append(NODE_OT_cryptomatte_layer_remove); +} + +void ED_operatormacros_node(void) +{ + wmOperatorType *ot; + wmOperatorTypeMacro *mot; + + ot = WM_operatortype_append_macro("NODE_OT_select_link_viewer", + "Link Viewer", + "Select node and link it to a viewer node", + OPTYPE_UNDO); + mot = WM_operatortype_macro_define(ot, "NODE_OT_select"); + RNA_boolean_set(mot->ptr, "extend", false); + RNA_boolean_set(mot->ptr, "socket_select", true); + WM_operatortype_macro_define(ot, "NODE_OT_link_viewer"); + + ot = WM_operatortype_append_macro("NODE_OT_translate_attach", + "Move and Attach", + "Move nodes and attach to frame", + OPTYPE_UNDO | OPTYPE_REGISTER); + mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + WM_operatortype_macro_define(ot, "NODE_OT_attach"); + WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); + + /* NODE_OT_translate_attach with remove_on_canel set to true */ + ot = WM_operatortype_append_macro("NODE_OT_translate_attach_remove_on_cancel", + "Move and Attach", + "Move nodes and attach to frame", + OPTYPE_UNDO | OPTYPE_REGISTER); + mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(mot->ptr, "remove_on_cancel", true); + RNA_boolean_set(mot->ptr, "view2d_edge_pan", true); + WM_operatortype_macro_define(ot, "NODE_OT_attach"); + WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); + + /* NOTE: Currently not in a default keymap or menu due to messy keymaps + * and tricky invoke functionality. + * Kept around in case users want to make own shortcuts. + */ + ot = WM_operatortype_append_macro("NODE_OT_detach_translate_attach", + "Detach and Move", + "Detach nodes, move and attach to frame", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "NODE_OT_detach"); + mot = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + WM_operatortype_macro_define(ot, "NODE_OT_attach"); + + ot = WM_operatortype_append_macro("NODE_OT_duplicate_move", + "Duplicate", + "Duplicate selected nodes and move them", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); + WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); + + /* modified operator call for duplicating with input links */ + ot = WM_operatortype_append_macro("NODE_OT_duplicate_move_keep_inputs", + "Duplicate", + "Duplicate selected nodes keeping input links and move them", + OPTYPE_UNDO | OPTYPE_REGISTER); + mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate"); + RNA_boolean_set(mot->ptr, "keep_inputs", true); + WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); + + ot = WM_operatortype_append_macro("NODE_OT_move_detach_links", + "Detach", + "Move a node to detach links", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "NODE_OT_links_detach"); + WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + WM_operatortype_macro_define(ot, "NODE_OT_insert_offset"); + + ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release", + "Detach", + "Move a node to detach links", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "NODE_OT_links_detach"); + WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); +} + +void node_keymap(struct wmKeyConfig *keyconf) +{ + /* Entire Editor only ----------------- */ + WM_keymap_ensure(keyconf, "Node Generic", SPACE_NODE, 0); + + /* Main Region only ----------------- */ + WM_keymap_ensure(keyconf, "Node Editor", SPACE_NODE, 0); +} diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 55b547d3195..2cf3be50f23 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -60,7 +60,7 @@ #include "NOD_node_declaration.hh" #include "NOD_node_tree_ref.hh" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ using namespace blender::nodes::node_tree_ref_types; diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 29b8372d043..3c7b404547b 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -61,7 +61,7 @@ #include "MEM_guardedalloc.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ /** * Function to detect if there is a visible view3d that uses workbench in texture mode. diff --git a/source/blender/editors/space_node/node_templates.cc b/source/blender/editors/space_node/node_templates.cc index f68d8589624..b2a7c1753fb 100644 --- a/source/blender/editors/space_node/node_templates.cc +++ b/source/blender/editors/space_node/node_templates.cc @@ -48,7 +48,7 @@ #include "UI_interface.h" #include "ED_node.h" /* own include */ -#include "node_intern.h" +#include "node_intern.hh" #include "ED_undo.h" diff --git a/source/blender/editors/space_node/node_toolbar.cc b/source/blender/editors/space_node/node_toolbar.cc index 2e7d6ab6cd5..c32dcbef91b 100644 --- a/source/blender/editors/space_node/node_toolbar.cc +++ b/source/blender/editors/space_node/node_toolbar.cc @@ -30,7 +30,7 @@ #include "WM_api.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ /* ******************* node toolbar registration ************** */ diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc index 762b4b36a39..36b84bec7eb 100644 --- a/source/blender/editors/space_node/node_view.cc +++ b/source/blender/editors/space_node/node_view.cc @@ -54,7 +54,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "node_intern.h" /* own include */ +#include "node_intern.hh" /* own include */ using blender::StringRef; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c deleted file mode 100644 index 0b5d7cdda82..00000000000 --- a/source/blender/editors/space_node/space_node.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup spnode - */ - -#include "DNA_gpencil_types.h" -#include "DNA_light_types.h" -#include "DNA_material_types.h" -#include "DNA_node_types.h" -#include "DNA_world_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BKE_context.h" -#include "BKE_lib_id.h" -#include "BKE_node.h" -#include "BKE_screen.h" - -#include "ED_node.h" -#include "ED_render.h" -#include "ED_screen.h" -#include "ED_space_api.h" - -#include "UI_resources.h" -#include "UI_view2d.h" - -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "node_intern.h" /* own include */ - -/* ******************** tree path ********************* */ - -void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from) -{ - bNodeTreePath *path, *path_next; - for (path = snode->treepath.first; path; path = path_next) { - path_next = path->next; - MEM_freeN(path); - } - BLI_listbase_clear(&snode->treepath); - - if (ntree) { - path = MEM_callocN(sizeof(bNodeTreePath), "node tree path"); - path->nodetree = ntree; - path->parent_key = NODE_INSTANCE_KEY_BASE; - - /* copy initial offset from bNodeTree */ - copy_v2_v2(path->view_center, ntree->view_center); - - if (id) { - BLI_strncpy(path->display_name, id->name + 2, sizeof(path->display_name)); - } - - BLI_addtail(&snode->treepath, path); - - if (ntree->type != NTREE_GEOMETRY) { - /* This can probably be removed for all node tree types. It mainly exists because it was not - * possible to store id references in custom properties. Also see T36024. I don't want to - * remove it for all tree types in bcon3 though. */ - id_us_ensure_real(&ntree->id); - } - } - - /* update current tree */ - snode->nodetree = snode->edittree = ntree; - snode->id = id; - snode->from = from; - - ED_node_set_active_viewer_key(snode); - - WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); -} - -void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode) -{ - bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path"); - bNodeTreePath *prev_path = snode->treepath.last; - path->nodetree = ntree; - if (gnode) { - if (prev_path) { - path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode); - } - else { - path->parent_key = NODE_INSTANCE_KEY_BASE; - } - - BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name)); - BLI_strncpy(path->display_name, gnode->name, sizeof(path->display_name)); - } - else { - path->parent_key = NODE_INSTANCE_KEY_BASE; - } - - /* copy initial offset from bNodeTree */ - copy_v2_v2(path->view_center, ntree->view_center); - - BLI_addtail(&snode->treepath, path); - - id_us_ensure_real(&ntree->id); - - /* update current tree */ - snode->edittree = ntree; - - ED_node_set_active_viewer_key(snode); - - WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); -} - -void ED_node_tree_pop(SpaceNode *snode) -{ - bNodeTreePath *path = snode->treepath.last; - - /* don't remove root */ - if (path == snode->treepath.first) { - return; - } - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); - - /* update current tree */ - path = snode->treepath.last; - snode->edittree = path->nodetree; - - ED_node_set_active_viewer_key(snode); - - /* listener updates the View2D center from edittree */ - WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); -} - -int ED_node_tree_depth(SpaceNode *snode) -{ - return BLI_listbase_count(&snode->treepath); -} - -bNodeTree *ED_node_tree_get(SpaceNode *snode, int level) -{ - bNodeTreePath *path; - int i; - for (path = snode->treepath.last, i = 0; path; path = path->prev, i++) { - if (i == level) { - return path->nodetree; - } - } - return NULL; -} - -int ED_node_tree_path_length(SpaceNode *snode) -{ - int length = 0; - int i = 0; - LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) { - length += strlen(path->display_name); - if (i > 0) { - length += 1; /* for separator char */ - } - } - return length; -} - -void ED_node_tree_path_get(SpaceNode *snode, char *value) -{ - int i = 0; - - value[0] = '\0'; - LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) { - if (i == 0) { - strcpy(value, path->display_name); - value += strlen(path->display_name); - } - else { - sprintf(value, "/%s", path->display_name); - value += strlen(path->display_name) + 1; - } - } -} - -void ED_node_set_active_viewer_key(SpaceNode *snode) -{ - bNodeTreePath *path = snode->treepath.last; - if (snode->nodetree && path) { - snode->nodetree->active_viewer_key = path->parent_key; - } -} - -void space_node_group_offset(SpaceNode *snode, float *x, float *y) -{ - bNodeTreePath *path = snode->treepath.last; - - if (path && path->prev) { - float dcenter[2]; - sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center); - *x = dcenter[0]; - *y = dcenter[1]; - } - else { - *x = *y = 0.0f; - } -} - -/* ******************** default callbacks for node space ***************** */ - -static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) -{ - ARegion *region; - SpaceNode *snode; - - snode = MEM_callocN(sizeof(SpaceNode), "initnode"); - snode->spacetype = SPACE_NODE; - - snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA; - snode->overlay.flag |= SN_OVERLAY_SHOW_OVERLAYS; - snode->overlay.flag |= SN_OVERLAY_SHOW_WIRE_COLORS; - - /* backdrop */ - snode->zoom = 1.0f; - - /* select the first tree type for valid type */ - NODE_TREE_TYPES_BEGIN (treetype) { - strcpy(snode->tree_idname, treetype->idname); - break; - } - NODE_TREE_TYPES_END; - - /* header */ - region = MEM_callocN(sizeof(ARegion), "header for node"); - - BLI_addtail(&snode->regionbase, region); - region->regiontype = RGN_TYPE_HEADER; - region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; - - /* buttons/list view */ - region = MEM_callocN(sizeof(ARegion), "buttons for node"); - - BLI_addtail(&snode->regionbase, region); - region->regiontype = RGN_TYPE_UI; - region->alignment = RGN_ALIGN_RIGHT; - - /* toolbar */ - region = MEM_callocN(sizeof(ARegion), "node tools"); - - BLI_addtail(&snode->regionbase, region); - region->regiontype = RGN_TYPE_TOOLS; - region->alignment = RGN_ALIGN_LEFT; - - region->flag = RGN_FLAG_HIDDEN; - - /* main region */ - region = MEM_callocN(sizeof(ARegion), "main region for node"); - - BLI_addtail(&snode->regionbase, region); - region->regiontype = RGN_TYPE_WINDOW; - - region->v2d.tot.xmin = -12.8f * U.widget_unit; - region->v2d.tot.ymin = -12.8f * U.widget_unit; - region->v2d.tot.xmax = 38.4f * U.widget_unit; - region->v2d.tot.ymax = 38.4f * U.widget_unit; - - region->v2d.cur = region->v2d.tot; - - region->v2d.min[0] = 1.0f; - region->v2d.min[1] = 1.0f; - - region->v2d.max[0] = 32000.0f; - region->v2d.max[1] = 32000.0f; - - region->v2d.minzoom = 0.09f; - region->v2d.maxzoom = 2.31f; - - region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); - region->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT; - region->v2d.keeptot = 0; - - return (SpaceLink *)snode; -} - -static void node_free(SpaceLink *sl) -{ - SpaceNode *snode = (SpaceNode *)sl; - - LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { - MEM_freeN(path); - } - - MEM_SAFE_FREE(snode->runtime); -} - -/* spacetype; init callback */ -static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) -{ - SpaceNode *snode = (SpaceNode *)area->spacedata.first; - - if (snode->runtime == NULL) { - snode->runtime = MEM_callocN(sizeof(SpaceNode_Runtime), __func__); - } -} - -static void node_area_listener(const wmSpaceTypeListenerParams *params) -{ - ScrArea *area = params->area; - wmNotifier *wmn = params->notifier; - - /* NOTE: #ED_area_tag_refresh will re-execute compositor. */ - SpaceNode *snode = area->spacedata.first; - /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ - short shader_type = snode->shaderfrom; - - /* preview renders */ - switch (wmn->category) { - case NC_SCENE: - switch (wmn->data) { - case ND_NODES: { - ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); - bNodeTreePath *path = snode->treepath.last; - /* shift view to node tree center */ - if (region && path) { - UI_view2d_center_set(®ion->v2d, path->view_center[0], path->view_center[1]); - } - - ED_area_tag_refresh(area); - break; - } - case ND_FRAME: - ED_area_tag_refresh(area); - break; - case ND_COMPO_RESULT: - ED_area_tag_redraw(area); - break; - case ND_TRANSFORM_DONE: - if (ED_node_is_compositor(snode)) { - if (snode->flag & SNODE_AUTO_RENDER) { - snode->runtime->recalc = true; - ED_area_tag_refresh(area); - } - } - break; - case ND_LAYER_CONTENT: - ED_area_tag_refresh(area); - break; - } - break; - - /* future: add ID checks? */ - case NC_MATERIAL: - if (ED_node_is_shader(snode)) { - if (wmn->data == ND_SHADING) { - ED_area_tag_refresh(area); - } - else if (wmn->data == ND_SHADING_DRAW) { - ED_area_tag_refresh(area); - } - else if (wmn->data == ND_SHADING_LINKS) { - ED_area_tag_refresh(area); - } - else if (wmn->action == NA_ADDED && snode->edittree) { - nodeSetActiveID(snode->edittree, ID_MA, wmn->reference); - } - } - break; - case NC_TEXTURE: - if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) { - if (wmn->data == ND_NODES) { - ED_area_tag_refresh(area); - } - } - break; - case NC_WORLD: - if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) { - ED_area_tag_refresh(area); - } - break; - case NC_OBJECT: - if (ED_node_is_shader(snode)) { - if (wmn->data == ND_OB_SHADING) { - ED_area_tag_refresh(area); - } - } - else if (ED_node_is_geometry(snode)) { - /* Rather strict check: only redraw when the reference matches the current editor's ID. */ - if (wmn->data == ND_MODIFIER) { - if (wmn->reference == snode->id || snode->id == NULL) { - ED_area_tag_refresh(area); - } - } - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_NODE) { - ED_area_tag_refresh(area); - } - else if (wmn->data == ND_SPACE_NODE_VIEW) { - ED_area_tag_redraw(area); - } - break; - case NC_NODE: - if (wmn->action == NA_EDITED) { - ED_area_tag_refresh(area); - } - else if (wmn->action == NA_SELECTED) { - ED_area_tag_redraw(area); - } - break; - case NC_SCREEN: - switch (wmn->data) { - case ND_ANIMPLAY: - ED_area_tag_refresh(area); - break; - } - break; - case NC_MASK: - if (wmn->action == NA_EDITED) { - if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) { - ED_area_tag_refresh(area); - } - } - break; - - case NC_IMAGE: - if (wmn->action == NA_EDITED) { - if (ED_node_is_compositor(snode)) { - /* note that nodeUpdateID is already called by BKE_image_signal() on all - * scenes so really this is just to know if the images is used in the compo else - * painting on images could become very slow when the compositor is open. */ - if (nodeUpdateID(snode->nodetree, wmn->reference)) { - ED_area_tag_refresh(area); - } - } - } - break; - - case NC_MOVIECLIP: - if (wmn->action == NA_EDITED) { - if (ED_node_is_compositor(snode)) { - if (nodeUpdateID(snode->nodetree, wmn->reference)) { - ED_area_tag_refresh(area); - } - } - } - break; - - case NC_LINESTYLE: - if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) { - ED_area_tag_refresh(area); - } - break; - case NC_WM: - if (wmn->data == ND_UNDO) { - ED_area_tag_refresh(area); - } - break; - case NC_GPENCIL: - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_area_tag_redraw(area); - } - break; - } -} - -static void node_area_refresh(const struct bContext *C, ScrArea *area) -{ - /* default now: refresh node is starting preview */ - SpaceNode *snode = area->spacedata.first; - - snode_set_context(C); - - if (snode->nodetree) { - if (snode->nodetree->type == NTREE_SHADER) { - if (GS(snode->id->name) == ID_MA) { - Material *ma = (Material *)snode->id; - if (ma->use_nodes) { - ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); - } - } - else if (GS(snode->id->name) == ID_LA) { - Light *la = (Light *)snode->id; - if (la->use_nodes) { - ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); - } - } - else if (GS(snode->id->name) == ID_WO) { - World *wo = (World *)snode->id; - if (wo->use_nodes) { - ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); - } - } - } - else if (snode->nodetree->type == NTREE_COMPOSIT) { - Scene *scene = (Scene *)snode->id; - if (scene->use_nodes) { - /* recalc is set on 3d view changes for auto compo */ - if (snode->runtime->recalc) { - snode->runtime->recalc = false; - node_render_changed_exec((struct bContext *)C, NULL); - } - else { - ED_node_composite_job(C, snode->nodetree, scene); - } - } - } - else if (snode->nodetree->type == NTREE_TEXTURE) { - Tex *tex = (Tex *)snode->id; - if (tex->use_nodes) { - ED_preview_shader_job(C, area, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); - } - } - } -} - -static SpaceLink *node_duplicate(SpaceLink *sl) -{ - SpaceNode *snode = (SpaceNode *)sl; - SpaceNode *snoden = MEM_dupallocN(snode); - - BLI_duplicatelist(&snoden->treepath, &snode->treepath); - - if (snode->runtime != NULL) { - snoden->runtime = MEM_dupallocN(snode->runtime); - BLI_listbase_clear(&snoden->runtime->linkdrag); - } - - /* NOTE: no need to set node tree user counts, - * the editor only keeps at least 1 (id_us_ensure_real), - * which is already done by the original SpaceNode. - */ - - return (SpaceLink *)snoden; -} - -/* add handlers, stuff you only do once or on area/region changes */ -static void node_buttons_region_init(wmWindowManager *wm, ARegion *region) -{ - wmKeyMap *keymap; - - ED_region_panels_init(wm, region); - - keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); - WM_event_add_keymap_handler(®ion->handlers, keymap); -} - -static void node_buttons_region_draw(const bContext *C, ARegion *region) -{ - ED_region_panels(C, region); -} - -/* add handlers, stuff you only do once or on area/region changes */ -static void node_toolbar_region_init(wmWindowManager *wm, ARegion *region) -{ - wmKeyMap *keymap; - - ED_region_panels_init(wm, region); - - keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); - WM_event_add_keymap_handler(®ion->handlers, keymap); -} - -static void node_toolbar_region_draw(const bContext *C, ARegion *region) -{ - ED_region_panels(C, region); -} - -void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]) -{ - copy_v2_v2(value, snode->runtime->cursor); -} - -void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]) -{ - copy_v2_v2(snode->runtime->cursor, value); -} - -static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) -{ - SpaceNode *snode = area->spacedata.first; - - /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view(®ion->v2d, - win->eventstate->xy[0] - region->winrct.xmin, - win->eventstate->xy[1] - region->winrct.ymin, - &snode->runtime->cursor[0], - &snode->runtime->cursor[1]); - - /* here snode->runtime->cursor is used to detect the node edge for sizing */ - node_set_cursor(win, snode, snode->runtime->cursor); - - /* XXX snode->runtime->cursor is in placing new nodes space */ - snode->runtime->cursor[0] /= UI_DPI_FAC; - snode->runtime->cursor[1] /= UI_DPI_FAC; -} - -/* Initialize main region, setting handlers. */ -static void node_main_region_init(wmWindowManager *wm, ARegion *region) -{ - wmKeyMap *keymap; - ListBase *lb; - - UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy); - - /* own keymaps */ - keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); - WM_event_add_keymap_handler(®ion->handlers, keymap); - - keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0); - WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); - - /* add drop boxes */ - lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); - - WM_event_add_dropbox_handler(®ion->handlers, lb); - - /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on - * region size changes. */ - WM_gizmomap_tag_refresh(region->gizmo_map); -} - -static void node_main_region_draw(const bContext *C, ARegion *region) -{ - node_draw_space(C, region); -} - -/* ************* dropboxes ************* */ - -static bool node_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_NT); -} - -static bool node_object_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_OB); -} - -static bool node_collection_drop_poll(bContext *UNUSED(C), - wmDrag *drag, - const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_GR); -} - -static bool node_texture_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_TE); -} - -static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - if (drag->type == WM_DRAG_PATH) { - /* rule might not work? */ - return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); - } - return WM_drag_is_ID_type(drag, ID_IM); -} - -static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) -{ - return WM_drag_is_ID_type(drag, ID_MSK); -} - -static void node_group_drop_copy(wmDrag *drag, wmDropBox *drop) -{ - ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); - - RNA_string_set(drop->ptr, "name", id->name + 2); -} - -static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) -{ - ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); - - RNA_string_set(drop->ptr, "name", id->name + 2); -} - -static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) -{ - ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); - - if (id) { - RNA_string_set(drop->ptr, "name", id->name + 2); - RNA_struct_property_unset(drop->ptr, "filepath"); - } - else if (drag->path[0]) { - RNA_string_set(drop->ptr, "filepath", drag->path); - RNA_struct_property_unset(drop->ptr, "name"); - } -} - -/* this region dropbox definition */ -static void node_dropboxes(void) -{ - ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); - - WM_dropbox_add(lb, - "NODE_OT_add_object", - node_object_drop_poll, - node_id_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, - "NODE_OT_add_collection", - node_collection_drop_poll, - node_id_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, - "NODE_OT_add_texture", - node_texture_drop_poll, - node_id_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, - "NODE_OT_add_group", - node_group_drop_poll, - node_group_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, - "NODE_OT_add_file", - node_ima_drop_poll, - node_id_path_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); - WM_dropbox_add(lb, - "NODE_OT_add_mask", - node_mask_drop_poll, - node_id_drop_copy, - WM_drag_free_imported_drag_ID, - NULL); -} - -/* ************* end drop *********** */ - -/* add handlers, stuff you only do once or on area/region changes */ -static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) -{ - ED_region_header_init(region); -} - -static void node_header_region_draw(const bContext *C, ARegion *region) -{ - /* find and set the context */ - snode_set_context(C); - - ED_region_header(C, region); -} - -/* used for header + main region */ -static void node_region_listener(const wmRegionListenerParams *params) -{ - ARegion *region = params->region; - wmNotifier *wmn = params->notifier; - wmGizmoMap *gzmap = region->gizmo_map; - - /* context changes */ - switch (wmn->category) { - case NC_SPACE: - switch (wmn->data) { - case ND_SPACE_NODE: - ED_region_tag_redraw(region); - break; - case ND_SPACE_NODE_VIEW: - WM_gizmomap_tag_refresh(gzmap); - break; - } - break; - case NC_SCREEN: - if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) { - WM_gizmomap_tag_refresh(gzmap); - } - switch (wmn->data) { - case ND_ANIMPLAY: - case ND_LAYER: - ED_region_tag_redraw(region); - break; - } - break; - case NC_WM: - if (wmn->data == ND_JOB) { - ED_region_tag_redraw(region); - } - break; - case NC_SCENE: - ED_region_tag_redraw(region); - if (wmn->data == ND_RENDER_RESULT) { - WM_gizmomap_tag_refresh(gzmap); - } - break; - case NC_NODE: - ED_region_tag_redraw(region); - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - WM_gizmomap_tag_refresh(gzmap); - } - break; - case NC_MATERIAL: - case NC_TEXTURE: - case NC_WORLD: - case NC_LINESTYLE: - ED_region_tag_redraw(region); - break; - case NC_OBJECT: - if (wmn->data == ND_OB_SHADING) { - ED_region_tag_redraw(region); - } - break; - case NC_ID: - if (wmn->action == NA_RENAME) { - ED_region_tag_redraw(region); - } - break; - case NC_GPENCIL: - if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(region); - } - else if (wmn->data & ND_GPENCIL_EDITMODE) { - ED_region_tag_redraw(region); - } - break; - } -} - -const char *node_context_dir[] = { - "selected_nodes", "active_node", "light", "material", "world", NULL}; -static int /*eContextResult*/ node_context(const bContext *C, - const char *member, - bContextDataResult *result) -{ - SpaceNode *snode = CTX_wm_space_node(C); - - if (CTX_data_dir(member)) { - CTX_data_dir_set(result, node_context_dir); - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "selected_nodes")) { - bNode *node; - - if (snode->edittree) { - for (node = snode->edittree->nodes.last; node; node = node->prev) { - if (node->flag & NODE_SELECT) { - CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node); - } - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "active_node")) { - if (snode->edittree) { - bNode *node = nodeGetActive(snode->edittree); - CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node); - } - - CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "node_previews")) { - if (snode->nodetree) { - CTX_data_pointer_set( - result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews); - } - - CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "material")) { - if (snode->id && GS(snode->id->name) == ID_MA) { - CTX_data_id_pointer_set(result, snode->id); - } - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "light")) { - if (snode->id && GS(snode->id->name) == ID_LA) { - CTX_data_id_pointer_set(result, snode->id); - } - return CTX_RESULT_OK; - } - if (CTX_data_equals(member, "world")) { - if (snode->id && GS(snode->id->name) == ID_WO) { - CTX_data_id_pointer_set(result, snode->id); - } - return CTX_RESULT_OK; - } - - return CTX_RESULT_MEMBER_NOT_FOUND; -} - -static void node_widgets(void) -{ - /* create the widgetmap for the area here */ - wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure( - &(const struct wmGizmoMapType_Params){SPACE_NODE, RGN_TYPE_WINDOW}); - WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform); - WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop); - WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams); - WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin); -} - -static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id) -{ - SpaceNode *snode = (SpaceNode *)slink; - - if (snode->id == old_id) { - /* nasty DNA logic for SpaceNode: - * ideally should be handled by editor code, but would be bad level call - */ - BLI_freelistN(&snode->treepath); - - /* XXX Untested in case new_id != NULL... */ - snode->id = new_id; - snode->from = NULL; - snode->nodetree = NULL; - snode->edittree = NULL; - } - else if (GS(old_id->name) == ID_OB) { - if (snode->from == old_id) { - if (new_id == NULL) { - snode->flag &= ~SNODE_PIN; - } - snode->from = new_id; - } - } - else if (GS(old_id->name) == ID_GD) { - if ((ID *)snode->gpd == old_id) { - snode->gpd = (bGPdata *)new_id; - id_us_min(old_id); - id_us_plus(new_id); - } - } - else if (GS(old_id->name) == ID_NT) { - bNodeTreePath *path, *path_next; - - for (path = snode->treepath.first; path; path = path->next) { - if ((ID *)path->nodetree == old_id) { - path->nodetree = (bNodeTree *)new_id; - id_us_ensure_real(new_id); - } - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - snode->nodetree = path->nodetree; - } - if (path->nodetree == NULL) { - break; - } - } - - /* remaining path entries are invalid, remove */ - for (; path; path = path_next) { - path_next = path->next; - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); - } - - /* edittree is just the last in the path, - * set this directly since the path may have been shortened above */ - if (snode->treepath.last) { - path = snode->treepath.last; - snode->edittree = path->nodetree; - } - else { - snode->edittree = NULL; - } - } -} - -static int node_space_subtype_get(ScrArea *area) -{ - SpaceNode *snode = area->spacedata.first; - return rna_node_tree_idname_to_enum(snode->tree_idname); -} - -static void node_space_subtype_set(ScrArea *area, int value) -{ - SpaceNode *snode = area->spacedata.first; - ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value)); -} - -static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem) -{ - bool free; - const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); - RNA_enum_items_add(item, totitem, item_src); - if (free) { - MEM_freeN((void *)item_src); - } -} - -/* only called once, from space/spacetypes.c */ -void ED_spacetype_node(void) -{ - SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype node"); - ARegionType *art; - - st->spaceid = SPACE_NODE; - strncpy(st->name, "Node", BKE_ST_MAXNAME); - - st->create = node_create; - st->free = node_free; - st->init = node_init; - st->duplicate = node_duplicate; - st->operatortypes = node_operatortypes; - st->keymap = node_keymap; - st->listener = node_area_listener; - st->refresh = node_area_refresh; - st->context = node_context; - st->dropboxes = node_dropboxes; - st->gizmos = node_widgets; - st->id_remap = node_id_remap; - st->space_subtype_item_extend = node_space_subtype_item_extend; - st->space_subtype_get = node_space_subtype_get; - st->space_subtype_set = node_space_subtype_set; - - /* regions: main window */ - art = MEM_callocN(sizeof(ARegionType), "spacetype node region"); - art->regionid = RGN_TYPE_WINDOW; - art->init = node_main_region_init; - art->draw = node_main_region_draw; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D | - ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL; - art->listener = node_region_listener; - art->cursor = node_cursor; - art->event_cursor = true; - art->clip_gizmo_events_by_ui = true; - - BLI_addhead(&st->regiontypes, art); - - /* regions: header */ - art = MEM_callocN(sizeof(ARegionType), "spacetype node region"); - art->regionid = RGN_TYPE_HEADER; - art->prefsizey = HEADERY; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; - art->listener = node_region_listener; - art->init = node_header_region_init; - art->draw = node_header_region_draw; - - BLI_addhead(&st->regiontypes, art); - - /* regions: listview/buttons */ - art = MEM_callocN(sizeof(ARegionType), "spacetype node region"); - art->regionid = RGN_TYPE_UI; - art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; - art->listener = node_region_listener; - art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; - art->init = node_buttons_region_init; - art->draw = node_buttons_region_draw; - BLI_addhead(&st->regiontypes, art); - - /* regions: toolbar */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); - art->regionid = RGN_TYPE_TOOLS; - art->prefsizex = 58; /* XXX */ - art->prefsizey = 50; /* XXX */ - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; - art->listener = node_region_listener; - art->message_subscribe = ED_region_generic_tools_region_message_subscribe; - art->snap_size = ED_region_generic_tools_region_snap_size; - art->init = node_toolbar_region_init; - art->draw = node_toolbar_region_draw; - BLI_addhead(&st->regiontypes, art); - - node_toolbar_register(art); - - BKE_spacetype_register(st); -} diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc new file mode 100644 index 00000000000..53592aef98b --- /dev/null +++ b/source/blender/editors/space_node/space_node.cc @@ -0,0 +1,1081 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup spnode + */ + +#include "DNA_gpencil_types.h" +#include "DNA_light_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" +#include "DNA_world_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_lib_id.h" +#include "BKE_node.h" +#include "BKE_screen.h" + +#include "ED_node.h" +#include "ED_render.h" +#include "ED_screen.h" +#include "ED_space_api.h" + +#include "UI_resources.h" +#include "UI_view2d.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "node_intern.hh" /* own include */ + +/* ******************** tree path ********************* */ + +void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from) +{ + LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { + MEM_freeN(path); + } + BLI_listbase_clear(&snode->treepath); + + if (ntree) { + bNodeTreePath *path = (bNodeTreePath *)MEM_callocN(sizeof(bNodeTreePath), "node tree path"); + path->nodetree = ntree; + path->parent_key = NODE_INSTANCE_KEY_BASE; + + /* copy initial offset from bNodeTree */ + copy_v2_v2(path->view_center, ntree->view_center); + + if (id) { + BLI_strncpy(path->display_name, id->name + 2, sizeof(path->display_name)); + } + + BLI_addtail(&snode->treepath, path); + + if (ntree->type != NTREE_GEOMETRY) { + /* This can probably be removed for all node tree types. It mainly exists because it was not + * possible to store id references in custom properties. Also see T36024. I don't want to + * remove it for all tree types in bcon3 though. */ + id_us_ensure_real(&ntree->id); + } + } + + /* update current tree */ + snode->nodetree = snode->edittree = ntree; + snode->id = id; + snode->from = from; + + ED_node_set_active_viewer_key(snode); + + WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr); +} + +void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode) +{ + bNodeTreePath *path = (bNodeTreePath *)MEM_callocN(sizeof(bNodeTreePath), "node tree path"); + bNodeTreePath *prev_path = (bNodeTreePath *)snode->treepath.last; + path->nodetree = ntree; + if (gnode) { + if (prev_path) { + path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode); + } + else { + path->parent_key = NODE_INSTANCE_KEY_BASE; + } + + BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name)); + BLI_strncpy(path->display_name, gnode->name, sizeof(path->display_name)); + } + else { + path->parent_key = NODE_INSTANCE_KEY_BASE; + } + + /* copy initial offset from bNodeTree */ + copy_v2_v2(path->view_center, ntree->view_center); + + BLI_addtail(&snode->treepath, path); + + id_us_ensure_real(&ntree->id); + + /* update current tree */ + snode->edittree = ntree; + + ED_node_set_active_viewer_key(snode); + + WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr); +} + +void ED_node_tree_pop(SpaceNode *snode) +{ + bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last; + + /* don't remove root */ + if (path == snode->treepath.first) { + return; + } + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + + /* update current tree */ + path = (bNodeTreePath *)snode->treepath.last; + snode->edittree = path->nodetree; + + ED_node_set_active_viewer_key(snode); + + /* listener updates the View2D center from edittree */ + WM_main_add_notifier(NC_SCENE | ND_NODES, nullptr); +} + +int ED_node_tree_depth(SpaceNode *snode) +{ + return BLI_listbase_count(&snode->treepath); +} + +bNodeTree *ED_node_tree_get(SpaceNode *snode, int level) +{ + bNodeTreePath *path; + int i; + for (path = (bNodeTreePath *)snode->treepath.last, i = 0; path; path = path->prev, i++) { + if (i == level) { + return path->nodetree; + } + } + return nullptr; +} + +int ED_node_tree_path_length(SpaceNode *snode) +{ + int length = 0; + int i = 0; + LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) { + length += strlen(path->display_name); + if (i > 0) { + length += 1; /* for separator char */ + } + } + return length; +} + +void ED_node_tree_path_get(SpaceNode *snode, char *value) +{ + int i = 0; + + value[0] = '\0'; + LISTBASE_FOREACH_INDEX (bNodeTreePath *, path, &snode->treepath, i) { + if (i == 0) { + strcpy(value, path->display_name); + value += strlen(path->display_name); + } + else { + sprintf(value, "/%s", path->display_name); + value += strlen(path->display_name) + 1; + } + } +} + +void ED_node_set_active_viewer_key(SpaceNode *snode) +{ + bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last; + if (snode->nodetree && path) { + snode->nodetree->active_viewer_key = path->parent_key; + } +} + +void space_node_group_offset(SpaceNode *snode, float *x, float *y) +{ + bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last; + + if (path && path->prev) { + float dcenter[2]; + sub_v2_v2v2(dcenter, path->view_center, path->prev->view_center); + *x = dcenter[0]; + *y = dcenter[1]; + } + else { + *x = *y = 0.0f; + } +} + +/* ******************** default callbacks for node space ***************** */ + +static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +{ + SpaceNode *snode = (SpaceNode *)MEM_callocN(sizeof(SpaceNode), "initnode"); + snode->spacetype = SPACE_NODE; + + snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA; + snode->overlay.flag |= SN_OVERLAY_SHOW_OVERLAYS; + snode->overlay.flag |= SN_OVERLAY_SHOW_WIRE_COLORS; + + /* backdrop */ + snode->zoom = 1.0f; + + /* select the first tree type for valid type */ + NODE_TREE_TYPES_BEGIN (treetype) { + strcpy(snode->tree_idname, treetype->idname); + break; + } + NODE_TREE_TYPES_END; + + /* header */ + ARegion *region = (ARegion *)MEM_callocN(sizeof(ARegion), "header for node"); + + BLI_addtail(&snode->regionbase, region); + region->regiontype = RGN_TYPE_HEADER; + region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + + /* buttons/list view */ + region = (ARegion *)MEM_callocN(sizeof(ARegion), "buttons for node"); + + BLI_addtail(&snode->regionbase, region); + region->regiontype = RGN_TYPE_UI; + region->alignment = RGN_ALIGN_RIGHT; + + /* toolbar */ + region = (ARegion *)MEM_callocN(sizeof(ARegion), "node tools"); + + BLI_addtail(&snode->regionbase, region); + region->regiontype = RGN_TYPE_TOOLS; + region->alignment = RGN_ALIGN_LEFT; + + region->flag = RGN_FLAG_HIDDEN; + + /* main region */ + region = (ARegion *)MEM_callocN(sizeof(ARegion), "main region for node"); + + BLI_addtail(&snode->regionbase, region); + region->regiontype = RGN_TYPE_WINDOW; + + region->v2d.tot.xmin = -12.8f * U.widget_unit; + region->v2d.tot.ymin = -12.8f * U.widget_unit; + region->v2d.tot.xmax = 38.4f * U.widget_unit; + region->v2d.tot.ymax = 38.4f * U.widget_unit; + + region->v2d.cur = region->v2d.tot; + + region->v2d.min[0] = 1.0f; + region->v2d.min[1] = 1.0f; + + region->v2d.max[0] = 32000.0f; + region->v2d.max[1] = 32000.0f; + + region->v2d.minzoom = 0.09f; + region->v2d.maxzoom = 2.31f; + + region->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); + region->v2d.keepzoom = V2D_LIMITZOOM | V2D_KEEPASPECT; + region->v2d.keeptot = 0; + + return (SpaceLink *)snode; +} + +static void node_free(SpaceLink *sl) +{ + SpaceNode *snode = (SpaceNode *)sl; + + LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { + MEM_freeN(path); + } + + MEM_SAFE_FREE(snode->runtime); +} + +/* spacetype; init callback */ +static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) +{ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + if (snode->runtime == nullptr) { + snode->runtime = (SpaceNode_Runtime *)MEM_callocN(sizeof(SpaceNode_Runtime), __func__); + } +} + +static void node_area_listener(const wmSpaceTypeListenerParams *params) +{ + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + + /* NOTE: #ED_area_tag_refresh will re-execute compositor. */ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ + short shader_type = snode->shaderfrom; + + /* preview renders */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + case ND_NODES: { + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last; + /* shift view to node tree center */ + if (region && path) { + UI_view2d_center_set(®ion->v2d, path->view_center[0], path->view_center[1]); + } + + ED_area_tag_refresh(area); + break; + } + case ND_FRAME: + ED_area_tag_refresh(area); + break; + case ND_COMPO_RESULT: + ED_area_tag_redraw(area); + break; + case ND_TRANSFORM_DONE: + if (ED_node_is_compositor(snode)) { + if (snode->flag & SNODE_AUTO_RENDER) { + snode->runtime->recalc = true; + ED_area_tag_refresh(area); + } + } + break; + case ND_LAYER_CONTENT: + ED_area_tag_refresh(area); + break; + } + break; + + /* future: add ID checks? */ + case NC_MATERIAL: + if (ED_node_is_shader(snode)) { + if (wmn->data == ND_SHADING) { + ED_area_tag_refresh(area); + } + else if (wmn->data == ND_SHADING_DRAW) { + ED_area_tag_refresh(area); + } + else if (wmn->data == ND_SHADING_LINKS) { + ED_area_tag_refresh(area); + } + else if (wmn->action == NA_ADDED && snode->edittree) { + nodeSetActiveID(snode->edittree, ID_MA, (ID *)wmn->reference); + } + } + break; + case NC_TEXTURE: + if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) { + if (wmn->data == ND_NODES) { + ED_area_tag_refresh(area); + } + } + break; + case NC_WORLD: + if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) { + ED_area_tag_refresh(area); + } + break; + case NC_OBJECT: + if (ED_node_is_shader(snode)) { + if (wmn->data == ND_OB_SHADING) { + ED_area_tag_refresh(area); + } + } + else if (ED_node_is_geometry(snode)) { + /* Rather strict check: only redraw when the reference matches the current editor's ID. */ + if (wmn->data == ND_MODIFIER) { + if (wmn->reference == snode->id || snode->id == nullptr) { + ED_area_tag_refresh(area); + } + } + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_NODE) { + ED_area_tag_refresh(area); + } + else if (wmn->data == ND_SPACE_NODE_VIEW) { + ED_area_tag_redraw(area); + } + break; + case NC_NODE: + if (wmn->action == NA_EDITED) { + ED_area_tag_refresh(area); + } + else if (wmn->action == NA_SELECTED) { + ED_area_tag_redraw(area); + } + break; + case NC_SCREEN: + switch (wmn->data) { + case ND_ANIMPLAY: + ED_area_tag_refresh(area); + break; + } + break; + case NC_MASK: + if (wmn->action == NA_EDITED) { + if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) { + ED_area_tag_refresh(area); + } + } + break; + + case NC_IMAGE: + if (wmn->action == NA_EDITED) { + if (ED_node_is_compositor(snode)) { + /* note that nodeUpdateID is already called by BKE_image_signal() on all + * scenes so really this is just to know if the images is used in the compo else + * painting on images could become very slow when the compositor is open. */ + if (nodeUpdateID(snode->nodetree, (ID *)wmn->reference)) { + ED_area_tag_refresh(area); + } + } + } + break; + + case NC_MOVIECLIP: + if (wmn->action == NA_EDITED) { + if (ED_node_is_compositor(snode)) { + if (nodeUpdateID(snode->nodetree, (ID *)wmn->reference)) { + ED_area_tag_refresh(area); + } + } + } + break; + + case NC_LINESTYLE: + if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_LINESTYLE) { + ED_area_tag_refresh(area); + } + break; + case NC_WM: + if (wmn->data == ND_UNDO) { + ED_area_tag_refresh(area); + } + break; + case NC_GPENCIL: + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + ED_area_tag_redraw(area); + } + break; + } +} + +static void node_area_refresh(const struct bContext *C, ScrArea *area) +{ + /* default now: refresh node is starting preview */ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + snode_set_context(C); + + if (snode->nodetree) { + if (snode->nodetree->type == NTREE_SHADER) { + if (GS(snode->id->name) == ID_MA) { + Material *ma = (Material *)snode->id; + if (ma->use_nodes) { + ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER); + } + } + else if (GS(snode->id->name) == ID_LA) { + Light *la = (Light *)snode->id; + if (la->use_nodes) { + ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER); + } + } + else if (GS(snode->id->name) == ID_WO) { + World *wo = (World *)snode->id; + if (wo->use_nodes) { + ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER); + } + } + } + else if (snode->nodetree->type == NTREE_COMPOSIT) { + Scene *scene = (Scene *)snode->id; + if (scene->use_nodes) { + /* recalc is set on 3d view changes for auto compo */ + if (snode->runtime->recalc) { + snode->runtime->recalc = false; + node_render_changed_exec((struct bContext *)C, nullptr); + } + else { + ED_node_composite_job(C, snode->nodetree, scene); + } + } + } + else if (snode->nodetree->type == NTREE_TEXTURE) { + Tex *tex = (Tex *)snode->id; + if (tex->use_nodes) { + ED_preview_shader_job(C, area, snode->id, nullptr, nullptr, 100, 100, PR_NODE_RENDER); + } + } + } +} + +static SpaceLink *node_duplicate(SpaceLink *sl) +{ + SpaceNode *snode = (SpaceNode *)sl; + SpaceNode *snoden = (SpaceNode *)MEM_dupallocN(snode); + + BLI_duplicatelist(&snoden->treepath, &snode->treepath); + + if (snode->runtime != nullptr) { + snoden->runtime = (SpaceNode_Runtime *)MEM_dupallocN(snode->runtime); + BLI_listbase_clear(&snoden->runtime->linkdrag); + } + + /* NOTE: no need to set node tree user counts, + * the editor only keeps at least 1 (id_us_ensure_real), + * which is already done by the original SpaceNode. + */ + + return (SpaceLink *)snoden; +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void node_buttons_region_init(wmWindowManager *wm, ARegion *region) +{ + wmKeyMap *keymap; + + ED_region_panels_init(wm, region); + + keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); +} + +static void node_buttons_region_draw(const bContext *C, ARegion *region) +{ + ED_region_panels(C, region); +} + +/* add handlers, stuff you only do once or on area/region changes */ +static void node_toolbar_region_init(wmWindowManager *wm, ARegion *region) +{ + wmKeyMap *keymap; + + ED_region_panels_init(wm, region); + + keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); +} + +static void node_toolbar_region_draw(const bContext *C, ARegion *region) +{ + ED_region_panels(C, region); +} + +void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]) +{ + copy_v2_v2(value, snode->runtime->cursor); +} + +void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]) +{ + copy_v2_v2(snode->runtime->cursor, value); +} + +static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) +{ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + /* convert mouse coordinates to v2d space */ + UI_view2d_region_to_view(®ion->v2d, + win->eventstate->xy[0] - region->winrct.xmin, + win->eventstate->xy[1] - region->winrct.ymin, + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); + + /* here snode->runtime->cursor is used to detect the node edge for sizing */ + node_set_cursor(win, snode, snode->runtime->cursor); + + /* XXX snode->runtime->cursor is in placing new nodes space */ + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; +} + +/* Initialize main region, setting handlers. */ +static void node_main_region_init(wmWindowManager *wm, ARegion *region) +{ + wmKeyMap *keymap; + ListBase *lb; + + UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy); + + /* own keymaps */ + keymap = WM_keymap_ensure(wm->defaultconf, "Node Generic", SPACE_NODE, 0); + WM_event_add_keymap_handler(®ion->handlers, keymap); + + keymap = WM_keymap_ensure(wm->defaultconf, "Node Editor", SPACE_NODE, 0); + WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); + + /* add drop boxes */ + lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); + + WM_event_add_dropbox_handler(®ion->handlers, lb); + + /* The backdrop image gizmo needs to change together with the view. So always refresh gizmos on + * region size changes. */ + WM_gizmomap_tag_refresh(region->gizmo_map); +} + +static void node_main_region_draw(const bContext *C, ARegion *region) +{ + node_draw_space(C, region); +} + +/* ************* dropboxes ************* */ + +static bool node_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) +{ + return WM_drag_is_ID_type(drag, ID_NT); +} + +static bool node_object_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) +{ + return WM_drag_is_ID_type(drag, ID_OB); +} + +static bool node_collection_drop_poll(bContext *UNUSED(C), + wmDrag *drag, + const wmEvent *UNUSED(event)) +{ + return WM_drag_is_ID_type(drag, ID_GR); +} + +static bool node_texture_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) +{ + return WM_drag_is_ID_type(drag, ID_TE); +} + +static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) +{ + if (drag->type == WM_DRAG_PATH) { + /* rule might not work? */ + return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); + } + return WM_drag_is_ID_type(drag, ID_IM); +} + +static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) +{ + return WM_drag_is_ID_type(drag, ID_MSK); +} + +static void node_group_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); + + RNA_string_set(drop->ptr, "name", id->name + 2); +} + +static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); + + RNA_string_set(drop->ptr, "name", id->name + 2); +} + +static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); + + if (id) { + RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_struct_property_unset(drop->ptr, "filepath"); + } + else if (drag->path[0]) { + RNA_string_set(drop->ptr, "filepath", drag->path); + RNA_struct_property_unset(drop->ptr, "name"); + } +} + +/* this region dropbox definition */ +static void node_dropboxes() +{ + ListBase *lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); + + WM_dropbox_add(lb, + "NODE_OT_add_object", + node_object_drop_poll, + node_id_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); + WM_dropbox_add(lb, + "NODE_OT_add_collection", + node_collection_drop_poll, + node_id_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); + WM_dropbox_add(lb, + "NODE_OT_add_texture", + node_texture_drop_poll, + node_id_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); + WM_dropbox_add(lb, + "NODE_OT_add_group", + node_group_drop_poll, + node_group_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); + WM_dropbox_add(lb, + "NODE_OT_add_file", + node_ima_drop_poll, + node_id_path_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); + WM_dropbox_add(lb, + "NODE_OT_add_mask", + node_mask_drop_poll, + node_id_drop_copy, + WM_drag_free_imported_drag_ID, + nullptr); +} + +/* ************* end drop *********** */ + +/* add handlers, stuff you only do once or on area/region changes */ +static void node_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) +{ + ED_region_header_init(region); +} + +static void node_header_region_draw(const bContext *C, ARegion *region) +{ + /* find and set the context */ + snode_set_context(C); + + ED_region_header(C, region); +} + +/* used for header + main region */ +static void node_region_listener(const wmRegionListenerParams *params) +{ + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + wmGizmoMap *gzmap = region->gizmo_map; + + /* context changes */ + switch (wmn->category) { + case NC_SPACE: + switch (wmn->data) { + case ND_SPACE_NODE: + ED_region_tag_redraw(region); + break; + case ND_SPACE_NODE_VIEW: + WM_gizmomap_tag_refresh(gzmap); + break; + } + break; + case NC_SCREEN: + if (wmn->data == ND_LAYOUTSET || wmn->action == NA_EDITED) { + WM_gizmomap_tag_refresh(gzmap); + } + switch (wmn->data) { + case ND_ANIMPLAY: + case ND_LAYER: + ED_region_tag_redraw(region); + break; + } + break; + case NC_WM: + if (wmn->data == ND_JOB) { + ED_region_tag_redraw(region); + } + break; + case NC_SCENE: + ED_region_tag_redraw(region); + if (wmn->data == ND_RENDER_RESULT) { + WM_gizmomap_tag_refresh(gzmap); + } + break; + case NC_NODE: + ED_region_tag_redraw(region); + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + WM_gizmomap_tag_refresh(gzmap); + } + break; + case NC_MATERIAL: + case NC_TEXTURE: + case NC_WORLD: + case NC_LINESTYLE: + ED_region_tag_redraw(region); + break; + case NC_OBJECT: + if (wmn->data == ND_OB_SHADING) { + ED_region_tag_redraw(region); + } + break; + case NC_ID: + if (wmn->action == NA_RENAME) { + ED_region_tag_redraw(region); + } + break; + case NC_GPENCIL: + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw(region); + } + else if (wmn->data & ND_GPENCIL_EDITMODE) { + ED_region_tag_redraw(region); + } + break; + } +} + +const char *node_context_dir[] = { + "selected_nodes", "active_node", "light", "material", "world", nullptr}; +static int /*eContextResult*/ node_context(const bContext *C, + const char *member, + bContextDataResult *result) +{ + SpaceNode *snode = CTX_wm_space_node(C); + + if (CTX_data_dir(member)) { + CTX_data_dir_set(result, node_context_dir); + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "selected_nodes")) { + if (snode->edittree) { + LISTBASE_FOREACH_BACKWARD (bNode *, node, &snode->edittree->nodes) { + if (node->flag & NODE_SELECT) { + CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node); + } + } + } + CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "active_node")) { + if (snode->edittree) { + bNode *node = nodeGetActive(snode->edittree); + CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node); + } + + CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "node_previews")) { + if (snode->nodetree) { + CTX_data_pointer_set( + result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews); + } + + CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "material")) { + if (snode->id && GS(snode->id->name) == ID_MA) { + CTX_data_id_pointer_set(result, snode->id); + } + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "light")) { + if (snode->id && GS(snode->id->name) == ID_LA) { + CTX_data_id_pointer_set(result, snode->id); + } + return CTX_RESULT_OK; + } + if (CTX_data_equals(member, "world")) { + if (snode->id && GS(snode->id->name) == ID_WO) { + CTX_data_id_pointer_set(result, snode->id); + } + return CTX_RESULT_OK; + } + + return CTX_RESULT_MEMBER_NOT_FOUND; +} + +static void node_widgets() +{ + /* create the widgetmap for the area here */ + wmGizmoMapType_Params params{SPACE_NODE, RGN_TYPE_WINDOW}; + wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(¶ms); + WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_transform); + WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_crop); + WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_sun_beams); + WM_gizmogrouptype_append_and_link(gzmap_type, NODE_GGT_backdrop_corner_pin); +} + +static void node_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id) +{ + SpaceNode *snode = (SpaceNode *)slink; + + if (snode->id == old_id) { + /* nasty DNA logic for SpaceNode: + * ideally should be handled by editor code, but would be bad level call + */ + BLI_freelistN(&snode->treepath); + + /* XXX Untested in case new_id != nullptr... */ + snode->id = new_id; + snode->from = nullptr; + snode->nodetree = nullptr; + snode->edittree = nullptr; + } + else if (GS(old_id->name) == ID_OB) { + if (snode->from == old_id) { + if (new_id == nullptr) { + snode->flag &= ~SNODE_PIN; + } + snode->from = new_id; + } + } + else if (GS(old_id->name) == ID_GD) { + if ((ID *)snode->gpd == old_id) { + snode->gpd = (bGPdata *)new_id; + id_us_min(old_id); + id_us_plus(new_id); + } + } + else if (GS(old_id->name) == ID_NT) { + bNodeTreePath *path, *path_next; + + for (path = (bNodeTreePath *)snode->treepath.first; path; path = path->next) { + if ((ID *)path->nodetree == old_id) { + path->nodetree = (bNodeTree *)new_id; + id_us_ensure_real(new_id); + } + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + snode->nodetree = path->nodetree; + } + if (path->nodetree == nullptr) { + break; + } + } + + /* remaining path entries are invalid, remove */ + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + } + + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = (bNodeTreePath *)snode->treepath.last; + snode->edittree = path->nodetree; + } + else { + snode->edittree = nullptr; + } + } +} + +static int node_space_subtype_get(ScrArea *area) +{ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + return rna_node_tree_idname_to_enum(snode->tree_idname); +} + +static void node_space_subtype_set(ScrArea *area, int value) +{ + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + ED_node_set_tree_type(snode, rna_node_tree_type_from_enum(value)); +} + +static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, int *totitem) +{ + bool free; + const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); + RNA_enum_items_add(item, totitem, item_src); + if (free) { + MEM_freeN((void *)item_src); + } +} + +/* only called once, from space/spacetypes.c */ +void ED_spacetype_node(void) +{ + SpaceType *st = (SpaceType *)MEM_callocN(sizeof(SpaceType), "spacetype node"); + ARegionType *art; + + st->spaceid = SPACE_NODE; + strncpy(st->name, "Node", BKE_ST_MAXNAME); + + st->create = node_create; + st->free = node_free; + st->init = node_init; + st->duplicate = node_duplicate; + st->operatortypes = node_operatortypes; + st->keymap = node_keymap; + st->listener = node_area_listener; + st->refresh = node_area_refresh; + st->context = node_context; + st->dropboxes = node_dropboxes; + st->gizmos = node_widgets; + st->id_remap = node_id_remap; + st->space_subtype_item_extend = node_space_subtype_item_extend; + st->space_subtype_get = node_space_subtype_get; + st->space_subtype_set = node_space_subtype_set; + + /* regions: main window */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region"); + art->regionid = RGN_TYPE_WINDOW; + art->init = node_main_region_init; + art->draw = node_main_region_draw; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_VIEW2D | + ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL; + art->listener = node_region_listener; + art->cursor = node_cursor; + art->event_cursor = true; + art->clip_gizmo_events_by_ui = true; + + BLI_addhead(&st->regiontypes, art); + + /* regions: header */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->listener = node_region_listener; + art->init = node_header_region_init; + art->draw = node_header_region_draw; + + BLI_addhead(&st->regiontypes, art); + + /* regions: listview/buttons */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype node region"); + art->regionid = RGN_TYPE_UI; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->listener = node_region_listener; + art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; + art->init = node_buttons_region_init; + art->draw = node_buttons_region_draw; + BLI_addhead(&st->regiontypes, art); + + /* regions: toolbar */ + art = (ARegionType *)MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); + art->regionid = RGN_TYPE_TOOLS; + art->prefsizex = 58; /* XXX */ + art->prefsizey = 50; /* XXX */ + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->listener = node_region_listener; + art->message_subscribe = ED_region_generic_tools_region_message_subscribe; + art->snap_size = ED_region_generic_tools_region_snap_size; + art->init = node_toolbar_region_init; + art->draw = node_toolbar_region_draw; + BLI_addhead(&st->regiontypes, art); + + node_toolbar_register(art); + + BKE_spacetype_register(st); +} -- cgit v1.2.3