Blender  V3.3
mask_shapekey.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2012 Blender Foundation. All rights reserved. */
3 
8 #include <stdlib.h>
9 
10 #include "BLI_listbase.h"
11 #include "BLI_math.h"
12 #include "BLI_utildefines.h"
13 
14 #include "BKE_context.h"
15 #include "BKE_mask.h"
16 
17 #include "DNA_mask_types.h"
18 #include "DNA_object_types.h"
19 #include "DNA_scene_types.h"
20 
21 #include "DEG_depsgraph.h"
22 
23 #include "RNA_access.h"
24 #include "RNA_define.h"
25 
26 #include "WM_api.h"
27 #include "WM_types.h"
28 
29 #include "ED_mask.h" /* own include */
30 
31 #include "mask_intern.h" /* own include */
32 
34 {
36  const int frame = scene->r.cfra;
38  bool changed = false;
39 
40  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
41  MaskLayerShape *mask_layer_shape;
42 
43  if (!ED_mask_layer_select_check(mask_layer)) {
44  continue;
45  }
46 
47  mask_layer_shape = BKE_mask_layer_shape_verify_frame(mask_layer, frame);
48  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape);
49  changed = true;
50  }
51 
52  if (changed) {
54  DEG_id_tag_update(&mask->id, 0);
55 
56  return OPERATOR_FINISHED;
57  }
58  return OPERATOR_CANCELLED;
59 }
60 
62 {
63  /* identifiers */
64  ot->name = "Insert Shape Key";
65  ot->description = "Insert mask shape keyframe for active mask layer at the current frame";
66  ot->idname = "MASK_OT_shape_key_insert";
67 
68  /* api callbacks */
71 
72  /* flags */
74 }
75 
77 {
79  const int frame = scene->r.cfra;
81  bool changed = false;
82 
83  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
84  MaskLayerShape *mask_layer_shape;
85 
86  if (!ED_mask_layer_select_check(mask_layer)) {
87  continue;
88  }
89 
90  mask_layer_shape = BKE_mask_layer_shape_find_frame(mask_layer, frame);
91 
92  if (mask_layer_shape) {
93  BKE_mask_layer_shape_unlink(mask_layer, mask_layer_shape);
94  changed = true;
95  }
96  }
97 
98  if (changed) {
101 
102  return OPERATOR_FINISHED;
103  }
104  return OPERATOR_CANCELLED;
105 }
106 
108 {
109  /* identifiers */
110  ot->name = "Clear Shape Key";
111  ot->description = "Remove mask shape keyframe for active mask layer at the current frame";
112  ot->idname = "MASK_OT_shape_key_clear";
113 
114  /* api callbacks */
117 
118  /* flags */
120 }
121 
123 {
125  const int frame = scene->r.cfra;
127  bool changed = false;
128 
129  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
130 
131  if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
132  continue;
133  }
134 
135  if (mask_layer->splines_shapes.first) {
136  MaskLayerShape *mask_layer_shape_reset;
137  MaskLayerShape *mask_layer_shape;
138 
139  /* get the shapekey of the current state */
140  mask_layer_shape_reset = BKE_mask_layer_shape_alloc(mask_layer, frame);
141  /* initialize from mask - as if inseting a keyframe */
142  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_reset);
143 
144  for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape;
145  mask_layer_shape = mask_layer_shape->next) {
146 
147  if (mask_layer_shape_reset->tot_vert == mask_layer_shape->tot_vert) {
148  int i_abs = 0;
149  MaskLayerShapeElem *shape_ele_src;
150  MaskLayerShapeElem *shape_ele_dst;
151 
152  shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_reset->data;
153  shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape->data;
154 
155  LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
156  for (int i = 0; i < spline->tot_point; i++) {
157  MaskSplinePoint *point = &spline->points[i];
158 
159  if (MASKPOINT_ISSEL_ANY(point)) {
160  /* TODO: nicer access here. */
161  shape_ele_dst->value[6] = shape_ele_src->value[6];
162  }
163 
164  shape_ele_src++;
165  shape_ele_dst++;
166 
167  i_abs++;
168  }
169  }
170  }
171  else {
172  // printf("%s: skipping\n", __func__);
173  }
174 
175  changed = true;
176  }
177 
178  BKE_mask_layer_shape_free(mask_layer_shape_reset);
179  }
180  }
181 
182  if (changed) {
184  DEG_id_tag_update(&mask->id, 0);
185 
186  return OPERATOR_FINISHED;
187  }
188  return OPERATOR_CANCELLED;
189 }
190 
192 {
193  /* identifiers */
194  ot->name = "Feather Reset Animation";
195  ot->description = "Reset feather weights on all selected points animation values";
196  ot->idname = "MASK_OT_shape_key_feather_reset";
197 
198  /* api callbacks */
201 
202  /* flags */
204 }
205 
206 /*
207  * - loop over selected shape-keys.
208  * - find first-selected/last-selected pairs.
209  * - move these into a temp list.
210  * - re-key all the original shapes.
211  * - copy unselected values back from the original.
212  * - free the original.
213  */
215 {
217  const int frame = scene->r.cfra;
219  bool changed = false;
220 
221  const bool do_feather = RNA_boolean_get(op->ptr, "feather");
222  const bool do_location = RNA_boolean_get(op->ptr, "location");
223 
224  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
225  if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
226  continue;
227  }
228 
229  /* we need at least one point selected here to bother re-interpolating */
230  if (!ED_mask_layer_select_check(mask_layer)) {
231  continue;
232  }
233 
234  if (mask_layer->splines_shapes.first) {
235  MaskLayerShape *mask_layer_shape, *mask_layer_shape_next;
236  MaskLayerShape *mask_layer_shape_lastsel = NULL;
237 
238  for (mask_layer_shape = mask_layer->splines_shapes.first; mask_layer_shape;
239  mask_layer_shape = mask_layer_shape_next) {
240  MaskLayerShape *mask_layer_shape_a = NULL;
241  MaskLayerShape *mask_layer_shape_b = NULL;
242 
243  mask_layer_shape_next = mask_layer_shape->next;
244 
245  /* find contiguous selections */
246  if (mask_layer_shape->flag & MASK_SHAPE_SELECT) {
247  if (mask_layer_shape_lastsel == NULL) {
248  mask_layer_shape_lastsel = mask_layer_shape;
249  }
250  if ((mask_layer_shape->next == NULL) ||
251  (((MaskLayerShape *)mask_layer_shape->next)->flag & MASK_SHAPE_SELECT) == 0) {
252  mask_layer_shape_a = mask_layer_shape_lastsel;
253  mask_layer_shape_b = mask_layer_shape;
254  mask_layer_shape_lastsel = NULL;
255 
256  /* this will be freed below, step over selection */
257  mask_layer_shape_next = mask_layer_shape->next;
258  }
259  }
260 
261  /* we have a from<>to? - re-interpolate! */
262  if (mask_layer_shape_a && mask_layer_shape_b) {
263  ListBase shapes_tmp = {NULL, NULL};
264  MaskLayerShape *mask_layer_shape_tmp;
265  MaskLayerShape *mask_layer_shape_tmp_next;
266  MaskLayerShape *mask_layer_shape_tmp_last = mask_layer_shape_b->next;
267  MaskLayerShape *mask_layer_shape_tmp_rekey;
268 
269  /* move keys */
270  for (mask_layer_shape_tmp = mask_layer_shape_a;
271  mask_layer_shape_tmp && (mask_layer_shape_tmp != mask_layer_shape_tmp_last);
272  mask_layer_shape_tmp = mask_layer_shape_tmp_next) {
273  mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
274  BLI_remlink(&mask_layer->splines_shapes, mask_layer_shape_tmp);
275  BLI_addtail(&shapes_tmp, mask_layer_shape_tmp);
276  }
277 
278  /* re-key, NOTE: can't modify the keys here since it messes up. */
279  for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp;
280  mask_layer_shape_tmp = mask_layer_shape_tmp->next) {
281  BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true);
282  mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(
283  mask_layer, mask_layer_shape_tmp->frame);
284  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_tmp_rekey);
285  mask_layer_shape_tmp_rekey->flag = mask_layer_shape_tmp->flag & MASK_SHAPE_SELECT;
286  }
287 
288  /* restore unselected points and free copies */
289  for (mask_layer_shape_tmp = shapes_tmp.first; mask_layer_shape_tmp;
290  mask_layer_shape_tmp = mask_layer_shape_tmp_next) {
291  /* restore */
292  int i_abs = 0;
293  MaskLayerShapeElem *shape_ele_src;
294  MaskLayerShapeElem *shape_ele_dst;
295 
296  mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
297 
298  /* we know this exists, added above */
299  mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(
300  mask_layer, mask_layer_shape_tmp->frame);
301 
302  shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_tmp->data;
303  shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape_tmp_rekey->data;
304 
305  LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
306  for (int i = 0; i < spline->tot_point; i++) {
307  MaskSplinePoint *point = &spline->points[i];
308 
309  /* not especially efficient but makes this easier to follow */
310  SWAP(MaskLayerShapeElem, *shape_ele_src, *shape_ele_dst);
311 
312  if (MASKPOINT_ISSEL_ANY(point)) {
313  if (do_location) {
314  memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float[6]));
315  }
316  if (do_feather) {
317  shape_ele_dst->value[6] = shape_ele_src->value[6];
318  }
319  }
320 
321  shape_ele_src++;
322  shape_ele_dst++;
323 
324  i_abs++;
325  }
326  }
327 
328  BKE_mask_layer_shape_free(mask_layer_shape_tmp);
329  }
330 
331  changed = true;
332  }
333  }
334 
335  /* re-evaluate */
336  BKE_mask_layer_evaluate(mask_layer, frame, true);
337  }
338  }
339 
340  if (changed) {
342  DEG_id_tag_update(&mask->id, 0);
343 
344  return OPERATOR_FINISHED;
345  }
346  return OPERATOR_CANCELLED;
347 }
348 
350 {
351  /* identifiers */
352  ot->name = "Re-Key Points of Selected Shapes";
353  ot->description =
354  "Recalculate animation data on selected points for frames selected in the dopesheet";
355  ot->idname = "MASK_OT_shape_key_rekey";
356 
357  /* api callbacks */
360 
361  /* flags */
363 
364  /* properties */
365  RNA_def_boolean(ot->srna, "location", true, "Location", "");
366  RNA_def_boolean(ot->srna, "feather", true, "Feather", "");
367 }
368 
369 /* *** Shape Key Utils *** */
370 
371 void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, const int frame)
372 {
373  MaskLayerShape *mask_layer_shape;
374 
375  mask_layer_shape = BKE_mask_layer_shape_verify_frame(mask_layer, frame);
376  BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape);
377 }
378 
380 {
381  bool changed = false;
382 
383  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
384  ED_mask_layer_shape_auto_key(mask_layer, frame);
385  changed = true;
386  }
387 
388  return changed;
389 }
390 
392 {
393  bool changed = false;
394 
395  LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
396 
397  if (!ED_mask_layer_select_check(mask_layer)) {
398  continue;
399  }
400 
401  ED_mask_layer_shape_auto_key(mask_layer, frame);
402  changed = true;
403  }
404 
405  return changed;
406 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Mask * CTX_data_edit_mask(const bContext *C)
Definition: context.c:1390
struct MaskLayerShape * BKE_mask_layer_shape_verify_frame(struct MaskLayer *masklay, int frame)
Definition: mask.c:1771
#define MASKPOINT_ISSEL_ANY(p)
Definition: BKE_mask.h:296
struct MaskLayerShape * BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, int frame)
Definition: mask.c:1120
void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
Definition: mask.c:1799
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, float ctime, bool do_newframe)
Definition: mask.c:1558
struct MaskLayerShape * BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame)
Definition: mask.c:1715
void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
Definition: mask.c:1617
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape)
Definition: mask.c:1134
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
#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:791
#define MASK_HIDE_SELECT
@ MASK_SHAPE_SELECT
#define MASK_HIDE_VIEW
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_maskedit_mask_visible_splines_poll(struct bContext *C)
Definition: mask_edit.c:77
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DATA
Definition: WM_types.h:456
#define NC_MASK
Definition: WM_types.h:348
Scene scene
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:33
void MASK_OT_shape_key_insert(wmOperatorType *ot)
Definition: mask_shapekey.c:61
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:76
static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op))
static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void * first
Definition: DNA_listBase.h:31
float value[MASK_OBJECT_SHAPE_ELEM_SIZE]
struct MaskLayerShape * next
struct RenderData r
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479