diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-08-04 09:45:33 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-08-04 09:45:33 +0300 |
commit | d7905dab6a858570258daf4a502820b340a52dbc (patch) | |
tree | 8b4e1c58609ba7d4608b2ee87afeb9352e0460f3 /source/blender/editors/space_node/node_manipulators.c | |
parent | 54cea98046962a7557ce1b75b4a6146373bdda42 (diff) |
Manipulator: add compositor crop manipulator
Diffstat (limited to 'source/blender/editors/space_node/node_manipulators.c')
-rw-r--r-- | source/blender/editors/space_node/node_manipulators.c | 260 |
1 files changed, 258 insertions, 2 deletions
diff --git a/source/blender/editors/space_node/node_manipulators.c b/source/blender/editors/space_node/node_manipulators.c index 7bc029ea660..8f614137a84 100644 --- a/source/blender/editors/space_node/node_manipulators.c +++ b/source/blender/editors/space_node/node_manipulators.c @@ -22,9 +22,14 @@ * \ingroup spnode */ +#include <math.h> + #include "BKE_context.h" #include "BKE_image.h" +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" + #include "ED_screen.h" #include "ED_manipulator_library.h" @@ -40,6 +45,11 @@ #include "node_intern.h" +/* -------------------------------------------------------------------- */ + +/** \name Backdrop Manipulator + * \{ */ + static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) { SpaceNode *snode = CTX_wm_space_node(C); @@ -51,7 +61,7 @@ static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmManipulatorGrou if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) { bNode *node = nodeGetActive(snode->edittree); - if (node && node->type == CMP_NODE_VIEWER) { + if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { return true; } } @@ -108,7 +118,7 @@ static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmManipulatorG void NODE_WGT_backdrop_transform(wmManipulatorGroupType *wgt) { - wgt->name = "Backdrop Transform Widgets"; + wgt->name = "Backdrop Transform Widget"; wgt->idname = "NODE_WGT_backdrop_transform"; wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; @@ -117,3 +127,249 @@ void NODE_WGT_backdrop_transform(wmManipulatorGroupType *wgt) wgt->setup = WIDGETGROUP_node_transform_setup; wgt->refresh = WIDGETGROUP_node_transform_refresh; } + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Crop Manipulator + * \{ */ + +struct NodeCropWidgetGroup { + wmManipulator *border; + + struct { + float dims[2]; + } state; + + struct { + PointerRNA ptr; + PropertyRNA *prop; + bContext *context; + } update_data; +}; + +static void manipulator_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 manipulator_node_crop_prop_size_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float *value = value_p; + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + BLI_assert(mpr_prop->type->array_length == 2); + const bNode *node = mpr_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); + value[0] = BLI_rctf_size_x(&rct); + value[1] = BLI_rctf_size_y(&rct); +} + +static void manipulator_node_crop_prop_size_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float *value = value_p; + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + bNode *node = mpr_prop->custom_func.user_data; + NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + BLI_assert(mpr_prop->type->array_length == 2); + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + BLI_rctf_resize(&rct, value[0], value[1]); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, &rct, &rct); + two_xy_from_rect(nxy, &rct, dims, is_relative); + + manipulator_node_crop_update(crop_group); +} + +/* offset callbacks */ +static void manipulator_node_crop_prop_offset_get( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + void *value_p) +{ + float *value = value_p; + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + BLI_assert(mpr_prop->type->array_length == 2); + const bNode *node = mpr_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); + value[0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0]; + value[1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1]; +} + +static void manipulator_node_crop_prop_offset_set( + const wmManipulator *mpr, wmManipulatorProperty *mpr_prop, + const void *value_p) +{ + const float *value = value_p; + struct NodeCropWidgetGroup *crop_group = mpr->parent_mgroup->customdata; + const float *dims = crop_group->state.dims; + bNode *node = mpr_prop->custom_func.user_data; + NodeTwoXYs *nxy = node->storage; + bool is_relative = (bool)node->custom2; + BLI_assert(mpr_prop->type->array_length == 2); + rctf rct; + two_xy_to_rect(nxy, &rct, dims, is_relative); + BLI_rctf_recenter(&rct, (value[0] / dims[0]) + 0.5f, (value[1] / dims[1]) + 0.5f); + BLI_rctf_isect(&(rctf){.xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1}, &rct, &rct); + two_xy_from_rect(nxy, &rct, dims, is_relative); + + manipulator_node_crop_update(crop_group); +} + + +static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt)) +{ + 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 & (0 << 1)) == 0) { + return true; + } + } + } + + return false; +} + +static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup), __func__); + + crop_group->border = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL); + + RNA_enum_set(crop_group->border->ptr, "transform", + ED_MANIPULATOR_RECT_TRANSFORM_FLAG_TRANSLATE | ED_MANIPULATOR_RECT_TRANSFORM_FLAG_SCALE); + + mgroup->customdata = crop_group; +} + +static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) +{ + ARegion *ar = CTX_wm_region(C); + wmManipulator *mpr = mgroup->manipulators.first; + + SpaceNode *snode = CTX_wm_space_node(C); + + unit_m4(mpr->matrix_space); + mul_v3_fl(mpr->matrix_space[0], snode->zoom); + mul_v3_fl(mpr->matrix_space[1], snode->zoom); + mpr->matrix_space[3][0] = (ar->winx / 2) + snode->xof; + mpr->matrix_space[3][1] = (ar->winy / 2) + snode->yof; +} + +static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmManipulatorGroup *mgroup) +{ + struct NodeCropWidgetGroup *crop_group = mgroup->customdata; + wmManipulator *mpr = crop_group->border; + + void *lock; + Image *ima = BKE_image_verify_viewer(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(mpr->ptr, "dimensions", crop_group->state.dims); + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_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_manipulator_target_property_def_func( + mpr, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_crop_prop_offset_get, + .value_set_fn = manipulator_node_crop_prop_offset_set, + .range_get_fn = NULL, + .user_data = node, + }); + + WM_manipulator_target_property_def_func( + mpr, "scale", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_node_crop_prop_size_get, + .value_set_fn = manipulator_node_crop_prop_size_set, + .range_get_fn = NULL, + .user_data = node, + }); + } + else { + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } + + BKE_image_release_ibuf(ima, ibuf, lock); +} + +void NODE_WGT_backdrop_crop(wmManipulatorGroupType *wgt) +{ + wgt->name = "Backdrop Crop Widget"; + wgt->idname = "NODE_WGT_backdrop_crop"; + + wgt->flag |= WM_MANIPULATORGROUPTYPE_PERSISTENT; + + wgt->poll = WIDGETGROUP_node_crop_poll; + wgt->setup = WIDGETGROUP_node_crop_setup; + wgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare; + wgt->refresh = WIDGETGROUP_node_crop_refresh; +} + +/** \} */ |