This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/mask/mask_ops.c

2386 lines
61 KiB
C
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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) 2012 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation,
* Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/mask/mask_ops.c
* \ingroup edmask
*/
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h" /* SELECT */
#include "WM_api.h"
#include "WM_types.h"
#include "ED_clip.h"
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_mask.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "mask_intern.h" /* own include */
/******************** utility functions *********************/
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point, /*const*/ eMaskWhichHandle which_handle,
const float scalex, const float scaley, float handle[2])
{
BKE_mask_point_handle(point, which_handle, handle);
handle[0] *= scalex;
handle[1] *= scaley;
}
MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, Mask *mask, const float normal_co[2], const float threshold,
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
MaskLayer **masklay_r, MaskSpline **spline_r,
eMaskWhichHandle *which_handle_r, float *score)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
MaskLayer *masklay;
MaskLayer *point_masklay = NULL;
MaskSpline *point_spline = NULL;
MaskSplinePoint *point = NULL;
2012-07-31 17:24:55 +00:00
float co[2];
const float threshold_sq = threshold * threshold;
2014-03-31 05:45:28 +11:00
float len_sq = FLT_MAX, scalex, scaley;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE;
int width, height;
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
co[0] = normal_co[0] * scalex;
co[1] = normal_co[1] * scaley;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
int i;
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *cur_point = &spline->points[i];
MaskSplinePoint *cur_point_deform = &points_array[i];
eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
BezTriple *bezt = &cur_point_deform->bezt;
2014-04-03 09:24:09 +11:00
float cur_len_sq, vec[2];
vec[0] = bezt->vec[1][0] * scalex;
vec[1] = bezt->vec[1][1] * scaley;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
cur_len_sq = len_squared_v2v2(co, vec);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (cur_len_sq < len_sq) {
point_spline = spline;
point_masklay = masklay;
point = cur_point;
len_sq = cur_len_sq;
which_handle = MASK_WHICH_HANDLE_NONE;
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) {
float handle[2];
mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
cur_len_sq = len_squared_v2v2(co, handle);
cur_which_handle = MASK_WHICH_HANDLE_STICK;
}
else {
float handle_left[2], handle_right[2];
float len_left_sq, len_right_sq;
mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
mask_point_scaled_handle(cur_point_deform, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
len_left_sq = len_squared_v2v2(co, handle_left);
len_right_sq = len_squared_v2v2(co, handle_right);
if (i == 0) {
if (len_left_sq <= len_right_sq) {
if (bezt->h1 != HD_VECT) {
cur_which_handle = MASK_WHICH_HANDLE_LEFT;
cur_len_sq = len_left_sq;
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
}
else if (bezt->h2 != HD_VECT) {
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
cur_len_sq = len_right_sq;
}
}
else {
if (len_right_sq <= len_left_sq) {
if (bezt->h2 != HD_VECT) {
cur_which_handle = MASK_WHICH_HANDLE_RIGHT;
cur_len_sq = len_right_sq;
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
}
else if (bezt->h1 != HD_VECT) {
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
cur_which_handle = MASK_WHICH_HANDLE_LEFT;
cur_len_sq = len_left_sq;
}
}
}
if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) {
point_masklay = masklay;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
point_spline = spline;
point = cur_point;
len_sq = cur_len_sq;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
which_handle = cur_which_handle;
}
}
}
}
if (len_sq < threshold_sq) {
if (masklay_r)
*masklay_r = point_masklay;
if (spline_r)
*spline_r = point_spline;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (which_handle_r)
*which_handle_r = which_handle;
if (score)
*score = sqrtf(len_sq);
return point;
}
if (masklay_r)
*masklay_r = NULL;
if (spline_r)
*spline_r = NULL;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (which_handle_r)
*which_handle_r = MASK_WHICH_HANDLE_NONE;
return NULL;
}
bool ED_mask_feather_find_nearest(const bContext *C, Mask *mask, const float normal_co[2], const float threshold,
MaskLayer **masklay_r, MaskSpline **spline_r, MaskSplinePoint **point_r,
MaskSplinePointUW **uw_r, float *score)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
MaskLayer *masklay, *point_masklay = NULL;
MaskSpline *point_spline = NULL;
MaskSplinePoint *point = NULL;
MaskSplinePointUW *uw = NULL;
const float threshold_sq = threshold * threshold;
float len = FLT_MAX, co[2];
2012-07-31 17:24:55 +00:00
float scalex, scaley;
int width, height;
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
co[0] = normal_co[0] * scalex;
co[1] = normal_co[1] * scaley;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
for (spline = masklay->splines.first; spline; spline = spline->next) {
//MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
int i, tot_feather_point;
float (*feather_points)[2], (*fp)[2];
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
for (i = 0; i < spline->tot_point; i++) {
int j;
MaskSplinePoint *cur_point = &spline->points[i];
for (j = 0; j <= cur_point->tot_uw; j++) {
float cur_len_sq, vec[2];
vec[0] = (*fp)[0] * scalex;
vec[1] = (*fp)[1] * scaley;
cur_len_sq = len_squared_v2v2(vec, co);
if (point == NULL || cur_len_sq < len) {
if (j == 0)
uw = NULL;
else
uw = &cur_point->uw[j - 1];
point_masklay = masklay;
point_spline = spline;
point = cur_point;
len = cur_len_sq;
}
fp++;
}
}
MEM_freeN(feather_points);
}
}
if (len < threshold_sq) {
if (masklay_r)
*masklay_r = point_masklay;
if (spline_r)
*spline_r = point_spline;
if (point_r)
*point_r = point;
if (uw_r)
*uw_r = uw;
if (score)
*score = sqrtf(len);
return true;
}
if (masklay_r)
*masklay_r = NULL;
if (spline_r)
*spline_r = NULL;
if (point_r)
*point_r = NULL;
return false;
}
/******************** create new mask *********************/
Mask *ED_mask_new(bContext *C, const char *name)
{
ScrArea *sa = CTX_wm_area(C);
Main *bmain = CTX_data_main(C);
Mask *mask;
mask = BKE_mask_new(bmain, name);
if (sa && sa->spacedata.first) {
switch (sa->spacetype) {
case SPACE_CLIP:
{
SpaceClip *sc = sa->spacedata.first;
ED_space_clip_set_mask(C, sc, mask);
break;
}
case SPACE_SEQ:
{
/* do nothing */
break;
}
case SPACE_IMAGE:
{
SpaceImage *sima = sa->spacedata.first;
ED_space_image_set_mask(C, sima, mask);
break;
}
}
}
return mask;
}
/* Get ative layer. Will create mask/layer to be sure there's an active layer. */
MaskLayer *ED_mask_layer_ensure(bContext *C, bool *r_added_mask)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer;
if (mask == NULL) {
/* If there's no active mask, create one. */
mask = ED_mask_new(C, NULL);
*r_added_mask = true;
}
mask_layer = BKE_mask_layer_active(mask);
if (mask_layer == NULL) {
/* If there's no active mask layer, create one. */
mask_layer = BKE_mask_layer_new(mask, "");
}
return mask_layer;
}
static int mask_new_exec(bContext *C, wmOperator *op)
{
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
ED_mask_new(C, name);
WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
return OPERATOR_FINISHED;
}
void MASK_OT_new(wmOperatorType *ot)
{
/* identifiers */
ot->name = "New Mask";
ot->description = "Create new mask";
ot->idname = "MASK_OT_new";
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = mask_new_exec;
ot->poll = ED_operator_mask;
/* properties */
RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask");
}
/******************** create new masklay *********************/
static int masklay_new_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
BKE_mask_layer_new(mask, name);
mask->masklay_act = mask->masklay_tot - 1;
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_layer_new(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Mask Layer";
ot->description = "Add new mask layer for masking";
ot->idname = "MASK_OT_layer_new";
/* api callbacks */
ot->exec = masklay_new_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Name of new mask layer");
}
/******************** remove mask layer *********************/
static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay = BKE_mask_layer_active(mask);
if (masklay) {
BKE_mask_layer_remove(mask, masklay);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
}
return OPERATOR_FINISHED;
}
void MASK_OT_layer_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Mask Layer";
ot->description = "Remove mask layer";
ot->idname = "MASK_OT_layer_remove";
/* api callbacks */
ot->exec = masklay_remove_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** slide *********************/
enum {
SLIDE_ACTION_NONE = 0,
SLIDE_ACTION_POINT = 1,
SLIDE_ACTION_HANDLE = 2,
SLIDE_ACTION_FEATHER = 3,
SLIDE_ACTION_SPLINE = 4,
};
typedef struct SlidePointData {
/* Generic fields. */
short event_invoke_type;
int action;
Mask *mask;
MaskLayer *masklay;
MaskSpline *spline, *orig_spline;
MaskSplinePoint *point;
MaskSplinePointUW *uw;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
eMaskWhichHandle which_handle;
int width, height;
float prev_mouse_coord[2];
float no[2];
bool is_curvature_only,
is_accurate,
is_initial_feather,
is_overall_feather;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
bool is_sliding_new_point;
/* Data needed to restre the state. */
float vec[3][3];
char old_h1, old_h2;
/* Point sliding. */
/* Handle sliding. */
float orig_handle_coord[2], prev_handle_coord[2];
/* Feather sliding. */
float prev_feather_coord[2];
float weight, weight_scalar;
} SlidePointData;
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
ED_clip_point_undistorted_pos(sc, r_co, r_co);
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
static bool spline_under_mouse_get(const bContext *C,
Mask *mask, const float co[2],
MaskLayer **mask_layer_r,
MaskSpline **mask_spline_r)
{
const float threshold = 19.0f;
ScrArea *sa = CTX_wm_area(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MaskLayer *mask_layer;
int width, height;
float pixel_co[2];
float closest_dist_squared = 0.0f;
MaskLayer *closest_layer = NULL;
MaskSpline *closest_spline = NULL;
bool undistort = false;
*mask_layer_r = NULL;
*mask_spline_r = NULL;
ED_mask_get_size(sa, &width, &height);
pixel_co[0] = co[0] * width;
pixel_co[1] = co[1] * height;
if (sc != NULL) {
undistort = (sc->clip != NULL) &&
(sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0;
}
for (mask_layer = mask->masklayers.first;
mask_layer != NULL;
mask_layer = mask_layer->next)
{
MaskSpline *spline;
if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
continue;
}
for (spline = mask_layer->splines.first;
spline != NULL;
spline = spline->next)
{
MaskSplinePoint *points_array;
float min[2], max[2], center[2];
float dist_squared;
int i;
float max_bb_side;
if ((spline->flag & SELECT) == 0) {
continue;
}
points_array = BKE_mask_spline_point_array(spline);
INIT_MINMAX2(min, max);
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point_deform = &points_array[i];
BezTriple *bezt = &point_deform->bezt;
float vert[2];
copy_v2_v2(vert, bezt->vec[1]);
if (undistort) {
mask_point_undistort_pos(sc, vert, vert);
}
minmax_v2v2_v2(min, max, vert);
}
center[0] = (min[0] + max[0]) / 2.0f * width;
center[1] = (min[1] + max[1]) / 2.0f * height;
dist_squared = len_squared_v2v2(pixel_co, center);
max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height);
if (dist_squared <= max_bb_side * max_bb_side * 0.5f &&
(closest_spline == NULL || dist_squared < closest_dist_squared))
{
closest_layer = mask_layer;
closest_spline = spline;
closest_dist_squared = dist_squared;
}
}
}
if (closest_dist_squared < SQUARE(threshold) && closest_spline != NULL) {
float diff_score;
if (ED_mask_find_nearest_diff_point(C, mask, co, threshold,
false, NULL, true, false,
NULL, NULL, NULL, NULL,
&diff_score))
{
if (SQUARE(diff_score) < closest_dist_squared) {
return false;
}
}
*mask_layer_r = closest_layer;
*mask_spline_r = closest_spline;
return true;
}
return false;
}
static bool slide_point_check_initial_feather(MaskSpline *spline)
{
int i;
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
if (point->bezt.weight != 0.0f) {
return false;
}
}
return true;
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
static void select_sliding_point(Mask *mask, MaskLayer *mask_layer, MaskSpline *spline,
MaskSplinePoint *point, eMaskWhichHandle which_handle)
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
{
ED_mask_select_toggle_all(mask, SEL_DESELECT);
switch (which_handle) {
case MASK_WHICH_HANDLE_NONE:
BKE_mask_point_select_set(point, true);
break;
case MASK_WHICH_HANDLE_LEFT:
point->bezt.f1 |= SELECT;
break;
case MASK_WHICH_HANDLE_RIGHT:
point->bezt.f3 |= SELECT;
break;
case MASK_WHICH_HANDLE_STICK:
point->bezt.f1 |= SELECT;
point->bezt.f3 |= SELECT;
break;
default:
BLI_assert(!"Unexpected situation in select_sliding_point()");
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
mask_layer->act_spline = spline;
mask_layer->act_point = point;
ED_mask_select_flush_all(mask);
}
static void check_sliding_handle_type(MaskSplinePoint *point, eMaskWhichHandle which_handle)
{
BezTriple *bezt = &point->bezt;
if (which_handle == MASK_WHICH_HANDLE_LEFT) {
if (bezt->h1 == HD_VECT) {
bezt->h1 = HD_FREE;
}
else if (bezt->h1 == HD_AUTO) {
bezt->h1 = HD_ALIGN_DOUBLESIDE;
bezt->h2 = HD_ALIGN_DOUBLESIDE;
}
}
else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
if (bezt->h2 == HD_VECT) {
bezt->h2 = HD_FREE;
}
else if (bezt->h2 == HD_AUTO) {
bezt->h1 = HD_ALIGN_DOUBLESIDE;
bezt->h2 = HD_ALIGN_DOUBLESIDE;
}
}
}
static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
Mask *mask = CTX_data_edit_mask(C);
SlidePointData *customdata = NULL;
MaskLayer *masklay, *cv_masklay, *feather_masklay;
MaskSpline *spline, *cv_spline, *feather_spline;
MaskSplinePoint *point, *cv_point, *feather_point;
MaskSplinePointUW *uw = NULL;
2014-02-03 18:55:59 +11:00
int width, height, action = SLIDE_ACTION_NONE;
const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
float co[2], cv_score, feather_score;
const float threshold = 19;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
eMaskWhichHandle which_handle;
ED_mask_mouse_pos(sa, ar, event->mval, co);
ED_mask_get_size(sa, &width, &height);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &which_handle, &cv_score);
if (ED_mask_feather_find_nearest(C, mask, co, threshold, &feather_masklay, &feather_spline, &feather_point, &uw, &feather_score)) {
if (slide_feather || !cv_point || feather_score < cv_score) {
action = SLIDE_ACTION_FEATHER;
masklay = feather_masklay;
spline = feather_spline;
point = feather_point;
}
}
if (cv_point && action == SLIDE_ACTION_NONE) {
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (which_handle != MASK_WHICH_HANDLE_NONE)
action = SLIDE_ACTION_HANDLE;
else
action = SLIDE_ACTION_POINT;
masklay = cv_masklay;
spline = cv_spline;
point = cv_point;
}
if (action == SLIDE_ACTION_NONE) {
if (spline_under_mouse_get(C, mask, co, &masklay, &spline)) {
action = SLIDE_ACTION_SPLINE;
point = NULL;
}
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (action != SLIDE_ACTION_NONE) {
customdata = MEM_callocN(sizeof(SlidePointData), "mask slide point data");
customdata->event_invoke_type = event->type;
customdata->mask = mask;
customdata->masklay = masklay;
customdata->spline = spline;
customdata->point = point;
customdata->width = width;
customdata->height = height;
customdata->action = action;
customdata->uw = uw;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point");
if (customdata->action != SLIDE_ACTION_SPLINE) {
customdata->old_h1 = point->bezt.h1;
customdata->old_h2 = point->bezt.h2;
select_sliding_point(mask, masklay, spline, point, which_handle);
check_sliding_handle_type(point, which_handle);
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (uw) {
2012-10-12 14:35:10 +00:00
float co_uw[2];
float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
customdata->weight = uw->w;
customdata->weight_scalar = weight_scalar;
2012-10-12 14:35:10 +00:00
BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
BKE_mask_point_normal(spline, point, uw->u, customdata->no);
madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar);
}
else if (customdata->action != SLIDE_ACTION_SPLINE) {
BezTriple *bezt = &point->bezt;
customdata->weight = bezt->weight;
customdata->weight_scalar = 1.0f;
BKE_mask_point_normal(spline, point, 0.0f, customdata->no);
madd_v2_v2v2fl(customdata->prev_feather_coord, bezt->vec[1], customdata->no, bezt->weight);
}
if (customdata->action == SLIDE_ACTION_FEATHER) {
customdata->is_initial_feather = slide_point_check_initial_feather(spline);
}
if (customdata->action != SLIDE_ACTION_SPLINE) {
copy_m3_m3(customdata->vec, point->bezt.vec);
if (which_handle != MASK_WHICH_HANDLE_NONE) {
BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
}
customdata->which_handle = which_handle;
ED_mask_mouse_pos(sa, ar, event->mval, customdata->prev_mouse_coord);
}
return customdata;
}
static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
Mask *mask = CTX_data_edit_mask(C);
SlidePointData *slidedata;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (mask == NULL) {
return OPERATOR_PASS_THROUGH;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
}
slidedata = slide_point_customdata(C, op, event);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (slidedata) {
op->customdata = slidedata;
WM_event_add_modal_handler(C, op);
slidedata->masklay->act_spline = slidedata->spline;
slidedata->masklay->act_point = slidedata->point;
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
}
static void slide_point_delta_all_feather(SlidePointData *data, float delta)
{
int i;
for (i = 0; i < data->spline->tot_point; i++) {
MaskSplinePoint *point = &data->spline->points[i];
MaskSplinePoint *orig_point = &data->orig_spline->points[i];
point->bezt.weight = orig_point->bezt.weight + delta;
if (point->bezt.weight < 0.0f) {
point->bezt.weight = 0.0f;
}
}
}
static void slide_point_restore_spline(SlidePointData *data)
{
int i;
for (i = 0; i < data->spline->tot_point; i++) {
MaskSplinePoint *point = &data->spline->points[i];
MaskSplinePoint *orig_point = &data->orig_spline->points[i];
int j;
point->bezt = orig_point->bezt;
for (j = 0; j < point->tot_uw; j++)
point->uw[j] = orig_point->uw[j];
}
}
static void cancel_slide_point(SlidePointData *data)
{
/* cancel sliding */
if (data->orig_spline) {
slide_point_restore_spline(data);
}
else {
if (data->action == SLIDE_ACTION_FEATHER) {
if (data->uw)
data->uw->w = data->weight;
else
data->point->bezt.weight = data->weight;
}
else if (data->action != SLIDE_ACTION_SPLINE) {
copy_m3_m3(data->point->bezt.vec, data->vec);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
data->point->bezt.h1 = data->old_h1;
data->point->bezt.h2 = data->old_h2;
}
}
}
static void free_slide_point_data(SlidePointData *data)
{
if (data->orig_spline)
BKE_mask_spline_free(data->orig_spline);
MEM_freeN(data);
}
static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SlidePointData *data = (SlidePointData *)op->customdata;
BezTriple *bezt = &data->point->bezt;
float co[2];
switch (event->type) {
case LEFTALTKEY:
case RIGHTALTKEY:
case LEFTSHIFTKEY:
case RIGHTSHIFTKEY:
if (ELEM(event->type, LEFTALTKEY, RIGHTALTKEY)) {
if (data->action == SLIDE_ACTION_FEATHER) {
data->is_overall_feather = (event->val == KM_PRESS);
}
else {
data->is_curvature_only = (event->val == KM_PRESS);
}
}
if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
data->is_accurate = (event->val == KM_PRESS);
ATTR_FALLTHROUGH; /* update CV position */
case MOUSEMOVE:
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
float delta[2];
ED_mask_mouse_pos(sa, ar, event->mval, co);
sub_v2_v2v2(delta, co, data->prev_mouse_coord);
if (data->is_accurate) {
mul_v2_fl(delta, 0.2f);
}
copy_v2_v2(data->prev_mouse_coord, co);
if (data->action == SLIDE_ACTION_HANDLE) {
float new_handle[2];
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (data->is_sliding_new_point && data->which_handle == MASK_WHICH_HANDLE_STICK) {
if (ELEM(data->point, &data->spline->points[0],
&data->spline->points[data->spline->tot_point - 1]))
{
SWAP(float, delta[0], delta[1]);
delta[1] *= -1;
/* flip last point */
if (data->point != &data->spline->points[0]) {
negate_v2(delta);
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
}
}
add_v2_v2v2(new_handle, data->prev_handle_coord, delta);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
BKE_mask_point_set_handle(data->point, data->which_handle,
new_handle, data->is_curvature_only,
data->orig_handle_coord, data->vec);
BKE_mask_point_handle(data->point, data->which_handle, data->prev_handle_coord);
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (data->is_sliding_new_point) {
if (ELEM(data->which_handle, MASK_WHICH_HANDLE_LEFT, MASK_WHICH_HANDLE_RIGHT)) {
float vec[2];
short self_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 0 : 2;
short other_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 2 : 0;
sub_v2_v2v2(vec, bezt->vec[1], bezt->vec[self_handle]);
add_v2_v2v2(bezt->vec[other_handle], bezt->vec[1], vec);
}
}
}
else if (data->action == SLIDE_ACTION_POINT) {
add_v2_v2(bezt->vec[0], delta);
add_v2_v2(bezt->vec[1], delta);
add_v2_v2(bezt->vec[2], delta);
}
else if (data->action == SLIDE_ACTION_FEATHER) {
float vec[2], no[2], p[2], c[2], w, offco[2];
float *weight = NULL;
float weight_scalar = 1.0f;
bool is_overall_feather = data->is_overall_feather || data->is_initial_feather;
add_v2_v2v2(offco, data->prev_feather_coord, delta);
if (data->uw) {
/* project on both sides and find the closest one,
* prevents flickering when projecting onto both sides can happen */
const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
data->uw->u, offco, MASK_PROJ_NEG);
const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
data->uw->u, offco, MASK_PROJ_POS);
float dist_pos = FLT_MAX;
float dist_neg = FLT_MAX;
float co_pos[2];
float co_neg[2];
float u;
if (u_pos > 0.0f && u_pos < 1.0f) {
BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
dist_pos = len_squared_v2v2(offco, co_pos);
}
if (u_neg > 0.0f && u_neg < 1.0f) {
BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
dist_neg = len_squared_v2v2(offco, co_neg);
}
u = dist_pos < dist_neg ? u_pos : u_neg;
if (u > 0.0f && u < 1.0f) {
data->uw->u = u;
data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
weight = &data->uw->w;
weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
if (weight_scalar != 0.0f) {
weight_scalar = 1.0f / weight_scalar;
}
BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
}
}
else {
weight = &bezt->weight;
/* weight_scalar = 1.0f; keep as is */
copy_v2_v2(no, data->no);
copy_v2_v2(p, bezt->vec[1]);
}
if (weight) {
sub_v2_v2v2(c, offco, p);
2017-09-07 01:19:37 +10:00
project_v2_v2v2_normalized(vec, c, no);
w = len_v2(vec);
if (is_overall_feather) {
2015-11-23 15:44:15 +11:00
float w_delta;
if (dot_v2v2(no, vec) <= 0.0f)
w = -w;
2015-11-23 15:44:15 +11:00
w_delta = w - data->weight * data->weight_scalar;
if (data->orig_spline == NULL) {
/* restore weight for currently sliding point, so orig_spline would be created
* with original weights used
*/
*weight = data->weight;
data->orig_spline = BKE_mask_spline_copy(data->spline);
}
if (data->is_initial_feather) {
*weight = w * weight_scalar;
}
2015-11-23 15:44:15 +11:00
slide_point_delta_all_feather(data, w_delta);
}
else {
if (dot_v2v2(no, vec) <= 0.0f)
w = 0.0f;
if (data->orig_spline) {
/* restore possible overall feather changes */
slide_point_restore_spline(data);
BKE_mask_spline_free(data->orig_spline);
data->orig_spline = NULL;
}
if (weight_scalar != 0.0f) {
*weight = w * weight_scalar;
}
}
copy_v2_v2(data->prev_feather_coord, offco);
}
}
else if (data->action == SLIDE_ACTION_SPLINE) {
int i;
if (data->orig_spline == NULL) {
data->orig_spline = BKE_mask_spline_copy(data->spline);
}
for (i = 0; i < data->spline->tot_point; i++) {
MaskSplinePoint *point = &data->spline->points[i];
add_v2_v2(point->bezt.vec[0], delta);
add_v2_v2(point->bezt.vec[1], delta);
add_v2_v2(point->bezt.vec[2], delta);
}
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
DEG_id_tag_update(&data->mask->id, 0);
break;
}
case LEFTMOUSE:
case RIGHTMOUSE:
if (event->type == data->event_invoke_type && event->val == KM_RELEASE) {
Scene *scene = CTX_data_scene(C);
/* dont key sliding feather uw's */
if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) {
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(data->masklay, CFRA);
}
}
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (data->is_sliding_new_point) {
if (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) < FLT_EPSILON) {
bezt->h1 = HD_VECT;
}
if (len_squared_v2v2(bezt->vec[2], bezt->vec[1]) < FLT_EPSILON) {
bezt->h2 = HD_VECT;
}
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
DEG_id_tag_update(&data->mask->id, 0);
free_slide_point_data(op->customdata); /* keep this last! */
return OPERATOR_FINISHED;
}
else if (event->type != data->event_invoke_type && event->val == KM_PRESS) {
/* pass to ESCKEY */
}
else {
break;
}
case ESCKEY:
cancel_slide_point(op->customdata);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
DEG_id_tag_update(&data->mask->id, 0);
free_slide_point_data(op->customdata); /* keep this last! */
return OPERATOR_CANCELLED;
}
return OPERATOR_RUNNING_MODAL;
}
void MASK_OT_slide_point(wmOperatorType *ot)
{
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
PropertyRNA *prop;
/* identifiers */
ot->name = "Slide Point";
ot->description = "Slide control points";
ot->idname = "MASK_OT_slide_point";
/* api callbacks */
ot->invoke = slide_point_invoke;
ot->modal = slide_point_modal;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
ot->poll = ED_operator_mask;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2012-06-04 19:43:12 +00:00
RNA_def_boolean(ot->srna, "slide_feather", 0, "Slide Feather", "First try to slide feather instead of vertex");
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
2014-03-31 21:15:56 +02:00
prop = RNA_def_boolean(ot->srna, "is_new_point", 0, "Slide New Point", "Newly created vertex is being slid");
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/******************** slide spline curvature *********************/
typedef struct SlideSplineCurvatureData {
short event_invoke_type;
Mask *mask;
MaskLayer *mask_layer;
MaskSpline *spline;
MaskSplinePoint *point;
float u;
bool accurate;
BezTriple *adjust_bezt, *other_bezt;
BezTriple bezt_backup, other_bezt_backup;
float prev_mouse_coord[2];
float prev_spline_coord[2];
float P0[2], P1[2], P2[2], P3[3];
} SlideSplineCurvatureData;
static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
{
*slide_data->adjust_bezt = slide_data->bezt_backup;
*slide_data->other_bezt = slide_data->other_bezt_backup;
}
static void free_slide_spline_curvature_data(SlideSplineCurvatureData *slide_data)
{
MEM_freeN(slide_data);
}
static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
{
Mask *mask = CTX_data_edit_mask(C);
float co[2];
const float threshold = 19.0f;
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
if (ED_mask_point_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL)) {
return false;
}
if (ED_mask_feather_find_nearest(C, mask, co, threshold, NULL, NULL, NULL, NULL, NULL)) {
return false;
}
return true;
}
static SlideSplineCurvatureData *slide_spline_curvature_customdata(
bContext *C, const wmEvent *event)
{
const float threshold = 19.0f;
Mask *mask = CTX_data_edit_mask(C);
SlideSplineCurvatureData *slide_data;
MaskLayer *mask_layer;
MaskSpline *spline;
MaskSplinePoint *point;
float u, co[2];
BezTriple *next_bezt;
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co);
if (!ED_mask_find_nearest_diff_point(C, mask, co, threshold, false,
NULL, true, false,
&mask_layer, &spline, &point, &u,
NULL))
{
return NULL;
}
next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
if (next_bezt == NULL) {
return NULL;
}
slide_data = MEM_callocN(sizeof(SlideSplineCurvatureData), "slide curvature slide");
slide_data->event_invoke_type = event->type;
slide_data->mask = mask;
slide_data->mask_layer = mask_layer;
slide_data->spline = spline;
slide_data->point = point;
slide_data->u = u;
copy_v2_v2(slide_data->prev_mouse_coord, co);
BKE_mask_point_segment_co(spline, point, u, slide_data->prev_spline_coord);
copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
/* Depending to which end we're closer to adjust either left or right side of the spline. */
if (u <= 0.5f) {
slide_data->adjust_bezt = &point->bezt;
slide_data->other_bezt = next_bezt;
}
else {
slide_data->adjust_bezt = next_bezt;
slide_data->other_bezt = &point->bezt;
}
/* Data needed for restoring state. */
slide_data->bezt_backup = *slide_data->adjust_bezt;
slide_data->other_bezt_backup = *slide_data->other_bezt;
/* Let's dont touch other side of the point for now, so set handle to FREE. */
if (u < 0.5f) {
if (slide_data->adjust_bezt->h2 <= HD_VECT) {
slide_data->adjust_bezt->h2 = HD_FREE;
}
}
else {
if (slide_data->adjust_bezt->h1 <= HD_VECT) {
slide_data->adjust_bezt->h1 = HD_FREE;
}
}
/* Change selection */
ED_mask_select_toggle_all(mask, SEL_DESELECT);
slide_data->adjust_bezt->f2 |= SELECT;
slide_data->other_bezt->f2 |= SELECT;
if (u < 0.5f) {
slide_data->adjust_bezt->f3 |= SELECT;
slide_data->other_bezt->f1 |= SELECT;
}
else {
slide_data->adjust_bezt->f1 |= SELECT;
slide_data->other_bezt->f3 |= SELECT;
}
mask_layer->act_spline = spline;
mask_layer->act_point = point;
ED_mask_select_flush_all(mask);
return slide_data;
}
static int slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Mask *mask = CTX_data_edit_mask(C);
SlideSplineCurvatureData *slide_data;
if (mask == NULL) {
return OPERATOR_PASS_THROUGH;
}
/* Be sure we don't conflict with point slide here. */
if (!slide_spline_curvature_check(C, event)) {
return OPERATOR_PASS_THROUGH;
}
slide_data = slide_spline_curvature_customdata(C, event);
if (slide_data != NULL) {
op->customdata = slide_data;
WM_event_add_modal_handler(C, op);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
}
static void slide_spline_solve_P1(const float u,
const float B[2],
2014-04-04 18:03:17 +06:00
const float P0[2],
const float P2[2],
const float P3[2],
float solution[2])
{
const float u2 = u * u, u3 = u * u * u;
const float v = 1.0f - u;
const float v2 = v * v, v3 = v * v * v;
const float inv_divider = 1.0f / (3.0f * v2 * u);
const float t = 3.0f * v * u2;
solution[0] = -(v3 * P0[0] + t * P2[0] + u3 * P3[0] - B[0]) * inv_divider;
solution[1] = -(v3 * P0[1] + t * P2[1] + u3 * P3[1] - B[1]) * inv_divider;
}
static void slide_spline_solve_P2(const float u,
const float B[2],
2014-04-04 18:03:17 +06:00
const float P0[2],
const float P1[2],
const float P3[2],
float solution[2])
{
const float u2 = u * u, u3 = u * u * u;
const float v = 1.0f - u;
const float v2 = v * v, v3 = v * v * v;
const float inv_divider = 1.0f / (3.0f * v * u2);
const float t = 3.0f * v2 * u;
solution[0] = -(v3 * P0[0] + t * P1[0] + u3 * P3[0] - B[0]) * inv_divider;
solution[1] = -(v3 * P0[1] + t * P1[1] + u3 * P3[1] - B[1]) * inv_divider;
}
static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
const float margin = 0.2f;
SlideSplineCurvatureData *slide_data = (SlideSplineCurvatureData *) op->customdata;
float u = slide_data->u;
switch (event->type) {
case LEFTSHIFTKEY:
case RIGHTSHIFTKEY:
case LEFTCTRLKEY:
case RIGHTCTRLKEY:
if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
slide_data->accurate = (event->val == KM_PRESS);
}
if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
if (event->val == KM_PRESS) {
slide_data->adjust_bezt->h1 = slide_data->adjust_bezt->h2 = HD_FREE;
if ((u > margin && u < 0.5f) || (u >= 0.5f && u < 1.0f - margin)) {
slide_data->other_bezt->h1 = slide_data->other_bezt->h2 = HD_FREE;
}
}
else if (event->val == KM_RELEASE) {
slide_data->adjust_bezt->h1 = slide_data->bezt_backup.h1;
slide_data->adjust_bezt->h2 = slide_data->bezt_backup.h2;
slide_data->other_bezt->h1 = slide_data->other_bezt_backup.h1;
slide_data->other_bezt->h2 = slide_data->other_bezt_backup.h2;
}
if (u < 0.5f) {
copy_v2_v2(slide_data->adjust_bezt->vec[0], slide_data->bezt_backup.vec[0]);
copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->other_bezt_backup.vec[2]);
}
else {
copy_v2_v2(slide_data->adjust_bezt->vec[2], slide_data->bezt_backup.vec[2]);
copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->other_bezt_backup.vec[0]);
}
}
ATTR_FALLTHROUGH; /* update CV position */
case MOUSEMOVE:
{
float B[2], mouse_coord[2], delta[2];
/* Get coordinate spline is expected to go through. */
ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, mouse_coord);
sub_v2_v2v2(delta, mouse_coord, slide_data->prev_mouse_coord);
if (slide_data->accurate) {
mul_v2_fl(delta, 0.2f);
}
add_v2_v2v2(B, slide_data->prev_spline_coord, delta);
copy_v2_v2(slide_data->prev_spline_coord, B);
copy_v2_v2(slide_data->prev_mouse_coord, mouse_coord);
if (u < 0.5f) {
float oldP2[2];
bool need_restore_P2 = false;
if (u > margin) {
float solution[2];
float x = (u - margin) * 0.5f / (0.5f - margin);
float weight = (3 * x * x - 2 * x * x * x);
slide_spline_solve_P2(u, B,
slide_data->P0,
slide_data->P1,
slide_data->P3,
solution);
copy_v2_v2(oldP2, slide_data->P2);
interp_v2_v2v2(slide_data->P2, slide_data->P2, solution, weight);
copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->P2);
need_restore_P2 = true;
/* Tweak handle type in order to be able to apply the delta. */
if (weight > 0.0f) {
if (slide_data->other_bezt->h1 <= HD_VECT) {
slide_data->other_bezt->h1 = HD_FREE;
}
}
}
slide_spline_solve_P1(u, B,
slide_data->P0,
slide_data->P2,
slide_data->P3,
slide_data->adjust_bezt->vec[2]);
if (need_restore_P2) {
copy_v2_v2(slide_data->P2, oldP2);
}
}
else {
float oldP1[2];
bool need_restore_P1 = false;
if (u < 1.0f - margin) {
float solution[2];
float x = ((1.0f - u) - margin) * 0.5f / (0.5f - margin);
float weight = 3 * x * x - 2 * x * x * x;
slide_spline_solve_P1(u, B,
slide_data->P0,
slide_data->P2,
slide_data->P3,
solution);
copy_v2_v2(oldP1, slide_data->P1);
interp_v2_v2v2(slide_data->P1, slide_data->P1, solution, weight);
copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->P1);
need_restore_P1 = true;
/* Tweak handle type in order to be able to apply the delta. */
if (weight > 0.0f) {
if (slide_data->other_bezt->h2 <= HD_VECT) {
slide_data->other_bezt->h2 = HD_FREE;
}
}
}
slide_spline_solve_P2(u, B,
slide_data->P0,
slide_data->P1,
slide_data->P3,
slide_data->adjust_bezt->vec[0]);
if (need_restore_P1) {
copy_v2_v2(slide_data->P1, oldP1);
}
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
DEG_id_tag_update(&slide_data->mask->id, 0);
break;
}
case LEFTMOUSE:
case RIGHTMOUSE:
if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) {
/* dont key sliding feather uw's */
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA);
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
DEG_id_tag_update(&slide_data->mask->id, 0);
free_slide_spline_curvature_data(slide_data); /* keep this last! */
return OPERATOR_FINISHED;
}
break;
case ESCKEY:
cancel_slide_spline_curvature(slide_data);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
DEG_id_tag_update(&slide_data->mask->id, 0);
free_slide_spline_curvature_data(op->customdata); /* keep this last! */
return OPERATOR_CANCELLED;
}
return OPERATOR_RUNNING_MODAL;
}
void MASK_OT_slide_spline_curvature(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Slide Spline Curvature";
ot->description = "Slide a point on the spline to define it's curvature";
ot->idname = "MASK_OT_slide_spline_curvature";
/* api callbacks */
ot->invoke = slide_spline_curvature_invoke;
ot->modal = slide_spline_curvature_modal;
ot->poll = ED_operator_mask;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** toggle cyclic *********************/
static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
if (ED_mask_spline_select_check(spline)) {
spline->flag ^= MASK_SPLINE_CYCLIC;
}
}
}
DEG_id_tag_update(&mask->id, 0);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_cyclic_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Cyclic";
ot->description = "Toggle cyclic for selected splines";
ot->idname = "MASK_OT_cyclic_toggle";
/* api callbacks */
ot->exec = cyclic_toggle_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** delete *********************/
static void delete_feather_points(MaskSplinePoint *point)
{
int i, count = 0;
if (!point->tot_uw)
return;
for (i = 0; i < point->tot_uw; i++) {
if ((point->uw[i].flag & SELECT) == 0)
count++;
}
if (count == 0) {
MEM_freeN(point->uw);
point->uw = NULL;
point->tot_uw = 0;
}
else {
MaskSplinePointUW *new_uw;
int j = 0;
new_uw = MEM_callocN(count * sizeof(MaskSplinePointUW), "new mask uw points");
for (i = 0; i < point->tot_uw; i++) {
if ((point->uw[i].flag & SELECT) == 0) {
new_uw[j++] = point->uw[i];
}
}
MEM_freeN(point->uw);
point->uw = new_uw;
point->tot_uw = count;
}
}
static int delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
int mask_layer_shape_ofs = 0;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
spline = masklay->splines.first;
while (spline) {
const int tot_point_orig = spline->tot_point;
int i, count = 0;
MaskSpline *next_spline = spline->next;
/* count unselected points */
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
if (!MASKPOINT_ISSEL_ANY(point))
count++;
}
if (count == 0) {
/* delete the whole spline */
BLI_remlink(&masklay->splines, spline);
BKE_mask_spline_free(spline);
if (spline == masklay->act_spline) {
masklay->act_spline = NULL;
masklay->act_point = NULL;
}
BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs, tot_point_orig);
}
else {
MaskSplinePoint *new_points;
int j;
new_points = MEM_callocN(count * sizeof(MaskSplinePoint), "deleteMaskPoints");
for (i = 0, j = 0; i < tot_point_orig; i++) {
MaskSplinePoint *point = &spline->points[i];
if (!MASKPOINT_ISSEL_ANY(point)) {
if (point == masklay->act_point)
masklay->act_point = &new_points[j];
delete_feather_points(point);
new_points[j] = *point;
j++;
}
else {
if (point == masklay->act_point)
masklay->act_point = NULL;
BKE_mask_point_free(point);
spline->tot_point--;
BKE_mask_layer_shape_changed_remove(masklay, mask_layer_shape_ofs + j, 1);
}
}
mask_layer_shape_ofs += spline->tot_point;
MEM_freeN(spline->points);
spline->points = new_points;
ED_mask_select_flush_all(mask);
}
changed = true;
spline = next_spline;
}
/* not essential but confuses users when there are keys with no data!
* assume if they delete all data from the layer they also dont care about keys */
if (BLI_listbase_is_empty(&masklay->splines)) {
BKE_mask_layer_free_shapes(masklay);
}
}
if (!changed) {
return OPERATOR_CANCELLED;
}
/* TODO: only update edited splines */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete";
ot->description = "Delete selected control points or splines";
ot->idname = "MASK_OT_delete";
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->exec = delete_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *** switch direction *** */
static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
/* do actual selection */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
bool changed_layer = false;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
if (ED_mask_spline_select_check(spline)) {
BKE_mask_spline_direction_switch(masklay, spline);
changed = true;
changed_layer = true;
}
}
if (changed_layer) {
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(masklay, CFRA);
}
}
}
if (changed) {
/* TODO: only update this spline */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
void MASK_OT_switch_direction(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Switch Direction";
ot->description = "Switch direction of selected splines";
ot->idname = "MASK_OT_switch_direction";
/* api callbacks */
ot->exec = mask_switch_direction_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *** recalc normals *** */
static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
int i;
bool changed = false;
/* do actual selection */
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
bool changed_layer = false;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
if (MASKPOINT_ISSEL_ANY(point)) {
BKE_mask_calc_handle_point_auto(spline, point, false);
changed = true;
changed_layer = true;
}
}
}
if (changed_layer) {
if (IS_AUTOKEY_ON(scene)) {
ED_mask_layer_shape_auto_key(masklay, CFRA);
}
}
}
if (changed) {
/* TODO: only update this spline */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
/* named to match mesh recalc normals */
void MASK_OT_normals_make_consistent(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Recalc Normals";
ot->description = "Re-calculate the direction of selected handles";
ot->idname = "MASK_OT_normals_make_consistent";
/* api callbacks */
ot->exec = mask_normals_make_consistent_exec;
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** set handle type *********************/
static int set_handle_type_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
int handle_type = RNA_enum_get(op->ptr, "type");
bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
int i;
if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
if (MASKPOINT_ISSEL_ANY(point)) {
BezTriple *bezt = &point->bezt;
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
if (bezt->f2 & SELECT) {
bezt->h1 = handle_type;
bezt->h2 = handle_type;
}
else {
if (bezt->f1 & SELECT) {
bezt->h1 = handle_type;
}
if (bezt->f3 & SELECT) {
bezt->h2 = handle_type;
}
}
if (handle_type == HD_ALIGN) {
float vec[3];
sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
}
changed = true;
}
}
}
}
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DATA, mask);
DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
void MASK_OT_handle_type_set(wmOperatorType *ot)
{
static const EnumPropertyItem editcurve_handle_type_items[] = {
{HD_AUTO, "AUTO", 0, "Auto", ""},
{HD_VECT, "VECTOR", 0, "Vector", ""},
Implement asymmetric and free handles type for masks Summary: The title actually says it all, it's just possible to have independent free handles for mask splines. Also it's now possible to have aligned handles displayed as independent handles. Required changes in quite a few places, but they're rather straightforward. From user perspective there's one really visible change which is removed Handle Type menu from the panel. With asymmetric handles it's not clear which handle type to display there. So now the only way to change handle type is via V-key menu. Rewrote normal evaluation function to make it deal with new type of handles we support. Now it works in the following way: - Offset the original spline by maximal weight - Calculate vector between corresponding U positions on offset and original spline - Normalize this vector. Seems to be giving more adequate results and doesn't tend to self-intersect as much as old behavior used to, There're still some changes which needed to be done, but which are planned for further patch: - Support colors and handle size via themes. - Make handles color-coded, just the same as done for regular bezier splines in 3D viewport. Additional changes to make roto workflow even better: - Use circles to draw handles - Support AA for handles - Change click-create-drag to change curvature of the spline instead of adjusting point position. Reviewers: campbellbarton CC: sebastian_k, hype, cronk Differential Revision: http://developer.blender.org/D121
2013-10-30 10:38:45 +01:00
{HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
{HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
{HD_FREE, "FREE", 0, "Free", ""},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name = "Set Handle Type";
ot->description = "Set type of handles for selected control points";
ot->idname = "MASK_OT_handle_type_set";
/* api callbacks */
ot->invoke = WM_menu_invoke;
ot->exec = set_handle_type_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
/* ********* clear/set restrict view *********/
static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
const bool select = RNA_boolean_get(op->ptr, "select");
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
if (masklay->restrictflag & OB_RESTRICT_VIEW) {
ED_mask_layer_select_set(masklay, select);
masklay->restrictflag &= ~OB_RESTRICT_VIEW;
changed = true;
}
}
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
}
void MASK_OT_hide_view_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Restrict View";
ot->description = "Reveal the layer by setting the hide flag";
ot->idname = "MASK_OT_hide_view_clear";
/* api callbacks */
ot->exec = mask_hide_view_clear_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "select", true, "Select", "");
}
static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
2014-04-11 11:25:41 +10:00
const bool unselected = RNA_boolean_get(op->ptr, "unselected");
bool changed = false;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
if (masklay->restrictflag & MASK_RESTRICT_SELECT) {
continue;
}
if (!unselected) {
if (ED_mask_layer_select_check(masklay)) {
ED_mask_layer_select_set(masklay, false);
masklay->restrictflag |= OB_RESTRICT_VIEW;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
}
}
}
else {
if (!ED_mask_layer_select_check(masklay)) {
masklay->restrictflag |= OB_RESTRICT_VIEW;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
}
}
}
}
if (changed) {
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
}
void MASK_OT_hide_view_set(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Set Restrict View";
ot->description = "Hide the layer by setting the hide flag";
ot->idname = "MASK_OT_hide_view_set";
/* api callbacks */
ot->exec = mask_hide_view_set_exec;
2012-06-04 17:30:54 +00:00
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
}
static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
int i;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
if (masklay->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) {
continue;
}
for (spline = masklay->splines.first; spline; spline = spline->next) {
for (i = 0; i < spline->tot_point; i++) {
MaskSplinePoint *point = &spline->points[i];
if (MASKPOINT_ISSEL_ANY(point)) {
BezTriple *bezt = &point->bezt;
bezt->weight = 0.0f;
changed = true;
}
}
}
}
if (changed) {
/* TODO: only update edited splines */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
DEG_id_tag_update(&mask->id, 0);
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
}
void MASK_OT_feather_weight_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Feather Weight";
ot->description = "Reset the feather weight to zero";
ot->idname = "MASK_OT_feather_weight_clear";
/* api callbacks */
ot->exec = mask_feather_weight_clear_exec;
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/******************** move mask layer operator *********************/
2018-07-02 11:47:00 +02:00
static bool mask_layer_move_poll(bContext *C)
{
if (ED_maskedit_mask_poll(C)) {
Mask *mask = CTX_data_edit_mask(C);
return mask->masklay_tot > 0;
}
return false;
}
static int mask_layer_move_exec(bContext *C, wmOperator *op)
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer = BLI_findlink(&mask->masklayers, mask->masklay_act);
MaskLayer *mask_layer_other;
int direction = RNA_enum_get(op->ptr, "direction");
if (!mask_layer)
return OPERATOR_CANCELLED;
if (direction == -1) {
mask_layer_other = mask_layer->prev;
if (!mask_layer_other)
return OPERATOR_CANCELLED;
BLI_remlink(&mask->masklayers, mask_layer);
BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
mask->masklay_act--;
}
else if (direction == 1) {
mask_layer_other = mask_layer->next;
if (!mask_layer_other)
return OPERATOR_CANCELLED;
BLI_remlink(&mask->masklayers, mask_layer);
BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
mask->masklay_act++;
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_layer_move(wmOperatorType *ot)
{
static const EnumPropertyItem direction_items[] = {
{-1, "UP", 0, "Up", ""},
{1, "DOWN", 0, "Down", ""},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name = "Move Layer";
ot->description = "Move the active layer up/down in the list";
ot->idname = "MASK_OT_layer_move";
/* api callbacks */
ot->exec = mask_layer_move_exec;
ot->poll = mask_layer_move_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer");
}
/******************** duplicate *********************/
static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer;
for (mask_layer = mask->masklayers.first;
mask_layer;
mask_layer = mask_layer->next)
{
MaskSpline *spline;
for (spline = mask_layer->splines.last;
spline;
spline = spline->prev)
{
MaskSplinePoint *point = spline->points;
int i = 0;
while (i < spline->tot_point) {
int start = i, end = -1;
/* Find next selected segment. */
while (MASKPOINT_ISSEL_ANY(point)) {
BKE_mask_point_select_set(point, false);
end = i;
if (i >= spline->tot_point - 1) {
break;
}
i++;
point++;
}
if (end >= start) {
int tot_point;
int tot_point_shape_start = 0;
MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
MaskSplinePoint *new_point;
int b;
/* BKE_mask_spline_add might allocate the points,
* need to free them in this case. */
if (new_spline->points) {
MEM_freeN(new_spline->points);
}
/* Copy options from old spline. */
new_spline->flag = spline->flag;
new_spline->offset_mode = spline->offset_mode;
new_spline->weight_interp = spline->weight_interp;
new_spline->parent = spline->parent;
/* Allocate new points and copy them from old spline. */
new_spline->tot_point = end - start + 1;
new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point,
"duplicated mask points");
memcpy(new_spline->points, spline->points + start,
new_spline->tot_point * sizeof(MaskSplinePoint));
tot_point = new_spline->tot_point;
/* animation requires points added one by one */
if (mask_layer->splines_shapes.first) {
new_spline->tot_point = 0;
tot_point_shape_start = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
}
/* Select points and duplicate their UWs (if needed). */
for (b = 0, new_point = new_spline->points;
b < tot_point;
b++, new_point++)
{
if (new_point->uw) {
new_point->uw = MEM_dupallocN(new_point->uw);
}
BKE_mask_point_select_set(new_point, true);
if (mask_layer->splines_shapes.first) {
new_spline->tot_point++;
BKE_mask_layer_shape_changed_add(mask_layer, tot_point_shape_start + b, true, false);
}
}
/* Clear cyclic flag if we didn't copy the whole spline. */
if (new_spline->flag & MASK_SPLINE_CYCLIC) {
if (start != 0 || end != spline->tot_point - 1) {
new_spline->flag &= ~MASK_SPLINE_CYCLIC;
}
}
/* Flush selection to splines. */
new_spline->flag |= SELECT;
spline->flag &= ~SELECT;
mask_layer->act_spline = new_spline;
}
i++;
point++;
}
}
}
/* TODO: only update edited splines */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_duplicate(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Duplicate Mask";
ot->description = "Duplicate selected control points and segments between them";
ot->idname = "MASK_OT_duplicate";
/* api callbacks */
ot->exec = mask_duplicate_exec;
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** copy splines to clipboard operator *********************/
static int copy_splines_exec(bContext *C, wmOperator *UNUSED(op))
{
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
if (mask_layer == NULL) {
return OPERATOR_CANCELLED;
}
BKE_mask_clipboard_copy_from_layer(mask_layer);
return OPERATOR_FINISHED;
}
void MASK_OT_copy_splines(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Copy Splines";
ot->description = "Copy selected splines to clipboard";
ot->idname = "MASK_OT_copy_splines";
/* api callbacks */
ot->exec = copy_splines_exec;
ot->poll = ED_maskedit_mask_poll;
/* flags */
ot->flag = OPTYPE_REGISTER;
}
/********************** paste tracks from clipboard operator *********************/
2018-07-02 11:47:00 +02:00
static bool paste_splines_poll(bContext *C)
{
if (ED_maskedit_mask_poll(C)) {
return BKE_mask_clipboard_is_empty() == false;
}
return 0;
}
static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
if (mask_layer == NULL) {
mask_layer = BKE_mask_layer_new(mask, "");
}
BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer);
/* TODO: only update edited splines */
BKE_mask_update_display(mask, CFRA);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
}
void MASK_OT_paste_splines(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Paste Splines";
ot->description = "Paste splines from clipboard";
ot->idname = "MASK_OT_paste_splines";
/* api callbacks */
ot->exec = paste_splines_exec;
ot->poll = paste_splines_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}