Blender  V3.3
object_shapekey.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <math.h>
9 #include <string.h>
10 
11 #ifndef WIN32
12 # include <unistd.h>
13 #else
14 # include <io.h>
15 #endif
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "BLI_blenlib.h"
20 #include "BLI_math.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BLT_translation.h"
24 
25 #include "DNA_key_types.h"
26 #include "DNA_lattice_types.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_meshdata_types.h"
29 #include "DNA_object_types.h"
30 
31 #include "BKE_context.h"
32 #include "BKE_crazyspace.h"
33 #include "BKE_key.h"
34 #include "BKE_lattice.h"
35 #include "BKE_main.h"
36 #include "BKE_object.h"
37 #include "BKE_report.h"
38 
39 #include "DEG_depsgraph.h"
40 #include "DEG_depsgraph_build.h"
41 #include "DEG_depsgraph_query.h"
42 
43 #include "BLI_sys_types.h" /* for intptr_t support */
44 
45 #include "ED_mesh.h"
46 #include "ED_object.h"
47 
48 #include "RNA_access.h"
49 #include "RNA_define.h"
50 
51 #include "WM_api.h"
52 #include "WM_types.h"
53 
54 #include "object_intern.h"
55 
56 /* -------------------------------------------------------------------- */
60 static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
61 {
62  Main *bmain = CTX_data_main(C);
63  KeyBlock *kb;
64  if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
65  Key *key = BKE_key_from_object(ob);
66  /* for absolute shape keys, new keys may not be added last */
67  ob->shapenr = BLI_findindex(&key->block, kb) + 1;
68 
70  }
71 }
72 
75 /* -------------------------------------------------------------------- */
79 static bool object_shapekey_remove(Main *bmain, Object *ob)
80 {
81  KeyBlock *kb;
82  Key *key = BKE_key_from_object(ob);
83 
84  if (key == NULL) {
85  return false;
86  }
87 
88  kb = BLI_findlink(&key->block, ob->shapenr - 1);
89  if (kb) {
90  return BKE_object_shapekey_remove(bmain, ob, kb);
91  }
92 
93  return false;
94 }
95 
97  bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
98 {
99  KeyBlock *kb;
100  Key *key;
101  int totmirr = 0, totfail = 0;
102 
103  *r_totmirr = *r_totfail = 0;
104 
105  key = BKE_key_from_object(ob);
106  if (key == NULL) {
107  return 0;
108  }
109 
110  kb = BLI_findlink(&key->block, ob->shapenr - 1);
111 
112  if (kb) {
113  char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
114 
115  if (ob->type == OB_MESH) {
116  Mesh *me = ob->data;
117  MVert *mv;
118  int i1, i2;
119  float *fp1, *fp2;
120  float tvec[3];
121 
123 
124  for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
125  i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
126  if (i2 == i1) {
127  fp1 = ((float *)kb->data) + i1 * 3;
128  fp1[0] = -fp1[0];
129  tag_elem[i1] = 1;
130  totmirr++;
131  }
132  else if (i2 != -1) {
133  if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
134  fp1 = ((float *)kb->data) + i1 * 3;
135  fp2 = ((float *)kb->data) + i2 * 3;
136 
137  copy_v3_v3(tvec, fp1);
138  copy_v3_v3(fp1, fp2);
139  copy_v3_v3(fp2, tvec);
140 
141  /* flip x axis */
142  fp1[0] = -fp1[0];
143  fp2[0] = -fp2[0];
144  totmirr++;
145  }
146  tag_elem[i1] = tag_elem[i2] = 1;
147  }
148  else {
149  totfail++;
150  }
151  }
152 
154  }
155  else if (ob->type == OB_LATTICE) {
156  Lattice *lt = ob->data;
157  int i1, i2;
158  float *fp1, *fp2;
159  int u, v, w;
160  /* half but found up odd value */
161  const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
162 
163  /* currently editmode isn't supported by mesh so
164  * ignore here for now too */
165 
166  /* if (lt->editlatt) lt = lt->editlatt->latt; */
167 
168  for (w = 0; w < lt->pntsw; w++) {
169  for (v = 0; v < lt->pntsv; v++) {
170  for (u = 0; u < pntsu_half; u++) {
171  int u_inv = (lt->pntsu - 1) - u;
172  float tvec[3];
173  if (u == u_inv) {
174  i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
175  fp1 = ((float *)kb->data) + i1 * 3;
176  fp1[0] = -fp1[0];
177  totmirr++;
178  }
179  else {
180  i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
181  i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
182 
183  fp1 = ((float *)kb->data) + i1 * 3;
184  fp2 = ((float *)kb->data) + i2 * 3;
185 
186  copy_v3_v3(tvec, fp1);
187  copy_v3_v3(fp1, fp2);
188  copy_v3_v3(fp2, tvec);
189  fp1[0] = -fp1[0];
190  fp2[0] = -fp2[0];
191  totmirr++;
192  }
193  }
194  }
195  }
196  }
197 
198  MEM_freeN(tag_elem);
199  }
200 
201  *r_totmirr = totmirr;
202  *r_totfail = totfail;
203 
206 
207  return 1;
208 }
209 
212 /* -------------------------------------------------------------------- */
216 static bool shape_key_poll(bContext *C)
217 {
218  Object *ob = ED_object_context(C);
219  ID *data = (ob) ? ob->data : NULL;
220 
221  return (ob != NULL && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && data != NULL &&
223 }
224 
226 {
227  Object *ob = ED_object_context(C);
228 
229  return (shape_key_poll(C) && ob->mode != OB_MODE_EDIT);
230 }
231 
233 {
234  Object *ob = ED_object_context(C);
235 
236  return (shape_key_mode_poll(C) &&
237  /* check a keyblock exists */
238  (BKE_keyblock_from_object(ob) != NULL));
239 }
240 
242 {
243  /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
244  Object *ob = ED_object_context(C);
245  Key *key = BKE_key_from_object(ob);
246 
247  return (shape_key_mode_poll(C) && key != NULL && key->totkey > 1);
248 }
249 
252 /* -------------------------------------------------------------------- */
257 {
258  Object *ob = ED_object_context(C);
259  const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
260 
261  ED_object_shape_key_add(C, ob, from_mix);
262 
265 
266  return OPERATOR_FINISHED;
267 }
268 
270 {
271  /* identifiers */
272  ot->name = "Add Shape Key";
273  ot->idname = "OBJECT_OT_shape_key_add";
274  ot->description = "Add shape key to the object";
275 
276  /* api callbacks */
279 
280  /* flags */
282 
283  /* properties */
285  "from_mix",
286  true,
287  "From Mix",
288  "Create the new shape key from the existing mix of keys");
289 }
290 
293 /* -------------------------------------------------------------------- */
298 {
299  Main *bmain = CTX_data_main(C);
300  Object *ob = ED_object_context(C);
301  bool changed = false;
302 
303  if (RNA_boolean_get(op->ptr, "all")) {
304  if (RNA_boolean_get(op->ptr, "apply_mix")) {
305  float *arr = BKE_key_evaluate_object_ex(ob, NULL, NULL, 0, ob->data);
306  MEM_freeN(arr);
307  }
308  changed = BKE_object_shapekey_free(bmain, ob);
309  }
310  else {
311  changed = object_shapekey_remove(bmain, ob);
312  }
313 
314  if (changed) {
318 
319  return OPERATOR_FINISHED;
320  }
321  return OPERATOR_CANCELLED;
322 }
323 
325  wmOperator *op,
326  const PropertyRNA *prop)
327 {
328  const char *prop_id = RNA_property_identifier(prop);
329  const bool do_all = RNA_enum_get(op->ptr, "all");
330 
331  /* Only show seed for randomize action! */
332  if (STREQ(prop_id, "apply_mix") && !do_all) {
333  return false;
334  }
335  return true;
336 }
337 
340  PointerRNA *ptr)
341 {
342  const bool do_apply_mix = RNA_boolean_get(ptr, "apply_mix");
343 
344  if (do_apply_mix) {
345  return BLI_strdup(
346  TIP_("Apply current visible shape to the object data, and delete all shape keys"));
347  }
348 
349  return NULL;
350 }
351 
353 {
354  /* identifiers */
355  ot->name = "Remove Shape Key";
356  ot->idname = "OBJECT_OT_shape_key_remove";
357  ot->description = "Remove shape key from the object";
358 
359  /* api callbacks */
364 
365  /* flags */
367 
368  /* properties */
369  RNA_def_boolean(ot->srna, "all", false, "All", "Remove all shape keys");
371  "apply_mix",
372  false,
373  "Apply Mix",
374  "Apply current mix of shape keys to the geometry before removing them");
375 }
376 
379 /* -------------------------------------------------------------------- */
384 {
385  Object *ob = ED_object_context(C);
386  Key *key = BKE_key_from_object(ob);
388 
389  if (!key || !kb) {
390  return OPERATOR_CANCELLED;
391  }
392 
393  for (kb = key->block.first; kb; kb = kb->next) {
394  kb->curval = 0.0f;
395  }
396 
399 
400  return OPERATOR_FINISHED;
401 }
402 
404 {
405  /* identifiers */
406  ot->name = "Clear Shape Keys";
407  ot->description = "Clear weights for all shape keys";
408  ot->idname = "OBJECT_OT_shape_key_clear";
409 
410  /* api callbacks */
413 
414  /* flags */
416 }
417 
418 /* starting point and step size could be optional */
420 {
421  Object *ob = ED_object_context(C);
422  Key *key = BKE_key_from_object(ob);
424  float cfra = 0.0f;
425 
426  if (!key || !kb) {
427  return OPERATOR_CANCELLED;
428  }
429 
430  for (kb = key->block.first; kb; kb = kb->next) {
431  kb->pos = cfra;
432  cfra += 0.1f;
433  }
434 
437 
438  return OPERATOR_FINISHED;
439 }
440 
442 {
443  /* identifiers */
444  ot->name = "Re-Time Shape Keys";
445  ot->description = "Resets the timing for absolute shape keys";
446  ot->idname = "OBJECT_OT_shape_key_retime";
447 
448  /* api callbacks */
451 
452  /* flags */
454 }
455 
458 /* -------------------------------------------------------------------- */
463 {
464  Object *ob = ED_object_context(C);
465  int totmirr = 0, totfail = 0;
466  bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
467 
468  if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology)) {
469  return OPERATOR_CANCELLED;
470  }
471 
472  ED_mesh_report_mirror(op, totmirr, totfail);
473 
474  return OPERATOR_FINISHED;
475 }
476 
478 {
479  /* identifiers */
480  ot->name = "Mirror Shape Key";
481  ot->idname = "OBJECT_OT_shape_key_mirror";
482  ot->description = "Mirror the current shape key along the local X axis";
483 
484  /* api callbacks */
487 
488  /* flags */
490 
491  /* properties */
493  ot->srna,
494  "use_topology",
495  0,
496  "Topology Mirror",
497  "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
498 }
499 
502 /* -------------------------------------------------------------------- */
506 enum {
511 };
512 
514 {
515  Object *ob = ED_object_context(C);
516 
517  Key *key = BKE_key_from_object(ob);
518  const int type = RNA_enum_get(op->ptr, "type");
519  const int totkey = key->totkey;
520  const int act_index = ob->shapenr - 1;
521  int new_index;
522 
523  switch (type) {
524  case KB_MOVE_TOP:
525  /* Replace the ref key only if we're at the top already (only for relative keys) */
526  new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
527  break;
528  case KB_MOVE_BOTTOM:
529  new_index = totkey - 1;
530  break;
531  case KB_MOVE_UP:
532  case KB_MOVE_DOWN:
533  default:
534  new_index = (totkey + act_index + type) % totkey;
535  break;
536  }
537 
538  if (!BKE_keyblock_move(ob, act_index, new_index)) {
539  return OPERATOR_CANCELLED;
540  }
541 
544 
545  return OPERATOR_FINISHED;
546 }
547 
549 {
550  static const EnumPropertyItem slot_move[] = {
551  {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
552  {KB_MOVE_UP, "UP", 0, "Up", ""},
553  {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
554  {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
555  {0, NULL, 0, NULL, NULL}};
556 
557  /* identifiers */
558  ot->name = "Move Shape Key";
559  ot->idname = "OBJECT_OT_shape_key_move";
560  ot->description = "Move the active shape key up/down in the list";
561 
562  /* api callbacks */
565 
566  /* flags */
568 
569  RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
570 }
571 
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index)
Definition: key.c:2492
float * BKE_key_evaluate_object_ex(struct Object *ob, int *r_totelem, float *arr, size_t arr_size, struct ID *obdata)
Definition: key.c:1511
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
struct KeyBlock * BKE_keyblock_from_object(struct Object *ob)
Definition: key.c:1890
int BKE_lattice_index_from_uvw(struct Lattice *lt, int u, int v, int w)
Definition: lattice.c:205
General operations, lookup, etc. for blender objects.
struct KeyBlock * BKE_object_shapekey_insert(struct Main *bmain, struct Object *ob, const char *name, bool from_mix)
Definition: object.cc:4697
bool BKE_object_shapekey_remove(struct Main *bmain, struct Object *ob, struct KeyBlock *kb)
Definition: object.cc:4746
bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob)
Definition: object.cc:4729
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define TIP_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ KEY_NORMAL
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail)
Definition: mesh_data.cc:1401
void ED_mesh_mirror_spatial_table_begin(struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval)
void ED_mesh_mirror_spatial_table_end(struct Object *ob)
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, bool use_topology)
Definition: meshtools.cc:916
struct Object * ED_object_context(const struct bContext *C)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DRAW
Definition: WM_types.h:410
#define NC_OBJECT
Definition: WM_types.h:329
return(oflags[bm->toolflag_index].f &oflag) !=0
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static bool shape_key_move_poll(bContext *C)
static char * shape_key_remove_get_description(bContext *UNUSED(C), wmOperatorType *UNUSED(ot), PointerRNA *ptr)
static bool object_shape_key_mirror(bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
@ KB_MOVE_DOWN
@ KB_MOVE_TOP
@ KB_MOVE_UP
@ KB_MOVE_BOTTOM
static int shape_key_remove_exec(bContext *C, wmOperator *op)
void OBJECT_OT_shape_key_retime(wmOperatorType *ot)
static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
static bool shape_key_mode_exists_poll(bContext *C)
static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
static bool shape_key_mode_poll(bContext *C)
static bool shape_key_remove_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
void OBJECT_OT_shape_key_add(wmOperatorType *ot)
static int shape_key_add_exec(bContext *C, wmOperator *op)
static bool shape_key_poll(bContext *C)
static int shape_key_mirror_exec(bContext *C, wmOperator *op)
void OBJECT_OT_shape_key_move(wmOperatorType *ot)
static bool object_shapekey_remove(Main *bmain, Object *ob)
static int shape_key_move_exec(bContext *C, wmOperator *op)
void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
Definition: DNA_ID.h:368
float pos
Definition: DNA_key_types.h:32
float curval
Definition: DNA_key_types.h:34
struct KeyBlock * next
Definition: DNA_key_types.h:25
void * data
Definition: DNA_key_types.h:50
int totkey
Definition: DNA_key_types.h:91
char type
Definition: DNA_key_types.h:94
ListBase block
Definition: DNA_key_types.h:84
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct MVert * mvert
short shapenr
void * data
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
char *(* get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:966
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
bool(* poll_property)(const struct bContext *C, struct wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:949
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)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479