Blender V4.3
mask_shapekey.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10
11#include "BLI_listbase.h"
12#include "BLI_utildefines.h"
13
14#include "BKE_context.hh"
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.hh"
22
23#include "RNA_access.hh"
24#include "RNA_define.hh"
25
26#include "WM_api.hh"
27#include "WM_types.hh"
28
29#include "ED_mask.hh" /* own include */
30
31#include "mask_intern.hh" /* own include */
32
34{
35 Scene *scene = CTX_data_scene(C);
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{
78 Scene *scene = CTX_data_scene(C);
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{
124 Scene *scene = CTX_data_scene(C);
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
138 /* Get the shape-key of the current state. */
139 mask_layer_shape_reset = BKE_mask_layer_shape_alloc(mask_layer, frame);
140 /* Initialize from mask - as if inserting a keyframe. */
141 BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_reset);
142
143 LISTBASE_FOREACH (MaskLayerShape *, mask_layer_shape, &mask_layer->splines_shapes) {
144 if (mask_layer_shape_reset->tot_vert == mask_layer_shape->tot_vert) {
145 int i_abs = 0;
146 MaskLayerShapeElem *shape_ele_src;
147 MaskLayerShapeElem *shape_ele_dst;
148
149 shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_reset->data;
150 shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape->data;
151
152 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
153 for (int i = 0; i < spline->tot_point; i++) {
154 MaskSplinePoint *point = &spline->points[i];
155
157 /* TODO: nicer access here. */
158 shape_ele_dst->value[6] = shape_ele_src->value[6];
159 }
160
161 shape_ele_src++;
162 shape_ele_dst++;
163
164 i_abs++;
165 }
166 }
167 (void)i_abs; /* Quiet set-but-unused warning (may be removed). */
168 }
169 else {
170 // printf("%s: skipping\n", __func__);
171 }
172
173 changed = true;
174 }
175
176 BKE_mask_layer_shape_free(mask_layer_shape_reset);
177 }
178 }
179
180 if (changed) {
182 DEG_id_tag_update(&mask->id, 0);
183
184 return OPERATOR_FINISHED;
185 }
186 return OPERATOR_CANCELLED;
187}
188
190{
191 /* identifiers */
192 ot->name = "Feather Reset Animation";
193 ot->description = "Reset feather weights on all selected points animation values";
194 ot->idname = "MASK_OT_shape_key_feather_reset";
195
196 /* api callbacks */
199
200 /* flags */
202}
203
204/*
205 * - loop over selected shape-keys.
206 * - find first-selected/last-selected pairs.
207 * - move these into a temp list.
208 * - re-key all the original shapes.
209 * - copy unselected values back from the original.
210 * - free the original.
211 */
213{
214 Scene *scene = CTX_data_scene(C);
215 const int frame = scene->r.cfra;
217 bool changed = false;
218
219 const bool do_feather = RNA_boolean_get(op->ptr, "feather");
220 const bool do_location = RNA_boolean_get(op->ptr, "location");
221
222 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
223 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
224 continue;
225 }
226
227 /* we need at least one point selected here to bother re-interpolating */
228 if (!ED_mask_layer_select_check(mask_layer)) {
229 continue;
230 }
231
232 if (mask_layer->splines_shapes.first) {
233 MaskLayerShape *mask_layer_shape, *mask_layer_shape_next;
234 MaskLayerShape *mask_layer_shape_lastsel = nullptr;
235
236 for (mask_layer_shape = static_cast<MaskLayerShape *>(mask_layer->splines_shapes.first);
237 mask_layer_shape;
238 mask_layer_shape = mask_layer_shape_next)
239 {
240 MaskLayerShape *mask_layer_shape_a = nullptr;
241 MaskLayerShape *mask_layer_shape_b = nullptr;
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 == nullptr) {
248 mask_layer_shape_lastsel = mask_layer_shape;
249 }
250 if ((mask_layer_shape->next == nullptr) ||
251 (((MaskLayerShape *)mask_layer_shape->next)->flag & MASK_SHAPE_SELECT) == 0)
252 {
253 mask_layer_shape_a = mask_layer_shape_lastsel;
254 mask_layer_shape_b = mask_layer_shape;
255 mask_layer_shape_lastsel = nullptr;
256
257 /* this will be freed below, step over selection */
258 mask_layer_shape_next = mask_layer_shape->next;
259 }
260 }
261
262 /* we have a from<>to? - re-interpolate! */
263 if (mask_layer_shape_a && mask_layer_shape_b) {
264 ListBase shapes_tmp = {nullptr, nullptr};
265 MaskLayerShape *mask_layer_shape_tmp;
266 MaskLayerShape *mask_layer_shape_tmp_next;
267 MaskLayerShape *mask_layer_shape_tmp_last = mask_layer_shape_b->next;
268 MaskLayerShape *mask_layer_shape_tmp_rekey;
269
270 /* move keys */
271 for (mask_layer_shape_tmp = mask_layer_shape_a;
272 mask_layer_shape_tmp && (mask_layer_shape_tmp != mask_layer_shape_tmp_last);
273 mask_layer_shape_tmp = mask_layer_shape_tmp_next)
274 {
275 mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
276 BLI_remlink(&mask_layer->splines_shapes, mask_layer_shape_tmp);
277 BLI_addtail(&shapes_tmp, mask_layer_shape_tmp);
278 }
279
280 /* re-key, NOTE: can't modify the keys here since it messes up. */
281 for (mask_layer_shape_tmp = static_cast<MaskLayerShape *>(shapes_tmp.first);
282 mask_layer_shape_tmp;
283 mask_layer_shape_tmp = mask_layer_shape_tmp->next)
284 {
285 BKE_mask_layer_evaluate(mask_layer, mask_layer_shape_tmp->frame, true);
286 mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_verify_frame(
287 mask_layer, mask_layer_shape_tmp->frame);
288 BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape_tmp_rekey);
289 mask_layer_shape_tmp_rekey->flag = mask_layer_shape_tmp->flag & MASK_SHAPE_SELECT;
290 }
291
292 /* restore unselected points and free copies */
293 for (mask_layer_shape_tmp = static_cast<MaskLayerShape *>(shapes_tmp.first);
294 mask_layer_shape_tmp;
295 mask_layer_shape_tmp = mask_layer_shape_tmp_next)
296 {
297 /* restore */
298 int i_abs = 0;
299 MaskLayerShapeElem *shape_ele_src;
300 MaskLayerShapeElem *shape_ele_dst;
301
302 mask_layer_shape_tmp_next = mask_layer_shape_tmp->next;
303
304 /* we know this exists, added above */
305 mask_layer_shape_tmp_rekey = BKE_mask_layer_shape_find_frame(
306 mask_layer, mask_layer_shape_tmp->frame);
307
308 shape_ele_src = (MaskLayerShapeElem *)mask_layer_shape_tmp->data;
309 shape_ele_dst = (MaskLayerShapeElem *)mask_layer_shape_tmp_rekey->data;
310
311 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
312 for (int i = 0; i < spline->tot_point; i++) {
313 MaskSplinePoint *point = &spline->points[i];
314
315 /* not especially efficient but makes this easier to follow */
316 std::swap(*shape_ele_src, *shape_ele_dst);
317
319 if (do_location) {
320 memcpy(shape_ele_dst->value, shape_ele_src->value, sizeof(float[6]));
321 }
322 if (do_feather) {
323 shape_ele_dst->value[6] = shape_ele_src->value[6];
324 }
325 }
326
327 shape_ele_src++;
328 shape_ele_dst++;
329
330 i_abs++;
331 }
332 }
333 (void)i_abs; /* Quiet set-but-unused warning (may be removed). */
334
335 BKE_mask_layer_shape_free(mask_layer_shape_tmp);
336 }
337
338 changed = true;
339 }
340 }
341
342 /* re-evaluate */
343 BKE_mask_layer_evaluate(mask_layer, frame, true);
344 }
345 }
346
347 if (changed) {
349 DEG_id_tag_update(&mask->id, 0);
350
351 return OPERATOR_FINISHED;
352 }
353 return OPERATOR_CANCELLED;
354}
355
357{
358 /* identifiers */
359 ot->name = "Re-Key Points of Selected Shapes";
360 ot->description =
361 "Recalculate animation data on selected points for frames selected in the dopesheet";
362 ot->idname = "MASK_OT_shape_key_rekey";
363
364 /* api callbacks */
367
368 /* flags */
370
371 /* properties */
372 RNA_def_boolean(ot->srna, "location", true, "Location", "");
373 RNA_def_boolean(ot->srna, "feather", true, "Feather", "");
374}
375
376/* *** Shape Key Utils *** */
377
378void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, const int frame)
379{
380 MaskLayerShape *mask_layer_shape;
381
382 mask_layer_shape = BKE_mask_layer_shape_verify_frame(mask_layer, frame);
383 BKE_mask_layer_shape_from_mask(mask_layer, mask_layer_shape);
384}
385
387{
388 bool changed = false;
389
390 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
391 ED_mask_layer_shape_auto_key(mask_layer, frame);
392 changed = true;
393 }
394
395 return changed;
396}
397
399{
400 bool changed = false;
401
402 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
403
404 if (!ED_mask_layer_select_check(mask_layer)) {
405 continue;
406 }
407
408 ED_mask_layer_shape_auto_key(mask_layer, frame);
409 changed = true;
410 }
411
412 return changed;
413}
Mask * CTX_data_edit_mask(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
#define MASKPOINT_ISSEL_ANY(p)
Definition BKE_mask.h:297
void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
struct MaskLayerShape * BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, int frame)
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, float ctime, bool do_newframe)
void BKE_mask_layer_shape_from_mask(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape)
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape)
struct MaskLayerShape * BKE_mask_layer_shape_verify_frame(struct MaskLayer *masklay, int frame)
struct MaskLayerShape * BKE_mask_layer_shape_find_frame(struct MaskLayer *masklay, int frame)
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ MASK_HIDE_SELECT
@ MASK_HIDE_VIEW
@ MASK_SHAPE_SELECT
Object is a sort of wrapper for general info.
bool ED_maskedit_mask_visible_splines_poll(bContext *C)
Definition mask_edit.cc:78
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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:29
#define ND_DATA
Definition WM_types.hh:475
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_MASK
Definition WM_types.hh:365
bool ED_mask_layer_select_check(const MaskLayer *mask_layer)
static int mask_shape_key_clear_exec(bContext *C, wmOperator *)
void MASK_OT_shape_key_insert(wmOperatorType *ot)
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)
static int mask_shape_key_insert_exec(bContext *C, wmOperator *)
static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *)
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_rekey_exec(bContext *C, wmOperator *op)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void * first
float value[MASK_OBJECT_SHAPE_ELEM_SIZE]
struct MaskLayerShape * next
struct RenderData r
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125