Blender V4.5
rna_action.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10
11#include "DNA_action_types.h"
12#include "DNA_anim_types.h"
13#include "DNA_scene_types.h"
14
15#include "BLT_translation.hh"
16
17#include "BKE_action.hh"
18#include "BKE_blender.hh"
19#include "BKE_report.hh"
20
21#include "RNA_access.hh"
22#include "RNA_define.hh"
23#include "RNA_enum_types.hh"
24
25#include "rna_internal.hh"
26
27#include "ANIM_action.hh"
28
29#include "WM_types.hh"
30
31using namespace blender;
32
33/* Disabled for now, see comment in `rna_def_action_layer()` for more info. */
34#if 0
35const EnumPropertyItem rna_enum_layer_mix_mode_items[] = {
36 {int(animrig::Layer::MixMode::Replace),
37 "REPLACE",
38 0,
39 "Replace",
40 "Channels in this layer override the same channels from underlying layers"},
41 {int(animrig::Layer::MixMode::Offset),
42 "OFFSET",
43 0,
44 "Offset",
45 "Channels in this layer are added to underlying layers as sequential operations"},
46 {int(animrig::Layer::MixMode::Add),
47 "ADD",
48 0,
49 "Add",
50 "Channels in this layer are added to underlying layers on a per-channel basis"},
51 {int(animrig::Layer::MixMode::Subtract),
52 "SUBTRACT",
53 0,
54 "Subtract",
55 "Channels in this layer are subtracted to underlying layers on a per-channel basis"},
56 {int(animrig::Layer::MixMode::Multiply),
57 "MULTIPLY",
58 0,
59 "Multiply",
60 "Channels in this layer are multiplied with underlying layers on a per-channel basis"},
61 {0, nullptr, 0, nullptr, nullptr},
62};
63#endif
64
66 {int(animrig::Strip::Type::Keyframe),
67 "KEYFRAME",
68 0,
69 "Keyframe",
70 "Strip containing keyframes on F-Curves"},
71 {0, nullptr, 0, nullptr, nullptr},
72};
73
74/* Cannot use rna_enum_dummy_DEFAULT_items because the UNSPECIFIED entry needs
75 * to exist as it is the default. */
77 {0,
78 "UNSPECIFIED",
79 ICON_NONE,
80 "Unspecified",
81 "Not yet specified. When this slot is first assigned to a data-block, this will be set to "
82 "the type of that data-block"},
83 {0, nullptr, 0, nullptr, nullptr},
84};
85
86#ifdef RNA_RUNTIME
87
88# include <algorithm>
89
90# include "BLI_math_base.h"
91# include "BLI_string.h"
92# include "BLI_string_utf8.h"
93
94# include "BKE_fcurve.hh"
95# include "BKE_main.hh"
96# include "BKE_report.hh"
97
98# include "DEG_depsgraph.hh"
99
100# include "ANIM_action.hh"
101# include "ANIM_animdata.hh"
102# include "ED_anim_api.hh"
103
104# include "WM_api.hh"
105
106# include "UI_interface_icons.hh"
107
108# include "ANIM_action_legacy.hh"
109# include "ANIM_keyframing.hh"
110
111# include <fmt/format.h>
112
113static animrig::Action &rna_action(const PointerRNA *ptr)
114{
115 return reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
116}
117
118static animrig::Slot &rna_data_slot(const PointerRNA *ptr)
119{
120 BLI_assert(ptr->type == &RNA_ActionSlot);
121 return reinterpret_cast<ActionSlot *>(ptr->data)->wrap();
122}
123
124static animrig::Layer &rna_data_layer(const PointerRNA *ptr)
125{
126 return reinterpret_cast<ActionLayer *>(ptr->data)->wrap();
127}
128
129static animrig::Strip &rna_data_strip(const PointerRNA *ptr)
130{
131 return reinterpret_cast<ActionStrip *>(ptr->data)->wrap();
132}
133
134/* Disabled for now, see comment in `rna_def_action_layer()` for more info. */
135# if 0
136static void rna_Action_tag_animupdate(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
137{
138 animrig::Action &action = rna_action(ptr);
140}
141# endif
142
143static animrig::Channelbag &rna_data_channelbag(const PointerRNA *ptr)
144{
145 return reinterpret_cast<ActionChannelbag *>(ptr->data)->wrap();
146}
147
148template<typename T>
151 Span<T *> items)
152{
153 rna_iterator_array_begin(iter, ptr, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
154}
155
156template<typename T>
159 MutableSpan<T *> items)
160{
161 rna_iterator_array_begin(iter, ptr, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
162}
163
164static PointerRNA rna_ActionSlots_active_get(PointerRNA *ptr)
165{
166 animrig::Action &action = rna_action(ptr);
167 animrig::Slot *active_slot = action.slot_active_get();
168
169 if (!active_slot) {
170 return PointerRNA_NULL;
171 }
172 return RNA_pointer_create_discrete(&action.id, &RNA_ActionSlot, active_slot);
173}
174
175static void rna_ActionSlots_active_set(PointerRNA *ptr,
176 PointerRNA value,
177 struct ReportList * /*reports*/)
178{
179 animrig::Action &action = rna_action(ptr);
180
181 if (value.data) {
182 animrig::Slot &slot = rna_data_slot(&value);
183 action.slot_active_set(slot.handle);
184 }
185 else {
187 }
188}
189
190static ActionSlot *rna_Action_slots_new(
191 bAction *dna_action, Main *bmain, bContext *C, ReportList *reports, int type, const char *name)
192{
193 animrig::Action &action = dna_action->wrap();
194
195 if (!action.is_action_layered()) {
197 RPT_ERROR,
198 "Cannot add slots to a legacy Action '%s'. Convert it to a layered Action first.",
199 action.id.name + 2);
200 return nullptr;
201 }
202
203 if (name[0] == 0) {
204 BKE_reportf(reports, RPT_ERROR, "Invalid slot name '%s': name must not be empty.", name);
205 return nullptr;
206 }
207
208 animrig::Slot *slot = &action.slot_add_for_id_type(ID_Type(type));
209 action.slot_display_name_set(*bmain, *slot, name);
210
212 return slot;
213}
214
215void rna_Action_slots_remove(bAction *dna_action,
216 bContext *C,
218 PointerRNA *slot_ptr)
219{
220 animrig::Action &action = dna_action->wrap();
221 animrig::Slot &slot = rna_data_slot(slot_ptr);
222 if (!action.slot_remove(slot)) {
223 BKE_report(reports, RPT_ERROR, "This slot does not belong to this Action");
224 return;
225 }
226
227 slot_ptr->invalidate();
230}
231
232static void rna_iterator_action_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
233{
234 animrig::Action &action = rna_action(ptr);
235 rna_iterator_array_begin(iter, ptr, action.layers());
236}
237
238static int rna_iterator_action_layers_length(PointerRNA *ptr)
239{
240 animrig::Action &action = rna_action(ptr);
241 return action.layers().size();
242}
243
244static ActionLayer *rna_Action_layers_new(bAction *dna_action,
245 bContext *C,
247 const char *name)
248{
249 animrig::Action &action = dna_action->wrap();
250
251 if (!action.is_action_layered()) {
253 RPT_ERROR,
254 "Cannot add layers to a legacy Action '%s'. Convert it to a layered Action first.",
255 action.id.name + 2);
256 return nullptr;
257 }
258
259 if (action.layers().size() >= 1) {
260 /* Not allowed to have more than one layer, for now. This limitation is in
261 * place until working with multiple animated IDs is fleshed out better. */
262 BKE_report(reports, RPT_ERROR, "An Action may not have more than one layer");
263 return nullptr;
264 }
265
266 animrig::Layer &layer = action.layer_add(name);
267
269 return &layer;
270}
271
272void rna_Action_layers_remove(bAction *dna_action,
273 bContext *C,
275 PointerRNA *layer_ptr)
276{
277 animrig::Action &action = dna_action->wrap();
278 animrig::Layer &layer = rna_data_layer(layer_ptr);
279 if (!action.layer_remove(layer)) {
280 BKE_report(reports, RPT_ERROR, "This layer does not belong to this Action");
281 return;
282 }
283
284 layer_ptr->invalidate();
287}
288
289static void rna_iterator_animation_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
290{
291 animrig::Action &action = rna_action(ptr);
292 rna_iterator_array_begin(iter, ptr, action.slots());
293}
294
295static int rna_iterator_animation_slots_length(PointerRNA *ptr)
296{
297 animrig::Action &action = rna_action(ptr);
298 return action.slots().size();
299}
300
301static std::optional<std::string> rna_ActionSlot_path(const PointerRNA *ptr)
302{
303 animrig::Slot &slot = rna_data_slot(ptr);
304
305 char identifier_esc[sizeof(slot.identifier) * 2];
306 BLI_str_escape(identifier_esc, slot.identifier, sizeof(identifier_esc));
307 return fmt::format("slots[\"{}\"]", identifier_esc);
308}
309
310int rna_ActionSlot_target_id_type_icon_get(PointerRNA *ptr)
311{
312 animrig::Slot &slot = rna_data_slot(ptr);
313 return UI_icon_from_idcode(slot.idtype);
314}
315
316/* Name functions that ignore the first two ID characters */
317void rna_ActionSlot_name_display_get(PointerRNA *ptr, char *value)
318{
319 animrig::Slot &slot = rna_data_slot(ptr);
321}
322
323int rna_ActionSlot_name_display_length(PointerRNA *ptr)
324{
325 animrig::Slot &slot = rna_data_slot(ptr);
326 return slot.identifier_without_prefix().size();
327}
328
329static void rna_ActionSlot_name_display_set(PointerRNA *ptr, const char *name)
330{
331 animrig::Action &action = rna_action(ptr);
332 animrig::Slot &slot = rna_data_slot(ptr);
333 const StringRef name_ref(name);
334
335 if (name_ref.is_empty()) {
336 WM_global_report(RPT_ERROR, "Action slot display names cannot be empty");
337 return;
338 }
339
340 action.slot_display_name_define(slot, name);
341}
342
343static void rna_ActionSlot_identifier_set(PointerRNA *ptr, const char *identifier)
344{
345 animrig::Action &action = rna_action(ptr);
346 animrig::Slot &slot = rna_data_slot(ptr);
347 const StringRef identifier_ref(identifier);
348
349 if (identifier_ref.size() < animrig::Slot::identifier_length_min) {
350 WM_global_report(RPT_ERROR, "Action slot identifiers should be at least three characters");
351 return;
352 }
353
354 /* Sanity check. These should never be out of sync in higher-level code. */
356
357 const std::string identifier_with_correct_prefix = slot.idtype_string() +
358 identifier_ref.substr(2);
359
360 if (identifier_with_correct_prefix != identifier_ref) {
363 "Attempted to set slot identifier to \"%s\", but the type prefix doesn't match the "
364 "slot's 'target_id_type' \"%s\". Setting to \"%s\" instead.\n",
365 identifier,
366 slot.idtype_string().c_str(),
367 identifier_with_correct_prefix.c_str());
368 }
369
370 action.slot_identifier_define(slot, identifier_with_correct_prefix);
371}
372
373static void rna_ActionSlot_identifier_update(Main *bmain, Scene *, PointerRNA *ptr)
374{
375 animrig::Action &action = rna_action(ptr);
376 animrig::Slot &slot = rna_data_slot(ptr);
377 action.slot_identifier_propagate(*bmain, slot);
378}
379
380static CollectionVector rna_ActionSlot_users(struct ActionSlot *self, Main *bmain)
381{
382 animrig::Slot &slot = self->wrap();
383 const Span<ID *> slot_users = slot.users(*bmain);
384
386 vector.items.resize(slot_users.size());
387 for (const int i : slot_users.index_range()) {
388 vector.items[i] = RNA_id_pointer_create(slot_users[i]);
389 }
390
391 return vector;
392}
393
394static ActionSlot *rna_ActionSlot_duplicate(ID *action_id, const ActionSlot *self)
395{
396 animrig::Action &action = reinterpret_cast<bAction *>(action_id)->wrap();
397 const animrig::Slot &source_slot = self->wrap();
398
399 animrig::Slot &dupli_slot = animrig::duplicate_slot(action, source_slot);
400 return &dupli_slot;
401}
402
403static std::optional<std::string> rna_ActionLayer_path(const PointerRNA *ptr)
404{
405 animrig::Layer &layer = rna_data_layer(ptr);
406
407 char name_esc[sizeof(layer.name) * 2];
408 BLI_str_escape(name_esc, layer.name, sizeof(name_esc));
409 return fmt::format("layers[\"{}\"]", name_esc);
410}
411
412static void rna_iterator_ActionLayer_strips_begin(CollectionPropertyIterator *iter,
414{
415 animrig::Layer &layer = rna_data_layer(ptr);
416 rna_iterator_array_begin(iter, ptr, layer.strips());
417}
418
419static int rna_iterator_ActionLayer_strips_length(PointerRNA *ptr)
420{
421 animrig::Layer &layer = rna_data_layer(ptr);
422 return layer.strips().size();
423}
424
425static StructRNA *rna_ActionStrip_refine(PointerRNA *ptr)
426{
427 animrig::Strip &strip = static_cast<ActionStrip *>(ptr->data)->wrap();
428
429 switch (strip.type()) {
430 case animrig::Strip::Type::Keyframe:
431 return &RNA_ActionKeyframeStrip;
432 }
433 return &RNA_UnknownType;
434}
435
436ActionStrip *rna_ActionStrips_new(
437 ID *dna_action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, const int type)
438{
439 const animrig::Strip::Type strip_type = animrig::Strip::Type(type);
440
441 animrig::Layer &layer = dna_layer->wrap();
442
443 if (layer.strips().size() >= 1) {
444 /* Not allowed to have more than one strip, for now. This limitation is in
445 * place until working with layers is fleshed out better. */
446 BKE_report(reports, RPT_ERROR, "A layer may not have more than one strip");
447 return nullptr;
448 }
449
450 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
451 animrig::Strip &strip = layer.strip_add(action, strip_type);
452
454 return &strip;
455}
456
457void rna_ActionStrips_remove(
458 ID *action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, PointerRNA *strip_ptr)
459{
460 animrig::Action &action = reinterpret_cast<bAction *>(action_id)->wrap();
461 animrig::Layer &layer = dna_layer->wrap();
462 animrig::Strip &strip = rna_data_strip(strip_ptr);
463 if (!layer.strip_remove(action, strip)) {
464 BKE_report(reports, RPT_ERROR, "This strip does not belong to this layer");
465 return;
466 }
467
468 strip_ptr->invalidate();
471}
472
473static std::optional<std::string> rna_ActionStrip_path(const PointerRNA *ptr)
474{
475 animrig::Action &action = rna_action(ptr);
476 animrig::Strip &strip_to_find = rna_data_strip(ptr);
477
478 for (animrig::Layer *layer : action.layers()) {
479 Span<animrig::Strip *> strips = layer->strips();
480 const int index = strips.first_index_try(&strip_to_find);
481 if (index < 0) {
482 continue;
483 }
484
485 PointerRNA layer_ptr = RNA_pointer_create_discrete(&action.id, &RNA_ActionLayer, layer);
486 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
487 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
488 const std::string strip_path = fmt::format("{}.strips[{}]", *layer_path, index);
489 return strip_path;
490 }
491
492 return std::nullopt;
493}
494
495static void rna_iterator_keyframestrip_channelbags_begin(CollectionPropertyIterator *iter,
497{
498 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
499 animrig::Strip &strip = rna_data_strip(ptr);
501 iter, ptr, strip.data<animrig::StripKeyframeData>(action).channelbags());
502}
503
504static int rna_iterator_keyframestrip_channelbags_length(PointerRNA *ptr)
505{
506 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
507 animrig::Strip &strip = rna_data_strip(ptr);
508 return strip.data<animrig::StripKeyframeData>(action).channelbags().size();
509}
510
511static ActionChannelbag *rna_Channelbags_new(ID *dna_action_id,
512 ActionStrip *dna_strip,
513 bContext *C,
515 ActionSlot *dna_slot)
516{
517 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
518 animrig::Strip &strip = dna_strip->wrap();
520 animrig::Slot &slot = dna_slot->wrap();
521
522 if (strip_data.channelbag_for_slot(slot) != nullptr) {
523 BKE_report(reports, RPT_ERROR, "A channelbag for this slot already exists");
524 return nullptr;
525 }
526
527 animrig::Channelbag &channelbag = strip_data.channelbag_for_slot_add(slot);
528
530 /* No need to tag the depsgraph, as there is no new animation yet. */
531
532 return &channelbag;
533}
534
535static void rna_Channelbags_remove(ID *dna_action_id,
536 ActionStrip *dna_strip,
537 bContext *C,
539 PointerRNA *channelbag_ptr)
540{
541 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
542 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
543 action);
544 animrig::Channelbag &channelbag = rna_data_channelbag(channelbag_ptr);
545
546 if (!strip_data.channelbag_remove(channelbag)) {
547 BKE_report(reports, RPT_ERROR, "This channelbag does not belong to this strip");
548 return;
549 }
550
551 channelbag_ptr->invalidate();
554}
555
556static bool rna_ActionStrip_key_insert(ID *dna_action_id,
557 ActionStrip *dna_strip,
558 Main *bmain,
560 ActionSlot *dna_slot,
561 const char *rna_path,
562 const int array_index,
563 const float value,
564 const float time)
565{
566 if (dna_slot == nullptr) {
567 BKE_report(reports, RPT_ERROR, "Slot cannot be None");
568 return false;
569 }
570
571 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
572 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
573 action);
574 const animrig::Slot &slot = dna_slot->wrap();
576
578 bmain, slot, {rna_path, array_index}, {time, value}, settings, INSERTKEY_NOFLAGS);
579
581 if (ok) {
582 DEG_id_tag_update_ex(bmain, dna_action_id, ID_RECALC_ANIMATION);
583 }
584
585 return ok;
586}
587
588std::optional<std::string> rna_Channelbag_path(const PointerRNA *ptr)
589{
590 animrig::Action &action = rna_action(ptr);
591 animrig::Channelbag &cbag_to_find = rna_data_channelbag(ptr);
592
593 for (animrig::Layer *layer : action.layers()) {
594 for (int64_t strip_index : layer->strips().index_range()) {
595 const animrig::Strip *strip = layer->strip(strip_index);
596 if (strip->type() != animrig::Strip::Type::Keyframe) {
597 continue;
598 }
599
601 action);
602 const int64_t index = strip_data.find_channelbag_index(cbag_to_find);
603 if (index < 0) {
604 continue;
605 }
606
607 PointerRNA layer_ptr = RNA_pointer_create_discrete(&action.id, &RNA_ActionLayer, layer);
608 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
609 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
610 return fmt::format("{}.strips[{}].channelbags[{}]", *layer_path, strip_index, index);
611 }
612 }
613
614 return std::nullopt;
615}
616
617static PointerRNA rna_Channelbag_slot_get(PointerRNA *ptr)
618{
619 animrig::Action &action = rna_action(ptr);
620 animrig::Channelbag &channelbag = rna_data_channelbag(ptr);
621 animrig::Slot *slot = action.slot_for_handle(channelbag.slot_handle);
622 BLI_assert(slot);
623
624 return RNA_pointer_create_with_parent(*ptr, &RNA_ActionSlot, slot);
625}
626
627static void rna_iterator_Channelbag_fcurves_begin(CollectionPropertyIterator *iter,
629{
630 animrig::Channelbag &bag = rna_data_channelbag(ptr);
632}
633
634static int rna_iterator_Channelbag_fcurves_length(PointerRNA *ptr)
635{
636 animrig::Channelbag &bag = rna_data_channelbag(ptr);
637 return bag.fcurves().size();
638}
639
640static FCurve *rna_Channelbag_fcurve_new(ActionChannelbag *dna_channelbag,
641 Main *bmain,
643 const char *data_path,
644 const int index)
645{
646 BLI_assert(data_path != nullptr);
647 if (data_path[0] == '\0') {
648 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
649 return nullptr;
650 }
651
652 animrig::Channelbag &self = dna_channelbag->wrap();
653 FCurve *fcurve = self.fcurve_create_unique(bmain, {data_path, index});
654 if (!fcurve) {
656 RPT_ERROR,
657 "F-Curve '%s[%d]' already exists in this channelbag",
658 data_path,
659 index);
660 return nullptr;
661 }
662 return fcurve;
663}
664
665static FCurve *rna_Channelbag_fcurve_find(ActionChannelbag *dna_channelbag,
667 const char *data_path,
668 const int index)
669{
670 if (data_path[0] == '\0') {
671 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
672 return nullptr;
673 }
674
675 animrig::Channelbag &self = dna_channelbag->wrap();
676 return self.fcurve_find({data_path, index});
677}
678
679static void rna_Channelbag_fcurve_remove(ID *dna_action_id,
680 ActionChannelbag *dna_channelbag,
681 bContext *C,
683 PointerRNA *fcurve_ptr)
684{
685 animrig::Channelbag &self = dna_channelbag->wrap();
686 FCurve *fcurve = static_cast<FCurve *>(fcurve_ptr->data);
687
688 if (!self.fcurve_remove(*fcurve)) {
689 BKE_reportf(reports, RPT_ERROR, "F-Curve not found");
690 return;
691 }
692
695}
696
697static void rna_Channelbag_fcurve_clear(ID *dna_action_id,
698 ActionChannelbag *dna_channelbag,
699 bContext *C)
700{
701 dna_channelbag->wrap().fcurves_clear();
704}
705
706static void rna_iterator_Channelbag_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
707{
708 animrig::Channelbag &bag = rna_data_channelbag(ptr);
710}
711
712static int rna_iterator_Channelbag_groups_length(PointerRNA *ptr)
713{
714 animrig::Channelbag &bag = rna_data_channelbag(ptr);
715 return bag.channel_groups().size();
716}
717
718static bActionGroup *rna_Channelbag_group_new(ActionChannelbag *dna_channelbag, const char *name)
719{
720 BLI_assert(name != nullptr);
721
722 animrig::Channelbag &self = dna_channelbag->wrap();
723 return &self.channel_group_create(name);
724}
725
726static void rna_Channelbag_group_remove(ActionChannelbag *dna_channelbag,
728 PointerRNA *agrp_ptr)
729{
730 animrig::Channelbag &self = dna_channelbag->wrap();
731
732 bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
733
734 if (!self.channel_group_remove(*agrp)) {
736 RPT_ERROR,
737 "Could not remove the F-Curve Group from the collection because it doesn't exist "
738 "in the collection");
739 return;
740 }
741
742 agrp_ptr->invalidate();
744}
745
746static ActionChannelbag *rna_ActionStrip_channelbag(ID *dna_action_id,
749 const ActionSlot *dna_slot,
750 const bool ensure)
751{
752 if (!dna_slot) {
753 BKE_report(reports, RPT_ERROR, "Cannot return channelbag when slot is None");
754 return nullptr;
755 }
756
757 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
758 animrig::StripKeyframeData &strip_data = self->wrap().data<animrig::StripKeyframeData>(action);
759 const animrig::Slot &slot = dna_slot->wrap();
760
761 if (ensure) {
762 return &strip_data.channelbag_for_slot_ensure(slot);
763 }
764 return strip_data.channelbag_for_slot(slot);
765}
766
777struct ActionGroupChannelsIterator {
778 /* Which kind of iterator it is. */
779 enum {
780 ARRAY,
781 LISTBASE,
782 } tag;
783
784 union {
785 ArrayIterator array;
786 ListBaseIterator listbase;
787 };
788};
789
790static void rna_ActionGroup_channels_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
791{
792 bActionGroup *group = (bActionGroup *)ptr->data;
793
794 ActionGroupChannelsIterator *custom_iter = MEM_callocN<ActionGroupChannelsIterator>(__func__);
795
796 iter->internal.custom = custom_iter;
797
798 /* We handle both the listbase (legacy action) and array (layered action)
799 * cases below. The code for each is based on the code in
800 * `rna_iterator_listbase_begin()` and `rna_iterator_array_begin()`,
801 * respectively. */
802
803 /* Group from a legacy action. */
804 if (group->wrap().is_legacy()) {
805 custom_iter->tag = ActionGroupChannelsIterator::LISTBASE;
806 custom_iter->listbase.link = static_cast<Link *>(group->channels.first);
807
808 iter->valid = custom_iter->listbase.link != nullptr;
809 return;
810 }
811
812 /* Group from a layered action. */
813 animrig::Channelbag &cbag = group->channelbag->wrap();
814
815 custom_iter->tag = ActionGroupChannelsIterator::ARRAY;
816 custom_iter->array.ptr = reinterpret_cast<char *>(cbag.fcurve_array + group->fcurve_range_start);
817 custom_iter->array.endptr = reinterpret_cast<char *>(
818 cbag.fcurve_array + group->fcurve_range_start + group->fcurve_range_length);
819 custom_iter->array.itemsize = sizeof(FCurve *);
820 custom_iter->array.length = group->fcurve_range_length;
821
822 iter->valid = group->fcurve_range_length > 0;
823}
824
825static void rna_ActionGroup_channels_end(CollectionPropertyIterator *iter)
826{
828}
829
830static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter)
831{
832 BLI_assert(iter->internal.custom != nullptr);
833 BLI_assert(iter->valid);
834
835 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
836 iter->internal.custom);
837
838 /* The code for both cases here is written based on the code in
839 * `rna_iterator_array_next()` and `rna_iterator_listbase_next()`,
840 * respectively. */
841 switch (custom_iter->tag) {
842 case ActionGroupChannelsIterator::ARRAY: {
843 custom_iter->array.ptr += custom_iter->array.itemsize;
844 iter->valid = (custom_iter->array.ptr != custom_iter->array.endptr);
845 break;
846 }
847 case ActionGroupChannelsIterator::LISTBASE: {
848 FCurve *fcurve = (FCurve *)custom_iter->listbase.link;
849 bActionGroup *grp = fcurve->grp;
850 /* Only continue if the next F-Curve (if existent) belongs in the same
851 * group. */
852 if ((fcurve->next) && (fcurve->next->grp == grp)) {
853 custom_iter->listbase.link = custom_iter->listbase.link->next;
854 iter->valid = (custom_iter->listbase.link != nullptr);
855 }
856 else {
857 custom_iter->listbase.link = nullptr;
858 iter->valid = false;
859 }
860 break;
861 }
862 }
863}
864
865static PointerRNA rna_ActionGroup_channels_get(CollectionPropertyIterator *iter)
866{
867 BLI_assert(iter->internal.custom != nullptr);
868 BLI_assert(iter->valid);
869 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
870 iter->internal.custom);
871
872 FCurve *fcurve;
873 switch (custom_iter->tag) {
874 case ActionGroupChannelsIterator::ARRAY:
875 fcurve = *reinterpret_cast<FCurve **>(custom_iter->array.ptr);
876 break;
877 case ActionGroupChannelsIterator::LISTBASE:
878 fcurve = reinterpret_cast<FCurve *>(custom_iter->listbase.link);
879 break;
880 }
881
882 return RNA_pointer_create_with_parent(iter->parent, &RNA_FCurve, fcurve);
883}
884
885/* Use the backward-compatible API only when we're working with the action as a
886 * layered action. */
887static bool use_backward_compatible_api(animrig::Action &action)
888{
890}
891
892static void rna_iterator_Action_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
893{
894 animrig::Action &action = rna_action(ptr);
895
896 if (use_backward_compatible_api(action)) {
898 if (!channelbag) {
899 return;
900 }
901 rna_iterator_array_begin(iter, ptr, channelbag->channel_groups());
902 }
903 else {
904 rna_iterator_listbase_begin(iter, ptr, &action.groups, nullptr);
905 }
906}
907static void rna_iterator_Action_groups_next(CollectionPropertyIterator *iter)
908{
909 animrig::Action &action = rna_action(&iter->parent);
910 if (use_backward_compatible_api(action)) {
912 }
913 else {
915 }
916}
917static void rna_iterator_Action_groups_end(CollectionPropertyIterator *iter)
918{
919 animrig::Action &action = rna_action(&iter->parent);
920 if (use_backward_compatible_api(action)) {
922 }
923 else {
925 }
926}
927static PointerRNA rna_iterator_Action_groups_get(CollectionPropertyIterator *iter)
928{
929 animrig::Action &action = rna_action(&iter->parent);
930 bActionGroup *group;
931 if (use_backward_compatible_api(action)) {
932 group = static_cast<bActionGroup *>(rna_iterator_array_dereference_get(iter));
933 }
934 else {
935 group = static_cast<bActionGroup *>(rna_iterator_listbase_get(iter));
936 }
937
938 return RNA_pointer_create_with_parent(iter->parent, &RNA_ActionGroup, group);
939}
940static int rna_iterator_Action_groups_length(PointerRNA *ptr)
941{
942 animrig::Action &action = rna_action(ptr);
943 if (use_backward_compatible_api(action)) {
945 if (!channelbag) {
946 return 0;
947 }
948 return channelbag->channel_groups().size();
949 }
950 return BLI_listbase_count(&action.groups);
951}
952
953static bActionGroup *rna_Action_groups_new(bAction *act, const char name[])
954{
955 bActionGroup *group;
956
957 animrig::Action &action = act->wrap();
958 if (use_backward_compatible_api(action)) {
960 group = &channelbag.channel_group_create(name);
961 }
962 else {
963 group = action_groups_add_new(act, name);
964 }
965
966 /* I (Sybren) expected that the commented-out notifier below was missing.
967 * However, the animation filtering code (`animfilter_act_group()`) hides
968 * empty groups. Because this group is newly created, it's not shown in the
969 * UI, and thus there is no need to send notifiers.
970 *
971 * WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_ADDED, nullptr); */
972
973 return group;
974}
975
976static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerRNA *agrp_ptr)
977{
978 bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
979 BLI_assert(agrp); /* Ensured by RNA flag PROP_NEVER_NULL. */
980
981 animrig::Action &action = act->wrap();
982 if (use_backward_compatible_api(action)) {
984 if (!channelbag || !channelbag->channel_group_remove(*agrp)) {
986 RPT_ERROR,
987 "Action group '%s' not found in action '%s'",
988 agrp->name,
989 act->id.name + 2);
990 }
991
992 /* Removing a group also removes its F-Curves. */
995
996 return;
997 }
998
999 FCurve *fcu, *fcn;
1000
1001 /* try to remove the F-Curve from the action */
1002 if (BLI_remlink_safe(&act->groups, agrp) == false) {
1004 RPT_ERROR,
1005 "Action group '%s' not found in action '%s'",
1006 agrp->name,
1007 act->id.name + 2);
1008 return;
1009 }
1010
1011 /* Move every one of the group's F-Curves out into the Action again. */
1012 for (fcu = static_cast<FCurve *>(agrp->channels.first); (fcu) && (fcu->grp == agrp); fcu = fcn) {
1013 fcn = fcu->next;
1014
1015 /* remove from group */
1017
1018 /* tack onto the end */
1019 BLI_addtail(&act->curves, fcu);
1020 }
1021
1022 MEM_freeN(agrp);
1023 agrp_ptr->invalidate();
1024
1027}
1028
1029static void rna_iterator_Action_fcurves_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
1030{
1031 animrig::Action &action = rna_action(ptr);
1032
1033 if (use_backward_compatible_api(action)) {
1035 if (!channelbag) {
1036 return;
1037 }
1038 rna_iterator_array_begin(iter, ptr, channelbag->fcurves());
1039 }
1040 else {
1041 rna_iterator_listbase_begin(iter, ptr, &action.curves, nullptr);
1042 }
1043}
1044static void rna_iterator_Action_fcurves_next(CollectionPropertyIterator *iter)
1045{
1046 animrig::Action &action = rna_action(&iter->parent);
1047 if (use_backward_compatible_api(action)) {
1049 }
1050 else {
1052 }
1053}
1054static void rna_iterator_Action_fcurves_end(CollectionPropertyIterator *iter)
1055{
1056 animrig::Action &action = rna_action(&iter->parent);
1057 if (use_backward_compatible_api(action)) {
1059 }
1060 else {
1062 }
1063}
1064static PointerRNA rna_iterator_Action_fcurves_get(CollectionPropertyIterator *iter)
1065{
1066 animrig::Action &action = rna_action(&iter->parent);
1067 FCurve *fcurve;
1068 if (use_backward_compatible_api(action)) {
1069 fcurve = static_cast<FCurve *>(rna_iterator_array_dereference_get(iter));
1070 }
1071 else {
1072 fcurve = static_cast<FCurve *>(rna_iterator_listbase_get(iter));
1073 }
1074
1075 return RNA_pointer_create_with_parent(iter->parent, &RNA_FCurve, fcurve);
1076}
1077static int rna_iterator_Action_fcurves_length(PointerRNA *ptr)
1078{
1079 animrig::Action &action = rna_action(ptr);
1080 if (use_backward_compatible_api(action)) {
1082 if (!channelbag) {
1083 return 0;
1084 }
1085 return channelbag->fcurves().size();
1086 }
1087 return BLI_listbase_count(&action.curves);
1088}
1089
1090static FCurve *rna_Action_fcurve_new(bAction *act,
1091 Main *bmain,
1093 const char *data_path,
1094 int index,
1095 const char *group)
1096{
1097 BLI_assert(data_path != nullptr);
1098 if (data_path[0] == '\0') {
1099 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
1100 return nullptr;
1101 }
1102
1103 animrig::FCurveDescriptor fcurve_descriptor = {data_path, index};
1104 if (group && group[0] != '\0') {
1105 fcurve_descriptor.channel_group = group;
1106 }
1107
1108 animrig::Action &action = act->wrap();
1109 if (use_backward_compatible_api(action)) {
1110 /* Add the F-Curve to the channelbag for the first slot. */
1112 FCurve *fcurve = channelbag.fcurve_create_unique(bmain, fcurve_descriptor);
1113 if (!fcurve) {
1114 /* The only reason fcurve_create_unique() returns nullptr is when the curve
1115 * already exists. */
1116
1117 /* This is using the same error as below, as this is mimicking the legacy API. */
1119 RPT_ERROR,
1120 "F-Curve '%s[%d]' already exists in action '%s'",
1121 data_path,
1122 index,
1123 act->id.name + 2);
1124 return nullptr;
1125 }
1126
1127 return fcurve;
1128 }
1129
1130 /* Annoying, check if this exists. */
1131 if (blender::animrig::fcurve_find_in_action(act, fcurve_descriptor)) {
1133 RPT_ERROR,
1134 "F-Curve '%s[%d]' already exists in action '%s'",
1135 data_path,
1136 index,
1137 act->id.name + 2);
1138 return nullptr;
1139 }
1141 bmain,
1142 act,
1143 fcurve_descriptor.channel_group ? fcurve_descriptor.channel_group->c_str() : nullptr,
1144 nullptr,
1145 fcurve_descriptor);
1146}
1147
1148static FCurve *rna_Action_fcurve_find(bAction *act,
1150 const char *data_path,
1151 int index)
1152{
1153 if (data_path[0] == '\0') {
1154 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
1155 return nullptr;
1156 }
1157
1158 animrig::Action &action = act->wrap();
1159 if (use_backward_compatible_api(action)) {
1161 if (!channelbag) {
1162 return nullptr;
1163 }
1164 return channelbag->fcurve_find({data_path, index});
1165 }
1166
1167 /* Returns nullptr if not found. */
1168 return animrig::fcurve_find_in_action(act, {data_path, index});
1169}
1170
1171static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerRNA *fcu_ptr)
1172{
1173 FCurve *fcu = static_cast<FCurve *>(fcu_ptr->data);
1174
1175 animrig::Action &action = act->wrap();
1176 if (use_backward_compatible_api(action)) {
1178 if (!channelbag) {
1179 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1180 return;
1181 }
1182 if (!channelbag->fcurve_remove(*fcu)) {
1183 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1184 return;
1185 }
1186 fcu_ptr->invalidate();
1187
1190
1191 return;
1192 }
1193
1194 if (fcu->grp) {
1195 if (BLI_findindex(&act->groups, fcu->grp) == -1) {
1197 RPT_ERROR,
1198 "F-Curve's action group '%s' not found in action '%s'",
1199 fcu->grp->name,
1200 act->id.name + 2);
1201 return;
1202 }
1203
1205 BKE_fcurve_free(fcu);
1206 fcu_ptr->invalidate();
1207 }
1208 else {
1209 if (BLI_findindex(&act->curves, fcu) == -1) {
1210 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1211 return;
1212 }
1213
1214 BLI_remlink(&act->curves, fcu);
1215 BKE_fcurve_free(fcu);
1216 fcu_ptr->invalidate();
1217 }
1218
1221}
1222
1223static void rna_Action_fcurve_clear(bAction *act)
1224{
1225 animrig::Action &action = act->wrap();
1226 if (use_backward_compatible_api(action)) {
1228 if (!channelbag) {
1229 /* Nothing to clear, so the post-condition of not having F-Curves is fulfilled. */
1230 return;
1231 }
1232 channelbag->fcurves_clear();
1233 }
1234 else {
1236 }
1237
1239}
1240
1241static TimeMarker *rna_Action_pose_markers_new(bAction *act, const char name[])
1242{
1243 TimeMarker *marker = MEM_callocN<TimeMarker>("TimeMarker");
1244 marker->flag = SELECT;
1245 marker->frame = 1;
1246 STRNCPY_UTF8(marker->name, name);
1247 BLI_addtail(&act->markers, marker);
1248 return marker;
1249}
1250
1251static void rna_Action_pose_markers_remove(bAction *act,
1253 PointerRNA *marker_ptr)
1254{
1255 TimeMarker *marker = static_cast<TimeMarker *>(marker_ptr->data);
1256 if (!BLI_remlink_safe(&act->markers, marker)) {
1258 RPT_ERROR,
1259 "Timeline marker '%s' not found in action '%s'",
1260 marker->name,
1261 act->id.name + 2);
1262 return;
1263 }
1264
1265 MEM_freeN(marker);
1266 marker_ptr->invalidate();
1267}
1268
1269static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr)
1270{
1271 bAction *act = (bAction *)ptr->data;
1273 *ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker - 1));
1274}
1275
1276static void rna_Action_active_pose_marker_set(PointerRNA *ptr,
1277 PointerRNA value,
1278 ReportList * /*reports*/)
1279{
1280 bAction *act = (bAction *)ptr->data;
1281 act->active_marker = BLI_findindex(&act->markers, value.data) + 1;
1282}
1283
1284static int rna_Action_active_pose_marker_index_get(PointerRNA *ptr)
1285{
1286 bAction *act = (bAction *)ptr->data;
1287 return std::max(act->active_marker - 1, 0);
1288}
1289
1290static void rna_Action_active_pose_marker_index_set(PointerRNA *ptr, int value)
1291{
1292 bAction *act = (bAction *)ptr->data;
1293 act->active_marker = value + 1;
1294}
1295
1296static void rna_Action_active_pose_marker_index_range(
1297 PointerRNA *ptr, int *min, int *max, int * /*softmin*/, int * /*softmax*/)
1298{
1299 bAction *act = (bAction *)ptr->data;
1300
1301 *min = 0;
1302 *max = max_ii(0, BLI_listbase_count(&act->markers) - 1);
1303}
1304
1305static bool rna_Action_is_empty_get(PointerRNA *ptr)
1306{
1307 animrig::Action &action = rna_action(ptr);
1308 return action.is_empty();
1309}
1310static bool rna_Action_is_action_legacy_get(PointerRNA *ptr)
1311{
1312 return rna_action(ptr).is_action_legacy();
1313}
1314static bool rna_Action_is_action_layered_get(PointerRNA *ptr)
1315{
1316 return rna_action(ptr).is_action_layered();
1317}
1318
1319static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values)
1320{
1321 const float2 frame_range = rna_action(ptr).get_frame_range();
1322 r_values[0] = frame_range[0];
1323 r_values[1] = frame_range[1];
1324}
1325
1326static void rna_Action_frame_range_set(PointerRNA *ptr, const float *values)
1327{
1328 bAction *data = (bAction *)ptr->owner_id;
1329
1330 data->flag |= ACT_FRAME_RANGE;
1331 data->frame_start = values[0];
1332 data->frame_end = values[1];
1333 CLAMP_MIN(data->frame_end, data->frame_start);
1334}
1335
1336static void rna_Action_curve_frame_range_get(PointerRNA *ptr, float *values)
1337{ /* don't include modifiers because they too easily can have very large
1338 * ranges: MINAFRAMEF to MAXFRAMEF. */
1339 const float2 frame_range = rna_action(ptr).get_frame_range_of_keys(false);
1340 values[0] = frame_range[0];
1341 values[1] = frame_range[1];
1342}
1343
1344static void rna_Action_use_frame_range_set(PointerRNA *ptr, bool value)
1345{
1346 animrig::Action &action = rna_action(ptr);
1347
1348 if (value) {
1349 /* If the frame range is blank, initialize it by scanning F-Curves. */
1350 if ((action.frame_start == action.frame_end) && (action.frame_start == 0)) {
1351 const float2 frame_range = action.get_frame_range_of_keys(false);
1352 action.frame_start = frame_range[0];
1353 action.frame_end = frame_range[1];
1354 }
1355
1356 action.flag |= ACT_FRAME_RANGE;
1357 }
1358 else {
1359 action.flag &= ~ACT_FRAME_RANGE;
1360 }
1361}
1362
1363static void rna_Action_start_frame_set(PointerRNA *ptr, float value)
1364{
1365 bAction *data = (bAction *)ptr->owner_id;
1366
1367 data->frame_start = value;
1368 CLAMP_MIN(data->frame_end, data->frame_start);
1369}
1370
1371static void rna_Action_end_frame_set(PointerRNA *ptr, float value)
1372{
1373 bAction *data = (bAction *)ptr->owner_id;
1374
1375 data->frame_end = value;
1376 CLAMP_MAX(data->frame_start, data->frame_end);
1377}
1378
1379static void rna_Action_deselect_keys(bAction *act)
1380{
1381 animrig::action_deselect_keys(act->wrap());
1383}
1384
1385static FCurve *rna_Action_fcurve_ensure_for_datablock(bAction *_self,
1386 Main *bmain,
1388 ID *datablock,
1389 const char *data_path,
1390 const int array_index)
1391{
1392 /* Precondition checks. */
1393 {
1394 if (blender::animrig::get_action(*datablock) != _self) {
1397 "Assign action \"%s\" to \"%s\" before calling this function",
1398 _self->id.name + 2,
1399 datablock->name + 2);
1400 return nullptr;
1401 }
1402
1403 BLI_assert(data_path != nullptr);
1404 if (data_path[0] == '\0') {
1405 BKE_report(reports, RPT_ERROR_INVALID_INPUT, "F-Curve data path empty, invalid argument");
1406 return nullptr;
1407 }
1408 }
1409
1411 bmain, *_self, *datablock, {data_path, array_index});
1412
1414 return &fcurve;
1415}
1416
1422{
1423 ID *srcId = ptr->owner_id;
1424 bAction *dna_action = (bAction *)value.owner_id;
1425
1426 if (!dna_action) {
1427 return false;
1428 }
1429
1430 animrig::Action &action = dna_action->wrap();
1432 /* there can still be actions that will have undefined id-root
1433 * (i.e. floating "action-library" members) which we will not
1434 * be able to resolve an idroot for automatically, so let these through
1435 */
1436 if (action.idroot == 0) {
1437 return true;
1438 }
1439 if (srcId) {
1440 return GS(srcId->name) == action.idroot;
1441 }
1442 }
1443
1444 /* Layered Actions can always be assigned. */
1445 BLI_assert(action.idroot == 0);
1446 return true;
1447}
1448
1454{
1455 SpaceAction *saction = (SpaceAction *)ptr->data;
1456 bAction *action = (bAction *)value.owner_id;
1457
1458 if (!saction) {
1459 /* Unable to determine what this Action is going to be assigned to, so
1460 * reject it for now. This is mostly to have a non-functional refactor of
1461 * this code; personally I (Sybren) wouldn't mind to always return `true` in
1462 * this case. */
1463 return false;
1464 }
1465
1466 switch (saction->mode) {
1467 case SACTCONT_ACTION:
1469 case SACTCONT_SHAPEKEY:
1471 case SACTCONT_GPENCIL:
1472 case SACTCONT_DOPESHEET:
1473 case SACTCONT_MASK:
1474 case SACTCONT_CACHEFILE:
1475 case SACTCONT_TIMELINE:
1476 break;
1477 }
1478
1479 /* Same as above, I (Sybren) wouldn't mind returning `true` here to just
1480 * always show all Actions in an unexpected place. */
1481 return false;
1482}
1483
1488static void reevaluate_fcurve_errors(bAnimContext *ac)
1489{
1490 /* Need to take off the flag before filtering, else the filter code would skip the FCurves, which
1491 * have not yet been validated. */
1492 const bool filtering_enabled = ac->ads->filterflag & ADS_FILTER_ONLY_ERRORS;
1493 if (filtering_enabled) {
1495 }
1496 ListBase anim_data = {nullptr, nullptr};
1498 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
1499
1500 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
1501 FCurve *fcu = (FCurve *)ale->key_data;
1503 PropertyRNA *prop;
1504 PointerRNA id_ptr = RNA_id_pointer_create(ale->id);
1505 if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
1506 fcu->flag &= ~FCURVE_DISABLED;
1507 }
1508 else {
1509 fcu->flag |= FCURVE_DISABLED;
1510 }
1511 }
1512
1513 ANIM_animdata_freelist(&anim_data);
1514 if (filtering_enabled) {
1516 }
1517}
1518
1519/* All FCurves need to be validated when the "show_only_errors" button is enabled. */
1520static void rna_Action_show_errors_update(bContext *C, PointerRNA * /*ptr*/)
1521{
1522 bAnimContext ac;
1523
1524 /* Get editor data. */
1525 if (ANIM_animdata_get_context(C, &ac) == 0) {
1526 return;
1527 }
1528
1529 if (!(ac.ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
1530 return;
1531 }
1532
1533 reevaluate_fcurve_errors(&ac);
1534}
1535
1536static std::optional<std::string> rna_DopeSheet_path(const PointerRNA *ptr)
1537{
1538 if (GS(ptr->owner_id->name) == ID_SCR) {
1539 const bScreen *screen = reinterpret_cast<bScreen *>(ptr->owner_id);
1540 const bDopeSheet *ads = static_cast<bDopeSheet *>(ptr->data);
1541 int area_index;
1542 int space_index;
1543 LISTBASE_FOREACH_INDEX (ScrArea *, area, &screen->areabase, area_index) {
1544 LISTBASE_FOREACH_INDEX (SpaceLink *, sl, &area->spacedata, space_index) {
1545 if (sl->spacetype == SPACE_GRAPH) {
1546 SpaceGraph *sipo = reinterpret_cast<SpaceGraph *>(sl);
1547 if (sipo->ads == ads) {
1548 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1549 }
1550 }
1551 else if (sl->spacetype == SPACE_NLA) {
1552 SpaceNla *snla = reinterpret_cast<SpaceNla *>(sl);
1553 if (snla->ads == ads) {
1554 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1555 }
1556 }
1557 else if (sl->spacetype == SPACE_ACTION) {
1558 SpaceAction *saction = reinterpret_cast<SpaceAction *>(sl);
1559 if (&saction->ads == ads) {
1560 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1561 }
1562 }
1563 }
1564 }
1565 }
1566 return "dopesheet";
1567}
1568
1576static const EnumPropertyItem *rna_ActionSlot_target_id_type_itemf(bContext * /* C */,
1577 PointerRNA * /* ptr */,
1578 PropertyRNA * /* prop */,
1579 bool *r_free)
1580{
1581 /* These items don't change, as the ID types are hard-coded. So better to
1582 * cache the list of enum items. */
1583 static EnumPropertyItem *_rna_ActionSlot_target_id_type_items = nullptr;
1584
1585 if (_rna_ActionSlot_target_id_type_items) {
1586 return _rna_ActionSlot_target_id_type_items;
1587 }
1588
1589 int totitem = 0;
1590 EnumPropertyItem *items = nullptr;
1591
1592 int i = 0;
1593 while (rna_enum_id_type_items[i].identifier != nullptr) {
1594 EnumPropertyItem item = {0};
1595 item.value = rna_enum_id_type_items[i].value;
1596 item.name = rna_enum_id_type_items[i].name;
1597 item.identifier = rna_enum_id_type_items[i].identifier;
1598 item.icon = rna_enum_id_type_items[i].icon;
1599 item.description = rna_enum_id_type_items[i].description;
1600 RNA_enum_item_add(&items, &totitem, &item);
1601 i++;
1602 }
1603
1605
1606 RNA_enum_item_end(&items, &totitem);
1607
1608 /* Don't free, but keep a reference to the created list. This is necessary
1609 * because of the PROP_ENUM_NO_CONTEXT flag. Without it, this will make
1610 * Blender use memory after it is freed:
1611 *
1612 * >>> slot = C.object.animation_data.action_slot
1613 * >>> enum_item = s.bl_rna.properties['target_id_type'].enum_items[slot.target_id_type]
1614 * >>> print(enum_item.name)
1615 */
1616 *r_free = false;
1617 _rna_ActionSlot_target_id_type_items = items;
1618
1620
1621 return items;
1622}
1623
1624static void rna_ActionSlot_target_id_type_set(PointerRNA *ptr, int value)
1625{
1626 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
1627 animrig::Slot &slot = reinterpret_cast<ActionSlot *>(ptr->data)->wrap();
1628
1629 if (slot.idtype != 0) {
1630 /* Ignore the assignment. */
1631 printf(
1632 "WARNING: ignoring assignment to target_id_type of Slot '%s' in Action '%s'. A Slot's "
1633 "target_id_type can only be changed when currently 'UNSPECIFIED'.\n",
1634 slot.identifier,
1635 action.id.name);
1636 return;
1637 }
1638
1639 action.slot_idtype_define(slot, ID_Type(value));
1640}
1641
1649static int rna_Action_id_root_get(PointerRNA *ptr)
1650{
1651 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
1652
1653 if (action.slots().is_empty()) {
1654 return 0;
1655 }
1656
1657 return action.slot(0)->idtype;
1658}
1659
1668static void rna_Action_id_root_set(PointerRNA *ptr, int value)
1669{
1670 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
1671
1673 action.slot_idtype_define(slot, ID_Type(value));
1674}
1675
1676static void rna_Action_id_root_update(Main *bmain, Scene *, PointerRNA *ptr)
1677{
1678 animrig::Action &action = rna_action(ptr);
1679
1680 if (action.slots().is_empty()) {
1681 /* Nothing to do: id_root can't be set without at least one slot, so no
1682 * change was possible that would necessitate an update. */
1683 return;
1684 }
1685
1686 /* Setting id_root actually sets the target ID type of the first slot, so it's
1687 * the resulting changes to the first slot that we need to propagate. */
1688 action.slot_identifier_propagate(*bmain, *action.slot(0));
1689}
1690
1691#else
1692
1694{
1695 StructRNA *srna;
1696 PropertyRNA *prop;
1697
1698 srna = RNA_def_struct(brna, "DopeSheet", nullptr);
1699 RNA_def_struct_sdna(srna, "bDopeSheet");
1700 RNA_def_struct_path_func(srna, "rna_DopeSheet_path");
1702 srna, "Dope Sheet", "Settings for filtering the channels shown in animation editors");
1703
1704 /* Source of DopeSheet data */
1705 /* XXX: make this obsolete? */
1706 prop = RNA_def_property(srna, "source", PROP_POINTER, PROP_NONE);
1707 RNA_def_property_struct_type(prop, "ID");
1709 prop, "Source", "ID-Block representing source data, usually ID_SCE (i.e. Scene)");
1710
1711 /* Show data-block filters */
1712 prop = RNA_def_property(srna, "show_datablock_filters", PROP_BOOLEAN, PROP_NONE);
1715 prop,
1716 "Show Data-Block Filters",
1717 "Show options for whether channels related to certain types of data are included");
1718 RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1);
1720
1721 /* General Filtering Settings */
1722 prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE);
1723 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLYSEL);
1725 prop, "Only Show Selected", "Only include channels relating to selected objects and data");
1726 RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0);
1728
1729 prop = RNA_def_property(srna, "show_only_slot_of_active_object", PROP_BOOLEAN, PROP_NONE);
1732 prop,
1733 "Only Show Slot of Active Object",
1734 "Only show the slot of the active Object. Otherwise show all the Action's Slots");
1735 RNA_def_property_ui_icon(prop, ICON_ACTION_SLOT, 0);
1737
1738 prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE);
1739 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_INCL_HIDDEN);
1741 prop, "Show Hidden", "Include channels from objects/bone that are not visible");
1742 RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0);
1744
1745 prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE);
1748 "Sort Data-Blocks",
1749 "Alphabetically sorts data-blocks - mainly objects in the scene "
1750 "(disable to increase viewport speed)");
1751 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1753
1754 prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
1756 RNA_def_property_ui_text(prop, "Invert", "Invert filter search");
1757 RNA_def_property_ui_icon(prop, ICON_ZOOM_IN, 0);
1759
1760 /* Debug Filtering Settings */
1761 prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE);
1762 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLY_ERRORS);
1764 "Only Show Errors",
1765 "Only include F-Curves and drivers that are disabled or have errors");
1766 RNA_def_property_ui_icon(prop, ICON_ERROR, 0);
1769 prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, "rna_Action_show_errors_update");
1770
1771 /* Object Collection Filtering Settings */
1772 prop = RNA_def_property(srna, "filter_collection", PROP_POINTER, PROP_NONE);
1773 RNA_def_property_pointer_sdna(prop, nullptr, "filter_grp");
1776 prop, "Filtering Collection", "Collection that included object should be a member of");
1778
1779 /* FCurve Display Name Search Settings */
1780 prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE);
1781 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1782 RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string");
1783 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1786
1787 /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */
1788 prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
1789 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1790 RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string");
1792 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1794
1795 /* Multi-word fuzzy search option for name/text filters */
1796 prop = RNA_def_property(srna, "use_multi_word_filter", PROP_BOOLEAN, PROP_NONE);
1799 "Multi-Word Fuzzy Filter",
1800 "Perform fuzzy/multi-word matching.\n"
1801 "Warning: May be slow");
1802 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1804
1805 /* NLA Specific Settings */
1806 prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE);
1809 "Include Missing NLA",
1810 "Include animation data-blocks with no NLA data (NLA editor only)");
1811 RNA_def_property_ui_icon(prop, ICON_ACTION, 0);
1813
1814 /* Summary Settings (DopeSheet editors only) */
1815 prop = RNA_def_property(srna, "show_summary", PROP_BOOLEAN, PROP_NONE);
1816 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_SUMMARY);
1818 prop, "Display Summary", "Display an additional 'summary' line (Dope Sheet editors only)");
1819 RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0);
1821
1822 prop = RNA_def_property(srna, "show_expanded_summary", PROP_BOOLEAN, PROP_NONE);
1825 prop,
1826 "Collapse Summary",
1827 "Collapse summary when shown, so all other channels get hidden (Dope Sheet editors only)");
1829
1830 /* General DataType Filtering Settings */
1831 prop = RNA_def_property(srna, "show_transforms", PROP_BOOLEAN, PROP_NONE);
1832 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOOBJ);
1834 prop,
1835 "Display Transforms",
1836 "Include visualization of object-level animation data (mostly transforms)");
1837 RNA_def_property_ui_icon(prop, ICON_ORIENTATION_GLOBAL, 0); /* XXX? */
1839
1840 prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE);
1843 prop, "Display Shape Keys", "Include visualization of shape key related animation data");
1844 RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0);
1846
1847 prop = RNA_def_property(srna, "show_modifiers", PROP_BOOLEAN, PROP_NONE);
1850 prop,
1851 "Display Modifier Data",
1852 "Include visualization of animation data related to data-blocks linked to modifiers");
1853 RNA_def_property_ui_icon(prop, ICON_MODIFIER_DATA, 0);
1855
1856 prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE);
1857 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMESH);
1859 prop, "Display Meshes", "Include visualization of mesh related animation data");
1860 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_MESH, 0);
1862
1863 prop = RNA_def_property(srna, "show_lattices", PROP_BOOLEAN, PROP_NONE);
1864 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAT);
1866 prop, "Display Lattices", "Include visualization of lattice related animation data");
1867 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LATTICE, 0);
1869
1870 prop = RNA_def_property(srna, "show_cameras", PROP_BOOLEAN, PROP_NONE);
1871 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCAM);
1873 prop, "Display Camera", "Include visualization of camera related animation data");
1874 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CAMERA, 0);
1876
1877 prop = RNA_def_property(srna, "show_materials", PROP_BOOLEAN, PROP_NONE);
1878 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMAT);
1880 prop, "Display Material", "Include visualization of material related animation data");
1881 RNA_def_property_ui_icon(prop, ICON_MATERIAL_DATA, 0);
1883
1884 prop = RNA_def_property(srna, "show_lights", PROP_BOOLEAN, PROP_NONE);
1885 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAM);
1887 prop, "Display Light", "Include visualization of light related animation data");
1888 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHT, 0);
1890
1891 prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE);
1894 prop, "Display Line Style", "Include visualization of Line Style related Animation data");
1895 RNA_def_property_ui_icon(prop, ICON_LINE_DATA, 0);
1897
1898 prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE);
1899 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOTEX);
1901 prop, "Display Texture", "Include visualization of texture related animation data");
1902 RNA_def_property_ui_icon(prop, ICON_TEXTURE_DATA, 0);
1904
1905 prop = RNA_def_property(srna, "show_curves", PROP_BOOLEAN, PROP_NONE);
1906 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCUR);
1908 prop, "Display Curve", "Include visualization of curve related animation data");
1909 RNA_def_property_ui_icon(prop, ICON_CURVE_DATA, 0);
1911
1912 prop = RNA_def_property(srna, "show_worlds", PROP_BOOLEAN, PROP_NONE);
1913 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOWOR);
1915 prop, "Display World", "Include visualization of world related animation data");
1916 RNA_def_property_ui_icon(prop, ICON_WORLD_DATA, 0);
1918
1919 prop = RNA_def_property(srna, "show_scenes", PROP_BOOLEAN, PROP_NONE);
1920 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSCE);
1922 prop, "Display Scene", "Include visualization of scene related animation data");
1923 RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0);
1925
1926 prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
1927 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOPART);
1929 prop, "Display Particle", "Include visualization of particle related animation data");
1930 RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0);
1932
1933 prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE);
1934 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMBA);
1936 prop, "Display Metaball", "Include visualization of metaball related animation data");
1937 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_META, 0);
1939
1940 prop = RNA_def_property(srna, "show_armatures", PROP_BOOLEAN, PROP_NONE);
1941 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOARM);
1943 prop, "Display Armature", "Include visualization of armature related animation data");
1944 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_ARMATURE, 0);
1946
1947 prop = RNA_def_property(srna, "show_nodes", PROP_BOOLEAN, PROP_NONE);
1948 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NONTREE);
1950 prop, "Display Node", "Include visualization of node related animation data");
1951 RNA_def_property_ui_icon(prop, ICON_NODETREE, 0);
1953
1954 prop = RNA_def_property(srna, "show_speakers", PROP_BOOLEAN, PROP_NONE);
1955 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSPK);
1957 prop, "Display Speaker", "Include visualization of speaker related animation data");
1958 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_SPEAKER, 0);
1960
1961 prop = RNA_def_property(srna, "show_cache_files", PROP_BOOLEAN, PROP_NONE);
1964 prop, "Display Cache Files", "Include visualization of cache file related animation data");
1965 RNA_def_property_ui_icon(prop, ICON_FILE, 0);
1967
1968 prop = RNA_def_property(srna, "show_hair_curves", PROP_BOOLEAN, PROP_NONE);
1969 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOHAIR);
1971 prop, "Display Hair", "Include visualization of hair related animation data");
1972 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CURVES, 0);
1974
1975 prop = RNA_def_property(srna, "show_pointclouds", PROP_BOOLEAN, PROP_NONE);
1978 prop, "Display Point Cloud", "Include visualization of point cloud related animation data");
1979 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_POINTCLOUD, 0);
1981
1982 prop = RNA_def_property(srna, "show_volumes", PROP_BOOLEAN, PROP_NONE);
1983 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOVOLUME);
1985 prop, "Display Volume", "Include visualization of volume related animation data");
1986 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_VOLUME, 0);
1988
1989 prop = RNA_def_property(srna, "show_lightprobes", PROP_BOOLEAN, PROP_NONE);
1992 prop, "Display Light Probe", "Include visualization of lightprobe related animation data");
1993 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHTPROBE, 0);
1995
1996 prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
1999 prop,
2000 "Display Grease Pencil",
2001 "Include visualization of Grease Pencil related animation data and frames");
2002 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_GREASEPENCIL, 0);
2004
2005 prop = RNA_def_property(srna, "show_movieclips", PROP_BOOLEAN, PROP_NONE);
2008 prop, "Display Movie Clips", "Include visualization of movie clip related animation data");
2009 RNA_def_property_ui_icon(prop, ICON_TRACKER, 0);
2011
2012 prop = RNA_def_property(srna, "show_driver_fallback_as_error", PROP_BOOLEAN, PROP_NONE);
2015 prop,
2016 "Variable Fallback As Error",
2017 "Include drivers that relied on any fallback values for their evaluation "
2018 "in the Only Show Errors filter, even if the driver evaluation succeeded");
2019 RNA_def_property_ui_icon(prop, ICON_RNA, 0);
2021}
2022
2023/* =========================== Layered Action interface =========================== */
2024
2026{
2027 StructRNA *srna;
2028 PropertyRNA *prop;
2029
2030 FunctionRNA *func;
2031 PropertyRNA *parm;
2032
2033 RNA_def_property_srna(cprop, "ActionSlots");
2034 srna = RNA_def_struct(brna, "ActionSlots", nullptr);
2035 RNA_def_struct_sdna(srna, "bAction");
2036 RNA_def_struct_ui_text(srna, "Action Slots", "Collection of action slots");
2037
2038 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
2039 RNA_def_property_struct_type(prop, "ActionSlot");
2042 prop, "rna_ActionSlots_active_get", "rna_ActionSlots_active_set", nullptr, nullptr);
2044
2045 RNA_def_property_ui_text(prop, "Active Slot", "Active slot for this action");
2046
2047 /* Animation.slots.new(...) */
2048 func = RNA_def_function(srna, "new", "rna_Action_slots_new");
2049 RNA_def_function_ui_description(func, "Add a slot to the Action");
2051 parm = RNA_def_enum(
2052 func,
2053 "id_type",
2055 ID_OB,
2056 "Data-block Type",
2057 "The data-block type that the slot is intended for. This is combined with the slot name to "
2058 "create the slot's unique identifier, and is also used to limit (on a best-effort basis) "
2059 "which data-blocks the slot can be assigned to.");
2061 parm = RNA_def_string(
2062 func,
2063 "name",
2064 nullptr,
2065 /* Minus 2 for the ID-type prefix. */
2066 sizeof(ActionSlot::identifier) - 2,
2067 "Name",
2068 "Name of the slot. This will be made unique within the Action among slots of the same type");
2070
2071 parm = RNA_def_pointer(func, "slot", "ActionSlot", "", "Newly created action slot");
2072 RNA_def_function_return(func, parm);
2073
2074 /* Animation.slots.remove(layer) */
2075 func = RNA_def_function(srna, "remove", "rna_Action_slots_remove");
2078 "Remove the slot from the Action, including all animation that "
2079 "is associated with that slot");
2080 parm = RNA_def_pointer(func, "action_slot", "ActionSlot", "Action Slot", "The slot to remove");
2082}
2083
2085{
2086 StructRNA *srna;
2087
2088 FunctionRNA *func;
2089 PropertyRNA *parm;
2090
2091 RNA_def_property_srna(cprop, "ActionLayers");
2092 srna = RNA_def_struct(brna, "ActionLayers", nullptr);
2093 RNA_def_struct_sdna(srna, "bAction");
2094 RNA_def_struct_ui_text(srna, "Action Layers", "Collection of animation layers");
2095
2096 /* Animation.layers.new(...) */
2097 func = RNA_def_function(srna, "new", "rna_Action_layers_new");
2100 func,
2101 "Add a layer to the Animation. Currently an Animation can only have at most one layer.");
2102 parm = RNA_def_string(func,
2103 "name",
2104 nullptr,
2105 sizeof(ActionLayer::name) - 1,
2106 "Name",
2107 "Name of the layer, will be made unique within the Action");
2109 parm = RNA_def_pointer(func, "layer", "ActionLayer", "", "Newly created animation layer");
2110 RNA_def_function_return(func, parm);
2111
2112 /* Animation.layers.remove(layer) */
2113 func = RNA_def_function(srna, "remove", "rna_Action_layers_remove");
2115 RNA_def_function_ui_description(func, "Remove the layer from the animation");
2116 parm = RNA_def_pointer(
2117 func, "anim_layer", "ActionLayer", "Animation Layer", "The layer to remove");
2119}
2120
2122{
2123 StructRNA *srna;
2124 PropertyRNA *prop;
2125 PropertyRNA *parm;
2126 FunctionRNA *func;
2127
2128 srna = RNA_def_struct(brna, "ActionSlot", nullptr);
2129 RNA_def_struct_path_func(srna, "rna_ActionSlot_path");
2130 RNA_def_struct_ui_icon(srna, ICON_ACTION_SLOT);
2132 srna,
2133 "Action slot",
2134 "Identifier for a set of channels in this Action, that can be used by a data-block "
2135 "to specify what it gets animated by");
2136
2138
2139 prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
2140 RNA_def_struct_name_property(srna, prop);
2141 RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_ActionSlot_identifier_set");
2143 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_identifier_update");
2145 prop,
2146 "Slot Identifier",
2147 "Used when connecting an Action to a data-block, to find the correct slot handle. This is "
2148 "the display name, prefixed by two characters determined by the slot's ID type");
2149
2150 prop = RNA_def_property(srna, "target_id_type", PROP_ENUM, PROP_NONE);
2151 RNA_def_property_enum_sdna(prop, nullptr, "idtype");
2154 prop, nullptr, "rna_ActionSlot_target_id_type_set", "rna_ActionSlot_target_id_type_itemf");
2155 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_identifier_update");
2158 "Target ID Type",
2159 "Type of data-block that this slot is intended to animate; can be set "
2160 "when 'UNSPECIFIED' but is otherwise read-only");
2162
2163 prop = RNA_def_property(srna, "target_id_type_icon", PROP_INT, PROP_NONE);
2164 RNA_def_property_int_funcs(prop, "rna_ActionSlot_target_id_type_icon_get", nullptr, nullptr);
2166
2167 prop = RNA_def_property(srna, "name_display", PROP_STRING, PROP_NONE);
2169 "rna_ActionSlot_name_display_get",
2170 "rna_ActionSlot_name_display_length",
2171 "rna_ActionSlot_name_display_set");
2174 prop, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, "rna_ActionSlot_identifier_update");
2176 prop,
2177 "Slot Display Name",
2178 "Name of the slot, for display in the user interface. This name combined with the slot's "
2179 "data-block type is unique within its Action");
2180
2181 prop = RNA_def_property(srna, "handle", PROP_INT, PROP_NONE);
2184 "Slot Handle",
2185 "Number specific to this Slot, unique within the Action.\n"
2186 "This is used, for example, on a ActionKeyframeStrip to look up the "
2187 "ActionChannelbag for this Slot");
2188
2189 prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
2190 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Active));
2192 prop,
2193 "Active",
2194 "Whether this is the active slot, can be set by assigning to action.slots.active");
2198
2199 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
2200 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Selected));
2201 RNA_def_property_ui_text(prop, "Select", "Selection state of the slot");
2205
2206 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
2207 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Expanded));
2208 RNA_def_property_ui_text(prop, "Show Expanded", "Expanded state of the slot");
2212
2213 func = RNA_def_function(srna, "users", "rna_ActionSlot_users");
2216 func, "Return the data-blocks that are animated by this slot of this action");
2217 /* Return value. */
2218 parm = RNA_def_property(func, "users", PROP_COLLECTION, PROP_NONE);
2219 RNA_def_property_struct_type(parm, "ID");
2220 RNA_def_function_return(func, parm);
2221
2222 func = RNA_def_function(srna, "duplicate", "rna_ActionSlot_duplicate");
2224 func, "Duplicate this slot, including all the animation data associated with it");
2225 /* Return value. */
2226 parm = RNA_def_property(func, "slot", PROP_POINTER, PROP_NONE);
2228 RNA_def_property_struct_type(parm, "ActionSlot");
2229 RNA_def_property_ui_text(parm, "Duplicated Slot", "The slot created by duplicating this one");
2230 RNA_def_function_return(func, parm);
2231}
2232
2234{
2235 StructRNA *srna;
2236
2237 FunctionRNA *func;
2238 PropertyRNA *parm;
2239
2240 RNA_def_property_srna(cprop, "ActionStrips");
2241 srna = RNA_def_struct(brna, "ActionStrips", nullptr);
2242 RNA_def_struct_sdna(srna, "ActionLayer");
2243 RNA_def_struct_ui_text(srna, "Action Strips", "Collection of animation strips");
2244
2245 /* Layer.strips.new(type='...') */
2246 func = RNA_def_function(srna, "new", "rna_ActionStrips_new");
2248 "Add a new strip to the layer. Currently a layer can only have "
2249 "one strip, with infinite boundaries.");
2251 parm = RNA_def_enum(func,
2252 "type",
2254 int(animrig::Strip::Type::Keyframe),
2255 "Type",
2256 "The type of strip to create");
2257 /* Return value. */
2258 parm = RNA_def_pointer(func, "strip", "ActionStrip", "", "Newly created animation strip");
2259 RNA_def_function_return(func, parm);
2260
2261 /* Layer.strips.remove(strip) */
2262 func = RNA_def_function(srna, "remove", "rna_ActionStrips_remove");
2264 RNA_def_function_ui_description(func, "Remove the strip from the animation layer");
2265 parm = RNA_def_pointer(
2266 func, "anim_strip", "ActionStrip", "Animation Strip", "The strip to remove");
2268}
2269
2271{
2272 StructRNA *srna;
2273 PropertyRNA *prop;
2274
2275 srna = RNA_def_struct(brna, "ActionLayer", nullptr);
2276 RNA_def_struct_ui_text(srna, "Action Layer", "");
2277 RNA_def_struct_path_func(srna, "rna_ActionLayer_path");
2278
2279 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
2280 RNA_def_struct_name_property(srna, prop);
2281
2282 /* Disabled in RNA until layered animation is actually implemented.
2283 *
2284 * The animation evaluation already takes these into account, but there is no guarantee that the
2285 * mixing that is currently implemented is going to be mathematically identical to the eventual
2286 * implementation. */
2287# if 0
2288 prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
2289 RNA_def_property_range(prop, 0.0f, 1.0f);
2291 prop, "Influence", "How much of this layer is used when blending into the lower layers");
2292 RNA_def_property_ui_range(prop, 0.0, 1.0, 3, 2);
2294 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
2295
2296 prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
2297 RNA_def_property_enum_sdna(prop, nullptr, "layer_mix_mode");
2299 prop, "Mix Mode", "How animation of this layer is blended into the lower layers");
2301 RNA_def_property_enum_items(prop, rna_enum_layer_mix_mode_items);
2302 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
2303# endif
2304
2305 /* Collection properties. */
2306 prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
2307 RNA_def_property_struct_type(prop, "ActionStrip");
2309 "rna_iterator_ActionLayer_strips_begin",
2310 "rna_iterator_array_next",
2311 "rna_iterator_array_end",
2312 "rna_iterator_array_dereference_get",
2313 "rna_iterator_ActionLayer_strips_length",
2314 nullptr,
2315 nullptr,
2316 nullptr);
2317 RNA_def_property_ui_text(prop, "Strips", "The list of strips that are on this animation layer");
2318
2319 rna_def_ActionLayer_strips(brna, prop);
2320}
2321
2323{
2324 StructRNA *srna;
2325
2326 FunctionRNA *func;
2327 PropertyRNA *parm;
2328
2329 RNA_def_property_srna(cprop, "ActionChannelbags");
2330 srna = RNA_def_struct(brna, "ActionChannelbags", nullptr);
2331 RNA_def_struct_sdna(srna, "ActionStrip");
2333 srna,
2334 "Animation Channels for Slots",
2335 "For each action slot, a list of animation channels that are meant for that slot");
2336
2337 /* Strip.channelbags.new(slot=...) */
2338 func = RNA_def_function(srna, "new", "rna_Channelbags_new");
2340 func,
2341 "Add a new channelbag to the strip, to contain animation channels for a specific slot");
2343 parm = RNA_def_pointer(func,
2344 "slot",
2345 "ActionSlot",
2346 "Action Slot",
2347 "The slot that should be animated by this channelbag");
2349
2350 /* Return value. */
2351 parm = RNA_def_pointer(func, "channelbag", "ActionChannelbag", "", "Newly created channelbag");
2352 RNA_def_function_return(func, parm);
2353
2354 /* Strip.channelbags.remove(strip) */
2355 func = RNA_def_function(srna, "remove", "rna_Channelbags_remove");
2357 RNA_def_function_ui_description(func, "Remove the channelbag from the strip");
2358 parm = RNA_def_pointer(func, "channelbag", "ActionChannelbag", "", "The channelbag to remove");
2360}
2361
2366{
2367 StructRNA *srna;
2368 PropertyRNA *prop;
2369
2370 srna = RNA_def_struct(brna, "ActionKeyframeStrip", "ActionStrip");
2372 srna, "Keyframe Animation Strip", "Strip with a set of F-Curves for each action slot");
2373 RNA_def_struct_sdna_from(srna, "ActionStrip", nullptr);
2374
2375 prop = RNA_def_property(srna, "channelbags", PROP_COLLECTION, PROP_NONE);
2376 RNA_def_property_struct_type(prop, "ActionChannelbag");
2378 "rna_iterator_keyframestrip_channelbags_begin",
2379 "rna_iterator_array_next",
2380 "rna_iterator_array_end",
2381 "rna_iterator_array_dereference_get",
2382 "rna_iterator_keyframestrip_channelbags_length",
2383 nullptr,
2384 nullptr,
2385 nullptr);
2387
2388 {
2389 FunctionRNA *func;
2390 PropertyRNA *parm;
2391
2392 /* Strip.channelbag(...). */
2393 func = RNA_def_function(srna, "channelbag", "rna_ActionStrip_channelbag");
2395 RNA_def_function_ui_description(func, "Find the ActionChannelbag for a specific Slot");
2396 parm = RNA_def_pointer(
2397 func, "slot", "ActionSlot", "Slot", "The slot for which to find the channelbag");
2399 RNA_def_boolean(func,
2400 "ensure",
2401 false,
2402 "Create if necessary",
2403 "Ensure the channelbag exists for this slot, creating it if necessary");
2404 parm = RNA_def_pointer(func, "channels", "ActionChannelbag", "Channels", "");
2405 RNA_def_function_return(func, parm);
2406
2407 /* Strip.key_insert(...). */
2408
2409 func = RNA_def_function(srna, "key_insert", "rna_ActionStrip_key_insert");
2411 parm = RNA_def_pointer(func,
2412 "slot",
2413 "ActionSlot",
2414 "Slot",
2415 "The slot that identifies which 'thing' should be keyed");
2417
2418 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2420
2421 parm = RNA_def_int(
2422 func,
2423 "array_index",
2424 -1,
2425 -INT_MAX,
2426 INT_MAX,
2427 "Array Index",
2428 "Index of the animated array element, or -1 if the property is not an array",
2429 -1,
2430 4);
2432
2433 parm = RNA_def_float(func,
2434 "value",
2435 0.0,
2436 -FLT_MAX,
2437 FLT_MAX,
2438 "Value to key",
2439 "Value of the animated property",
2440 -FLT_MAX,
2441 FLT_MAX);
2443
2444 parm = RNA_def_float(func,
2445 "time",
2446 0.0,
2447 -FLT_MAX,
2448 FLT_MAX,
2449 "Time of the key",
2450 "Time, in frames, of the key",
2451 -FLT_MAX,
2452 FLT_MAX);
2454
2455 parm = RNA_def_boolean(
2456 func, "success", true, "Success", "Whether the key was successfully inserted");
2457
2458 RNA_def_function_return(func, parm);
2459 }
2460}
2461
2463{
2464 StructRNA *srna;
2465 PropertyRNA *prop;
2466
2467 srna = RNA_def_struct(brna, "ActionStrip", nullptr);
2468 RNA_def_struct_ui_text(srna, "Action Strip", "");
2469 RNA_def_struct_path_func(srna, "rna_ActionStrip_path");
2470 RNA_def_struct_refine_func(srna, "rna_ActionStrip_refine");
2471
2472 static const EnumPropertyItem prop_type_items[] = {
2473 {int(animrig::Strip::Type::Keyframe),
2474 "KEYFRAME",
2475 0,
2476 "Keyframe",
2477 "Strip with a set of F-Curves for each action slot"},
2478 {0, nullptr, 0, nullptr, nullptr},
2479 };
2480
2481 prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
2482 RNA_def_property_enum_sdna(prop, nullptr, "strip_type");
2483 RNA_def_property_enum_items(prop, prop_type_items);
2485
2486 /* Define Strip subtypes. */
2488}
2489
2491{
2492 StructRNA *srna;
2493
2494 FunctionRNA *func;
2495 PropertyRNA *parm;
2496
2497 RNA_def_property_srna(cprop, "ActionChannelbagFCurves");
2498 srna = RNA_def_struct(brna, "ActionChannelbagFCurves", nullptr);
2499 RNA_def_struct_sdna(srna, "ActionChannelbag");
2501 srna, "F-Curves", "Collection of F-Curves for a specific action slot, on a specific strip");
2502
2503 /* Channelbag.fcurves.new(...) */
2504 extern FCurve *ActionChannelbagFCurves_new_func(ID * _selfid,
2505 ActionChannelbag * _self,
2506 Main * bmain,
2508 const char *data_path,
2509 int index);
2510
2511 func = RNA_def_function(srna, "new", "rna_Channelbag_fcurve_new");
2512 RNA_def_function_ui_description(func, "Add an F-Curve to the channelbag");
2514 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2516 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2517
2518 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2519 RNA_def_function_return(func, parm);
2520
2521 /* Channelbag.fcurves.find(...) */
2522 func = RNA_def_function(srna, "find", "rna_Channelbag_fcurve_find");
2524 func,
2525 "Find an F-Curve. Note that this function performs a linear scan "
2526 "of all F-Curves in the channelbag.");
2528 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2530 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2531 parm = RNA_def_pointer(
2532 func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
2533 RNA_def_function_return(func, parm);
2534
2535 /* Channelbag.fcurves.remove(...) */
2536 func = RNA_def_function(srna, "remove", "rna_Channelbag_fcurve_remove");
2537 RNA_def_function_ui_description(func, "Remove F-Curve");
2539 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove");
2542
2543 /* Channelbag.fcurves.clear() */
2544 func = RNA_def_function(srna, "clear", "rna_Channelbag_fcurve_clear");
2546 RNA_def_function_ui_description(func, "Remove all F-Curves from this channelbag");
2547}
2548
2550{
2551 StructRNA *srna;
2552
2553 FunctionRNA *func;
2554 PropertyRNA *parm;
2555
2556 RNA_def_property_srna(cprop, "ActionChannelbagGroups");
2557 srna = RNA_def_struct(brna, "ActionChannelbagGroups", nullptr);
2558 RNA_def_struct_sdna(srna, "ActionChannelbag");
2559 RNA_def_struct_ui_text(srna, "F-Curve Groups", "Collection of f-curve groups");
2560
2561 func = RNA_def_function(srna, "new", "rna_Channelbag_group_new");
2563 RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
2564 parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
2566 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Newly created action group");
2567 RNA_def_function_return(func, parm);
2568
2569 func = RNA_def_function(srna, "remove", "rna_Channelbag_group_remove");
2570 RNA_def_function_ui_description(func, "Remove action group");
2572 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove");
2575}
2576
2578{
2579 StructRNA *srna;
2580 PropertyRNA *prop;
2581
2582 srna = RNA_def_struct(brna, "ActionChannelbag", nullptr);
2584 srna,
2585 "Animation Channel Bag",
2586 "Collection of animation channels, typically associated with an action slot");
2587 RNA_def_struct_path_func(srna, "rna_Channelbag_path");
2588
2589 prop = RNA_def_property(srna, "slot_handle", PROP_INT, PROP_NONE);
2591
2592 prop = RNA_def_property(srna, "slot", PROP_POINTER, PROP_NONE);
2593 RNA_def_property_struct_type(prop, "ActionSlot");
2594 RNA_def_property_ui_text(prop, "Slot", "The Slot that the Channelbag's animation data is for");
2596 RNA_def_property_pointer_funcs(prop, "rna_Channelbag_slot_get", nullptr, nullptr, nullptr);
2597
2598 /* Channelbag.fcurves */
2599 prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
2601 "rna_iterator_Channelbag_fcurves_begin",
2602 "rna_iterator_array_next",
2603 "rna_iterator_array_end",
2604 "rna_iterator_array_dereference_get",
2605 "rna_iterator_Channelbag_fcurves_length",
2606 nullptr,
2607 nullptr,
2608 nullptr);
2609 RNA_def_property_struct_type(prop, "FCurve");
2610 RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that animate the slot");
2611 rna_def_channelbag_fcurves(brna, prop);
2612
2613 /* Channelbag.groups */
2614 prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
2616 "rna_iterator_Channelbag_groups_begin",
2617 "rna_iterator_array_next",
2618 "rna_iterator_array_end",
2619 "rna_iterator_array_dereference_get",
2620 "rna_iterator_Channelbag_groups_length",
2621 nullptr,
2622 nullptr,
2623 nullptr);
2624 RNA_def_property_struct_type(prop, "ActionGroup");
2626 prop,
2627 "F-Curve Groups",
2628 "Groupings of F-Curves for display purposes, in e.g. the dopesheet and graph editor");
2629 rna_def_channelbag_groups(brna, prop);
2630}
2631
2633{
2634 StructRNA *srna;
2635 PropertyRNA *prop;
2636
2637 srna = RNA_def_struct(brna, "ActionGroup", nullptr);
2638 RNA_def_struct_sdna(srna, "bActionGroup");
2639 RNA_def_struct_ui_text(srna, "Action Group", "Groups of F-Curves");
2640
2641 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
2642 RNA_def_property_ui_text(prop, "Name", "");
2643 RNA_def_struct_name_property(srna, prop);
2645
2646 /* WARNING: be very careful when working with this list, since the endpoint is not
2647 * defined like a standard ListBase. Adding/removing channels from this list needs
2648 * extreme care, otherwise the F-Curve list running through adjacent groups does
2649 * not match up with the one stored in the Action, resulting in curves which do not
2650 * show up in animation editors. In extreme cases, animation may also selectively
2651 * fail to play back correctly.
2652 *
2653 * If such changes are required, these MUST go through the API functions for manipulating
2654 * these F-Curve groupings. Also, note that groups only apply in actions ONLY.
2655 */
2656 prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
2657 RNA_def_property_collection_sdna(prop, nullptr, "channels", nullptr);
2658 RNA_def_property_struct_type(prop, "FCurve");
2660 "rna_ActionGroup_channels_begin",
2661 "rna_ActionGroup_channels_next",
2662 "rna_ActionGroup_channels_end",
2663 "rna_ActionGroup_channels_get",
2664 nullptr,
2665 nullptr,
2666 nullptr,
2667 nullptr);
2668 RNA_def_property_ui_text(prop, "Channels", "F-Curves in this group");
2669
2670 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
2671 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_SELECTED);
2672 RNA_def_property_ui_text(prop, "Select", "Action group is selected");
2674
2675 prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
2676 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_PROTECTED);
2677 RNA_def_property_ui_text(prop, "Lock", "Action group is locked");
2679
2680 prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
2681 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_MUTED);
2682 RNA_def_property_ui_text(prop, "Mute", "Action group is muted");
2684
2685 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
2687 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED);
2688 RNA_def_property_ui_text(prop, "Expanded", "Action group is expanded except in graph editor");
2690
2691 prop = RNA_def_property(srna, "show_expanded_graph", PROP_BOOLEAN, PROP_NONE);
2693 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED_G);
2695 prop, "Expanded in Graph Editor", "Action group is expanded in graph editor");
2697
2698 prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
2701 RNA_def_property_ui_text(prop, "Pin in Graph Editor", "");
2703
2704 /* color set */
2706}
2707
2708/* =========================== Legacy Action interface =========================== */
2709
2710/* fcurve.keyframe_points */
2712{
2713 StructRNA *srna;
2714
2715 FunctionRNA *func;
2716 PropertyRNA *parm;
2717
2718 RNA_def_property_srna(cprop, "ActionGroups");
2719 srna = RNA_def_struct(brna, "ActionGroups", nullptr);
2720 RNA_def_struct_sdna(srna, "bAction");
2721 RNA_def_struct_ui_text(srna, "Action Groups", "Collection of action groups");
2723 "rna_iterator_Action_groups_begin",
2724 "rna_iterator_Action_groups_next",
2725 "rna_iterator_Action_groups_end",
2726 "rna_iterator_Action_groups_get",
2727 "rna_iterator_Action_groups_length",
2728 nullptr,
2729 nullptr,
2730 nullptr);
2731
2732 func = RNA_def_function(srna, "new", "rna_Action_groups_new");
2733 RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
2734 parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
2736 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Newly created action group");
2737 RNA_def_function_return(func, parm);
2738
2739 func = RNA_def_function(srna, "remove", "rna_Action_groups_remove");
2740 RNA_def_function_ui_description(func, "Remove action group");
2742 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove");
2745}
2746
2748{
2749 StructRNA *srna;
2750
2751 FunctionRNA *func;
2752 PropertyRNA *parm;
2753
2754 RNA_def_property_srna(cprop, "ActionFCurves");
2755 srna = RNA_def_struct(brna, "ActionFCurves", nullptr);
2756 RNA_def_struct_sdna(srna, "bAction");
2758 srna,
2759 "Action F-Curves",
2760 "Collection of action F-Curves. Note that this is a legacy API that is unaware of action "
2761 "slots, and will only consider the F-Curves for this action's first slot");
2763 "rna_iterator_Action_fcurves_begin",
2764 "rna_iterator_Action_fcurves_next",
2765 "rna_iterator_Action_fcurves_end",
2766 "rna_iterator_Action_fcurves_get",
2767 "rna_iterator_Action_fcurves_length",
2768 nullptr,
2769 nullptr,
2770 nullptr);
2771
2772 /* Action.fcurves.new(...) */
2773 func = RNA_def_function(srna, "new", "rna_Action_fcurve_new");
2775 "Add an F-Curve for the first slot of this action, creating the "
2776 "necessary layer, strip, and slot if necessary");
2778 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2780 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2782 func, "action_group", nullptr, 0, "Action Group", "Acton group to add this F-Curve into");
2783
2784 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2785 RNA_def_function_return(func, parm);
2786
2787 /* Action.fcurves.find(...) */
2788 func = RNA_def_function(srna, "find", "rna_Action_fcurve_find");
2790 func,
2791 "Find an F-Curve. Note that this function performs a linear scan "
2792 "of all F-Curves for the action's first slot.");
2794 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2796 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2797 parm = RNA_def_pointer(
2798 func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
2799 RNA_def_function_return(func, parm);
2800
2801 /* Action.fcurves.remove(...) */
2802 func = RNA_def_function(srna, "remove", "rna_Action_fcurve_remove");
2803 RNA_def_function_ui_description(func, "Remove the F-Curve from the action's first slot");
2805 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove");
2808
2809 /* Action.fcurves.clear() */
2810 func = RNA_def_function(srna, "clear", "rna_Action_fcurve_clear");
2811 RNA_def_function_ui_description(func, "Remove all F-Curves from the action's first slot");
2812}
2813
2815{
2816 StructRNA *srna;
2817 PropertyRNA *prop;
2818
2819 FunctionRNA *func;
2820 PropertyRNA *parm;
2821
2822 RNA_def_property_srna(cprop, "ActionPoseMarkers");
2823 srna = RNA_def_struct(brna, "ActionPoseMarkers", nullptr);
2824 RNA_def_struct_sdna(srna, "bAction");
2825 RNA_def_struct_ui_text(srna, "Action Pose Markers", "Collection of timeline markers");
2826
2827 func = RNA_def_function(srna, "new", "rna_Action_pose_markers_new");
2828 RNA_def_function_ui_description(func, "Add a pose marker to the action");
2829 parm = RNA_def_string(
2830 func, "name", "Marker", 0, nullptr, "New name for the marker (not unique)");
2832 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Newly created marker");
2833 RNA_def_function_return(func, parm);
2834
2835 func = RNA_def_function(srna, "remove", "rna_Action_pose_markers_remove");
2836 RNA_def_function_ui_description(func, "Remove a timeline marker");
2838 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove");
2841
2842 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
2843 RNA_def_property_struct_type(prop, "TimelineMarker");
2846 "rna_Action_active_pose_marker_get",
2847 "rna_Action_active_pose_marker_set",
2848 nullptr,
2849 nullptr);
2850 RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action");
2851
2852 prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
2853 RNA_def_property_int_sdna(prop, nullptr, "active_marker");
2856 "rna_Action_active_pose_marker_index_get",
2857 "rna_Action_active_pose_marker_index_set",
2858 "rna_Action_active_pose_marker_index_range");
2859 RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker");
2860}
2861
2862/* Access to 'legacy' Action features, like the top-level F-Curves, the corresponding F-Curve
2863 * groups, and the top-level id_root. */
2865{
2866 PropertyRNA *prop;
2867
2868 /* collections */
2869 prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
2870 RNA_def_property_collection_sdna(prop, nullptr, "curves", nullptr);
2871 RNA_def_property_struct_type(prop, "FCurve");
2873 prop,
2874 "F-Curves",
2875 "Legacy API, for backward compatibility with code that does not handle slotted actions yet. "
2876 "This collection contains the F-Curves for the action's first slot");
2877 rna_def_action_fcurves(brna, prop);
2878
2879 prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
2880 RNA_def_property_collection_sdna(prop, nullptr, "groups", nullptr);
2881 RNA_def_property_struct_type(prop, "ActionGroup");
2883 prop,
2884 "Groups",
2885 "Legacy API, for backward compatibility with code that does not handle slotted actions yet. "
2886 "This collection contains the F-Curve groups for the action's first slot");
2887 rna_def_action_groups(brna, prop);
2888
2889 /* special "type" limiter - should not really be edited in general,
2890 * but is still available/editable in 'emergencies' */
2891 prop = RNA_def_property(srna, "id_root", PROP_ENUM, PROP_NONE);
2892 RNA_def_property_enum_sdna(prop, nullptr, "idroot");
2895 "rna_Action_id_root_get",
2896 "rna_Action_id_root_set",
2897 "rna_ActionSlot_target_id_type_itemf");
2898 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_id_root_update");
2901 prop,
2902 "ID Root Type",
2903 "Legacy API, for backward compatibility with code that does not handle slotted actions yet. "
2904 "Type of data-block that the action's first slot can be used on. Do not change unless you "
2905 "know what you are doing");
2907}
2908
2909static void rna_def_action(BlenderRNA *brna)
2910{
2911 StructRNA *srna;
2912 PropertyRNA *prop;
2913
2914 FunctionRNA *func;
2915 PropertyRNA *parm;
2916
2917 srna = RNA_def_struct(brna, "Action", "ID");
2918 RNA_def_struct_sdna(srna, "bAction");
2919 RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation");
2920 RNA_def_struct_ui_icon(srna, ICON_ACTION);
2921
2922 /* Properties. */
2923 prop = RNA_def_property(srna, "is_empty", PROP_BOOLEAN, PROP_NONE);
2926 prop, "Is Empty", "False when there is any Layer, Slot, or legacy F-Curve");
2927 RNA_def_property_boolean_funcs(prop, "rna_Action_is_empty_get", nullptr);
2928
2929 prop = RNA_def_property(srna, "is_action_legacy", PROP_BOOLEAN, PROP_NONE);
2932 prop,
2933 "Is Legacy Action",
2934 "Return whether this is a legacy Action. Legacy Actions have no layers or slots. An "
2935 "empty Action is considered as both a 'legacy' and a 'layered' Action. Since Blender 4.4 "
2936 "actions are automatically updated to layered actions, and thus this will only return True "
2937 "when the action is empty");
2938 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_legacy_get", nullptr);
2939
2940 prop = RNA_def_property(srna, "is_action_layered", PROP_BOOLEAN, PROP_NONE);
2943 prop,
2944 "Is Layered Action",
2945 "Return whether this is a layered Action. An empty Action is considered "
2946 "as both a 'legacy' and a 'layered' Action.");
2947 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_layered_get", nullptr);
2948
2949 /* Collection properties. */
2950 prop = RNA_def_property(srna, "slots", PROP_COLLECTION, PROP_NONE);
2951 RNA_def_property_struct_type(prop, "ActionSlot");
2953 "rna_iterator_animation_slots_begin",
2954 "rna_iterator_array_next",
2955 "rna_iterator_array_end",
2956 "rna_iterator_array_dereference_get",
2957 "rna_iterator_animation_slots_length",
2958 nullptr,
2959 nullptr,
2960 nullptr);
2961 RNA_def_property_ui_text(prop, "Slots", "The list of slots in this Action");
2962 rna_def_action_slots(brna, prop);
2963
2964 prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
2965 RNA_def_property_struct_type(prop, "ActionLayer");
2967 "rna_iterator_action_layers_begin",
2968 "rna_iterator_array_next",
2969 "rna_iterator_array_end",
2970 "rna_iterator_array_dereference_get",
2971 "rna_iterator_action_layers_length",
2972 nullptr,
2973 nullptr,
2974 nullptr);
2975 RNA_def_property_ui_text(prop, "Layers", "The list of layers that make up this Action");
2976 rna_def_action_layers(brna, prop);
2977
2978 prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
2979 RNA_def_property_collection_sdna(prop, nullptr, "markers", nullptr);
2980 RNA_def_property_struct_type(prop, "TimelineMarker");
2981 /* Use lib exception so the list isn't grayed out;
2982 * adding/removing is still banned though, see #45689. */
2985 prop, "Pose Markers", "Markers specific to this action, for labeling poses");
2986 rna_def_action_pose_markers(brna, prop);
2987
2988 /* properties */
2989 prop = RNA_def_property(srna, "use_frame_range", PROP_BOOLEAN, PROP_NONE);
2991 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_FRAME_RANGE);
2992 RNA_def_property_boolean_funcs(prop, nullptr, "rna_Action_use_frame_range_set");
2994 prop,
2995 "Manual Frame Range",
2996 "Manually specify the intended playback frame range for the action "
2997 "(this range is used by some tools, but does not affect animation evaluation)");
2999
3000 prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
3002 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_CYCLIC);
3004 prop,
3005 "Cyclic Animation",
3006 "The action is intended to be used as a cycle looping over its manually set "
3007 "playback frame range (enabling this doesn't automatically make it loop)");
3009
3010 prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
3012 RNA_def_property_float_sdna(prop, nullptr, "frame_start");
3013 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_start_frame_set", nullptr);
3016 prop, "Start Frame", "The start frame of the manually set intended playback range");
3018
3019 prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME);
3021 RNA_def_property_float_sdna(prop, nullptr, "frame_end");
3022 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_end_frame_set", nullptr);
3025 prop, "End Frame", "The end frame of the manually set intended playback range");
3027
3028 prop = RNA_def_float_vector(
3029 srna,
3030 "frame_range",
3031 2,
3032 nullptr,
3033 0,
3034 0,
3035 "Frame Range",
3036 "The intended playback frame range of this action, using the manually set range "
3037 "if available, or the combined frame range of all F-Curves within this action "
3038 "if not (assigning sets the manual frame range)",
3039 0,
3040 0);
3042 prop, "rna_Action_frame_range_get", "rna_Action_frame_range_set", nullptr);
3044
3045 prop = RNA_def_float_vector(srna,
3046 "curve_frame_range",
3047 2,
3048 nullptr,
3049 0,
3050 0,
3051 "Curve Frame Range",
3052 "The combined frame range of all F-Curves within this action",
3053 0,
3054 0);
3055 RNA_def_property_float_funcs(prop, "rna_Action_curve_frame_range_get", nullptr, nullptr);
3057
3058 func = RNA_def_function(srna, "deselect_keys", "rna_Action_deselect_keys");
3060 func, "Deselects all keys of the Action. The selection status of F-Curves is unchanged.");
3061
3062 /* action.fcurve_ensure_for_datablock() */
3063 func = RNA_def_function(
3064 srna, "fcurve_ensure_for_datablock", "rna_Action_fcurve_ensure_for_datablock");
3066 func,
3067 "Ensure that an F-Curve exists, with the given data path and array index, for the given "
3068 "data-block. This action must already be assigned to the data-block. This function will "
3069 "also create the layer, keyframe strip, and action slot if necessary, and take care of "
3070 "assigning the action slot too");
3072
3073 parm = RNA_def_pointer(func,
3074 "datablock",
3075 "ID",
3076 "",
3077 "The data-block animated by this action, for which to ensure the F-Curve "
3078 "exists. This action must already be assigned to the data-block");
3080 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
3082 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
3083 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "The found or created F-Curve");
3084 RNA_def_function_return(func, parm);
3085
3086 rna_def_action_legacy(brna, srna);
3087
3088 /* API calls */
3089 RNA_api_action(srna);
3090}
3091
3092/* --------- */
3093
3095{
3096 rna_def_action(brna);
3098 rna_def_dopesheet(brna);
3099
3100 rna_def_action_slot(brna);
3104}
3105
3106#endif
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to insert, delete or modify keyframes.
Blender kernel action and pose functionality.
void BKE_action_fcurves_clear(bAction *act)
void action_groups_remove_channel(bAction *act, FCurve *fcu)
bActionGroup * action_groups_add_new(bAction *act, const char name[])
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:487
void BKE_fcurve_free(FCurve *fcu)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#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_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
bool BLI_remlink_safe(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:154
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
MINLINE int max_ii(int a, int b)
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define CLAMP_MAX(a, c)
#define CLAMP_MIN(a, b)
#define BLT_I18NCONTEXT_ID_ID
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:985
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1084
ID_Type
@ ID_KE
@ ID_SCR
@ ID_OB
@ ADS_FILTER_NOLIGHTPROBE
@ ADS_FILTER_DRIVER_FALLBACK_AS_ERROR
@ ADS_FILTER_NOMOVIECLIPS
@ ADS_FILTER_NOVOLUME
@ ADS_FILTER_NOHAIR
@ ADS_FILTER_NOCACHEFILES
@ ADS_FILTER_NOPOINTCLOUD
@ ADS_FILTER_ONLYSEL
@ ADS_FILTER_NOARM
@ ADS_FILTER_NLA_NOACT
@ ADS_FILTER_NOMAT
@ ADS_FILTER_NONTREE
@ ADS_FILTER_NOCAM
@ ADS_FILTER_NOSHAPEKEYS
@ ADS_FILTER_NOTEX
@ ADS_FILTER_ONLY_ERRORS
@ ADS_FILTER_NOSCE
@ ADS_FILTER_NOLAM
@ ADS_FILTER_ONLY_SLOTS_OF_ACTIVE
@ ADS_FILTER_NOMODIFIERS
@ ADS_FILTER_NOLINESTYLE
@ ADS_FILTER_SUMMARY
@ ADS_FILTER_NOGPENCIL
@ ADS_FILTER_NOOBJ
@ ADS_FILTER_NOCUR
@ ADS_FILTER_NOPART
@ ADS_FILTER_NOSPK
@ ADS_FILTER_NOMESH
@ ADS_FILTER_NOWOR
@ ADS_FILTER_INCL_HIDDEN
@ ADS_FILTER_NOMBA
@ ADS_FILTER_NOLAT
@ AGRP_SELECTED
@ AGRP_EXPANDED_G
@ AGRP_EXPANDED
@ AGRP_PROTECTED
@ AGRP_MUTED
@ ACT_FRAME_RANGE
@ ACT_CYCLIC
@ ADS_FLAG_SHOW_DBFILTERS
@ ADS_FLAG_SUMMARY_COLLAPSED
@ ADS_FLAG_INVERT_FILTER
@ ADS_FLAG_NO_DB_SORT
@ ADS_FLAG_FUZZY_NAMES
@ SACTCONT_GPENCIL
@ SACTCONT_ACTION
@ SACTCONT_TIMELINE
@ SACTCONT_DOPESHEET
@ SACTCONT_SHAPEKEY
@ SACTCONT_MASK
@ SACTCONT_CACHEFILE
@ ADT_CURVES_ALWAYS_VISIBLE
@ INSERTKEY_NOFLAGS
@ FCURVE_DISABLED
#define MAXFRAMEF
#define MINAFRAMEF
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_GRAPH
@ RPT_ERROR_INVALID_INPUT
eAnimCont_Types
eAnimFilter_Flags
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_FCURVESONLY
ParameterFlag
Definition RNA_types.hh:510
@ PARM_RNAPTR
Definition RNA_types.hh:513
@ PARM_REQUIRED
Definition RNA_types.hh:511
FunctionFlag
Definition RNA_types.hh:787
@ FUNC_USE_REPORTS
Definition RNA_types.hh:805
@ FUNC_USE_MAIN
Definition RNA_types.hh:803
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:804
@ FUNC_USE_SELF_ID
Definition RNA_types.hh:792
@ PROP_FLOAT
Definition RNA_types.hh:152
@ PROP_BOOLEAN
Definition RNA_types.hh:150
@ PROP_ENUM
Definition RNA_types.hh:154
@ PROP_INT
Definition RNA_types.hh:151
@ PROP_STRING
Definition RNA_types.hh:153
@ PROP_POINTER
Definition RNA_types.hh:155
@ PROP_COLLECTION
Definition RNA_types.hh:156
@ PROPOVERRIDE_OVERRIDABLE_LIBRARY
Definition RNA_types.hh:469
PropertyFlag
Definition RNA_types.hh:286
@ PROP_THICK_WRAP
Definition RNA_types.hh:397
@ PROP_CONTEXT_UPDATE
Definition RNA_types.hh:381
@ PROP_ANIMATABLE
Definition RNA_types.hh:305
@ PROP_EDITABLE
Definition RNA_types.hh:292
@ PROP_LIB_EXCEPTION
Definition RNA_types.hh:298
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:404
@ PROP_NEVER_NULL
Definition RNA_types.hh:351
@ PROP_NO_DEG_UPDATE
Definition RNA_types.hh:413
@ PROP_TEXTEDIT_UPDATE
Definition RNA_types.hh:312
@ PROP_TIME
Definition RNA_types.hh:241
@ PROP_NONE
Definition RNA_types.hh:221
@ PROP_FACTOR
Definition RNA_types.hh:239
@ PROP_UNSIGNED
Definition RNA_types.hh:237
#define C
Definition RandGen.cpp:29
int UI_icon_from_idcode(int idcode)
#define NC_ANIMATION
Definition WM_types.hh:385
#define NA_EDITED
Definition WM_types.hh:581
ReportList * reports
Definition WM_types.hh:1025
#define NA_RENAME
Definition WM_types.hh:585
#define ND_KEYFRAME
Definition WM_types.hh:491
#define ND_ANIMCHAN
Definition WM_types.hh:493
#define NA_SELECTED
Definition WM_types.hh:586
void ANIM_animdata_freelist(ListBase *anim_data)
Definition anim_deps.cc:463
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, const eAnimFilter_Flags filter_mode, void *data, const eAnimCont_Types datatype)
BMesh const char void * data
PyObject * self
long long int int64_t
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr T * data() const
Definition BLI_span.hh:539
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr int64_t first_index_try(const T &search_value) const
Definition BLI_span.hh:387
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void copy_unsafe(char *dst) const
constexpr int64_t size() const
void slot_active_set(slot_handle_t slot_handle)
void slot_display_name_define(Slot &slot, StringRefNull new_display_name)
void slot_identifier_propagate(Main &bmain, const Slot &slot)
const Slot * slot(int64_t index) const
void slot_idtype_define(Slot &slot, ID_Type idtype)
blender::Span< const Layer * > layers() const
void slot_display_name_set(Main &bmain, Slot &slot, StringRefNull new_display_name)
Slot & slot_add_for_id_type(ID_Type idtype)
blender::Span< const Slot * > slots() const
bool layer_remove(Layer &layer_to_remove)
float2 get_frame_range_of_keys(bool include_modifiers) const ATTR_WARN_UNUSED_RESULT
void slot_identifier_define(Slot &slot, StringRefNull new_identifier)
bool slot_remove(Slot &slot_to_remove)
Slot * slot_for_handle(slot_handle_t handle)
Layer & layer_add(std::optional< StringRefNull > name)
bool channel_group_remove(bActionGroup &group)
bActionGroup & channel_group_create(StringRefNull name)
bool fcurve_remove(FCurve &fcurve_to_remove)
FCurve * fcurve_create_unique(Main *bmain, const FCurveDescriptor &fcurve_descriptor)
const FCurve * fcurve_find(const FCurveDescriptor &fcurve_descriptor) const
blender::Span< const FCurve * > fcurves() const
blender::Span< const bActionGroup * > channel_groups() const
bool strip_remove(Action &owning_action, Strip &strip)
blender::Span< const Strip * > strips() const
const Strip * strip(int64_t index) const
Strip & strip_add(Action &owning_action, Strip::Type strip_type)
std::string idtype_string() const
static constexpr int identifier_length_min
Span< ID * > users(Main &bmain) const
static constexpr slot_handle_t unassigned
StringRefNull identifier_without_prefix() const
const Channelbag * channelbag_for_slot(const Slot &slot) const
int64_t find_channelbag_index(const Channelbag &channelbag) const
Channelbag & channelbag_for_slot_add(const Slot &slot)
SingleKeyingResult keyframe_insert(Main *bmain, const Slot &slot, const FCurveDescriptor &fcurve_descriptor, float2 time_value, const KeyframeSettings &settings, eInsertKeyFlags insert_key_flags=INSERTKEY_NOFLAGS, std::optional< float2 > cycle_range=std::nullopt)
Channelbag & channelbag_for_slot_ensure(const Slot &slot)
blender::Span< const Channelbag * > channelbags() const
bool channelbag_remove(Channelbag &channelbag_to_remove)
const T & data(const Action &owning_action) const
#define SELECT
#define filter
#define printf(...)
#define GS(a)
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define T
Slot & slot_ensure(Action &action)
Channelbag & channelbag_ensure(Action &action)
Channelbag * channelbag_get(Action &action)
bool action_treat_as_legacy(const bAction &action)
KeyframeSettings get_keyframe_settings(bool from_userprefs)
void action_deselect_keys(Action &action)
Slot & duplicate_slot(Action &action, const Slot &slot)
FCurve * action_fcurve_ensure_legacy(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, const FCurveDescriptor &fcurve_descriptor)
bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code)
Action * get_action(ID &animated_id)
FCurve & action_fcurve_ensure(Main *bmain, bAction &action, ID &animated_id, const FCurveDescriptor &fcurve_descriptor)
FCurve * fcurve_find_in_action(bAction *act, const FCurveDescriptor &fcurve_descriptor)
float wrap(float value, float max, float min)
Definition node_math.h:71
const EnumPropertyItem rna_enum_id_type_items[]
Definition rna_ID.cc:29
void rna_iterator_array_end(CollectionPropertyIterator *iter)
void rna_iterator_listbase_end(CollectionPropertyIterator *)
void rna_iterator_array_begin(CollectionPropertyIterator *iter, PointerRNA *ptr, void *data, int itemsize, int length, bool free_ptr, IteratorSkipFunc skip)
const PointerRNA PointerRNA_NULL
void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, PointerRNA *ptr, ListBase *lb, IteratorSkipFunc skip)
void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
void rna_iterator_array_next(CollectionPropertyIterator *iter)
void * rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
void * rna_iterator_listbase_get(CollectionPropertyIterator *iter)
PointerRNA RNA_pointer_create_with_parent(const PointerRNA &parent, StructRNA *type, void *data)
PointerRNA RNA_id_pointer_create(ID *id)
static void rna_def_action_slots(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_channelbag_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_slot(BlenderRNA *brna)
static void rna_def_action_legacy(BlenderRNA *brna, StructRNA *srna)
static void rna_def_channelbag_groups(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_keyframe_strip(BlenderRNA *brna)
static void rna_def_action(BlenderRNA *brna)
static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_ActionLayer_strips(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_channelbag(BlenderRNA *brna)
const EnumPropertyItem default_ActionSlot_target_id_type_items[]
Definition rna_action.cc:76
static void rna_def_dopesheet(BlenderRNA *brna)
static void rna_def_action_layer(BlenderRNA *brna)
static void rna_def_keyframestrip_channelbags(BlenderRNA *brna, PropertyRNA *cprop)
const EnumPropertyItem rna_enum_strip_type_items[]
Definition rna_action.cc:65
void RNA_def_action(BlenderRNA *brna)
static void rna_def_action_layers(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_strip(BlenderRNA *brna)
static void rna_def_action_group(BlenderRNA *brna)
static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop)
void RNA_api_action(StructRNA *srna)
void RNA_def_property_boolean_sdna(PropertyRNA *prop, const char *structname, const char *propname, int64_t booleanbit)
void RNA_def_struct_name_property(StructRNA *srna, PropertyRNA *prop)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
void RNA_def_struct_refine_func(StructRNA *srna, const char *refine)
void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, const char *propname)
void RNA_define_lib_overridable(const bool make_overridable)
void RNA_def_struct_path_func(StructRNA *srna, const char *path)
void RNA_def_parameter_clear_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const char *length, const char *set)
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
void RNA_def_property_string_sdna(PropertyRNA *prop, const char *structname, const char *propname)
void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, int consecutive)
void RNA_def_property_srna(PropertyRNA *prop, const char *type)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_collection_funcs(PropertyRNA *prop, const char *begin, const char *next, const char *end, const char *get, const char *length, const char *lookupint, const char *lookupstring, const char *assignint)
void RNA_def_struct_ui_text(StructRNA *srna, const char *name, const char *description)
PropertyRNA * RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
void RNA_def_property_update_notifier(PropertyRNA *prop, const int noteflag)
void RNA_def_struct_sdna(StructRNA *srna, const char *structname)
FunctionRNA * RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
void RNA_def_property_range(PropertyRNA *prop, double min, double max)
PropertyRNA * RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description)
void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength)
void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const char *propname)
void RNA_def_property_struct_type(PropertyRNA *prop, const char *type)
void RNA_def_property_collection_sdna(PropertyRNA *prop, const char *structname, const char *propname, const char *lengthpropname)
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func)
PropertyRNA * RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
void RNA_def_property_enum_funcs(PropertyRNA *prop, const char *get, const char *set, const char *item)
StructRNA * RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *from)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_def_function_flag(FunctionRNA *func, int flag)
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_property_pointer_funcs(PropertyRNA *prop, const char *get, const char *set, const char *type_fn, const char *poll)
void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const char *propname)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
void RNA_def_struct_ui_icon(StructRNA *srna, int icon)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, const char *propname)
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const char *propname)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_property_boolean_negative_sdna(PropertyRNA *prop, const char *structname, const char *propname, int64_t booleanbit)
void RNA_def_property_override_flag(PropertyRNA *prop, PropertyOverrideFlag flag)
void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
std::optional< std::string > rna_Channelbag_path(const PointerRNA *ptr)
bool rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value)
void rna_def_actionbone_group_common(StructRNA *srna, int update_flag, const char *update_cb)
Definition rna_pose.cc:673
bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:560
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
struct FCurve ** fcurve_array
char identifier[66]
union CollectionPropertyIterator::@277172262001176145116102322066145204253046376362 internal
const char * identifier
Definition RNA_types.hh:623
const char * name
Definition RNA_types.hh:627
const char * description
Definition RNA_types.hh:629
struct FCurve * next
bActionGroup * grp
char * rna_path
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * first
ID * owner_id
Definition RNA_types.hh:51
void invalidate()
Definition RNA_types.hh:110
void * data
Definition RNA_types.hh:53
struct bDopeSheet * ads
struct bDopeSheet * ads
unsigned int flag
ListBase curves
float frame_start
ListBase groups
ListBase markers
eAnimCont_Types datatype
bDopeSheet * ads
ListBase areabase
std::optional< blender::StringRefNull > channel_group
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
void WM_global_report(eReportType type, const char *message)
void WM_main_add_notifier(uint type, void *reference)
void WM_global_reportf(eReportType type, const char *format,...)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4226