Blender V4.5
key.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 <algorithm>
10#include <cmath>
11#include <cstddef>
12#include <cstring>
13#include <optional>
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_endian_switch.h"
18#include "BLI_listbase.h"
19#include "BLI_math_matrix.h"
20#include "BLI_math_vector.h"
21#include "BLI_string.h"
22#include "BLI_string_utf8.h"
23#include "BLI_string_utils.hh"
24#include "BLI_utildefines.h"
25
26#include "BLT_translation.hh"
27
28/* Allow using deprecated functionality for .blend file I/O. */
29#define DNA_DEPRECATED_ALLOW
30
31#include "DNA_ID.h"
32#include "DNA_curve_types.h"
33#include "DNA_key_types.h"
34#include "DNA_lattice_types.h"
35#include "DNA_mesh_types.h"
36#include "DNA_meshdata_types.h"
37#include "DNA_object_types.h"
38
39#include "BKE_anim_data.hh"
40#include "BKE_attribute.hh"
41#include "BKE_curve.hh"
42#include "BKE_customdata.hh"
43#include "BKE_deform.hh"
44#include "BKE_editmesh.hh"
45#include "BKE_idtype.hh"
46#include "BKE_key.hh"
47#include "BKE_lattice.hh"
48#include "BKE_lib_id.hh"
49#include "BKE_lib_query.hh"
50#include "BKE_main.hh"
51#include "BKE_mesh.hh"
52#include "BKE_scene.hh"
53
54#include "RNA_access.hh"
55#include "RNA_path.hh"
56#include "RNA_prototypes.hh"
57
58#include "BLO_read_write.hh"
59
60using blender::float3;
63using blender::Span;
64
65static void shapekey_copy_data(Main * /*bmain*/,
66 std::optional<Library *> /*owner_library*/,
67 ID *id_dst,
68 const ID *id_src,
69 const int /*flag*/)
70{
71 Key *key_dst = (Key *)id_dst;
72 const Key *key_src = (const Key *)id_src;
73 BLI_duplicatelist(&key_dst->block, &key_src->block);
74
75 KeyBlock *kb_dst, *kb_src;
76 for (kb_src = static_cast<KeyBlock *>(key_src->block.first),
77 kb_dst = static_cast<KeyBlock *>(key_dst->block.first);
78 kb_dst;
79 kb_src = kb_src->next, kb_dst = kb_dst->next)
80 {
81 if (kb_dst->data) {
82 kb_dst->data = MEM_dupallocN(kb_dst->data);
83 }
84 if (kb_src == key_src->refkey) {
85 key_dst->refkey = kb_dst;
86 }
87 }
88}
89
90static void shapekey_free_data(ID *id)
91{
92 Key *key = (Key *)id;
93 while (KeyBlock *kb = static_cast<KeyBlock *>(BLI_pophead(&key->block))) {
94 if (kb->data) {
95 MEM_freeN(kb->data);
96 }
97 MEM_freeN(kb);
98 }
99}
100
112
113static ID **shapekey_owner_pointer_get(ID *id, const bool debug_relationship_assert)
114{
115 Key *key = (Key *)id;
116
117 if (debug_relationship_assert) {
118 BLI_assert(key->from != nullptr);
119 BLI_assert(BKE_key_from_id(key->from) == key);
120 }
121
122 return &key->from;
123}
124
125static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_address)
126{
127 Key *key = (Key *)id;
128 const bool is_undo = BLO_write_is_undo(writer);
129
130 /* write LibData */
131 BLO_write_id_struct(writer, Key, id_address, &key->id);
132 BKE_id_blend_write(writer, &key->id);
133
134 /* direct data */
135 LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
136 KeyBlock tmp_kb = *kb;
137 /* Do not store actual geometry data in case this is a library override ID. */
138 if (ID_IS_OVERRIDE_LIBRARY(key) && !is_undo) {
139 tmp_kb.totelem = 0;
140 tmp_kb.data = nullptr;
141 }
142 BLO_write_struct_at_address(writer, KeyBlock, kb, &tmp_kb);
143 if (tmp_kb.data != nullptr) {
144 BLO_write_raw(writer, tmp_kb.totelem * key->elemsize, tmp_kb.data);
145 }
146 }
147}
148
149/* old defines from DNA_ipo_types.h for data-type, stored in DNA - don't modify! */
150#define IPO_FLOAT 4
151#define IPO_BEZTRIPLE 100
152#define IPO_BPOINT 101
153
154static void switch_endian_keyblock(Key *key, KeyBlock *kb)
155{
156 int elemsize = key->elemsize;
157 char *data = static_cast<char *>(kb->data);
158
159 for (int a = 0; a < kb->totelem; a++) {
160 const char *cp = key->elemstr;
161 char *poin = data;
162
163 while (cp[0]) { /* cp[0] == amount */
164 switch (cp[1]) { /* cp[1] = type */
165 case IPO_FLOAT:
166 case IPO_BPOINT:
167 case IPO_BEZTRIPLE: {
168 int b = cp[0];
169 BLI_endian_switch_float_array((float *)poin, b);
170 poin += sizeof(float) * b;
171 break;
172 }
173 }
174
175 cp += 2;
176 }
177 data += elemsize;
178 }
179}
180
182{
183 Key *key = (Key *)id;
184 BLO_read_struct_list(reader, KeyBlock, &(key->block));
185
186 BLO_read_struct(reader, KeyBlock, &key->refkey);
187
188 LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
189 BLO_read_data_address(reader, &kb->data);
190
192 switch_endian_keyblock(key, kb);
193 }
194 }
195}
196
198{
199 /* ShapeKeys should always only be linked indirectly through their user ID (mesh, Curve etc.), or
200 * be fully local data. */
201 BLI_assert((id->tag & ID_TAG_EXTERN) == 0);
203}
204
206 /*id_code*/ Key::id_type,
207 /*id_filter*/ FILTER_ID_KE,
208 /* Warning! key->from, could be more types in future? */
209 /*dependencies_id_types*/ FILTER_ID_ME | FILTER_ID_CU_LEGACY | FILTER_ID_LT,
210 /*main_listbase_index*/ INDEX_ID_KE,
211 /*struct_size*/ sizeof(Key),
212 /*name*/ "Key",
213 /*name_plural*/ N_("shape_keys"),
214 /*translation_context*/ BLT_I18NCONTEXT_ID_SHAPEKEY,
216 /*asset_type_info*/ nullptr,
217
218 /*init_data*/ nullptr,
219 /*copy_data*/ shapekey_copy_data,
220 /*free_data*/ shapekey_free_data,
221 /*make_local*/ nullptr,
222 /*foreach_id*/ shapekey_foreach_id,
223 /*foreach_cache*/ nullptr,
224 /*foreach_path*/ nullptr,
225 /* A bit weird, due to shape-keys not being strictly speaking embedded data... But they also
226 * share a lot with those (non linkable, only ever used by one owner ID, etc.). */
227 /*owner_pointer_get*/ shapekey_owner_pointer_get,
228
229 /*blend_write*/ shapekey_blend_write,
230 /*blend_read_data*/ shapekey_blend_read_data,
231 /*blend_read_after_liblink*/ shapekey_blend_read_after_liblink,
232
233 /*blend_read_undo_preserve*/ nullptr,
234
235 /*lib_override_apply_post*/ nullptr,
236};
237
238#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */
239#define KEY_MODE_BPOINT 1
240#define KEY_MODE_BEZTRIPLE 2
241
242/* Internal use only. */
247
249{
250 while (KeyBlock *kb = static_cast<KeyBlock *>(BLI_pophead(&key->block))) {
251 if (kb->data) {
252 MEM_freeN(kb->data);
253 }
254 MEM_freeN(kb);
255 }
256}
257
258Key *BKE_key_add(Main *bmain, ID *id) /* common function */
259{
260 Key *key;
261 char *el;
262
263 key = BKE_id_new<Key>(bmain, "Key");
264
265 key->type = KEY_NORMAL;
266 key->from = id;
267
268 key->uidgen = 1;
269
270 /* XXX the code here uses some defines which will soon be deprecated... */
271 switch (GS(id->name)) {
272 case ID_ME:
273 el = key->elemstr;
274
276 el[1] = IPO_FLOAT;
277 el[2] = 0;
278
279 key->elemsize = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
280
281 break;
282 case ID_LT:
283 el = key->elemstr;
284
286 el[1] = IPO_FLOAT;
287 el[2] = 0;
288
289 key->elemsize = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
290
291 break;
292 case ID_CU_LEGACY:
293 el = key->elemstr;
294
296 el[1] = IPO_BPOINT;
297 el[2] = 0;
298
299 key->elemsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
300
301 break;
302
303 default:
304 break;
305 }
306
307 return key;
308}
309
311{
312 KeyBlock *kb;
313
314 /* locate the key which is out of position */
315 for (kb = static_cast<KeyBlock *>(key->block.first); kb; kb = kb->next) {
316 if ((kb->next) && (kb->pos > kb->next->pos)) {
317 break;
318 }
319 }
320
321 /* if we find a key, move it */
322 if (kb) {
323 kb = kb->next; /* next key is the out-of-order one */
324 BLI_remlink(&key->block, kb);
325
326 /* find the right location and insert before */
327 LISTBASE_FOREACH (KeyBlock *, kb2, &key->block) {
328 if (kb2->pos > kb->pos) {
329 BLI_insertlinkafter(&key->block, kb2->prev, kb);
330 break;
331 }
332 }
333 }
334
335 /* new rule; first key is refkey, this to match drawing channels... */
336 key->refkey = static_cast<KeyBlock *>(key->block.first);
337}
338
339/**************** do the key ****************/
340
342{
343 float t2, t3, fc;
344
345 switch (type) {
346 case KEY_LINEAR:
347 data[0] = 0.0f;
348 data[1] = -t + 1.0f;
349 data[2] = t;
350 data[3] = 0.0f;
351 break;
352 case KEY_CARDINAL:
353 t2 = t * t;
354 t3 = t2 * t;
355 fc = 0.71f;
356
357 data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
358 data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
359 data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
360 data[3] = fc * t3 - fc * t2;
361 break;
362 case KEY_BSPLINE:
363 t2 = t * t;
364 t3 = t2 * t;
365
366 data[0] = -0.16666666f * t3 + 0.5f * t2 - 0.5f * t + 0.16666666f;
367 data[1] = 0.5f * t3 - t2 + 0.66666666f;
368 data[2] = -0.5f * t3 + 0.5f * t2 + 0.5f * t + 0.16666666f;
369 data[3] = 0.16666666f * t3;
370 break;
371 case KEY_CATMULL_ROM:
372 t2 = t * t;
373 t3 = t2 * t;
374 fc = 0.5f;
375
376 data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
377 data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
378 data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
379 data[3] = fc * t3 - fc * t2;
380 break;
381 }
382}
383
385{
386 float t2, fc;
387
388 switch (type) {
389 case KEY_LINEAR:
390 data[0] = 0.0f;
391 data[1] = -1.0f;
392 data[2] = 1.0f;
393 data[3] = 0.0f;
394 break;
395 case KEY_CARDINAL:
396 t2 = t * t;
397 fc = 0.71f;
398
399 data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
400 data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
401 data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
402 data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
403 break;
404 case KEY_BSPLINE:
405 t2 = t * t;
406
407 data[0] = -0.5f * t2 + t - 0.5f;
408 data[1] = 1.5f * t2 - t * 2.0f;
409 data[2] = -1.5f * t2 + t + 0.5f;
410 data[3] = 0.5f * t2;
411 break;
412 case KEY_CATMULL_ROM:
413 t2 = t * t;
414 fc = 0.5f;
415
416 data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
417 data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
418 data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
419 data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
420 break;
421 }
422}
423
425{
426 float fc;
427
428 switch (type) {
429 case KEY_LINEAR:
430 data[0] = 0.0f;
431 data[1] = 0.0f;
432 data[2] = 0.0f;
433 data[3] = 0.0f;
434 break;
435 case KEY_CARDINAL:
436 fc = 0.71f;
437
438 data[0] = -6.0f * fc * t + 4.0f * fc;
439 data[1] = 6.0f * (2.0f - fc) * t + 2.0f * (fc - 3.0f);
440 data[2] = 6.0f * (fc - 2.0f) * t + 2.0f * (3.0f - 2.0f * fc);
441 data[3] = 6.0f * fc * t - 2.0f * fc;
442 break;
443 case KEY_BSPLINE:
444 data[0] = -1.0f * t + 1.0f;
445 data[1] = 3.0f * t - 2.0f;
446 data[2] = -3.0f * t + 1.0f;
447 data[3] = 1.0f * t;
448 break;
449 case KEY_CATMULL_ROM:
450 fc = 0.5f;
451
452 data[0] = -6.0f * fc * t + 4.0f * fc;
453 data[1] = 6.0f * (2.0f - fc) * t + 2.0f * (fc - 3.0f);
454 data[2] = 6.0f * (fc - 2.0f) * t + 2.0f * (3.0f - 2.0f * fc);
455 data[3] = 6.0f * fc * t - 2.0f * fc;
456 break;
457 }
458}
459
460static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl)
461{
462 /* return 1 means k[2] is the position, return 0 means interpolate */
463 KeyBlock *k1, *firstkey;
464 float d, dpos, ofs = 0, lastpos;
465 short bsplinetype;
466
467 firstkey = static_cast<KeyBlock *>(lb->first);
468 k1 = static_cast<KeyBlock *>(lb->last);
469 lastpos = k1->pos;
470 dpos = lastpos - firstkey->pos;
471
472 if (fac < firstkey->pos) {
473 fac = firstkey->pos;
474 }
475 else if (fac > k1->pos) {
476 fac = k1->pos;
477 }
478
479 k1 = k[0] = k[1] = k[2] = k[3] = firstkey;
480 t[0] = t[1] = t[2] = t[3] = k1->pos;
481
482#if 0
483 if (fac < 0.0 || fac > 1.0) {
484 return 1;
485 }
486#endif
487
488 if (k1->next == nullptr) {
489 return 1;
490 }
491
492 if (cycl) { /* pre-sort */
493 k[2] = k1->next;
494 k[3] = k[2]->next;
495 if (k[3] == nullptr) {
496 k[3] = k1;
497 }
498 while (k1) {
499 if (k1->next == nullptr) {
500 k[0] = k1;
501 }
502 k1 = k1->next;
503 }
504 // k1 = k[1]; /* UNUSED */
505 t[0] = k[0]->pos;
506 t[1] += dpos;
507 t[2] = k[2]->pos + dpos;
508 t[3] = k[3]->pos + dpos;
509 fac += dpos;
510 ofs = dpos;
511 if (k[3] == k[1]) {
512 t[3] += dpos;
513 ofs = 2.0f * dpos;
514 }
515 if (fac < t[1]) {
516 fac += dpos;
517 }
518 k1 = k[3];
519 }
520 else { /* pre-sort */
521 k[2] = k1->next;
522 t[2] = k[2]->pos;
523 k[3] = k[2]->next;
524 if (k[3] == nullptr) {
525 k[3] = k[2];
526 }
527 t[3] = k[3]->pos;
528 k1 = k[3];
529 }
530
531 while (t[2] < fac) { /* find correct location */
532 if (k1->next == nullptr) {
533 if (cycl) {
534 k1 = firstkey;
535 ofs += dpos;
536 }
537 else if (t[2] == t[3]) {
538 break;
539 }
540 }
541 else {
542 k1 = k1->next;
543 }
544
545 t[0] = t[1];
546 k[0] = k[1];
547 t[1] = t[2];
548 k[1] = k[2];
549 t[2] = t[3];
550 k[2] = k[3];
551 t[3] = k1->pos + ofs;
552 k[3] = k1;
553
554 if (ofs > 2.1f + lastpos) {
555 break;
556 }
557 }
558
559 bsplinetype = 0;
560 if (k[1]->type == KEY_BSPLINE || k[2]->type == KEY_BSPLINE) {
561 bsplinetype = 1;
562 }
563
564 if (cycl == 0) {
565 if (bsplinetype == 0) { /* B spline doesn't go through the control points */
566 if (fac <= t[1]) { /* fac for 1st key */
567 t[2] = t[1];
568 k[2] = k[1];
569 return 1;
570 }
571 if (fac >= t[2]) { /* fac after 2nd key */
572 return 1;
573 }
574 }
575 else if (fac > t[2]) { /* last key */
576 fac = t[2];
577 k[3] = k[2];
578 t[3] = t[2];
579 }
580 }
581
582 d = t[2] - t[1];
583 if (d == 0.0f) {
584 if (bsplinetype == 0) {
585 return 1; /* both keys equal */
586 }
587 }
588 else {
589 d = (fac - t[1]) / d;
590 }
591
592 /* interpolation */
594
595 if (k[1]->type != k[2]->type) {
596 float t_other[4];
597 key_curve_position_weights(d, t_other, KeyInterpolationType(k[2]->type));
598 interp_v4_v4v4(t, t, t_other, d);
599 }
600
601 return 0;
602}
603
604static void flerp(int tot,
605 float *in,
606 const float *f0,
607 const float *f1,
608 const float *f2,
609 const float *f3,
610 const float *t)
611{
612 int a;
613
614 for (a = 0; a < tot; a++) {
615 in[a] = t[0] * f0[a] + t[1] * f1[a] + t[2] * f2[a] + t[3] * f3[a];
616 }
617}
618
619static void rel_flerp(int tot, float *in, const float *ref, const float *out, float fac)
620{
621 int a;
622
623 for (a = 0; a < tot; a++) {
624 in[a] -= fac * (ref[a] - out[a]);
625 }
626}
627
628static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **freedata)
629{
630 if (kb == actkb) {
631 /* this hack makes it possible to edit shape keys in
632 * edit mode with shape keys blending applied */
633 if (GS(key->from->name) == ID_ME) {
634 Mesh *mesh;
635 BMVert *eve;
636 BMIter iter;
637 float(*co)[3];
638 int a;
639
640 mesh = (Mesh *)key->from;
641
642 if (mesh->runtime->edit_mesh && mesh->runtime->edit_mesh->bm->totvert == kb->totelem) {
643 a = 0;
644 co = MEM_malloc_arrayN<float[3]>(size_t(mesh->runtime->edit_mesh->bm->totvert),
645 "key_block_get_data");
646
647 BM_ITER_MESH (eve, &iter, mesh->runtime->edit_mesh->bm, BM_VERTS_OF_MESH) {
648 copy_v3_v3(co[a], eve->co);
649 a++;
650 }
651
652 *freedata = (char *)co;
653 return (char *)co;
654 }
655 }
656 }
657
658 *freedata = nullptr;
659 return static_cast<char *>(kb->data);
660}
661
662/* currently only the first value of 'r_ofs' may be set. */
664 const Key *key, const int mode, int *r_poinsize, int *r_ofs, int *r_step)
665{
666 if (key->from == nullptr) {
667 return false;
668 }
669
670 *r_step = 1;
671
672 switch (GS(key->from->name)) {
673 case ID_ME:
674 *r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
675 *r_poinsize = *r_ofs;
676 break;
677 case ID_LT:
678 *r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
679 *r_poinsize = *r_ofs;
680 break;
681 case ID_CU_LEGACY:
682 if (mode == KEY_MODE_BPOINT) {
683 *r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
684 *r_step = KEYELEM_ELEM_LEN_BPOINT;
685 }
686 else {
687 *r_ofs = sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]);
689 }
690 *r_poinsize = sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
691 break;
692 default:
693 BLI_assert_msg(0, "invalid 'key->from' ID type");
694 return false;
695 }
696
697 return true;
698}
699
700static void cp_key(const int start,
701 int end,
702 const int tot,
703 char *poin,
704 Key *key,
705 KeyBlock *actkb,
706 KeyBlock *kb,
707 float *weights,
708 const int mode)
709{
710 float ktot = 0.0, kd = 0.0;
711 int elemsize, poinsize = 0, a, step, *ofsp, ofs[32], flagflo = 0;
712 char *k1, *kref, *freek1, *freekref;
713 char *cp, elemstr[8];
714
715 /* currently always 0, in future key_pointer_size may assign */
716 ofs[1] = 0;
717
718 if (!key_pointer_size(key, mode, &poinsize, &ofs[0], &step)) {
719 return;
720 }
721
722 end = std::min(end, tot);
723
724 if (tot != kb->totelem) {
725 ktot = 0.0;
726 flagflo = 1;
727 if (kb->totelem) {
728 kd = kb->totelem / float(tot);
729 }
730 else {
731 return;
732 }
733 }
734
735 k1 = key_block_get_data(key, actkb, kb, &freek1);
736 kref = key_block_get_data(key, actkb, key->refkey, &freekref);
737
738 /* this exception is needed curves with multiple splines */
739 if (start != 0) {
740
741 poin += poinsize * start;
742
743 if (flagflo) {
744 ktot += start * kd;
745 a = int(floor(ktot));
746 if (a) {
747 ktot -= a;
748 k1 += a * key->elemsize;
749 }
750 }
751 else {
752 k1 += start * key->elemsize;
753 }
754 }
755
756 if (mode == KEY_MODE_BEZTRIPLE) {
757 elemstr[0] = 1;
758 elemstr[1] = IPO_BEZTRIPLE;
759 elemstr[2] = 0;
760 }
761
762 /* just do it here, not above! */
763 elemsize = key->elemsize * step;
764
765 for (a = start; a < end; a += step) {
766 cp = key->elemstr;
767 if (mode == KEY_MODE_BEZTRIPLE) {
768 cp = elemstr;
769 }
770
771 ofsp = ofs;
772
773 while (cp[0]) {
774
775 switch (cp[1]) {
776 case IPO_FLOAT:
777 if (weights) {
778 memcpy(poin, kref, sizeof(float[KEYELEM_FLOAT_LEN_COORD]));
779 if (*weights != 0.0f) {
780 rel_flerp(
781 KEYELEM_FLOAT_LEN_COORD, (float *)poin, (float *)kref, (float *)k1, *weights);
782 }
783 weights++;
784 }
785 else {
786 memcpy(poin, k1, sizeof(float[KEYELEM_FLOAT_LEN_COORD]));
787 }
788 break;
789 case IPO_BPOINT:
790 memcpy(poin, k1, sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]));
791 break;
792 case IPO_BEZTRIPLE:
793 memcpy(poin, k1, sizeof(float[KEYELEM_FLOAT_LEN_BEZTRIPLE]));
794 break;
795 default:
796 /* should never happen */
797 if (freek1) {
798 MEM_freeN(freek1);
799 }
800 if (freekref) {
801 MEM_freeN(freekref);
802 }
803 BLI_assert_msg(0, "invalid 'cp[1]'");
804 return;
805 }
806
807 poin += *ofsp;
808 cp += 2;
809 ofsp++;
810 }
811
812 /* are we going to be nasty? */
813 if (flagflo) {
814 ktot += kd;
815 while (ktot >= 1.0f) {
816 ktot -= 1.0f;
817 k1 += elemsize;
818 kref += elemsize;
819 }
820 }
821 else {
822 k1 += elemsize;
823 kref += elemsize;
824 }
825 }
826
827 if (freek1) {
828 MEM_freeN(freek1);
829 }
830 if (freekref) {
831 MEM_freeN(freekref);
832 }
833}
834
835static void cp_cu_key(Curve *cu,
836 Key *key,
837 KeyBlock *actkb,
838 KeyBlock *kb,
839 const int start,
840 int end,
841 char *out,
842 const int tot)
843{
844 Nurb *nu;
845 int a, step, a1, a2;
846
847 for (a = 0, nu = static_cast<Nurb *>(cu->nurb.first); nu; nu = nu->next, a += step) {
848 if (nu->bp) {
850
851 a1 = max_ii(a, start);
852 a2 = min_ii(a + step, end);
853
854 if (a1 < a2) {
855 cp_key(a1, a2, tot, out, key, actkb, kb, nullptr, KEY_MODE_BPOINT);
856 }
857 }
858 else if (nu->bezt) {
860
861 /* exception because keys prefer to work with complete blocks */
862 a1 = max_ii(a, start);
863 a2 = min_ii(a + step, end);
864
865 if (a1 < a2) {
866 cp_key(a1, a2, tot, out, key, actkb, kb, nullptr, KEY_MODE_BEZTRIPLE);
867 }
868 }
869 else {
870 step = 0;
871 }
872 }
873}
874
875static void key_evaluate_relative(const int start,
876 int end,
877 const int tot,
878 char *basispoin,
879 Key *key,
880 KeyBlock *actkb,
881 float **per_keyblock_weights,
882 const int mode)
883{
884 KeyBlock *kb;
885 int *ofsp, ofs[3], elemsize, b, step;
886 char *cp, *poin, *reffrom, *from, elemstr[8];
887 int poinsize, keyblock_index;
888
889 /* currently always 0, in future key_pointer_size may assign */
890 ofs[1] = 0;
891
892 if (!key_pointer_size(key, mode, &poinsize, &ofs[0], &step)) {
893 return;
894 }
895
896 end = std::min(end, tot);
897
898 /* In case of Bezier-triple. */
899 elemstr[0] = 1; /* Number of IPO-floats. */
900 elemstr[1] = IPO_BEZTRIPLE;
901 elemstr[2] = 0;
902
903 /* just here, not above! */
904 elemsize = key->elemsize * step;
905
906 /* step 1 init */
907 cp_key(start, end, tot, basispoin, key, actkb, key->refkey, nullptr, mode);
908
909 /* step 2: do it */
910
911 for (kb = static_cast<KeyBlock *>(key->block.first), keyblock_index = 0; kb;
912 kb = kb->next, keyblock_index++)
913 {
914 if (kb != key->refkey) {
915 float icuval = kb->curval;
916
917 /* only with value, and no difference allowed */
918 if (!(kb->flag & KEYBLOCK_MUTE) && icuval != 0.0f && kb->totelem == tot) {
919 KeyBlock *refb;
920 float weight,
921 *weights = per_keyblock_weights ? per_keyblock_weights[keyblock_index] : nullptr;
922 char *freefrom = nullptr;
923
924 /* reference now can be any block */
925 refb = static_cast<KeyBlock *>(BLI_findlink(&key->block, kb->relative));
926 if (refb == nullptr) {
927 continue;
928 }
929
930 poin = basispoin;
931 from = key_block_get_data(key, actkb, kb, &freefrom);
932
933 /* For meshes, use the original values instead of the bmesh values to
934 * maintain a constant offset. */
935 reffrom = static_cast<char *>(refb->data);
936
937 poin += start * poinsize;
938 reffrom += key->elemsize * start; /* key elemsize yes! */
939 from += key->elemsize * start;
940
941 for (b = start; b < end; b += step) {
942
943 weight = weights ? (*weights * icuval) : icuval;
944
945 cp = key->elemstr;
946 if (mode == KEY_MODE_BEZTRIPLE) {
947 cp = elemstr;
948 }
949
950 ofsp = ofs;
951
952 while (cp[0]) { /* (cp[0] == amount) */
953
954 switch (cp[1]) {
955 case IPO_FLOAT:
957 (float *)poin,
958 (float *)reffrom,
959 (float *)from,
960 weight);
961 break;
962 case IPO_BPOINT:
964 (float *)poin,
965 (float *)reffrom,
966 (float *)from,
967 weight);
968 break;
969 case IPO_BEZTRIPLE:
971 (float *)poin,
972 (float *)reffrom,
973 (float *)from,
974 weight);
975 break;
976 default:
977 /* should never happen */
978 if (freefrom) {
979 MEM_freeN(freefrom);
980 }
981 BLI_assert_msg(0, "invalid 'cp[1]'");
982 return;
983 }
984
985 poin += *ofsp;
986
987 cp += 2;
988 ofsp++;
989 }
990
991 reffrom += elemsize;
992 from += elemsize;
993
994 if (weights) {
995 weights++;
996 }
997 }
998
999 if (freefrom) {
1000 MEM_freeN(freefrom);
1001 }
1002 }
1003 }
1004 }
1005}
1006
1007static void do_key(const int start,
1008 int end,
1009 const int tot,
1010 char *poin,
1011 Key *key,
1012 KeyBlock *actkb,
1013 KeyBlock **k,
1014 float *t,
1015 const int mode)
1016{
1017 float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
1018 float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
1019 int a, step, ofs[32], *ofsp;
1020 int flagdo = 15, flagflo = 0, elemsize, poinsize = 0;
1021 char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
1022 char *cp, elemstr[8];
1023
1024 /* currently always 0, in future key_pointer_size may assign */
1025 ofs[1] = 0;
1026
1027 if (!key_pointer_size(key, mode, &poinsize, &ofs[0], &step)) {
1028 return;
1029 }
1030
1031 end = std::min(end, tot);
1032
1033 k1 = key_block_get_data(key, actkb, k[0], &freek1);
1034 k2 = key_block_get_data(key, actkb, k[1], &freek2);
1035 k3 = key_block_get_data(key, actkb, k[2], &freek3);
1036 k4 = key_block_get_data(key, actkb, k[3], &freek4);
1037
1038 /* Test for more or less points (per key!) */
1039 if (tot != k[0]->totelem) {
1040 k1tot = 0.0;
1041 flagflo |= 1;
1042 if (k[0]->totelem) {
1043 k1d = k[0]->totelem / float(tot);
1044 }
1045 else {
1046 flagdo -= 1;
1047 }
1048 }
1049 if (tot != k[1]->totelem) {
1050 k2tot = 0.0;
1051 flagflo |= 2;
1052 if (k[0]->totelem) {
1053 k2d = k[1]->totelem / float(tot);
1054 }
1055 else {
1056 flagdo -= 2;
1057 }
1058 }
1059 if (tot != k[2]->totelem) {
1060 k3tot = 0.0;
1061 flagflo |= 4;
1062 if (k[0]->totelem) {
1063 k3d = k[2]->totelem / float(tot);
1064 }
1065 else {
1066 flagdo -= 4;
1067 }
1068 }
1069 if (tot != k[3]->totelem) {
1070 k4tot = 0.0;
1071 flagflo |= 8;
1072 if (k[0]->totelem) {
1073 k4d = k[3]->totelem / float(tot);
1074 }
1075 else {
1076 flagdo -= 8;
1077 }
1078 }
1079
1080 /* this exception is needed for curves with multiple splines */
1081 if (start != 0) {
1082
1083 poin += poinsize * start;
1084
1085 if (flagdo & 1) {
1086 if (flagflo & 1) {
1087 k1tot += start * k1d;
1088 a = int(floor(k1tot));
1089 if (a) {
1090 k1tot -= a;
1091 k1 += a * key->elemsize;
1092 }
1093 }
1094 else {
1095 k1 += start * key->elemsize;
1096 }
1097 }
1098 if (flagdo & 2) {
1099 if (flagflo & 2) {
1100 k2tot += start * k2d;
1101 a = int(floor(k2tot));
1102 if (a) {
1103 k2tot -= a;
1104 k2 += a * key->elemsize;
1105 }
1106 }
1107 else {
1108 k2 += start * key->elemsize;
1109 }
1110 }
1111 if (flagdo & 4) {
1112 if (flagflo & 4) {
1113 k3tot += start * k3d;
1114 a = int(floor(k3tot));
1115 if (a) {
1116 k3tot -= a;
1117 k3 += a * key->elemsize;
1118 }
1119 }
1120 else {
1121 k3 += start * key->elemsize;
1122 }
1123 }
1124 if (flagdo & 8) {
1125 if (flagflo & 8) {
1126 k4tot += start * k4d;
1127 a = int(floor(k4tot));
1128 if (a) {
1129 k4tot -= a;
1130 k4 += a * key->elemsize;
1131 }
1132 }
1133 else {
1134 k4 += start * key->elemsize;
1135 }
1136 }
1137 }
1138
1139 /* In case of bezier-triples. */
1140 elemstr[0] = 1; /* Number of IPO-floats. */
1141 elemstr[1] = IPO_BEZTRIPLE;
1142 elemstr[2] = 0;
1143
1144 /* only here, not above! */
1145 elemsize = key->elemsize * step;
1146
1147 for (a = start; a < end; a += step) {
1148 cp = key->elemstr;
1149 if (mode == KEY_MODE_BEZTRIPLE) {
1150 cp = elemstr;
1151 }
1152
1153 ofsp = ofs;
1154
1155 while (cp[0]) { /* (cp[0] == amount) */
1156
1157 switch (cp[1]) {
1158 case IPO_FLOAT:
1160 (float *)poin,
1161 (float *)k1,
1162 (float *)k2,
1163 (float *)k3,
1164 (float *)k4,
1165 t);
1166 break;
1167 case IPO_BPOINT:
1169 (float *)poin,
1170 (float *)k1,
1171 (float *)k2,
1172 (float *)k3,
1173 (float *)k4,
1174 t);
1175 break;
1176 case IPO_BEZTRIPLE:
1178 (float *)poin,
1179 (float *)k1,
1180 (float *)k2,
1181 (float *)k3,
1182 (float *)k4,
1183 t);
1184 break;
1185 default:
1186 /* should never happen */
1187 if (freek1) {
1188 MEM_freeN(freek1);
1189 }
1190 if (freek2) {
1191 MEM_freeN(freek2);
1192 }
1193 if (freek3) {
1194 MEM_freeN(freek3);
1195 }
1196 if (freek4) {
1197 MEM_freeN(freek4);
1198 }
1199 BLI_assert_msg(0, "invalid 'cp[1]'");
1200 return;
1201 }
1202
1203 poin += *ofsp;
1204 cp += 2;
1205 ofsp++;
1206 }
1207 /* lets do it the difficult way: when keys have a different size */
1208 if (flagdo & 1) {
1209 if (flagflo & 1) {
1210 k1tot += k1d;
1211 while (k1tot >= 1.0f) {
1212 k1tot -= 1.0f;
1213 k1 += elemsize;
1214 }
1215 }
1216 else {
1217 k1 += elemsize;
1218 }
1219 }
1220 if (flagdo & 2) {
1221 if (flagflo & 2) {
1222 k2tot += k2d;
1223 while (k2tot >= 1.0f) {
1224 k2tot -= 1.0f;
1225 k2 += elemsize;
1226 }
1227 }
1228 else {
1229 k2 += elemsize;
1230 }
1231 }
1232 if (flagdo & 4) {
1233 if (flagflo & 4) {
1234 k3tot += k3d;
1235 while (k3tot >= 1.0f) {
1236 k3tot -= 1.0f;
1237 k3 += elemsize;
1238 }
1239 }
1240 else {
1241 k3 += elemsize;
1242 }
1243 }
1244 if (flagdo & 8) {
1245 if (flagflo & 8) {
1246 k4tot += k4d;
1247 while (k4tot >= 1.0f) {
1248 k4tot -= 1.0f;
1249 k4 += elemsize;
1250 }
1251 }
1252 else {
1253 k4 += elemsize;
1254 }
1255 }
1256 }
1257
1258 if (freek1) {
1259 MEM_freeN(freek1);
1260 }
1261 if (freek2) {
1262 MEM_freeN(freek2);
1263 }
1264 if (freek3) {
1265 MEM_freeN(freek3);
1266 }
1267 if (freek4) {
1268 MEM_freeN(freek4);
1269 }
1270}
1271
1272static float *get_weights_array(Object *ob, const char *vgroup, WeightsArrayCache *cache)
1273{
1274 const MDeformVert *dvert = nullptr;
1275 BMEditMesh *em = nullptr;
1276 BMIter iter;
1277 BMVert *eve;
1278 int totvert = 0, defgrp_index = 0;
1279
1280 /* no vgroup string set? */
1281 if (vgroup[0] == 0) {
1282 return nullptr;
1283 }
1284
1285 /* gather dvert and totvert */
1286 if (ob->type == OB_MESH) {
1287 Mesh *mesh = static_cast<Mesh *>(ob->data);
1288 dvert = mesh->deform_verts().data();
1289 totvert = mesh->verts_num;
1290
1291 if (mesh->runtime->edit_mesh && mesh->runtime->edit_mesh->bm->totvert == totvert) {
1292 em = mesh->runtime->edit_mesh.get();
1293 }
1294 }
1295 else if (ob->type == OB_LATTICE) {
1296 Lattice *lt = static_cast<Lattice *>(ob->data);
1297 dvert = lt->dvert;
1298 totvert = lt->pntsu * lt->pntsv * lt->pntsw;
1299 }
1300
1301 if (dvert == nullptr) {
1302 return nullptr;
1303 }
1304
1305 /* find the group (weak loop-in-loop) */
1306 defgrp_index = BKE_object_defgroup_name_index(ob, vgroup);
1307 if (defgrp_index != -1) {
1308 float *weights;
1309
1310 if (cache) {
1311 if (cache->defgroup_weights == nullptr) {
1312 int num_defgroup = BKE_object_defgroup_count(ob);
1313 cache->defgroup_weights = MEM_calloc_arrayN<float *>(num_defgroup,
1314 "cached defgroup weights");
1315 cache->num_defgroup_weights = num_defgroup;
1316 }
1317
1318 if (cache->defgroup_weights[defgrp_index]) {
1319 return cache->defgroup_weights[defgrp_index];
1320 }
1321 }
1322
1323 weights = MEM_malloc_arrayN<float>(size_t(totvert), "weights");
1324
1325 if (em) {
1326 int i;
1327 const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
1328 BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
1329 dvert = static_cast<const MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
1330 weights[i] = BKE_defvert_find_weight(dvert, defgrp_index);
1331 }
1332 }
1333 else {
1334 for (int i = 0; i < totvert; i++, dvert++) {
1335 weights[i] = BKE_defvert_find_weight(dvert, defgrp_index);
1336 }
1337 }
1338
1339 if (cache) {
1340 cache->defgroup_weights[defgrp_index] = weights;
1341 }
1342
1343 return weights;
1344 }
1345 return nullptr;
1346}
1347
1349{
1350 KeyBlock *keyblock;
1351 float **per_keyblock_weights;
1352 int keyblock_index;
1353
1354 per_keyblock_weights = MEM_malloc_arrayN<float *>(size_t(key->totkey), "per keyblock weights");
1355
1356 for (keyblock = static_cast<KeyBlock *>(key->block.first), keyblock_index = 0; keyblock;
1357 keyblock = keyblock->next, keyblock_index++)
1358 {
1359 per_keyblock_weights[keyblock_index] = get_weights_array(ob, keyblock->vgroup, cache);
1360 }
1361
1362 return per_keyblock_weights;
1363}
1364
1366 float **per_keyblock_weights,
1367 WeightsArrayCache *cache)
1368{
1369 int a;
1370
1371 if (cache) {
1372 if (cache->num_defgroup_weights) {
1373 for (a = 0; a < cache->num_defgroup_weights; a++) {
1374 if (cache->defgroup_weights[a]) {
1375 MEM_freeN(cache->defgroup_weights[a]);
1376 }
1377 }
1379 }
1380 cache->defgroup_weights = nullptr;
1381 }
1382 else {
1383 for (a = 0; a < key->totkey; a++) {
1384 if (per_keyblock_weights[a]) {
1385 MEM_freeN(per_keyblock_weights[a]);
1386 }
1387 }
1388 }
1389
1390 MEM_freeN(per_keyblock_weights);
1391}
1392
1393static void do_mesh_key(Object *ob, Key *key, char *out, const int tot)
1394{
1395 KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
1396 float t[4];
1397 int flag = 0;
1398
1399 if (key->type == KEY_RELATIVE) {
1400 WeightsArrayCache cache = {0, nullptr};
1401 float **per_keyblock_weights;
1402 per_keyblock_weights = keyblock_get_per_block_weights(ob, key, &cache);
1403 key_evaluate_relative(0, tot, tot, out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
1404 keyblock_free_per_block_weights(key, per_keyblock_weights, &cache);
1405 }
1406 else {
1407 const float ctime_scaled = key->ctime / 100.0f;
1408
1409 flag = setkeys(ctime_scaled, &key->block, k, t, 0);
1410
1411 if (flag == 0) {
1412 do_key(0, tot, tot, out, key, actkb, k, t, KEY_MODE_DUMMY);
1413 }
1414 else {
1415 cp_key(0, tot, tot, out, key, actkb, k[2], nullptr, KEY_MODE_DUMMY);
1416 }
1417 }
1418}
1419
1420static void do_cu_key(
1421 Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, const int tot)
1422{
1423 Nurb *nu;
1424 int a, step;
1425
1426 for (a = 0, nu = static_cast<Nurb *>(cu->nurb.first); nu; nu = nu->next, a += step) {
1427 if (nu->bp) {
1429 do_key(a, a + step, tot, out, key, actkb, k, t, KEY_MODE_BPOINT);
1430 }
1431 else if (nu->bezt) {
1433 do_key(a, a + step, tot, out, key, actkb, k, t, KEY_MODE_BEZTRIPLE);
1434 }
1435 else {
1436 step = 0;
1437 }
1438 }
1439}
1440
1441static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const int tot)
1442{
1443 Nurb *nu;
1444 int a, step;
1445
1446 for (a = 0, nu = static_cast<Nurb *>(cu->nurb.first); nu; nu = nu->next, a += step) {
1447 if (nu->bp) {
1449 key_evaluate_relative(a, a + step, tot, out, key, actkb, nullptr, KEY_MODE_BPOINT);
1450 }
1451 else if (nu->bezt) {
1453 key_evaluate_relative(a, a + step, tot, out, key, actkb, nullptr, KEY_MODE_BEZTRIPLE);
1454 }
1455 else {
1456 step = 0;
1457 }
1458 }
1459}
1460
1461static void do_curve_key(Object *ob, Key *key, char *out, const int tot)
1462{
1463 Curve *cu = static_cast<Curve *>(ob->data);
1464 KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
1465 float t[4];
1466 int flag = 0;
1467
1468 if (key->type == KEY_RELATIVE) {
1469 do_rel_cu_key(cu, cu->key, actkb, out, tot);
1470 }
1471 else {
1472 const float ctime_scaled = key->ctime / 100.0f;
1473
1474 flag = setkeys(ctime_scaled, &key->block, k, t, 0);
1475
1476 if (flag == 0) {
1477 do_cu_key(cu, key, actkb, k, t, out, tot);
1478 }
1479 else {
1480 cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
1481 }
1482 }
1483}
1484
1485static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
1486{
1487 Lattice *lt = static_cast<Lattice *>(ob->data);
1488 KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob);
1489 float t[4];
1490 int flag;
1491
1492 if (key->type == KEY_RELATIVE) {
1493 float **per_keyblock_weights;
1494 per_keyblock_weights = keyblock_get_per_block_weights(ob, key, nullptr);
1495 key_evaluate_relative(0, tot, tot, out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY);
1496 keyblock_free_per_block_weights(key, per_keyblock_weights, nullptr);
1497 }
1498 else {
1499 const float ctime_scaled = key->ctime / 100.0f;
1500
1501 flag = setkeys(ctime_scaled, &key->block, k, t, 0);
1502
1503 if (flag == 0) {
1504 do_key(0, tot, tot, out, key, actkb, k, t, KEY_MODE_DUMMY);
1505 }
1506 else {
1507 cp_key(0, tot, tot, out, key, actkb, k[2], nullptr, KEY_MODE_DUMMY);
1508 }
1509 }
1510
1511 if (lt->flag & LT_OUTSIDE) {
1512 outside_lattice(lt);
1513 }
1514}
1515
1516static void keyblock_data_convert_to_lattice(const float (*fp)[3],
1517 BPoint *bpoint,
1518 const int totpoint);
1519static void keyblock_data_convert_to_curve(const float *fp, ListBase *nurb, const int totpoint);
1520
1522 Object *ob, int *r_totelem, float *arr, size_t arr_size, ID *obdata)
1523{
1524 Key *key = BKE_key_from_object(ob);
1526 char *out;
1527 int tot = 0, size = 0;
1528
1529 if (key == nullptr || BLI_listbase_is_empty(&key->block)) {
1530 return nullptr;
1531 }
1532
1533 /* compute size of output array */
1534 if (ob->type == OB_MESH) {
1535 Mesh *mesh = static_cast<Mesh *>(ob->data);
1536
1537 tot = mesh->verts_num;
1538 size = tot * sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
1539 }
1540 else if (ob->type == OB_LATTICE) {
1541 Lattice *lt = static_cast<Lattice *>(ob->data);
1542
1543 tot = lt->pntsu * lt->pntsv * lt->pntsw;
1544 size = tot * sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
1545 }
1546 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
1547 Curve *cu = static_cast<Curve *>(ob->data);
1548
1550 size = tot * sizeof(float[KEYELEM_ELEM_SIZE_CURVE]);
1551 }
1552
1553 /* if nothing to interpolate, cancel */
1554 if (tot == 0 || size == 0) {
1555 return nullptr;
1556 }
1557
1558 /* allocate array */
1559 if (arr == nullptr) {
1560 out = MEM_calloc_arrayN<char>(size, "BKE_key_evaluate_object out");
1561 }
1562 else {
1563 if (arr_size != size) {
1564 return nullptr;
1565 }
1566
1567 out = (char *)arr;
1568 }
1569
1570 if (ob->shapeflag & OB_SHAPE_LOCK) {
1571 /* shape locked, copy the locked shape instead of blending */
1572 KeyBlock *kb = static_cast<KeyBlock *>(BLI_findlink(&key->block, ob->shapenr - 1));
1573
1574 if (kb && (kb->flag & KEYBLOCK_MUTE)) {
1575 kb = key->refkey;
1576 }
1577
1578 if (kb == nullptr) {
1579 kb = static_cast<KeyBlock *>(key->block.first);
1580 ob->shapenr = 1;
1581 }
1582
1583 if (OB_TYPE_SUPPORT_VGROUP(ob->type)) {
1584 float *weights = get_weights_array(ob, kb->vgroup, nullptr);
1585
1586 cp_key(0, tot, tot, out, key, actkb, kb, weights, 0);
1587
1588 if (weights) {
1589 MEM_freeN(weights);
1590 }
1591 }
1592 else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
1593 cp_cu_key(static_cast<Curve *>(ob->data), key, actkb, kb, 0, tot, out, tot);
1594 }
1595 }
1596 else {
1597 if (ob->type == OB_MESH) {
1598 do_mesh_key(ob, key, out, tot);
1599 }
1600 else if (ob->type == OB_LATTICE) {
1601 do_latt_key(ob, key, out, tot);
1602 }
1603 else if (ob->type == OB_CURVES_LEGACY) {
1604 do_curve_key(ob, key, out, tot);
1605 }
1606 else if (ob->type == OB_SURF) {
1607 do_curve_key(ob, key, out, tot);
1608 }
1609 }
1610
1611 if (obdata != nullptr) {
1612 switch (GS(obdata->name)) {
1613 case ID_ME: {
1614 Mesh *mesh = (Mesh *)obdata;
1615 const int totvert = min_ii(tot, mesh->verts_num);
1616 mesh->vert_positions_for_write().take_front(totvert).copy_from(
1617 {reinterpret_cast<const blender::float3 *>(out), totvert});
1618 mesh->tag_positions_changed();
1619 break;
1620 }
1621 case ID_LT: {
1622 Lattice *lattice = (Lattice *)obdata;
1623 const int totpoint = min_ii(tot, lattice->pntsu * lattice->pntsv * lattice->pntsw);
1624 keyblock_data_convert_to_lattice((const float(*)[3])out, lattice->def, totpoint);
1625 break;
1626 }
1627 case ID_CU_LEGACY: {
1628 Curve *curve = (Curve *)obdata;
1629 const int totpoint = min_ii(tot, BKE_keyblock_curve_element_count(&curve->nurb));
1630 keyblock_data_convert_to_curve((const float *)out, &curve->nurb, totpoint);
1631 break;
1632 }
1633 default:
1635 }
1636 }
1637
1638 if (r_totelem) {
1639 *r_totelem = tot;
1640 }
1641 return (float *)out;
1642}
1643
1644float *BKE_key_evaluate_object(Object *ob, int *r_totelem)
1645{
1646 return BKE_key_evaluate_object_ex(ob, r_totelem, nullptr, 0, nullptr);
1647}
1648
1649int BKE_keyblock_element_count_from_shape(const Key *key, const int shape_index)
1650{
1651 int result = 0;
1652 int index = 0;
1653 for (const KeyBlock *kb = static_cast<const KeyBlock *>(key->block.first); kb;
1654 kb = kb->next, index++)
1655 {
1656 if (ELEM(shape_index, -1, index)) {
1657 result += kb->totelem;
1658 }
1659 }
1660 return result;
1661}
1662
1664{
1666}
1667
1668size_t BKE_keyblock_element_calc_size_from_shape(const Key *key, const int shape_index)
1669{
1670 return size_t(BKE_keyblock_element_count_from_shape(key, shape_index)) * key->elemsize;
1671}
1672
1674{
1676}
1677
1678/* -------------------------------------------------------------------- */
1684
1687 const int shape_index)
1688{
1689 uint8_t *elements = (uint8_t *)arr.data();
1690 int index = 0;
1691 for (const KeyBlock *kb = static_cast<const KeyBlock *>(key->block.first); kb;
1692 kb = kb->next, index++)
1693 {
1694 if (ELEM(shape_index, -1, index)) {
1695 const int block_elem_len = kb->totelem * key->elemsize;
1696 memcpy(elements, kb->data, block_elem_len);
1697 elements += block_elem_len;
1698 }
1699 }
1700}
1701
1703{
1705}
1706
1708 const int shape_index,
1709 const Span<float3> coords,
1710 const float4x4 &transform)
1711{
1712 if (key->elemsize != sizeof(float[3])) {
1713 BLI_assert_msg(0, "Invalid elemsize");
1714 return;
1715 }
1716
1717 const float3 *elements = coords.data();
1718
1719 int index = 0;
1720 for (KeyBlock *kb = static_cast<KeyBlock *>(key->block.first); kb; kb = kb->next, index++) {
1721 if (ELEM(shape_index, -1, index)) {
1722 const int block_elem_len = kb->totelem;
1723 float(*block_data)[3] = (float(*)[3])kb->data;
1724 for (int data_offset = 0; data_offset < block_elem_len; ++data_offset) {
1725 const float *src_data = (const float *)(elements + data_offset);
1726 float *dst_data = (float *)(block_data + data_offset);
1727 mul_v3_m4v3(dst_data, transform.ptr(), src_data);
1728 }
1729 elements += block_elem_len;
1730 }
1731 }
1732}
1733
1735 const ListBase *nurb,
1736 const int shape_index,
1737 const void *data,
1738 const float4x4 &transform)
1739{
1740 const uint8_t *elements = static_cast<const uint8_t *>(data);
1741
1742 int index = 0;
1743 for (KeyBlock *kb = static_cast<KeyBlock *>(key->block.first); kb; kb = kb->next, index++) {
1744 if (ELEM(shape_index, -1, index)) {
1745 const int block_elem_size = kb->totelem * key->elemsize;
1746 BKE_keyblock_curve_data_transform(nurb, transform.ptr(), elements, kb->data);
1747 elements += block_elem_size;
1748 }
1749 }
1750}
1751
1752void BKE_keyblock_data_set(Key *key, const int shape_index, const void *data)
1753{
1754 const uint8_t *elements = static_cast<const uint8_t *>(data);
1755 int index = 0;
1756 for (KeyBlock *kb = static_cast<KeyBlock *>(key->block.first); kb; kb = kb->next, index++) {
1757 if (ELEM(shape_index, -1, index)) {
1758 const int block_elem_size = kb->totelem * key->elemsize;
1759 memcpy(kb->data, elements, block_elem_size);
1760 elements += block_elem_size;
1761 }
1762 }
1763}
1764
1766
1767bool BKE_key_idtype_support(const short id_type)
1768{
1769 switch (id_type) {
1770 case ID_ME:
1771 case ID_CU_LEGACY:
1772 case ID_LT:
1773 return true;
1774 default:
1775 return false;
1776 }
1777}
1778
1780{
1781 switch (GS(id->name)) {
1782 case ID_ME: {
1783 Mesh *mesh = (Mesh *)id;
1784 return &mesh->key;
1785 }
1786 case ID_CU_LEGACY: {
1787 Curve *cu = (Curve *)id;
1788 if (cu->ob_type != OB_FONT) {
1789 return &cu->key;
1790 }
1791 break;
1792 }
1793 case ID_LT: {
1794 Lattice *lt = (Lattice *)id;
1795 return &lt->key;
1796 }
1797 default:
1798 break;
1799 }
1800
1801 return nullptr;
1802}
1803
1805{
1806 Key **key_p;
1807 key_p = BKE_key_from_id_p(id);
1808 if (key_p) {
1809 return *key_p;
1810 }
1811
1812 return nullptr;
1813}
1814
1816{
1817 if (ob == nullptr || ob->data == nullptr) {
1818 return nullptr;
1819 }
1820
1821 return BKE_key_from_id_p(static_cast<ID *>(ob->data));
1822}
1823
1825{
1826 Key **key_p;
1827 key_p = BKE_key_from_object_p(ob);
1828 if (key_p) {
1829 return *key_p;
1830 }
1831
1832 return nullptr;
1833}
1834
1835KeyBlock *BKE_keyblock_add(Key *key, const char *name)
1836{
1837 KeyBlock *kb;
1838 float curpos = -0.1;
1839 int tot;
1840
1841 kb = static_cast<KeyBlock *>(key->block.last);
1842 if (kb) {
1843 curpos = kb->pos;
1844 }
1845
1846 kb = MEM_callocN<KeyBlock>("Keyblock");
1847 BLI_addtail(&key->block, kb);
1848 kb->type = KEY_LINEAR;
1849
1850 tot = BLI_listbase_count(&key->block);
1851 if (name) {
1852 STRNCPY(kb->name, name);
1853 }
1854 else {
1855 if (tot == 1) {
1856 STRNCPY_UTF8(kb->name, DATA_("Basis"));
1857 }
1858 else {
1859 SNPRINTF(kb->name, DATA_("Key %d"), tot - 1);
1860 }
1861 }
1862
1863 BLI_uniquename(&key->block, kb, DATA_("Key"), '.', offsetof(KeyBlock, name), sizeof(kb->name));
1864
1865 kb->uid = key->uidgen++;
1866
1867 key->totkey++;
1868 if (key->totkey == 1) {
1869 key->refkey = kb;
1870 }
1871
1872 kb->slidermin = 0.0f;
1873 kb->slidermax = 1.0f;
1874
1875 /* \note caller may want to set this to current time, but don't do it here since we need to sort
1876 * which could cause problems in some cases, see #BKE_keyblock_add_ctime. */
1877 kb->pos = curpos + 0.1f; /* only used for absolute shape keys */
1878
1879 return kb;
1880}
1881
1883{
1884 BLI_assert(BLI_findindex(&key->block, kb_src) != -1);
1885 KeyBlock *kb_dst = BKE_keyblock_add(key, kb_src->name);
1886 kb_dst->totelem = kb_src->totelem;
1887 kb_dst->data = MEM_dupallocN(kb_src->data);
1888 BLI_remlink(&key->block, kb_dst);
1889 BLI_insertlinkafter(&key->block, kb_src, kb_dst);
1890 BKE_keyblock_copy_settings(kb_dst, kb_src);
1891 kb_dst->flag = kb_src->flag;
1892 return kb_dst;
1893}
1894
1895KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force)
1896{
1897 KeyBlock *kb = BKE_keyblock_add(key, name);
1898 const float cpos = key->ctime / 100.0f;
1899
1900 /* In case of absolute keys, there is no point in adding more than one key with the same pos.
1901 * Hence only set new key-block pos to current time if none previous one already use it.
1902 * Now at least people just adding absolute keys without touching to ctime
1903 * won't have to systematically use retiming func (and have ordering issues, too). See #39897.
1904 */
1905 if (!do_force && (key->type != KEY_RELATIVE)) {
1906 LISTBASE_FOREACH (KeyBlock *, it_kb, &key->block) {
1907 /* Use epsilon to avoid floating point precision issues.
1908 * 1e-3 because the position is stored as frame * 1e-2. */
1909 if (compare_ff(it_kb->pos, cpos, 1e-3f)) {
1910 return kb;
1911 }
1912 }
1913 }
1914 if (do_force || (key->type != KEY_RELATIVE)) {
1915 kb->pos = cpos;
1916 BKE_key_sort(key);
1917 }
1918
1919 return kb;
1920}
1921
1923{
1924 Key *key = BKE_key_from_object(ob);
1925
1926 return BKE_keyblock_find_by_index(key, ob->shapenr - 1);
1927}
1928
1930{
1931 Key *key = BKE_key_from_object(ob);
1932
1933 if (key) {
1934 return key->refkey;
1935 }
1936
1937 return nullptr;
1938}
1939
1941{
1942 if (!key) {
1943 return nullptr;
1944 }
1945
1946 return static_cast<KeyBlock *>(BLI_findlink(&key->block, index));
1947}
1948
1949KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])
1950{
1951 return static_cast<KeyBlock *>(BLI_findstring(&key->block, name, offsetof(KeyBlock, name)));
1952}
1953
1955{
1956 LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
1957 if (kb->uid == uid) {
1958 return kb;
1959 }
1960 }
1961 return nullptr;
1962}
1963
1965{
1966 kb_dst->pos = kb_src->pos;
1967 kb_dst->curval = kb_src->curval;
1968 kb_dst->type = kb_src->type;
1969 kb_dst->relative = kb_src->relative;
1970 STRNCPY(kb_dst->vgroup, kb_src->vgroup);
1971 kb_dst->slidermin = kb_src->slidermin;
1972 kb_dst->slidermax = kb_src->slidermax;
1973}
1974
1975std::optional<std::string> BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb)
1976{
1977 if (ELEM(nullptr, key, kb)) {
1978 return std::nullopt;
1979 }
1980 PointerRNA ptr = RNA_pointer_create_discrete((ID *)&key->id, &RNA_ShapeKey, (KeyBlock *)kb);
1981 PropertyRNA *prop = RNA_struct_find_property(&ptr, "value");
1982 return RNA_path_from_ID_to_property(&ptr, prop);
1983}
1984
1985/* conversion functions */
1986
1987/************************* Lattice ************************/
1988
1990{
1991 BPoint *bp;
1992 float(*fp)[3];
1993 int a, tot;
1994
1995 BLI_assert(kb->totelem == lt->pntsu * lt->pntsv * lt->pntsw);
1996
1997 tot = kb->totelem;
1998 if (tot == 0) {
1999 return;
2000 }
2001
2002 bp = lt->def;
2003 fp = static_cast<float(*)[3]>(kb->data);
2004 for (a = 0; a < kb->totelem; a++, fp++, bp++) {
2005 copy_v3_v3(*fp, bp->vec);
2006 }
2007}
2008
2010{
2011 int tot;
2012
2013 tot = lt->pntsu * lt->pntsv * lt->pntsw;
2014 if (tot == 0) {
2015 return;
2016 }
2017
2018 MEM_SAFE_FREE(kb->data);
2019
2020 kb->data = MEM_malloc_arrayN(size_t(tot), size_t(lt->key->elemsize), __func__);
2021 kb->totelem = tot;
2022
2024}
2025
2026static void keyblock_data_convert_to_lattice(const float (*fp)[3],
2027 BPoint *bpoint,
2028 const int totpoint)
2029{
2030 for (int i = 0; i < totpoint; i++, fp++, bpoint++) {
2031 copy_v3_v3(bpoint->vec, *fp);
2032 }
2033}
2034
2036{
2037 BPoint *bp = lt->def;
2038 const float(*fp)[3] = static_cast<const float(*)[3]>(kb->data);
2039 const int tot = min_ii(kb->totelem, lt->pntsu * lt->pntsv * lt->pntsw);
2040
2042}
2043
2044/************************* Curve ************************/
2045
2047{
2048 const Nurb *nu;
2049 int tot = 0;
2050
2051 nu = static_cast<const Nurb *>(nurb->first);
2052 while (nu) {
2053 if (nu->bezt) {
2054 tot += KEYELEM_ELEM_LEN_BEZTRIPLE * nu->pntsu;
2055 }
2056 else if (nu->bp) {
2057 tot += KEYELEM_ELEM_LEN_BPOINT * nu->pntsu * nu->pntsv;
2058 }
2059
2060 nu = nu->next;
2061 }
2062 return tot;
2063}
2064
2065void BKE_keyblock_update_from_curve(const Curve * /*cu*/, KeyBlock *kb, const ListBase *nurb)
2066{
2067 BezTriple *bezt;
2068 BPoint *bp;
2069 float *fp;
2070 int a, tot;
2071
2072 /* count */
2074
2075 tot = kb->totelem;
2076 if (tot == 0) {
2077 return;
2078 }
2079
2080 fp = static_cast<float *>(kb->data);
2081 LISTBASE_FOREACH (Nurb *, nu, nurb) {
2082 if (nu->bezt) {
2083 for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) {
2084 for (int i = 0; i < 3; i++) {
2085 copy_v3_v3(&fp[i * 3], bezt->vec[i]);
2086 }
2087 fp[9] = bezt->tilt;
2088 fp[10] = bezt->radius;
2090 }
2091 }
2092 else {
2093 for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++) {
2094 copy_v3_v3(fp, bp->vec);
2095 fp[3] = bp->tilt;
2096 fp[4] = bp->radius;
2098 }
2099 }
2100 }
2101}
2102
2104 const float mat[4][4],
2105 const void *src_data,
2106 void *dst_data)
2107{
2108 const float *src = static_cast<const float *>(src_data);
2109 float *dst = static_cast<float *>(dst_data);
2110 LISTBASE_FOREACH (Nurb *, nu, nurb) {
2111 if (nu->bezt) {
2112 for (int a = nu->pntsu; a; a--) {
2113 for (int i = 0; i < 3; i++) {
2114 mul_v3_m4v3(&dst[i * 3], mat, &src[i * 3]);
2115 }
2116 dst[9] = src[9];
2117 dst[10] = src[10];
2120 }
2121 }
2122 else {
2123 for (int a = nu->pntsu * nu->pntsv; a; a--) {
2124 mul_v3_m4v3(dst, mat, src);
2125 dst[3] = src[3];
2126 dst[4] = src[4];
2129 }
2130 }
2131 }
2132}
2133
2135{
2136 int tot;
2137
2138 /* count */
2140 if (tot == 0) {
2141 return;
2142 }
2143
2144 MEM_SAFE_FREE(kb->data);
2145
2146 kb->data = MEM_malloc_arrayN(size_t(tot), size_t(cu->key->elemsize), __func__);
2147 kb->totelem = tot;
2148
2149 BKE_keyblock_update_from_curve(cu, kb, nurb);
2150}
2151
2152static void keyblock_data_convert_to_curve(const float *fp, ListBase *nurb, int totpoint)
2153{
2154 for (Nurb *nu = static_cast<Nurb *>(nurb->first); nu && totpoint > 0; nu = nu->next) {
2155 if (nu->bezt != nullptr) {
2156 BezTriple *bezt = nu->bezt;
2157 for (int i = nu->pntsu; i && (totpoint -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0;
2158 i--, bezt++, fp += KEYELEM_FLOAT_LEN_BEZTRIPLE)
2159 {
2160 for (int j = 0; j < 3; j++) {
2161 copy_v3_v3(bezt->vec[j], &fp[j * 3]);
2162 }
2163 bezt->tilt = fp[9];
2164 bezt->radius = fp[10];
2165 }
2166 }
2167 else {
2168 BPoint *bp = nu->bp;
2169 for (int i = nu->pntsu * nu->pntsv; i && (totpoint -= KEYELEM_ELEM_LEN_BPOINT) >= 0;
2170 i--, bp++, fp += KEYELEM_FLOAT_LEN_BPOINT)
2171 {
2172 copy_v3_v3(bp->vec, fp);
2173 bp->tilt = fp[3];
2174 bp->radius = fp[4];
2175 }
2176 }
2177 }
2178}
2179
2181{
2182 const float *fp = static_cast<const float *>(kb->data);
2183 const int tot = min_ii(kb->totelem, BKE_keyblock_curve_element_count(nurb));
2184
2185 keyblock_data_convert_to_curve(fp, nurb, tot);
2186}
2187
2188/************************* Mesh ************************/
2189
2191{
2192 BLI_assert(mesh->verts_num == kb->totelem);
2193
2194 const int tot = mesh->verts_num;
2195 if (tot == 0) {
2196 return;
2197 }
2198
2199 const blender::Span<blender::float3> positions = mesh->vert_positions();
2200 memcpy(kb->data, positions.data(), sizeof(float[3]) * tot);
2201}
2202
2203void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
2204{
2205 const int len = mesh->verts_num;
2206
2207 if (mesh->verts_num == 0) {
2208 return;
2209 }
2210
2211 MEM_SAFE_FREE(kb->data);
2212
2213 kb->data = MEM_malloc_arrayN(size_t(len), size_t(key->elemsize), __func__);
2214 kb->totelem = len;
2215
2217}
2218
2221{
2222 vert_positions.take_front(kb->totelem)
2223 .copy_from({static_cast<blender::float3 *>(kb->data), kb->totelem});
2224}
2225
2227 Mesh *mesh,
2228 float (*r_vert_normals)[3],
2229 float (*r_face_normals)[3],
2230 float (*r_loop_normals)[3])
2231{
2232 using namespace blender;
2233 using namespace blender::bke;
2234 if (r_vert_normals == nullptr && r_face_normals == nullptr && r_loop_normals == nullptr) {
2235 return;
2236 }
2237
2238 blender::Array<blender::float3> positions(mesh->vert_positions());
2239 BKE_keyblock_convert_to_mesh(kb, positions);
2240 const blender::OffsetIndices faces = mesh->faces();
2241 const blender::Span<int> corner_verts = mesh->corner_verts();
2242 const blender::Span<int> corner_edges = mesh->corner_edges();
2243
2244 const bool loop_normals_needed = r_loop_normals != nullptr;
2245 const bool vert_normals_needed = r_vert_normals != nullptr;
2246 const bool face_normals_needed = r_face_normals != nullptr || vert_normals_needed ||
2247 loop_normals_needed;
2248
2249 float(*vert_normals)[3] = r_vert_normals;
2250 float(*face_normals)[3] = r_face_normals;
2251 bool free_vert_normals = false;
2252 bool free_face_normals = false;
2253 if (vert_normals_needed && r_vert_normals == nullptr) {
2254 vert_normals = MEM_malloc_arrayN<float[3]>(size_t(mesh->verts_num), __func__);
2255 free_vert_normals = true;
2256 }
2257 if (face_normals_needed && r_face_normals == nullptr) {
2258 face_normals = MEM_malloc_arrayN<float[3]>(size_t(mesh->faces_num), __func__);
2259 free_face_normals = true;
2260 }
2261
2262 if (face_normals_needed) {
2263 mesh::normals_calc_faces(positions,
2264 faces,
2265 corner_verts,
2266 {reinterpret_cast<blender::float3 *>(face_normals), faces.size()});
2267 }
2268 if (vert_normals_needed) {
2270 positions,
2271 faces,
2272 corner_verts,
2273 mesh->vert_to_face_map(),
2274 {reinterpret_cast<const blender::float3 *>(face_normals), faces.size()},
2275 {reinterpret_cast<blender::float3 *>(vert_normals), mesh->verts_num});
2276 }
2277 if (loop_normals_needed) {
2278 const AttributeAccessor attributes = mesh->attributes();
2279 const VArraySpan sharp_edges = *attributes.lookup<bool>("sharp_edge", AttrDomain::Edge);
2280 const VArraySpan sharp_faces = *attributes.lookup<bool>("sharp_face", AttrDomain::Face);
2281 const VArraySpan custom_normals = *attributes.lookup<short2>("custom_normal",
2284 positions,
2285 faces,
2286 corner_verts,
2287 corner_edges,
2288 mesh->vert_to_face_map(),
2289 {reinterpret_cast<blender::float3 *>(face_normals), faces.size()},
2290 sharp_edges,
2291 sharp_faces,
2292 custom_normals,
2293 nullptr,
2294 {reinterpret_cast<blender::float3 *>(r_loop_normals), corner_verts.size()});
2295 }
2296
2297 if (free_vert_normals) {
2298 MEM_freeN(vert_normals);
2299 }
2300 if (free_face_normals) {
2301 MEM_freeN(face_normals);
2302 }
2303}
2304
2305/************************* raw coords ************************/
2306
2307bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
2308{
2309 Key *key = BKE_key_from_object(ob);
2310 KeyBlock *kb;
2311 const int act_index = ob->shapenr - 1;
2312 const int totkey = key->totkey;
2313 int i;
2314 bool rev, in_range = false;
2315
2316 if (org_index < 0) {
2317 org_index = act_index;
2318 }
2319
2320 CLAMP(new_index, 0, key->totkey - 1);
2321 CLAMP(org_index, 0, key->totkey - 1);
2322
2323 if (new_index == org_index) {
2324 return false;
2325 }
2326
2327 rev = ((new_index - org_index) < 0) ? true : false;
2328
2329 /* We swap 'org' element with its previous/next neighbor (depending on direction of the move)
2330 * repeatedly, until we reach final position.
2331 * This allows us to only loop on the list once! */
2332 for (kb = static_cast<KeyBlock *>(rev ? key->block.last : key->block.first),
2333 i = (rev ? totkey - 1 : 0);
2334 kb;
2335 kb = (rev ? kb->prev : kb->next), rev ? i-- : i++)
2336 {
2337 if (i == org_index) {
2338 in_range = true; /* Start list items swapping... */
2339 }
2340 else if (i == new_index) {
2341 in_range = false; /* End list items swapping. */
2342 }
2343
2344 if (in_range) {
2345 KeyBlock *other_kb = rev ? kb->prev : kb->next;
2346
2347 /* Swap with previous/next list item. */
2348 BLI_listbase_swaplinks(&key->block, kb, other_kb);
2349
2350 /* Swap absolute positions. */
2351 std::swap(kb->pos, other_kb->pos);
2352
2353 kb = other_kb;
2354 }
2355
2356 /* Adjust relative indices, this has to be done on the whole list! */
2357 if (kb->relative == org_index) {
2358 kb->relative = new_index;
2359 }
2360 else if (kb->relative < org_index && kb->relative >= new_index) {
2361 /* remove after, insert before this index */
2362 kb->relative++;
2363 }
2364 else if (kb->relative > org_index && kb->relative <= new_index) {
2365 /* remove before, insert after this index */
2366 kb->relative--;
2367 }
2368 }
2369
2370 /* Need to update active shape number if it's affected,
2371 * same principle as for relative indices above. */
2372 if (org_index == act_index) {
2373 ob->shapenr = new_index + 1;
2374 }
2375 else if (act_index < org_index && act_index >= new_index) {
2376 ob->shapenr++;
2377 }
2378 else if (act_index > org_index && act_index <= new_index) {
2379 ob->shapenr--;
2380 }
2381
2382 /* First key is always refkey, matches interface and BKE_key_sort */
2383 key->refkey = static_cast<KeyBlock *>(key->block.first);
2384
2385 return true;
2386}
2387
2388bool BKE_keyblock_is_basis(const Key *key, const int index)
2389{
2390 const KeyBlock *kb;
2391 int i;
2392
2393 if (key->type == KEY_RELATIVE) {
2394 for (i = 0, kb = static_cast<const KeyBlock *>(key->block.first); kb; i++, kb = kb->next) {
2395 if ((i != index) && (kb->relative == index)) {
2396 return true;
2397 }
2398 }
2399 }
2400
2401 return false;
2402}
2403
2404std::optional<blender::Array<bool>> BKE_keyblock_get_dependent_keys(const Key *key,
2405 const int index)
2406{
2407 if (key->type != KEY_RELATIVE) {
2408 return std::nullopt;
2409 }
2410
2411 const int count = BLI_listbase_count(&key->block);
2412
2413 if (index < 0 || index >= count) {
2414 return std::nullopt;
2415 }
2416
2417 /* Seed the table with the specified key. */
2418 blender::Array<bool> marked(count, false);
2419
2420 marked[index] = true;
2421
2422 /* Iterative breadth-first search through the key list. This method minimizes
2423 * the number of scans through the list and is fail-safe vs reference cycles. */
2424 bool updated, found = false;
2425 int i;
2426
2427 do {
2428 updated = false;
2429
2430 LISTBASE_FOREACH_INDEX (const KeyBlock *, kb, &key->block, i) {
2431 if (!marked[i] && kb->relative >= 0 && kb->relative < count && marked[kb->relative]) {
2432 marked[i] = true;
2433 updated = found = true;
2434 }
2435 }
2436 } while (updated);
2437
2438 if (!found) {
2439 return std::nullopt;
2440 }
2441
2442 /* After the search is complete, exclude the original key. */
2443 marked[index] = false;
2444 return marked;
2445}
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
int BKE_object_defgroup_count(const Object *ob)
Definition deform.cc:591
float BKE_defvert_find_weight(const MDeformVert *dvert, int defgroup)
Definition deform.cc:763
int BKE_object_defgroup_name_index(const Object *ob, blender::StringRef name)
Definition deform.cc:580
IDTypeInfo IDType_ID_KE
Definition key.cc:205
@ IDTYPE_FLAGS_NO_LIBLINKING
Definition BKE_idtype.hh:32
int BKE_keyblock_curve_element_count(const ListBase *nurb)
Definition key.cc:2046
void outside_lattice(Lattice *lt)
Definition lattice.cc:406
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1495
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_USER
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_DO_DEPRECATED_POINTERS
#define BKE_LIB_FOREACHID_PROCESS_ID_NOCHECK(data_, id_, cb_flag_)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void BLI_endian_switch_float_array(float *val, int size) ATTR_NONNULL(1)
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)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:252
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE int compare_ff(float a, float b, float max_diff)
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define CLAMP(a, b, c)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_read_requires_endian_switch(BlendDataReader *reader)
Definition readfile.cc:5244
#define BLO_read_struct_list(reader, struct_name, list)
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLO_write_struct_at_address(writer, struct_name, address, data_ptr)
#define BLT_I18NCONTEXT_ID_SHAPEKEY
#define DATA_(msgid)
ID and Library types, which are fundamental for SDNA.
@ ID_TAG_EXTERN
Definition DNA_ID.h:750
@ INDEX_ID_KE
Definition DNA_ID.h:1230
@ ID_CU_LEGACY
@ ID_ME
@ ID_LT
@ CD_MDEFORMVERT
@ KEY_RELATIVE
@ KEY_NORMAL
@ KEYBLOCK_MUTE
#define KEYELEM_FLOAT_LEN_COORD
#define KEYELEM_ELEM_LEN_BPOINT
#define KEYELEM_FLOAT_LEN_BEZTRIPLE
#define KEYELEM_ELEM_SIZE_CURVE
KeyInterpolationType
@ KEY_LINEAR
@ KEY_CARDINAL
@ KEY_BSPLINE
@ KEY_CATMULL_ROM
#define KEYELEM_FLOAT_LEN_BPOINT
#define KEYELEM_ELEM_LEN_BEZTRIPLE
@ LT_OUTSIDE
Object is a sort of wrapper for general info.
@ OB_SHAPE_LOCK
@ OB_LATTICE
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_CURVES_LEGACY
#define OB_TYPE_SUPPORT_VGROUP(_type)
Read Guarded memory(de)allocation.
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
BMesh const char void * data
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr T * data() const
Definition BLI_span.hh:539
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr MutableSpan take_front(const int64_t n) const
Definition BLI_span.hh:629
constexpr const T * data() const
Definition BLI_span.hh:215
GAttributeReader lookup(const StringRef attribute_id) const
#define offsetof(t, d)
uint pos
VecBase< short, 2 > short2
#define in
#define floor
#define out
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
#define MEM_SAFE_FREE(v)
#define FILTER_ID_CU_LEGACY
#define FILTER_ID_LT
#define FILTER_ID_ME
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define FILTER_ID_KE
#define GS(a)
int count
static void shapekey_blend_read_data(BlendDataReader *reader, ID *id)
Definition key.cc:181
void BKE_keyblock_curve_data_set_with_mat4(Key *key, const ListBase *nurb, const int shape_index, const void *data, const float4x4 &transform)
Definition key.cc:1734
#define IPO_FLOAT
Definition key.cc:150
static void key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, float **per_keyblock_weights, const int mode)
Definition key.cc:875
void BKE_keyblock_curve_data_transform(const ListBase *nurb, const float mat[4][4], const void *src_data, void *dst_data)
Definition key.cc:2103
void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb, Mesh *mesh, float(*r_vert_normals)[3], float(*r_face_normals)[3], float(*r_loop_normals)[3])
Definition key.cc:2226
KeyBlock * BKE_keyblock_from_object(Object *ob)
Definition key.cc:1922
static void flerp(int tot, float *in, const float *f0, const float *f1, const float *f2, const float *f3, const float *t)
Definition key.cc:604
void BKE_keyblock_convert_to_lattice(const KeyBlock *kb, Lattice *lt)
Definition key.cc:2035
Key ** BKE_key_from_id_p(ID *id)
Definition key.cc:1779
std::optional< std::string > BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb)
Definition key.cc:1975
static ID ** shapekey_owner_pointer_get(ID *id, const bool debug_relationship_assert)
Definition key.cc:113
static float * get_weights_array(Object *ob, const char *vgroup, WeightsArrayCache *cache)
Definition key.cc:1272
size_t BKE_keyblock_element_calc_size_from_shape(const Key *key, const int shape_index)
Definition key.cc:1668
void BKE_key_free_nolib(Key *key)
Definition key.cc:248
void BKE_keyblock_data_get_from_shape(const Key *key, MutableSpan< float3 > arr, const int shape_index)
Definition key.cc:1685
int BKE_keyblock_element_count_from_shape(const Key *key, const int shape_index)
Definition key.cc:1649
#define IPO_BEZTRIPLE
Definition key.cc:151
Key * BKE_key_add(Main *bmain, ID *id)
Definition key.cc:258
std::optional< blender::Array< bool > > BKE_keyblock_get_dependent_keys(const Key *key, const int index)
Definition key.cc:2404
bool BKE_key_idtype_support(const short id_type)
Definition key.cc:1767
static void keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights, WeightsArrayCache *cache)
Definition key.cc:1365
#define KEY_MODE_BPOINT
Definition key.cc:239
void BKE_keyblock_data_get(const Key *key, MutableSpan< float3 > arr)
Definition key.cc:1702
KeyBlock * BKE_keyblock_add(Key *key, const char *name)
Definition key.cc:1835
KeyBlock * BKE_keyblock_from_object_reference(Object *ob)
Definition key.cc:1929
void BKE_keyblock_convert_to_mesh(const KeyBlock *kb, blender::MutableSpan< blender::float3 > vert_positions)
Definition key.cc:2219
KeyBlock * BKE_keyblock_duplicate(Key *key, KeyBlock *kb_src)
Definition key.cc:1882
bool BKE_keyblock_move(Object *ob, int org_index, int new_index)
Definition key.cc:2307
void BKE_keyblock_update_from_mesh(const Mesh *mesh, KeyBlock *kb)
Definition key.cc:2190
static void shapekey_foreach_id(ID *id, LibraryForeachIDData *data)
Definition key.cc:101
static bool key_pointer_size(const Key *key, const int mode, int *r_poinsize, int *r_ofs, int *r_step)
Definition key.cc:663
void BKE_keyblock_data_set(Key *key, const int shape_index, const void *data)
Definition key.cc:1752
static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const int tot)
Definition key.cc:1441
void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *, ListBase *nurb)
Definition key.cc:2180
static void do_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, const int mode)
Definition key.cc:1007
KeyBlock * BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force)
Definition key.cc:1895
int BKE_keyblock_curve_element_count(const ListBase *nurb)
Definition key.cc:2046
void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
Definition key.cc:2203
static void switch_endian_keyblock(Key *key, KeyBlock *kb)
Definition key.cc:154
static void shapekey_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
Definition key.cc:65
size_t BKE_keyblock_element_calc_size(const Key *key)
Definition key.cc:1673
void BKE_keyblock_update_from_curve(const Curve *, KeyBlock *kb, const ListBase *nurb)
Definition key.cc:2065
float * BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t arr_size, ID *obdata)
Definition key.cc:1521
KeyBlock * BKE_keyblock_find_by_index(Key *key, int index)
Definition key.cc:1940
static void do_curve_key(Object *ob, Key *key, char *out, const int tot)
Definition key.cc:1461
void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
copy shape-key attributes, but not key data or name/UID.
Definition key.cc:1964
void BKE_keyblock_convert_from_curve(const Curve *cu, KeyBlock *kb, const ListBase *nurb)
Definition key.cc:2134
#define KEY_MODE_BEZTRIPLE
Definition key.cc:240
KeyBlock * BKE_keyblock_find_name(Key *key, const char name[])
Definition key.cc:1949
void BKE_keyblock_convert_from_lattice(const Lattice *lt, KeyBlock *kb)
Definition key.cc:2009
static void keyblock_data_convert_to_curve(const float *fp, ListBase *nurb, const int totpoint)
Definition key.cc:2152
float * BKE_key_evaluate_object(Object *ob, int *r_totelem)
Definition key.cc:1644
static void do_mesh_key(Object *ob, Key *key, char *out, const int tot)
Definition key.cc:1393
static char * key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **freedata)
Definition key.cc:628
static void keyblock_data_convert_to_lattice(const float(*fp)[3], BPoint *bpoint, const int totpoint)
Definition key.cc:2026
static void do_latt_key(Object *ob, Key *key, char *out, const int tot)
Definition key.cc:1485
static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode)
Definition key.cc:700
static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition key.cc:125
void BKE_keyblock_update_from_lattice(const Lattice *lt, KeyBlock *kb)
Definition key.cc:1989
int BKE_keyblock_element_count(const Key *key)
Definition key.cc:1663
#define KEY_MODE_DUMMY
Definition key.cc:238
static void rel_flerp(int tot, float *in, const float *ref, const float *out, float fac)
Definition key.cc:619
static float ** keyblock_get_per_block_weights(Object *ob, Key *key, WeightsArrayCache *cache)
Definition key.cc:1348
Key ** BKE_key_from_object_p(Object *ob)
Definition key.cc:1815
void BKE_keyblock_data_set_with_mat4(Key *key, const int shape_index, const Span< float3 > coords, const float4x4 &transform)
Definition key.cc:1707
static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, const int tot)
Definition key.cc:1420
void key_curve_position_weights(float t, float data[4], KeyInterpolationType type)
Definition key.cc:341
Key * BKE_key_from_id(ID *id)
Definition key.cc:1804
KeyBlock * BKE_keyblock_find_uid(Key *key, const int uid)
Definition key.cc:1954
void key_curve_tangent_weights(float t, float data[4], KeyInterpolationType type)
Definition key.cc:384
static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl)
Definition key.cc:460
void BKE_key_sort(Key *key)
Definition key.cc:310
bool BKE_keyblock_is_basis(const Key *key, const int index)
Definition key.cc:2388
static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const int start, int end, char *out, const int tot)
Definition key.cc:835
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1824
static void shapekey_free_data(ID *id)
Definition key.cc:90
void key_curve_normal_weights(float t, float data[4], KeyInterpolationType type)
Definition key.cc:424
static void shapekey_blend_read_after_liblink(BlendLibReader *, ID *id)
Definition key.cc:197
#define IPO_BPOINT
Definition key.cc:152
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static char faces[256]
void normals_calc_corners(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int > corner_edges, GroupedSpan< int > vert_to_face_map, Span< float3 > face_normals, Span< bool > sharp_edges, Span< bool > sharp_faces, Span< short2 > custom_normals, CornerNormalSpaceArray *r_fan_spaces, MutableSpan< float3 > r_corner_normals)
void normals_calc_verts(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, Span< float3 > face_normals, MutableSpan< float3 > vert_normals)
void normals_calc_faces(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, MutableSpan< float3 > face_normals)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
float co[3]
CustomData vdata
float vec[4]
float vec[3][3]
struct Key * key
ListBase nurb
short ob_type
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
char name[66]
Definition DNA_ID.h:415
struct KeyBlock * prev
char name[64]
float slidermax
float slidermin
float curval
struct KeyBlock * next
char vgroup[64]
short relative
void * data
ID * from
int totkey
float ctime
char elemstr[32]
int uidgen
int elemsize
char type
ListBase block
KeyBlock * refkey
struct Key * key
struct MDeformVert * dvert
struct BPoint * def
void * last
void * first
MeshRuntimeHandle * runtime
struct Key * key
int verts_num
struct Nurb * next
BezTriple * bezt
BPoint * bp
int num_defgroup_weights
Definition key.cc:244
float ** defgroup_weights
Definition key.cc:245
i
Definition text_draw.cc:230
uint len
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4227
uint8_t flag
Definition wm_window.cc:139