Blender V5.0
object_shapekey.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
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_listbase.h"
20#include "BLI_math_vector.h"
21#include "BLI_utildefines.h"
22
23#include "BLT_translation.hh"
24
25#include "DNA_key_types.h"
26#include "DNA_lattice_types.h"
27#include "DNA_mesh_types.h"
28#include "DNA_object_types.h"
29
30#include "BKE_context.hh"
31#include "BKE_key.hh"
32#include "BKE_lattice.hh"
33#include "BKE_library.hh"
34#include "BKE_object.hh"
35#include "BKE_report.hh"
36
37#include "DEG_depsgraph.hh"
39
40#include "ED_curve.hh"
41#include "ED_lattice.hh"
42#include "ED_mesh.hh"
43#include "ED_object.hh"
44
45#include "RNA_access.hh"
46#include "RNA_define.hh"
47
48#include "WM_api.hh"
49#include "WM_types.hh"
50
51#include "object_intern.hh"
52
53namespace blender::ed::object {
54
55/* -------------------------------------------------------------------- */
58
59bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
60{
61 KeyBlock *key_block;
62
63 switch (obedit->type) {
64 case OB_MESH:
65 key_block = ED_mesh_get_edit_shape_key(static_cast<Mesh *>(obedit->data));
66 break;
67 case OB_SURF:
69 key_block = ED_curve_get_edit_shape_key(static_cast<Curve *>(obedit->data));
70 break;
71 case OB_LATTICE:
72 key_block = ED_lattice_get_edit_shape_key(static_cast<Lattice *>(obedit->data));
73 break;
74 default:
75 return false;
76 }
77
78 if (key_block && (key_block->flag & KEYBLOCK_LOCKED_SHAPE) != 0) {
79 if (reports) {
80 BKE_reportf(reports, RPT_ERROR, "The active shape key of %s is locked", obedit->id.name + 2);
81 }
82 return true;
83 }
84
85 return false;
86}
87
89{
90 const KeyBlock *kb = BKE_keyblock_from_object(ob);
91
92 if (kb && (kb->flag & KEYBLOCK_LOCKED_SHAPE) != 0) {
93 if (reports) {
94 BKE_reportf(reports, RPT_ERROR, "The active shape key of %s is locked", ob->id.name + 2);
95 }
96 return true;
97 }
98
99 return false;
100}
101
103{
104 const Key *key = BKE_key_from_object(ob);
105
106 if (key) {
107 LISTBASE_FOREACH (const KeyBlock *, kb, &key->block) {
108 if (kb->flag & KEYBLOCK_LOCKED_SHAPE) {
109 return true;
110 }
111 }
112 }
113
114 return false;
115}
116
118{
120 if (reports) {
121 BKE_reportf(reports, RPT_ERROR, "The object %s has locked shape keys", ob->id.name + 2);
122 }
123 return true;
124 }
125
126 return false;
127}
128
129bool shape_key_is_selected(const Object &object, const KeyBlock &kb, const int keyblock_index)
130{
131 /* The active shape key is always considered selected. */
132 return (kb.flag & KEYBLOCK_SEL) || keyblock_index == object.shapenr - 1;
133}
134
136
137/* -------------------------------------------------------------------- */
140
141static void object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
142{
143 Main *bmain = CTX_data_main(C);
144 KeyBlock *kb = BKE_object_shapekey_insert(bmain, ob, nullptr, from_mix);
145 if (kb) {
146 /* Shapekeys created via this operator should get default value 1.0. */
147 kb->curval = 1.0f;
148
149 Key *key = BKE_key_from_object(ob);
150 /* for absolute shape keys, new keys may not be added last */
151 ob->shapenr = BLI_findindex(&key->block, kb) + 1;
152
154 }
155}
156
158
159/* -------------------------------------------------------------------- */
162
164 Object *ob, KeyBlock *kb, const bool use_topology, int &totmirr, int &totfail)
165{
166 char *tag_elem = MEM_calloc_arrayN<char>(kb->totelem, "shape_key_mirror");
167
168 if (ob->type == OB_MESH) {
169 Mesh *mesh = static_cast<Mesh *>(ob->data);
170 int i1, i2;
171 float *fp1, *fp2;
172 float tvec[3];
173
174 ED_mesh_mirror_spatial_table_begin(ob, nullptr, nullptr);
175
176 for (i1 = 0; i1 < mesh->verts_num; i1++) {
177 i2 = mesh_get_x_mirror_vert(ob, nullptr, i1, use_topology);
178 if (i2 == i1) {
179 fp1 = ((float *)kb->data) + i1 * 3;
180 fp1[0] = -fp1[0];
181 tag_elem[i1] = 1;
182 totmirr++;
183 }
184 else if (i2 != -1) {
185 if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
186 fp1 = ((float *)kb->data) + i1 * 3;
187 fp2 = ((float *)kb->data) + i2 * 3;
188
189 copy_v3_v3(tvec, fp1);
190 copy_v3_v3(fp1, fp2);
191 copy_v3_v3(fp2, tvec);
192
193 /* flip x axis */
194 fp1[0] = -fp1[0];
195 fp2[0] = -fp2[0];
196 totmirr++;
197 }
198 tag_elem[i1] = tag_elem[i2] = 1;
199 }
200 else {
201 totfail++;
202 }
203 }
204
206 }
207 else if (ob->type == OB_LATTICE) {
208 const Lattice *lt = static_cast<const Lattice *>(ob->data);
209 int i1, i2;
210 float *fp1, *fp2;
211 int u, v, w;
212 /* half but found up odd value */
213 const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
214
215 /* Currently edit-mode isn't supported by mesh so ignore here for now too. */
216#if 0
217 if (lt->editlatt) {
218 lt = lt->editlatt->latt;
219 }
220#endif
221
222 for (w = 0; w < lt->pntsw; w++) {
223 for (v = 0; v < lt->pntsv; v++) {
224 for (u = 0; u < pntsu_half; u++) {
225 int u_inv = (lt->pntsu - 1) - u;
226 float tvec[3];
227 if (u == u_inv) {
228 i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
229 fp1 = ((float *)kb->data) + i1 * 3;
230 fp1[0] = -fp1[0];
231 totmirr++;
232 }
233 else {
234 i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
235 i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
236
237 fp1 = ((float *)kb->data) + i1 * 3;
238 fp2 = ((float *)kb->data) + i2 * 3;
239
240 copy_v3_v3(tvec, fp1);
241 copy_v3_v3(fp1, fp2);
242 copy_v3_v3(fp2, tvec);
243 fp1[0] = -fp1[0];
244 fp2[0] = -fp2[0];
245 totmirr++;
246 }
247 }
248 }
249 }
250 }
251
252 MEM_freeN(tag_elem);
253}
254
256 bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
257{
258 Key *key;
259 int totmirr = 0, totfail = 0;
260
261 *r_totmirr = *r_totfail = 0;
262
263 key = BKE_key_from_object(ob);
264 if (key == nullptr) {
265 return false;
266 }
267
268 if (KeyBlock *kb = static_cast<KeyBlock *>(BLI_findlink(&key->block, ob->shapenr - 1))) {
269 shape_key_mirror(ob, kb, use_topology, totmirr, totfail);
270 }
271
272 *r_totmirr = totmirr;
273 *r_totfail = totfail;
274
277
278 return true;
279}
280
282
283/* -------------------------------------------------------------------- */
286
288{
289 Object *ob = context_object(C);
290 ID *data = static_cast<ID *>((ob) ? ob->data : nullptr);
291
292 return (ob != nullptr && ID_IS_EDITABLE(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && data != nullptr &&
294}
295
297{
298 Object *ob = context_object(C);
299
300 return (shape_key_poll(C) &&
301 /* check a keyblock exists */
302 (BKE_keyblock_from_object(ob) != nullptr));
303}
304
306{
307 Object *ob = context_object(C);
308
309 return (shape_key_poll(C) && ob->mode != OB_MODE_EDIT);
310}
311
313{
314 Object *ob = context_object(C);
315
316 return (shape_key_mode_poll(C) &&
317 /* check a keyblock exists */
318 (BKE_keyblock_from_object(ob) != nullptr));
319}
320
322{
323 /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */
324 Object *ob = context_object(C);
325 Key *key = BKE_key_from_object(ob);
326
327 return (shape_key_mode_poll(C) && key != nullptr && key->totkey > 1);
328}
329
331
332/* -------------------------------------------------------------------- */
335
337{
338 Object *ob = context_object(C);
339 const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
340
341 object_shape_key_add(C, ob, from_mix);
342
345
346 return OPERATOR_FINISHED;
347}
348
350{
351 /* identifiers */
352 ot->name = "Add Shape Key";
353 ot->idname = "OBJECT_OT_shape_key_add";
354 ot->description = "Add shape key to the object";
355
356 /* API callbacks. */
357 ot->poll = shape_key_mode_poll;
358 ot->exec = shape_key_add_exec;
359
360 /* flags */
362
363 /* properties */
364 RNA_def_boolean(ot->srna,
365 "from_mix",
366 true,
367 "From Mix",
368 "Create the new shape key from the existing mix of keys");
369}
370
372
373/* -------------------------------------------------------------------- */
376
389
391{
392 ot->name = "Duplicate Shape Key";
393 ot->idname = "OBJECT_OT_shape_key_copy";
394 ot->description = "Duplicate the active shape key";
395
397 ot->exec = shape_key_copy_exec;
398
400}
401
403
404/* -------------------------------------------------------------------- */
407
409{
410 Main *bmain = CTX_data_main(C);
411 Object *ob = context_object(C);
412 bool changed = false;
413
414 if (RNA_boolean_get(op->ptr, "all")) {
416 return OPERATOR_CANCELLED;
417 }
418
419 if (RNA_boolean_get(op->ptr, "apply_mix")) {
420 float *arr = BKE_key_evaluate_object_ex(
421 ob, nullptr, nullptr, 0, static_cast<ID *>(ob->data));
422 MEM_freeN(arr);
423 }
424 changed = BKE_object_shapekey_free(bmain, ob);
425 }
426 else {
427 int num_selected_but_locked = 0;
428 /* This could be moved into a function of its own at some point. Right now it's only used here,
429 * though, since its inner structure is tailored for allowing shapekey deletion. */
430 Key &key = *BKE_key_from_object(ob);
432 /* Always try to find the keyblock again, as the previous one may have been deleted. For
433 * the same reason, ob->shapenr has to be re-evaluated on every loop iteration. */
434 const int cur_index = BLI_findindex(&key.block, kb);
435 if (!shape_key_is_selected(*ob, *kb, cur_index)) {
436 continue;
437 }
438 if (kb->flag & KEYBLOCK_LOCKED_SHAPE) {
439 num_selected_but_locked++;
440 continue;
441 }
442
443 changed |= BKE_object_shapekey_remove(bmain, ob, kb);
444
445 /* When `BKE_object_shapekey_remove()` deletes the active shapekey, the active shapekeyindex
446 * is updated as well. It usually decrements, which means that even when the same index is
447 * re-visited, we don't see the active one any more. However, when the basis key (index=0) is
448 * deleted AND there are keys remaining, the active index remains set to 0, and so every
449 * iteration sees "the active shapekey", effectively deleting all of them. */
450 if (cur_index == 0) {
451 ob->shapenr = 0;
452 }
453 }
454
455 if (num_selected_but_locked) {
457 changed ? RPT_WARNING : RPT_ERROR,
458 "Could not delete %d locked shape key(s)",
459 num_selected_but_locked);
460 }
461 }
462
463 /* Ensure that there is still a shapekey active, if there are any. See the comment above. Be
464 * extra careful here, because the deletion of the last shapekey can delete the entire Key ID,
465 * making our `key` reference (from the code above) invalid. */
466 if (ob->shapenr == 0) {
467 Key *key = BKE_key_from_object(ob);
468 if (key && key->totkey > 0) {
469 ob->shapenr = 1;
470 }
471 }
472
473 if (changed) {
477
478 return OPERATOR_FINISHED;
479 }
480 return OPERATOR_CANCELLED;
481}
482
483static bool shape_key_remove_poll_property(const bContext * /*C*/,
484 wmOperator *op,
485 const PropertyRNA *prop)
486{
487 const char *prop_id = RNA_property_identifier(prop);
488 const bool do_all = RNA_enum_get(op->ptr, "all");
489
490 /* Only show seed for randomize action! */
491 if (STREQ(prop_id, "apply_mix") && !do_all) {
492 return false;
493 }
494 return true;
495}
496
498 wmOperatorType * /*ot*/,
500{
501 const bool do_apply_mix = RNA_boolean_get(ptr, "apply_mix");
502 if (do_apply_mix) {
503 return TIP_("Apply current visible shape to the object data, and delete all shape keys");
504 }
505
506 return "";
507}
508
510{
511 /* identifiers */
512 ot->name = "Remove Shape Key";
513 ot->idname = "OBJECT_OT_shape_key_remove";
514 ot->description = "Remove shape key from the object";
515
516 /* API callbacks. */
519 ot->poll_property = shape_key_remove_poll_property;
520 ot->get_description = shape_key_remove_get_description;
521
522 /* flags */
524
525 /* properties */
526 RNA_def_boolean(ot->srna, "all", false, "All", "Remove all shape keys");
527 RNA_def_boolean(ot->srna,
528 "apply_mix",
529 false,
530 "Apply Mix",
531 "Apply current mix of shape keys to the geometry before removing them");
532}
533
535
536/* -------------------------------------------------------------------- */
539
541{
542 Object *ob = context_object(C);
543 Key *key = BKE_key_from_object(ob);
544
545 if (!key || BLI_listbase_is_empty(&key->block)) {
546 return OPERATOR_CANCELLED;
547 }
548
549 LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
550 kb->curval = clamp_f(0.0f, kb->slidermin, kb->slidermax);
551 }
552
555
556 return OPERATOR_FINISHED;
557}
558
560{
561 /* identifiers */
562 ot->name = "Clear Shape Keys";
563 ot->description =
564 "Reset the weights of all shape keys to 0 or to the closest value respecting the limits";
565 ot->idname = "OBJECT_OT_shape_key_clear";
566
567 /* API callbacks. */
568 ot->poll = shape_key_poll;
569 ot->exec = shape_key_clear_exec;
570
571 /* flags */
573}
574
575/* starting point and step size could be optional */
577{
578 Object *ob = context_object(C);
579 Key *key = BKE_key_from_object(ob);
580 float cfra = 0.0f;
581
582 if (!key || BLI_listbase_is_empty(&key->block)) {
583 return OPERATOR_CANCELLED;
584 }
585
586 LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
587 kb->pos = cfra;
588 cfra += 0.1f;
589 }
590
593
594 return OPERATOR_FINISHED;
595}
596
598{
599 /* identifiers */
600 ot->name = "Re-Time Shape Keys";
601 ot->description = "Resets the timing for absolute shape keys";
602 ot->idname = "OBJECT_OT_shape_key_retime";
603
604 /* API callbacks. */
605 ot->poll = shape_key_poll;
607
608 /* flags */
610}
611
613
614/* -------------------------------------------------------------------- */
617
619{
620 Object *ob = context_object(C);
621 int totmirr = 0, totfail = 0;
622 bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
623
625 return OPERATOR_CANCELLED;
626 }
627
628 if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology)) {
629 return OPERATOR_CANCELLED;
630 }
631
632 ED_mesh_report_mirror(*op->reports, totmirr, totfail);
633
634 return OPERATOR_FINISHED;
635}
636
638{
639 /* identifiers */
640 ot->name = "Mirror Shape Key";
641 ot->idname = "OBJECT_OT_shape_key_mirror";
642 ot->description = "Mirror the current shape key along the local X axis";
643
644 /* API callbacks. */
647
648 /* flags */
650
651 /* properties */
653 ot->srna,
654 "use_topology",
655 false,
656 "Topology Mirror",
657 "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
658}
659
661
662/* -------------------------------------------------------------------- */
665
672
674{
675 Object *ob = context_object(C);
676
677 const Key &key = *BKE_key_from_object(ob);
678 const KeyBlockMove type = KeyBlockMove(RNA_enum_get(op->ptr, "type"));
679 const int totkey = key.totkey;
680 int new_index = 0;
681 bool changed = false;
682
683 if (type < 0) { /* Moving upwards. */
684 /* Don't move above the position of the basis key */
685 int top_index = 1;
686 /* Start from index 1 to ignore basis key from being able to move above. */
687 for (int index = 1; index < totkey; index++) {
688 const KeyBlock &kb = *static_cast<KeyBlock *>(BLI_findlink(&key.block, index));
689 if (!shape_key_is_selected(*ob, kb, index)) {
690 continue;
691 }
692 switch (type) {
693 case KB_MOVE_TOP:
694 new_index = top_index;
695 break;
696 case KB_MOVE_UP:
697 new_index = max_ii(index - 1, top_index);
698 break;
699 case KB_MOVE_BOTTOM:
700 case KB_MOVE_DOWN:
702 break;
703 }
704 top_index++;
705 if (new_index < 0) {
706 continue;
707 }
708 changed |= BKE_keyblock_move(ob, index, new_index);
709 }
710 }
711 else { /* Moving downwards. */
712 int bottom_index = totkey - 1;
713 /* Skip basis key to prevent it from moving downwards. */
714 for (int index = totkey - 1; index >= 1; index--) {
715 const KeyBlock &kb = *static_cast<KeyBlock *>(BLI_findlink(&key.block, index));
716 if (!shape_key_is_selected(*ob, kb, index)) {
717 continue;
718 }
719 switch (type) {
720 case KB_MOVE_BOTTOM:
721 new_index = bottom_index;
722 break;
723 case KB_MOVE_DOWN:
724 new_index = min_ii(index + 1, bottom_index);
725 break;
726 case KB_MOVE_TOP:
727 case KB_MOVE_UP:
729 break;
730 }
731 bottom_index--;
732 changed |= BKE_keyblock_move(ob, index, new_index);
733 }
734 }
735
736 if (!changed) {
737 return OPERATOR_CANCELLED;
738 }
739
742
743 return OPERATOR_FINISHED;
744}
745
747{
748 static const EnumPropertyItem slot_move[] = {
749 {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
750 {KB_MOVE_UP, "UP", 0, "Up", ""},
751 {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
752 {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
753 {0, nullptr, 0, nullptr, nullptr}};
754
755 /* identifiers */
756 ot->name = "Move Shape Key";
757 ot->idname = "OBJECT_OT_shape_key_move";
758 ot->description = "Move selected shape keys up/down in the list";
759
760 /* API callbacks. */
761 ot->poll = shape_key_move_poll;
762 ot->exec = shape_key_move_exec;
763
764 /* flags */
766
767 RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
768}
769
771
772/* -------------------------------------------------------------------- */
775
776enum {
779};
780
782{
784 const int action = RNA_enum_get(op->ptr, "action");
785 const Key *keys = BKE_key_from_object(ob);
786
787 if (!keys || BLI_listbase_is_empty(&keys->block)) {
788 return OPERATOR_CANCELLED;
789 }
790
791 LISTBASE_FOREACH (KeyBlock *, kb, &keys->block) {
792 switch (action) {
793 case SHAPE_KEY_LOCK:
794 kb->flag |= KEYBLOCK_LOCKED_SHAPE;
795 break;
796 case SHAPE_KEY_UNLOCK:
797 kb->flag &= ~KEYBLOCK_LOCKED_SHAPE;
798 break;
799 default:
800 BLI_assert(0);
801 }
802 }
803
805
806 return OPERATOR_FINISHED;
807}
808
809static std::string shape_key_lock_get_description(bContext * /*C*/,
810 wmOperatorType * /*op*/,
812{
813 const int action = RNA_enum_get(ptr, "action");
814
815 switch (action) {
816 case SHAPE_KEY_LOCK:
817 return TIP_("Lock all shape keys of the active object");
818 break;
819 case SHAPE_KEY_UNLOCK:
820 return TIP_("Unlock all shape keys of the active object");
821 break;
822 default:
823 return "";
824 }
825}
826
828{
829 static const EnumPropertyItem shape_key_lock_actions[] = {
830 {SHAPE_KEY_LOCK, "LOCK", 0, "Lock", "Lock all shape keys"},
831 {SHAPE_KEY_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all shape keys"},
832 {0, nullptr, 0, nullptr, nullptr},
833 };
834
835 /* identifiers */
836 ot->name = "Change the Lock On Shape Keys";
837 ot->idname = "OBJECT_OT_shape_key_lock";
838 ot->description = "Change the lock state of all shape keys of active object";
839
840 /* API callbacks. */
842 ot->exec = shape_key_lock_exec;
843 ot->get_description = shape_key_lock_get_description;
844
845 /* flags */
847
848 RNA_def_enum(ot->srna,
849 "action",
850 shape_key_lock_actions,
852 "Action",
853 "Lock action to execute on vertex groups");
854}
855
857
858/* -------------------------------------------------------------------- */
861
863{
864 if (!shape_key_exists_poll(C)) {
865 return false;
866 }
867
868 Object *ob = context_object(C);
869 /* 0 = nothing active, 1 = basis key active. */
870 return ob->shapenr > 1;
871}
872
874{
876 Key *key = BKE_key_from_object(ob);
877 KeyBlock *old_basis_key = static_cast<KeyBlock *>(key->block.first);
878
879 /* Make the new basis by moving the active key to index 0. */
880 const int from_index = -1; /* Interpreted as "the active key". */
881 const int to_index = 0; /* Offset by 1 compared to ob->shapenr. */
882 const bool changed = BKE_keyblock_move(ob, from_index, to_index);
883
884 if (!changed) {
885 /* The poll function should have prevented this operator from being called
886 * on the current basis key. */
888 return OPERATOR_CANCELLED;
889 }
890
891 /* Make the old & new basis keys "Relative to" the new basis key. For the new key it doesn't
892 * matter much, as it's treated as special anyway, but keeping it relative to another key makes
893 * no sense. For the old basis key (which just became a normal key), it would otherwise still be
894 * relative to itself, effectively disabling it. */
895 KeyBlock *new_basis_key = static_cast<KeyBlock *>(key->block.first);
896 new_basis_key->relative = 0;
897 old_basis_key->relative = 0;
898
901
902 return OPERATOR_FINISHED;
903}
904
906{
907 /* identifiers */
908 ot->name = "Make Shape Key the Basis Key";
909 ot->idname = "OBJECT_OT_shape_key_make_basis";
910 ot->description =
911 "Make this shape key the new basis key, effectively applying it to the mesh. Note that this "
912 "applies the shape key at its 100% value";
913
914 /* API callbacks. */
917
918 /* flags */
920}
921
923
924} // namespace blender::ed::object
Object * CTX_data_active_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
KeyBlock * BKE_keyblock_from_object(Object *ob)
Definition key.cc:1889
KeyBlock * BKE_keyblock_duplicate(Key *key, KeyBlock *kb_src)
Definition key.cc:1849
bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
Definition key.cc:2274
float * BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t arr_size, ID *obdata)
Definition key.cc:1488
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1791
int BKE_lattice_index_from_uvw(const Lattice *lt, int u, int v, int w)
Definition lattice.cc:194
General operations, lookup, etc. for blender objects.
KeyBlock * BKE_object_shapekey_insert(Main *bmain, Object *ob, const char *name, bool from_mix)
bool BKE_object_shapekey_free(Main *bmain, Object *ob)
bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int max_ii(int a, int b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define STREQ(a, b)
#define TIP_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
@ KEYBLOCK_LOCKED_SHAPE
@ KEYBLOCK_SEL
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OB_SURF
@ OB_MESH
@ OB_CURVES_LEGACY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
KeyBlock * ED_lattice_get_edit_shape_key(const Lattice *latt)
void ED_mesh_report_mirror(ReportList &reports, int totmirr, int totfail)
int mesh_get_x_mirror_vert(Object *ob, Mesh *mesh_eval, int index, bool use_topology)
Definition meshtools.cc:302
void ED_mesh_mirror_spatial_table_begin(Object *ob, BMEditMesh *em, Mesh *mesh_eval)
void ED_mesh_mirror_spatial_table_end(Object *ob)
KeyBlock * ED_mesh_get_edit_shape_key(const Mesh *me)
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:461
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
KeyBlock * ED_curve_get_edit_shape_key(const Curve *cu)
Definition editcurve.cc:101
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
static wmOperatorStatus shape_key_clear_exec(bContext *C, wmOperator *)
static bool shape_key_make_basis_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_move(wmOperatorType *ot)
static void object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
static wmOperatorStatus shape_key_retime_exec(bContext *C, wmOperator *)
bool shape_key_report_if_any_locked(Object *ob, ReportList *reports)
static bool shape_key_exists_poll(bContext *C)
Object * context_object(const bContext *C)
static wmOperatorStatus shape_key_copy_exec(bContext *C, wmOperator *)
void OBJECT_OT_shape_key_copy(wmOperatorType *ot)
static bool shape_key_mode_exists_poll(bContext *C)
static bool shape_key_move_poll(bContext *C)
static bool shape_key_mode_poll(bContext *C)
static wmOperatorStatus shape_key_remove_exec(bContext *C, wmOperator *op)
static wmOperatorStatus shape_key_add_exec(bContext *C, wmOperator *op)
void shape_key_mirror(Object *ob, KeyBlock *kb, bool use_topology, int &totmirr, int &totfail)
bool shape_key_report_if_active_locked(Object *ob, ReportList *reports)
static bool object_is_any_shape_key_locked(Object *ob)
static wmOperatorStatus shape_key_make_basis_exec(bContext *C, wmOperator *)
void OBJECT_OT_shape_key_lock(wmOperatorType *ot)
static wmOperatorStatus shape_key_lock_exec(bContext *C, wmOperator *op)
static bool shape_key_poll(bContext *C)
void OBJECT_OT_shape_key_make_basis(wmOperatorType *ot)
void OBJECT_OT_shape_key_retime(wmOperatorType *ot)
void OBJECT_OT_shape_key_add(wmOperatorType *ot)
static bool shape_key_remove_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
static std::string shape_key_remove_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
static wmOperatorStatus shape_key_move_exec(bContext *C, wmOperator *op)
bool shape_key_is_selected(const Object &object, const KeyBlock &kb, int keyblock_index)
static std::string shape_key_lock_get_description(bContext *, wmOperatorType *, PointerRNA *ptr)
void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
static wmOperatorStatus shape_key_mirror_exec(bContext *C, wmOperator *op)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
struct Lattice * latt
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
float curval
short relative
void * data
int totkey
ListBase block
struct EditLatt * editlatt
void * first
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237