Blender  V2.93
object_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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <math.h>
25 #include <string.h>
26 
27 #ifndef WIN32
28 # include <unistd.h>
29 #else
30 # include <io.h>
31 #endif
32 
33 #include "MEM_guardedalloc.h"
34 
35 #include "BLI_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 
39 #include "DNA_key_types.h"
40 #include "DNA_lattice_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_object_types.h"
44 
45 #include "BKE_context.h"
46 #include "BKE_key.h"
47 #include "BKE_lattice.h"
48 #include "BKE_main.h"
49 #include "BKE_object.h"
50 
51 #include "DEG_depsgraph.h"
52 #include "DEG_depsgraph_build.h"
53 
54 #include "BLI_sys_types.h" /* for intptr_t support */
55 
56 #include "ED_mesh.h"
57 #include "ED_object.h"
58 
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61 
62 #include "WM_api.h"
63 #include "WM_types.h"
64 
65 #include "object_intern.h"
66 
67 /* -------------------------------------------------------------------- */
71 static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
72 {
73  Main *bmain = CTX_data_main(C);
74  KeyBlock *kb;
75  if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
76  Key *key = BKE_key_from_object(ob);
77  /* for absolute shape keys, new keys may not be added last */
78  ob->shapenr = BLI_findindex(&key->block, kb) + 1;
79 
81  }
82 }
83 
86 /* -------------------------------------------------------------------- */
90 static bool object_shapekey_remove(Main *bmain, Object *ob)
91 {
92  KeyBlock *kb;
93  Key *key = BKE_key_from_object(ob);
94 
95  if (key == NULL) {
96  return false;
97  }
98 
99  kb = BLI_findlink(&key->block, ob->shapenr - 1);
100  if (kb) {
101  return BKE_object_shapekey_remove(bmain, ob, kb);
102  }
103 
104  return false;
105 }
106 
108  bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
109 {
110  KeyBlock *kb;
111  Key *key;
112  int totmirr = 0, totfail = 0;
113 
114  *r_totmirr = *r_totfail = 0;
115 
116  key = BKE_key_from_object(ob);
117  if (key == NULL) {
118  return 0;
119  }
120 
121  kb = BLI_findlink(&key->block, ob->shapenr - 1);
122 
123  if (kb) {
124  char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
125 
126  if (ob->type == OB_MESH) {
127  Mesh *me = ob->data;
128  MVert *mv;
129  int i1, i2;
130  float *fp1, *fp2;
131  float tvec[3];
132 
134 
135  for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
136  i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
137  if (i2 == i1) {
138  fp1 = ((float *)kb->data) + i1 * 3;
139  fp1[0] = -fp1[0];
140  tag_elem[i1] = 1;
141  totmirr++;
142  }
143  else if (i2 != -1) {
144  if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
145  fp1 = ((float *)kb->data) + i1 * 3;
146  fp2 = ((float *)kb->data) + i2 * 3;
147 
148  copy_v3_v3(tvec, fp1);
149  copy_v3_v3(fp1, fp2);
150  copy_v3_v3(fp2, tvec);
151 
152  /* flip x axis */
153  fp1[0] = -fp1[0];
154  fp2[0] = -fp2[0];
155  totmirr++;
156  }
157  tag_elem[i1] = tag_elem[i2] = 1;
158  }
159  else {
160  totfail++;
161  }
162  }
163 
165  }
166  else if (ob->type == OB_LATTICE) {
167  Lattice *lt = ob->data;
168  int i1, i2;
169  float *fp1, *fp2;
170  int u, v, w;
171  /* half but found up odd value */
172  const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
173 
174  /* currently editmode isn't supported by mesh so
175  * ignore here for now too */
176 
177  /* if (lt->editlatt) lt = lt->editlatt->latt; */
178 
179  for (w = 0; w < lt->pntsw; w++) {
180  for (v = 0; v < lt->pntsv; v++) {
181  for (u = 0; u < pntsu_half; u++) {
182  int u_inv = (lt->pntsu - 1) - u;
183  float tvec[3];
184  if (u == u_inv) {
185  i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
186  fp1 = ((float *)kb->data) + i1 * 3;
187  fp1[0] = -fp1[0];
188  totmirr++;
189  }
190  else {
191  i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
192  i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
193 
194  fp1 = ((float *)kb->data) + i1 * 3;
195  fp2 = ((float *)kb->data) + i2 * 3;
196 
197  copy_v3_v3(tvec, fp1);
198  copy_v3_v3(fp1, fp2);
199  copy_v3_v3(fp2, tvec);
200  fp1[0] = -fp1[0];
201  fp2[0] = -fp2[0];
202  totmirr++;
203  }
204  }
205  }
206  }
207  }
208 
209  MEM_freeN(tag_elem);
210  }
211 
212  *r_totmirr = totmirr;
213  *r_totfail = totfail;
214 
217 
218  return 1;
219 }
220 
223 /* -------------------------------------------------------------------- */
227 static bool shape_key_poll(bContext *C)
228 {
229  Object *ob = ED_object_context(C);
230  ID *data = (ob) ? ob->data : NULL;
231 
232  return (ob != NULL && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && data != NULL &&
234 }
235 
237 {
238  Object *ob = ED_object_context(C);
239 
240  return (shape_key_poll(C) && ob->mode != OB_MODE_EDIT);
241 }
242 
244 {
245  Object *ob = ED_object_context(C);
246 
247  return (shape_key_mode_poll(C) &&
248  /* check a keyblock exists */
249  (BKE_keyblock_from_object(ob) != NULL));
250 }
251 
253 {
254  /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
255  Object *ob = ED_object_context(C);
256  Key *key = BKE_key_from_object(ob);
257 
258  return (shape_key_mode_poll(C) && key != NULL && key->totkey > 1);
259 }
260 
263 /* -------------------------------------------------------------------- */
268 {
269  Object *ob = ED_object_context(C);
270  const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
271 
272  ED_object_shape_key_add(C, ob, from_mix);
273 
276 
277  return OPERATOR_FINISHED;
278 }
279 
281 {
282  /* identifiers */
283  ot->name = "Add Shape Key";
284  ot->idname = "OBJECT_OT_shape_key_add";
285  ot->description = "Add shape key to the object";
286 
287  /* api callbacks */
290 
291  /* flags */
293 
294  /* properties */
296  "from_mix",
297  true,
298  "From Mix",
299  "Create the new shape key from the existing mix of keys");
300 }
301 
304 /* -------------------------------------------------------------------- */
309 {
310  Main *bmain = CTX_data_main(C);
311  Object *ob = ED_object_context(C);
312  bool changed = false;
313 
314  if (RNA_boolean_get(op->ptr, "all")) {
315  changed = BKE_object_shapekey_free(bmain, ob);
316  }
317  else {
318  changed = object_shapekey_remove(bmain, ob);
319  }
320 
321  if (changed) {
325 
326  return OPERATOR_FINISHED;
327  }
328  return OPERATOR_CANCELLED;
329 }
330 
332 {
333  /* identifiers */
334  ot->name = "Remove Shape Key";
335  ot->idname = "OBJECT_OT_shape_key_remove";
336  ot->description = "Remove shape key from the object";
337 
338  /* api callbacks */
341 
342  /* flags */
344 
345  /* properties */
346  RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
347 }
348 
351 /* -------------------------------------------------------------------- */
356 {
357  Object *ob = ED_object_context(C);
358  Key *key = BKE_key_from_object(ob);
360 
361  if (!key || !kb) {
362  return OPERATOR_CANCELLED;
363  }
364 
365  for (kb = key->block.first; kb; kb = kb->next) {
366  kb->curval = 0.0f;
367  }
368 
371 
372  return OPERATOR_FINISHED;
373 }
374 
376 {
377  /* identifiers */
378  ot->name = "Clear Shape Keys";
379  ot->description = "Clear weights for all shape keys";
380  ot->idname = "OBJECT_OT_shape_key_clear";
381 
382  /* api callbacks */
385 
386  /* flags */
388 }
389 
390 /* starting point and step size could be optional */
392 {
393  Object *ob = ED_object_context(C);
394  Key *key = BKE_key_from_object(ob);
396  float cfra = 0.0f;
397 
398  if (!key || !kb) {
399  return OPERATOR_CANCELLED;
400  }
401 
402  for (kb = key->block.first; kb; kb = kb->next) {
403  kb->pos = cfra;
404  cfra += 0.1f;
405  }
406 
409 
410  return OPERATOR_FINISHED;
411 }
412 
414 {
415  /* identifiers */
416  ot->name = "Re-Time Shape Keys";
417  ot->description = "Resets the timing for absolute shape keys";
418  ot->idname = "OBJECT_OT_shape_key_retime";
419 
420  /* api callbacks */
423 
424  /* flags */
426 }
427 
430 /* -------------------------------------------------------------------- */
435 {
436  Object *ob = ED_object_context(C);
437  int totmirr = 0, totfail = 0;
438  bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
439 
440  if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology)) {
441  return OPERATOR_CANCELLED;
442  }
443 
444  ED_mesh_report_mirror(op, totmirr, totfail);
445 
446  return OPERATOR_FINISHED;
447 }
448 
450 {
451  /* identifiers */
452  ot->name = "Mirror Shape Key";
453  ot->idname = "OBJECT_OT_shape_key_mirror";
454  ot->description = "Mirror the current shape key along the local X axis";
455 
456  /* api callbacks */
459 
460  /* flags */
462 
463  /* properties */
465  ot->srna,
466  "use_topology",
467  0,
468  "Topology Mirror",
469  "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
470 }
471 
474 /* -------------------------------------------------------------------- */
478 enum {
483 };
484 
486 {
487  Object *ob = ED_object_context(C);
488 
489  Key *key = BKE_key_from_object(ob);
490  const int type = RNA_enum_get(op->ptr, "type");
491  const int totkey = key->totkey;
492  const int act_index = ob->shapenr - 1;
493  int new_index;
494 
495  switch (type) {
496  case KB_MOVE_TOP:
497  /* Replace the ref key only if we're at the top already (only for relative keys) */
498  new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
499  break;
500  case KB_MOVE_BOTTOM:
501  new_index = totkey - 1;
502  break;
503  case KB_MOVE_UP:
504  case KB_MOVE_DOWN:
505  default:
506  new_index = (totkey + act_index + type) % totkey;
507  break;
508  }
509 
510  if (!BKE_keyblock_move(ob, act_index, new_index)) {
511  return OPERATOR_CANCELLED;
512  }
513 
516 
517  return OPERATOR_FINISHED;
518 }
519 
521 {
522  static const EnumPropertyItem slot_move[] = {
523  {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
524  {KB_MOVE_UP, "UP", 0, "Up", ""},
525  {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
526  {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
527  {0, NULL, 0, NULL, NULL}};
528 
529  /* identifiers */
530  ot->name = "Move Shape Key";
531  ot->idname = "OBJECT_OT_shape_key_move";
532  ot->description = "Move the active shape key up/down in the list";
533 
534  /* api callbacks */
537 
538  /* flags */
540 
541  RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
542 }
543 
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index)
Definition: key.c:2519
struct Key * BKE_key_from_object(const struct Object *ob)
struct KeyBlock * BKE_keyblock_from_object(struct Object *ob)
Definition: key.c:1902
int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w)
Definition: lattice.c:214
General operations, lookup, etc. for blender objects.
struct KeyBlock * BKE_object_shapekey_insert(struct Main *bmain, struct Object *ob, const char *name, const bool from_mix)
Definition: object.c:4726
bool BKE_object_shapekey_remove(struct Main *bmain, struct Object *ob, struct KeyBlock *kb)
Definition: object.c:4775
bool BKE_object_shapekey_free(struct Main *bmain, struct Object *ob)
Definition: object.c:4758
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])
#define UNUSED(x)
#define ELEM(...)
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:611
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ KEY_NORMAL
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
int mesh_get_x_mirror_vert(struct Object *ob, struct Mesh *me_eval, int index, const bool use_topology)
Definition: meshtools.c:932
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail)
Definition: mesh_data.c:1355
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)
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:39
#define ND_DRAW
Definition: WM_types.h:362
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_OBJECT
Definition: WM_types.h:280
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:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static bool shape_key_move_poll(bContext *C)
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)
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)
@ KB_MOVE_DOWN
@ KB_MOVE_TOP
@ KB_MOVE_UP
@ KB_MOVE_BOTTOM
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)
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))
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
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
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:3771
Definition: DNA_ID.h:273
float pos
Definition: DNA_key_types.h:48
float curval
Definition: DNA_key_types.h:50
struct KeyBlock * next
Definition: DNA_key_types.h:41
void * data
Definition: DNA_key_types.h:66
int totkey
char type
ListBase block
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct MVert * mvert
short shapenr
void * data
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
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156