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