Blender  V2.93
mask_shapekey.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2012 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <stdlib.h>
25 
26 #include "BLI_listbase.h"
27 #include "BLI_math.h"
28 #include "BLI_utildefines.h"
29 
30 #include "BKE_context.h"
31 #include "BKE_mask.h"
32 
33 #include "DNA_mask_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 
37 #include "DEG_depsgraph.h"
38 
39 #include "RNA_access.h"
40 #include "RNA_define.h"
41 
42 #include "WM_api.h"
43 #include "WM_types.h"
44 
45 #include "ED_mask.h" /* own include */
46 
47 #include "mask_intern.h" /* own include */
48 
50 {
52  const int frame = CFRA;
54  bool changed = false;
55 
56  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
57  MaskLayerShape *mask_layer_shape;
58 
59  if (!ED_mask_layer_select_check(mask_layer)) {
60  continue;
61  }
62 
63  mask_layer_shape = BKE_mask_layer_shape_verify_frame(mask_layer, frame);
64  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape);
65  changed = true;
66  }
67 
68  if (changed) {
70  DEG_id_tag_update(&mask->id, 0);
71 
72  return OPERATOR_FINISHED;
73  }
74  return OPERATOR_CANCELLED;
75 }
76 
78 {
79  /* identifiers */
80  ot->name = "Insert Shape Key";
81  ot->description = "Insert mask shape keyframe for active mask layer at the current frame";
82  ot->idname = "MASK_OT_shape_key_insert";
83 
84  /* api callbacks */
87 
88  /* flags */
90 }
91 
93 {
95  const int frame = CFRA;
97  bool changed = false;
98 
99  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
100  MaskLayerShape *mask_layer_shape;
101 
102  if (!ED_mask_layer_select_check(mask_layer)) {
103  continue;
104  }
105 
106  mask_layer_shape = BKE_mask_layer_shape_find_frame(mask_layer, frame);
107 
108  if (mask_layer_shape) {
109  BKE_mask_layer_shape_unlink(mask_layer, mask_layer_shape);
110  changed = true;
111  }
112  }
113 
114  if (changed) {
117 
118  return OPERATOR_FINISHED;
119  }
120  return OPERATOR_CANCELLED;
121 }
122 
124 {
125  /* identifiers */
126  ot->name = "Clear Shape Key";
127  ot->description = "Remove mask shape keyframe for active mask layer at the current frame";
128  ot->idname = "MASK_OT_shape_key_clear";
129 
130  /* api callbacks */
133 
134  /* flags */
136 }
137 
139 {
141  const int frame = CFRA;
143  bool changed = false;
144 
145  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
146 
147  if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
148  continue;
149  }
150 
151  if (mask_layer->splines_shapes.first) {
152  MaskLayerShape *mask_layer_shape_reset;
153  MaskLayerShape *mask_layer_shape;
154 
155  /* get the shapekey of the current state */
156  mask_layer_shape_reset = BKE_mask_layer_shape_alloc(mask_layer, frame);
157  /* initialize from mask - as if inseting a keyframe */
158  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_reset);
159 
160  for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape;
161  mask_layer_shape = mask_layer_shape->next) {
162 
163  if (mask_layer_shape_reset->tot_vert == mask_layer_shape->tot_vert) {
164  int i_abs = 0;
165  MaskLayerShapeElem *shape_ele_src;
166  MaskLayerShapeElem *shape_ele_dst;
167 
168  shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_reset->data;
169  shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape->data;
170 
171  LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
172  for (int i = 0; i < spline->tot_point; i++) {
173  MaskSplinePoint *point = &spline->points[i];
174 
175  if (MASKPOINT_ISSEL_ANY(point)) {
176  /* TODO - nicer access here */
177  shape_ele_dst->value[6] = shape_ele_src->value[6];
178  }
179 
180  shape_ele_src++;
181  shape_ele_dst++;
182 
183  i_abs++;
184  }
185  }
186  }
187  else {
188  // printf("%s: skipping\n", __func__);
189  }
190 
191  changed = true;
192  }
193 
194  BKE_mask_layer_shape_free(mask_layer_shape_reset);
195  }
196  }
197 
198  if (changed) {
200  DEG_id_tag_update(&mask->id, 0);
201 
202  return OPERATOR_FINISHED;
203  }
204  return OPERATOR_CANCELLED;
205 }
206 
208 {
209  /* identifiers */
210  ot->name = "Feather Reset Animation";
211  ot->description = "Reset feather weights on all selected points animation values";
212  ot->idname = "MASK_OT_shape_key_feather_reset";
213 
214  /* api callbacks */
217 
218  /* flags */
220 }
221 
222 /*
223  * - loop over selected shapekeys.
224  * - find firstsel/lastsel pairs.
225  * - move these into a temp list.
226  * - re-key all the original shapes.
227  * - copy unselected values back from the original.
228  * - free the original.
229  */
231 {
233  const int frame = CFRA;
235  bool changed = false;
236 
237  const bool do_feather = RNA_boolean_get(op->ptr, "feather");
238  const bool do_location = RNA_boolean_get(op->ptr, "location");
239 
240  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
241  if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
242  continue;
243  }
244 
245  /* we need at least one point selected here to bother re-interpolating */
246  if (!ED_mask_layer_select_check(mask_layer)) {
247  continue;
248  }
249 
250  if (mask_layer->splines_shapes.first) {
251  MaskLayerShape *mask_layer_shape, *mask_layer_shape_next;
252  MaskLayerShape *mask_layer_shape_lastsel = NULL;
253 
254  for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape;
255  mask_layer_shape = mask_layer_shape_next) {
256  MaskLayerShape *mask_layer_shape_a = NULL;
257  MaskLayerShape *mask_layer_shape_b = NULL;
258 
259  mask_layer_shape_next = mask_layer_shape->next;
260 
261  /* find contiguous selections */
262  if (mask_layer_shape->flag & MASK_SHAPE_SELECT) {
263  if (mask_layer_shape_lastsel == NULL) {
264  mask_layer_shape_lastsel = mask_layer_shape;
265  }
266  if ((mask_layer_shape->next == NULL) ||
267  (((MaskLayerShape *)mask_layer_shape->next)->flag & MASK_SHAPE_SELECT) == 0) {
268  mask_layer_shape_a = mask_layer_shape_lastsel;
269  mask_layer_shape_b = mask_layer_shape;
270  mask_layer_shape_lastsel = NULL;
271 
272  /* this will be freed below, step over selection */
273  mask_layer_shape_next = mask_layer_shape->next;
274  }
275  }
276 
277  /* we have a from<>to? - re-interpolate! */
278  if (mask_layer_shape_a && mask_layer_shape_b) {
279  ListBase shapes_tmp = {NULL, NULL};
280  MaskLayerShape *mask_layer_shape_tmp;
281  MaskLayerShape *mask_layer_shape_tmp_next;
282  MaskLayerShape *mask_layer_shape_tmp_last = mask_layer_shape_b->next;
283  MaskLayerShape *mask_layer_shape_tmp_rekey;
284 
285  /* move keys */
286  for (mask_layer_shape_tmp = mask_layer_shape_a;
287  mask_layer_shape_tmp && (mask_layer_shape_tmp != mask_layer_shape_tmp_last);
288  mask_layer_shape_tmp = mask_layer_shape_tmp_next) {
289  mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
290  BLI_remlink(&mask_layer->splines_shapes, mask_layer_shape_tmp);
291  BLI_addtail(&shapes_tmp, mask_layer_shape_tmp);
292  }
293 
294  /* re-key, note: cant modify the keys here since it messes uop */
295  for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp;
296  mask_layer_shape_tmp = mask_layer_shape_tmp->next) {
297  BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true);
298  mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(
299  mask_layer, mask_layer_shape_tmp->frame);
300  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_tmp_rekey);
301  mask_layer_shape_tmp_rekey->flag = mask_layer_shape_tmp->flag & MASK_SHAPE_SELECT;
302  }
303 
304  /* restore unselected points and free copies */
305  for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp;
306  mask_layer_shape_tmp = mask_layer_shape_tmp_next) {
307  /* restore */
308  int i_abs = 0;
309  MaskLayerShapeElem *shape_ele_src;
310  MaskLayerShapeElem *shape_ele_dst;
311 
312  mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
313 
314  /* we know this exists, added above */
315  mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(
316  mask_layer, mask_layer_shape_tmp->frame);
317 
318  shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_tmp->data;
319  shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape_tmp_rekey->data;
320 
321  LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
322  for (int i = 0; i < spline->tot_point; i++) {
323  MaskSplinePoint *point = &spline->points[i];
324 
325  /* not especially efficient but makes this easier to follow */
326  SWAP(MaskLayerShapeElem, *shape_ele_src, *shape_ele_dst);
327 
328  if (MASKPOINT_ISSEL_ANY(point)) {
329  if (do_location) {
330  memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float[6]));
331  }
332  if (do_feather) {
333  shape_ele_dst->value[6] = shape_ele_src->value[6];
334  }
335  }
336 
337  shape_ele_src++;
338  shape_ele_dst++;
339 
340  i_abs++;
341  }
342  }
343 
344  BKE_mask_layer_shape_free(mask_layer_shape_tmp);
345  }
346 
347  changed = true;
348  }
349  }
350 
351  /* re-evaluate */
352  BKE_mask_layer_evaluate(mask_layer, frame, true);
353  }
354  }
355 
356  if (changed) {
358  DEG_id_tag_update(&mask->id, 0);
359 
360  return OPERATOR_FINISHED;
361  }
362  return OPERATOR_CANCELLED;
363 }
364 
366 {
367  /* identifiers */
368  ot->name = "Re-Key Points of Selected Shapes";
369  ot->description =
370  "Recalculate animation data on selected points for frames selected in the dopesheet";
371  ot->idname = "MASK_OT_shape_key_rekey";
372 
373  /* api callbacks */
376 
377  /* flags */
379 
380  /* properties */
381  RNA_def_boolean(ot->srna, "location", true, "Location", "");
382  RNA_def_boolean(ot->srna, "feather", true, "Feather", "");
383 }
384 
385 /* *** Shape Key Utils *** */
386 
387 void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, const int frame)
388 {
389  MaskLayerShape *mask_layer_shape;
390 
391  mask_layer_shape = BKE_mask_layer_shape_verify_frame(mask_layer, frame);
392  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape);
393 }
394 
396 {
397  bool changed = false;
398 
399  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
400  ED_mask_layer_shape_auto_key(mask_layer, frame);
401  changed = true;
402  }
403 
404  return changed;
405 }
406 
408 {
409  bool changed = false;
410 
411  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
412 
413  if (!ED_mask_layer_select_check(mask_layer)) {
414  continue;
415  }
416 
417  ED_mask_layer_shape_auto_key(mask_layer, frame);
418  changed = true;
419  }
420 
421  return changed;
422 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Mask * CTX_data_edit_mask(const bContext *C)
Definition: context.c:1316
#define MASKPOINT_ISSEL_ANY(p)
Definition: BKE_mask.h:232
struct MaskLayerShape * BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, const int frame)
Definition: mask.c:1744
void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
Definition: mask.c:1831
struct MaskLayerShape * BKE_mask_layer_shape_verify_frame(struct MaskLayer *masklay, const int frame)
Definition: mask.c:1803
void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
Definition: mask.c:1645
struct MaskLayerShape * BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame)
Definition: mask.c:1137
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe)
Definition: mask.c:1585
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape)
Definition: mask.c:1151
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
#define SWAP(type, a, b)
#define UNUSED(x)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define MASK_RESTRICT_SELECT
@ MASK_SHAPE_SELECT
#define MASK_RESTRICT_VIEW
Object is a sort of wrapper for general info.
#define CFRA
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NC_MASK
Definition: WM_types.h:299
Scene scene
bool ED_maskedit_mask_poll(bContext *C)
Definition: mask_edit.c:61
bool ED_mask_layer_select_check(const struct MaskLayer *mask_layer)
static int mask_shape_key_insert_exec(bContext *C, wmOperator *UNUSED(op))
Definition: mask_shapekey.c:49
void MASK_OT_shape_key_insert(wmOperatorType *ot)
Definition: mask_shapekey.c:77
void MASK_OT_shape_key_feather_reset(wmOperatorType *ot)
void MASK_OT_shape_key_rekey(wmOperatorType *ot)
void MASK_OT_shape_key_clear(wmOperatorType *ot)
bool ED_mask_layer_shape_auto_key_select(Mask *mask, const int frame)
void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, const int frame)
bool ED_mask_layer_shape_auto_key_all(Mask *mask, const int frame)
static int mask_shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
Definition: mask_shapekey.c:92
static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op))
static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void * first
Definition: DNA_listBase.h:47
float value[MASK_OBJECT_SHAPE_ELEM_SIZE]
struct MaskLayerShape * next
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct PointerRNA * ptr
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156