Blender V5.0
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_fcurve.hh"
20#include "BKE_report.hh"
21
22#include "RNA_access.hh"
23#include "RNA_define.hh"
24#include "RNA_enum_types.hh"
25
26#include "rna_internal.hh"
27
28#include "ANIM_action.hh"
29
30#include "WM_types.hh"
31
32using namespace blender;
33
34/* Disabled for now, see comment in `rna_def_action_layer()` for more info. */
35#if 0
36const EnumPropertyItem rna_enum_layer_mix_mode_items[] = {
37 {int(animrig::Layer::MixMode::Replace),
38 "REPLACE",
39 0,
40 "Replace",
41 "Channels in this layer override the same channels from underlying layers"},
42 {int(animrig::Layer::MixMode::Offset),
43 "OFFSET",
44 0,
45 "Offset",
46 "Channels in this layer are added to underlying layers as sequential operations"},
47 {int(animrig::Layer::MixMode::Add),
48 "ADD",
49 0,
50 "Add",
51 "Channels in this layer are added to underlying layers on a per-channel basis"},
52 {int(animrig::Layer::MixMode::Subtract),
53 "SUBTRACT",
54 0,
55 "Subtract",
56 "Channels in this layer are subtracted to underlying layers on a per-channel basis"},
57 {int(animrig::Layer::MixMode::Multiply),
58 "MULTIPLY",
59 0,
60 "Multiply",
61 "Channels in this layer are multiplied with underlying layers on a per-channel basis"},
62 {0, nullptr, 0, nullptr, nullptr},
63};
64#endif
65
67 {int(animrig::Strip::Type::Keyframe),
68 "KEYFRAME",
69 0,
70 "Keyframe",
71 "Strip containing keyframes on F-Curves"},
72 {0, nullptr, 0, nullptr, nullptr},
73};
74
75/* Cannot use rna_enum_dummy_DEFAULT_items because the UNSPECIFIED entry needs
76 * to exist as it is the default. */
78 {0,
79 "UNSPECIFIED",
80 ICON_NONE,
81 "Unspecified",
82 "Not yet specified. When this slot is first assigned to a data-block, this will be set to "
83 "the type of that data-block"},
84 {0, nullptr, 0, nullptr, nullptr},
85};
86
87#ifdef RNA_RUNTIME
88
89# include <algorithm>
90
91# include "BLI_math_base.h"
92# include "BLI_string.h"
93# include "BLI_string_utf8.h"
94
95# include "BKE_fcurve.hh"
96# include "BKE_main.hh"
97# include "BKE_report.hh"
98
99# include "DEG_depsgraph.hh"
100
101# include "ANIM_action.hh"
102# include "ANIM_animdata.hh"
103# include "ED_anim_api.hh"
104
105# include "WM_api.hh"
106
107# include "UI_interface_icons.hh"
108
109# include "ANIM_action_legacy.hh"
110# include "ANIM_fcurve.hh"
111# include "ANIM_keyframing.hh"
112
113# include <fmt/format.h>
114
115static animrig::Action &rna_action(const PointerRNA *ptr)
116{
117 return reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
118}
119
120static animrig::Slot &rna_data_slot(const PointerRNA *ptr)
121{
122 BLI_assert(ptr->type == &RNA_ActionSlot);
123 return reinterpret_cast<ActionSlot *>(ptr->data)->wrap();
124}
125
126static animrig::Layer &rna_data_layer(const PointerRNA *ptr)
127{
128 return reinterpret_cast<ActionLayer *>(ptr->data)->wrap();
129}
130
131static animrig::Strip &rna_data_strip(const PointerRNA *ptr)
132{
133 return reinterpret_cast<ActionStrip *>(ptr->data)->wrap();
134}
135
136/* Disabled for now, see comment in `rna_def_action_layer()` for more info. */
137# if 0
138static void rna_Action_tag_animupdate(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
139{
140 animrig::Action &action = rna_action(ptr);
142}
143# endif
144
145static animrig::Channelbag &rna_data_channelbag(const PointerRNA *ptr)
146{
147 return reinterpret_cast<ActionChannelbag *>(ptr->data)->wrap();
148}
149
150template<typename T>
153 Span<T *> items)
154{
155 rna_iterator_array_begin(iter, ptr, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
156}
157
158template<typename T>
161 MutableSpan<T *> items)
162{
163 rna_iterator_array_begin(iter, ptr, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
164}
165
166static PointerRNA rna_ActionSlots_active_get(PointerRNA *ptr)
167{
168 animrig::Action &action = rna_action(ptr);
169 animrig::Slot *active_slot = action.slot_active_get();
170
171 if (!active_slot) {
172 return PointerRNA_NULL;
173 }
174 return RNA_pointer_create_discrete(&action.id, &RNA_ActionSlot, active_slot);
175}
176
177static void rna_ActionSlots_active_set(PointerRNA *ptr,
178 PointerRNA value,
179 struct ReportList * /*reports*/)
180{
181 animrig::Action &action = rna_action(ptr);
182
183 if (value.data) {
184 animrig::Slot &slot = rna_data_slot(&value);
185 action.slot_active_set(slot.handle);
186 }
187 else {
189 }
190}
191
192static ActionSlot *rna_Action_slots_new(
193 bAction *dna_action, Main *bmain, bContext *C, ReportList *reports, int type, const char *name)
194{
195 animrig::Action &action = dna_action->wrap();
196
197 if (!action.is_action_layered()) {
198 BKE_reportf(reports,
199 RPT_ERROR,
200 "Cannot add slots to a legacy Action '%s'. Convert it to a layered Action first.",
201 action.id.name + 2);
202 return nullptr;
203 }
204
205 if (name[0] == 0) {
206 BKE_reportf(reports, RPT_ERROR, "Invalid slot name '%s': name must not be empty.", name);
207 return nullptr;
208 }
209
210 animrig::Slot *slot = &action.slot_add_for_id_type(ID_Type(type));
211 action.slot_display_name_set(*bmain, *slot, name);
212
214 return slot;
215}
216
217void rna_Action_slots_remove(bAction *dna_action,
218 bContext *C,
219 ReportList *reports,
220 PointerRNA *slot_ptr)
221{
222 animrig::Action &action = dna_action->wrap();
223 animrig::Slot &slot = rna_data_slot(slot_ptr);
224 if (!action.slot_remove(slot)) {
225 BKE_report(reports, RPT_ERROR, "This slot does not belong to this Action");
226 return;
227 }
228
229 slot_ptr->invalidate();
232}
233
234static void rna_iterator_action_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
235{
236 animrig::Action &action = rna_action(ptr);
237 rna_iterator_array_begin(iter, ptr, action.layers());
238}
239
240static int rna_iterator_action_layers_length(PointerRNA *ptr)
241{
242 animrig::Action &action = rna_action(ptr);
243 return action.layers().size();
244}
245
246static ActionLayer *rna_Action_layers_new(bAction *dna_action,
247 bContext *C,
248 ReportList *reports,
249 const char *name)
250{
251 animrig::Action &action = dna_action->wrap();
252
253 if (!action.is_action_layered()) {
254 BKE_reportf(reports,
255 RPT_ERROR,
256 "Cannot add layers to a legacy Action '%s'. Convert it to a layered Action first.",
257 action.id.name + 2);
258 return nullptr;
259 }
260
261 if (action.layers().size() >= 1) {
262 /* Not allowed to have more than one layer, for now. This limitation is in
263 * place until working with multiple animated IDs is fleshed out better. */
264 BKE_report(reports, RPT_ERROR, "An Action may not have more than one layer");
265 return nullptr;
266 }
267
268 animrig::Layer &layer = action.layer_add(name);
269
271 return &layer;
272}
273
274void rna_Action_layers_remove(bAction *dna_action,
275 bContext *C,
276 ReportList *reports,
277 PointerRNA *layer_ptr)
278{
279 animrig::Action &action = dna_action->wrap();
280 animrig::Layer &layer = rna_data_layer(layer_ptr);
281 if (!action.layer_remove(layer)) {
282 BKE_report(reports, RPT_ERROR, "This layer does not belong to this Action");
283 return;
284 }
285
286 layer_ptr->invalidate();
289}
290
291static void rna_iterator_animation_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
292{
293 animrig::Action &action = rna_action(ptr);
294 rna_iterator_array_begin(iter, ptr, action.slots());
295}
296
297static int rna_iterator_animation_slots_length(PointerRNA *ptr)
298{
299 animrig::Action &action = rna_action(ptr);
300 return action.slots().size();
301}
302
303static std::optional<std::string> rna_ActionSlot_path(const PointerRNA *ptr)
304{
305 animrig::Slot &slot = rna_data_slot(ptr);
306
307 char identifier_esc[sizeof(slot.identifier) * 2];
308 BLI_str_escape(identifier_esc, slot.identifier, sizeof(identifier_esc));
309 return fmt::format("slots[\"{}\"]", identifier_esc);
310}
311
312int rna_ActionSlot_target_id_type_icon_get(PointerRNA *ptr)
313{
314 animrig::Slot &slot = rna_data_slot(ptr);
315 return UI_icon_from_idcode(slot.idtype);
316}
317
318/* Name functions that ignore the first two ID characters */
319void rna_ActionSlot_name_display_get(PointerRNA *ptr, char *value)
320{
321 animrig::Slot &slot = rna_data_slot(ptr);
323}
324
325int rna_ActionSlot_name_display_length(PointerRNA *ptr)
326{
327 animrig::Slot &slot = rna_data_slot(ptr);
328 return slot.identifier_without_prefix().size();
329}
330
331static void rna_ActionSlot_name_display_set(PointerRNA *ptr, const char *name)
332{
333 animrig::Action &action = rna_action(ptr);
334 animrig::Slot &slot = rna_data_slot(ptr);
335 const StringRef name_ref(name);
336
337 if (name_ref.is_empty()) {
338 WM_global_report(RPT_ERROR, "Action slot display names cannot be empty");
339 return;
340 }
341
342 action.slot_display_name_define(slot, name);
343}
344
345static void rna_ActionSlot_identifier_set(PointerRNA *ptr, const char *identifier)
346{
347 animrig::Action &action = rna_action(ptr);
348 animrig::Slot &slot = rna_data_slot(ptr);
349 const StringRef identifier_ref(identifier);
350
351 if (identifier_ref.size() < animrig::Slot::identifier_length_min) {
352 WM_global_report(RPT_ERROR, "Action slot identifiers should be at least three characters");
353 return;
354 }
355
356 /* Sanity check. These should never be out of sync in higher-level code. */
358
359 const std::string identifier_with_correct_prefix = slot.idtype_string() +
360 identifier_ref.substr(2);
361
362 if (identifier_with_correct_prefix != identifier_ref) {
365 "Attempted to set slot identifier to \"%s\", but the type prefix does not match the "
366 "slot's 'target_id_type' \"%s\". Setting to \"%s\" instead.\n",
367 identifier,
368 slot.idtype_string().c_str(),
369 identifier_with_correct_prefix.c_str());
370 }
371
372 action.slot_identifier_define(slot, identifier_with_correct_prefix);
373}
374
375static void rna_ActionSlot_identifier_update(Main *bmain, Scene *, PointerRNA *ptr)
376{
377 animrig::Action &action = rna_action(ptr);
378 animrig::Slot &slot = rna_data_slot(ptr);
379 action.slot_identifier_propagate(*bmain, slot);
380}
381
382static CollectionVector rna_ActionSlot_users(struct ActionSlot *self, Main *bmain)
383{
384 animrig::Slot &slot = self->wrap();
385 const Span<ID *> slot_users = slot.users(*bmain);
386
388 vector.items.resize(slot_users.size());
389 for (const int i : slot_users.index_range()) {
390 vector.items[i] = RNA_id_pointer_create(slot_users[i]);
391 }
392
393 return vector;
394}
395
396static ActionSlot *rna_ActionSlot_duplicate(ID *action_id, const ActionSlot *self)
397{
398 animrig::Action &action = reinterpret_cast<bAction *>(action_id)->wrap();
399 const animrig::Slot &source_slot = self->wrap();
400
401 animrig::Slot &dupli_slot = animrig::duplicate_slot(action, source_slot);
402 return &dupli_slot;
403}
404
405static std::optional<std::string> rna_ActionLayer_path(const PointerRNA *ptr)
406{
407 animrig::Layer &layer = rna_data_layer(ptr);
408
409 char name_esc[sizeof(layer.name) * 2];
410 BLI_str_escape(name_esc, layer.name, sizeof(name_esc));
411 return fmt::format("layers[\"{}\"]", name_esc);
412}
413
414static void rna_iterator_ActionLayer_strips_begin(CollectionPropertyIterator *iter,
416{
417 animrig::Layer &layer = rna_data_layer(ptr);
418 rna_iterator_array_begin(iter, ptr, layer.strips());
419}
420
421static int rna_iterator_ActionLayer_strips_length(PointerRNA *ptr)
422{
423 animrig::Layer &layer = rna_data_layer(ptr);
424 return layer.strips().size();
425}
426
427static StructRNA *rna_ActionStrip_refine(PointerRNA *ptr)
428{
429 animrig::Strip &strip = static_cast<ActionStrip *>(ptr->data)->wrap();
430
431 switch (strip.type()) {
432 case animrig::Strip::Type::Keyframe:
433 return &RNA_ActionKeyframeStrip;
434 }
435 return &RNA_UnknownType;
436}
437
438ActionStrip *rna_ActionStrips_new(
439 ID *dna_action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, const int type)
440{
441 const animrig::Strip::Type strip_type = animrig::Strip::Type(type);
442
443 animrig::Layer &layer = dna_layer->wrap();
444
445 if (layer.strips().size() >= 1) {
446 /* Not allowed to have more than one strip, for now. This limitation is in
447 * place until working with layers is fleshed out better. */
448 BKE_report(reports, RPT_ERROR, "A layer may not have more than one strip");
449 return nullptr;
450 }
451
452 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
453 animrig::Strip &strip = layer.strip_add(action, strip_type);
454
456 return &strip;
457}
458
459void rna_ActionStrips_remove(
460 ID *action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, PointerRNA *strip_ptr)
461{
462 animrig::Action &action = reinterpret_cast<bAction *>(action_id)->wrap();
463 animrig::Layer &layer = dna_layer->wrap();
464 animrig::Strip &strip = rna_data_strip(strip_ptr);
465 if (!layer.strip_remove(action, strip)) {
466 BKE_report(reports, RPT_ERROR, "This strip does not belong to this layer");
467 return;
468 }
469
470 strip_ptr->invalidate();
473}
474
475static std::optional<std::string> rna_ActionStrip_path(const PointerRNA *ptr)
476{
477 animrig::Action &action = rna_action(ptr);
478 animrig::Strip &strip_to_find = rna_data_strip(ptr);
479
480 for (animrig::Layer *layer : action.layers()) {
481 Span<animrig::Strip *> strips = layer->strips();
482 const int index = strips.first_index_try(&strip_to_find);
483 if (index < 0) {
484 continue;
485 }
486
487 PointerRNA layer_ptr = RNA_pointer_create_discrete(&action.id, &RNA_ActionLayer, layer);
488 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
489 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
490 const std::string strip_path = fmt::format("{}.strips[{}]", *layer_path, index);
491 return strip_path;
492 }
493
494 return std::nullopt;
495}
496
497static void rna_iterator_keyframestrip_channelbags_begin(CollectionPropertyIterator *iter,
499{
500 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
501 animrig::Strip &strip = rna_data_strip(ptr);
503 iter, ptr, strip.data<animrig::StripKeyframeData>(action).channelbags());
504}
505
506static int rna_iterator_keyframestrip_channelbags_length(PointerRNA *ptr)
507{
508 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
509 animrig::Strip &strip = rna_data_strip(ptr);
510 return strip.data<animrig::StripKeyframeData>(action).channelbags().size();
511}
512
513static ActionChannelbag *rna_Channelbags_new(ID *dna_action_id,
514 ActionStrip *dna_strip,
515 bContext *C,
516 ReportList *reports,
517 ActionSlot *dna_slot)
518{
519 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
520 animrig::Strip &strip = dna_strip->wrap();
522 animrig::Slot &slot = dna_slot->wrap();
523
524 if (strip_data.channelbag_for_slot(slot) != nullptr) {
525 BKE_report(reports, RPT_ERROR, "A channelbag for this slot already exists");
526 return nullptr;
527 }
528
529 animrig::Channelbag &channelbag = strip_data.channelbag_for_slot_add(slot);
530
532 /* No need to tag the depsgraph, as there is no new animation yet. */
533
534 return &channelbag;
535}
536
537static void rna_Channelbags_remove(ID *dna_action_id,
538 ActionStrip *dna_strip,
539 bContext *C,
540 ReportList *reports,
541 PointerRNA *channelbag_ptr)
542{
543 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
544 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
545 action);
546 animrig::Channelbag &channelbag = rna_data_channelbag(channelbag_ptr);
547
548 if (!strip_data.channelbag_remove(channelbag)) {
549 BKE_report(reports, RPT_ERROR, "This channelbag does not belong to this strip");
550 return;
551 }
552
553 channelbag_ptr->invalidate();
556}
557
558static bool rna_ActionStrip_key_insert(ID *dna_action_id,
559 ActionStrip *dna_strip,
560 Main *bmain,
561 ReportList *reports,
562 ActionSlot *dna_slot,
563 const char *rna_path,
564 const int array_index,
565 const float value,
566 const float time)
567{
568 if (dna_slot == nullptr) {
569 BKE_report(reports, RPT_ERROR, "Slot cannot be None");
570 return false;
571 }
572
573 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
574 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
575 action);
576 const animrig::Slot &slot = dna_slot->wrap();
578
580 bmain, slot, {rna_path, array_index}, {time, value}, settings, INSERTKEY_NOFLAGS);
581
583 if (ok) {
584 DEG_id_tag_update_ex(bmain, dna_action_id, ID_RECALC_ANIMATION);
585 }
586
587 return ok;
588}
589
590std::optional<std::string> rna_Channelbag_path(const PointerRNA *ptr)
591{
592 animrig::Action &action = rna_action(ptr);
593 animrig::Channelbag &cbag_to_find = rna_data_channelbag(ptr);
594
595 for (animrig::Layer *layer : action.layers()) {
596 for (int64_t strip_index : layer->strips().index_range()) {
597 const animrig::Strip *strip = layer->strip(strip_index);
598 if (strip->type() != animrig::Strip::Type::Keyframe) {
599 continue;
600 }
601
603 action);
604 const int64_t index = strip_data.find_channelbag_index(cbag_to_find);
605 if (index < 0) {
606 continue;
607 }
608
609 PointerRNA layer_ptr = RNA_pointer_create_discrete(&action.id, &RNA_ActionLayer, layer);
610 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
611 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
612 return fmt::format("{}.strips[{}].channelbags[{}]", *layer_path, strip_index, index);
613 }
614 }
615
616 return std::nullopt;
617}
618
619static PointerRNA rna_Channelbag_slot_get(PointerRNA *ptr)
620{
621 animrig::Action &action = rna_action(ptr);
622 animrig::Channelbag &channelbag = rna_data_channelbag(ptr);
623 animrig::Slot *slot = action.slot_for_handle(channelbag.slot_handle);
624 BLI_assert(slot);
625
626 return RNA_pointer_create_with_parent(*ptr, &RNA_ActionSlot, slot);
627}
628
629static void rna_iterator_Channelbag_fcurves_begin(CollectionPropertyIterator *iter,
631{
632 animrig::Channelbag &bag = rna_data_channelbag(ptr);
634}
635
636static int rna_iterator_Channelbag_fcurves_length(PointerRNA *ptr)
637{
638 animrig::Channelbag &bag = rna_data_channelbag(ptr);
639 return bag.fcurves().size();
640}
641
642static FCurve *rna_Channelbag_fcurve_new(ActionChannelbag *dna_channelbag,
643 Main *bmain,
644 ReportList *reports,
645 const char *data_path,
646 const int index,
647 const char *group_name)
648{
649 BLI_assert(data_path != nullptr);
650 if (data_path[0] == '\0') {
651 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
652 return nullptr;
653 }
654
655 blender::animrig::FCurveDescriptor descr = {data_path, index};
656 if (group_name && group_name[0]) {
657 descr.channel_group = {group_name};
658 }
659
660 animrig::Channelbag &self = dna_channelbag->wrap();
661 FCurve *fcurve = self.fcurve_create_unique(bmain, descr);
662 if (!fcurve) {
663 BKE_reportf(reports,
664 RPT_ERROR,
665 "F-Curve '%s[%d]' already exists in this channelbag",
666 data_path,
667 index);
668 return nullptr;
669 }
670 return fcurve;
671}
672
673static FCurve *rna_Channelbag_fcurve_new_from_fcurve(ID *dna_action_id,
674 ActionChannelbag *dna_channelbag,
675 ReportList *reports,
676 FCurve *source,
677 const char *data_path)
678{
679 animrig::Channelbag &self = dna_channelbag->wrap();
680
681 if (!data_path) {
682 data_path = source->rna_path;
683 }
684
685 if (self.fcurve_find({data_path, source->array_index})) {
686 BKE_reportf(reports,
687 RPT_ERROR,
688 "F-Curve '%s[%d]' already exists in this channelbag",
689 data_path,
690 source->array_index);
691 return nullptr;
692 }
693 FCurve *copy = BKE_fcurve_copy(source);
694 MEM_SAFE_FREE(copy->rna_path);
695 copy->rna_path = BLI_strdupn(data_path, strlen(data_path));
696 self.fcurve_append(*copy);
697
699
700 return copy;
701}
702
703static FCurve *rna_Channelbag_fcurve_ensure(ActionChannelbag *dna_channelbag,
704 Main *bmain,
705 ReportList *reports,
706 const char *data_path,
707 const int index,
708 const char *group_name)
709{
710 BLI_assert(data_path != nullptr);
711 if (data_path[0] == '\0') {
712 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
713 return nullptr;
714 }
715
716 blender::animrig::FCurveDescriptor descr = {data_path, index};
717 if (group_name && group_name[0]) {
718 descr.channel_group = {group_name};
719 }
720
721 animrig::Channelbag &self = dna_channelbag->wrap();
722 FCurve &fcurve = self.fcurve_ensure(bmain, descr);
723 return &fcurve;
724}
725
726static FCurve *rna_Channelbag_fcurve_find(ActionChannelbag *dna_channelbag,
727 ReportList *reports,
728 const char *data_path,
729 const int index)
730{
731 if (data_path[0] == '\0') {
732 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
733 return nullptr;
734 }
735
736 animrig::Channelbag &self = dna_channelbag->wrap();
737 return self.fcurve_find({data_path, index});
738}
739
740static void rna_Channelbag_fcurve_remove(ID *dna_action_id,
741 ActionChannelbag *dna_channelbag,
742 bContext *C,
743 ReportList *reports,
744 PointerRNA *fcurve_ptr)
745{
746 animrig::Channelbag &self = dna_channelbag->wrap();
747 FCurve *fcurve = static_cast<FCurve *>(fcurve_ptr->data);
748
749 if (!self.fcurve_remove(*fcurve)) {
750 BKE_reportf(reports, RPT_ERROR, "F-Curve not found");
751 return;
752 }
753
756}
757
758static void rna_Channelbag_fcurve_clear(ID *dna_action_id,
759 ActionChannelbag *dna_channelbag,
760 bContext *C)
761{
762 dna_channelbag->wrap().fcurves_clear();
765}
766
767static void rna_iterator_Channelbag_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
768{
769 animrig::Channelbag &bag = rna_data_channelbag(ptr);
771}
772
773static int rna_iterator_Channelbag_groups_length(PointerRNA *ptr)
774{
775 animrig::Channelbag &bag = rna_data_channelbag(ptr);
776 return bag.channel_groups().size();
777}
778
779static bActionGroup *rna_Channelbag_group_new(ActionChannelbag *dna_channelbag, const char *name)
780{
781 BLI_assert(name != nullptr);
782
783 animrig::Channelbag &self = dna_channelbag->wrap();
784 return &self.channel_group_create(name);
785}
786
787static void rna_Channelbag_group_remove(ActionChannelbag *dna_channelbag,
788 ReportList *reports,
789 PointerRNA *agrp_ptr)
790{
791 animrig::Channelbag &self = dna_channelbag->wrap();
792
793 bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
794
795 if (!self.channel_group_remove(*agrp)) {
796 BKE_report(reports,
797 RPT_ERROR,
798 "Could not remove the F-Curve Group from the collection because it does not exist "
799 "in the collection");
800 return;
801 }
802
803 agrp_ptr->invalidate();
805}
806
807static ActionChannelbag *rna_ActionStrip_channelbag(ID *dna_action_id,
809 ReportList *reports,
810 const ActionSlot *dna_slot,
811 const bool ensure)
812{
813 if (!dna_slot) {
814 BKE_report(reports, RPT_ERROR, "Cannot return channelbag when slot is None");
815 return nullptr;
816 }
817
818 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
819 animrig::StripKeyframeData &strip_data = self->wrap().data<animrig::StripKeyframeData>(action);
820 const animrig::Slot &slot = dna_slot->wrap();
821
822 if (ensure) {
823 return &strip_data.channelbag_for_slot_ensure(slot);
824 }
825 return strip_data.channelbag_for_slot(slot);
826}
827
838struct ActionGroupChannelsIterator {
839 /* Which kind of iterator it is. */
840 enum {
841 ARRAY,
842 LISTBASE,
843 } tag;
844
845 union {
846 ArrayIterator array;
847 ListBaseIterator listbase;
848 };
849};
850
851static void rna_ActionGroup_channels_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
852{
853 bActionGroup *group = (bActionGroup *)ptr->data;
854
855 ActionGroupChannelsIterator *custom_iter = MEM_callocN<ActionGroupChannelsIterator>(__func__);
856
857 iter->internal.custom = custom_iter;
858
859 /* We handle both the listbase (legacy action) and array (layered action)
860 * cases below. The code for each is based on the code in
861 * `rna_iterator_listbase_begin()` and `rna_iterator_array_begin()`,
862 * respectively. */
863
864 /* Group from a legacy action. */
865 if (group->wrap().is_legacy()) {
866 custom_iter->tag = ActionGroupChannelsIterator::LISTBASE;
867 custom_iter->listbase.link = static_cast<Link *>(group->channels.first);
868
869 iter->valid = custom_iter->listbase.link != nullptr;
870 return;
871 }
872
873 /* Group from a layered action. */
874 animrig::Channelbag &cbag = group->channelbag->wrap();
875
876 custom_iter->tag = ActionGroupChannelsIterator::ARRAY;
877 custom_iter->array.ptr = reinterpret_cast<char *>(cbag.fcurve_array + group->fcurve_range_start);
878 custom_iter->array.endptr = reinterpret_cast<char *>(
879 cbag.fcurve_array + group->fcurve_range_start + group->fcurve_range_length);
880 custom_iter->array.itemsize = sizeof(FCurve *);
881 custom_iter->array.length = group->fcurve_range_length;
882
883 iter->valid = group->fcurve_range_length > 0;
884}
885
886static void rna_ActionGroup_channels_end(CollectionPropertyIterator *iter)
887{
889}
890
891static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter)
892{
893 BLI_assert(iter->internal.custom != nullptr);
894 BLI_assert(iter->valid);
895
896 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
897 iter->internal.custom);
898
899 /* The code for both cases here is written based on the code in
900 * `rna_iterator_array_next()` and `rna_iterator_listbase_next()`,
901 * respectively. */
902 switch (custom_iter->tag) {
903 case ActionGroupChannelsIterator::ARRAY: {
904 custom_iter->array.ptr += custom_iter->array.itemsize;
905 iter->valid = (custom_iter->array.ptr != custom_iter->array.endptr);
906 break;
907 }
908 case ActionGroupChannelsIterator::LISTBASE: {
909 FCurve *fcurve = (FCurve *)custom_iter->listbase.link;
910 bActionGroup *grp = fcurve->grp;
911 /* Only continue if the next F-Curve (if existent) belongs in the same
912 * group. */
913 if ((fcurve->next) && (fcurve->next->grp == grp)) {
914 custom_iter->listbase.link = custom_iter->listbase.link->next;
915 iter->valid = (custom_iter->listbase.link != nullptr);
916 }
917 else {
918 custom_iter->listbase.link = nullptr;
919 iter->valid = false;
920 }
921 break;
922 }
923 }
924}
925
926static PointerRNA rna_ActionGroup_channels_get(CollectionPropertyIterator *iter)
927{
928 BLI_assert(iter->internal.custom != nullptr);
929 BLI_assert(iter->valid);
930 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
931 iter->internal.custom);
932
933 FCurve *fcurve;
934 switch (custom_iter->tag) {
935 case ActionGroupChannelsIterator::ARRAY:
936 fcurve = *reinterpret_cast<FCurve **>(custom_iter->array.ptr);
937 break;
938 case ActionGroupChannelsIterator::LISTBASE:
939 fcurve = reinterpret_cast<FCurve *>(custom_iter->listbase.link);
940 break;
941 }
942
943 return RNA_pointer_create_with_parent(iter->parent, &RNA_FCurve, fcurve);
944}
945
946static TimeMarker *rna_Action_pose_markers_new(bAction *act, const char name[])
947{
948 TimeMarker *marker = MEM_callocN<TimeMarker>("TimeMarker");
949 marker->flag = SELECT;
950 marker->frame = 1;
951 STRNCPY_UTF8(marker->name, name);
952 BLI_addtail(&act->markers, marker);
953 return marker;
954}
955
956static void rna_Action_pose_markers_remove(bAction *act,
957 ReportList *reports,
958 PointerRNA *marker_ptr)
959{
960 TimeMarker *marker = static_cast<TimeMarker *>(marker_ptr->data);
961 if (!BLI_remlink_safe(&act->markers, marker)) {
962 BKE_reportf(reports,
963 RPT_ERROR,
964 "Timeline marker '%s' not found in action '%s'",
965 marker->name,
966 act->id.name + 2);
967 return;
968 }
969
970 MEM_freeN(marker);
971 marker_ptr->invalidate();
972}
973
974static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr)
975{
976 bAction *act = (bAction *)ptr->data;
978 *ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker - 1));
979}
980
981static void rna_Action_active_pose_marker_set(PointerRNA *ptr,
982 PointerRNA value,
983 ReportList * /*reports*/)
984{
985 bAction *act = (bAction *)ptr->data;
986 act->active_marker = BLI_findindex(&act->markers, value.data) + 1;
987}
988
989static int rna_Action_active_pose_marker_index_get(PointerRNA *ptr)
990{
991 bAction *act = (bAction *)ptr->data;
992 return std::max(act->active_marker - 1, 0);
993}
994
995static void rna_Action_active_pose_marker_index_set(PointerRNA *ptr, int value)
996{
997 bAction *act = (bAction *)ptr->data;
998 act->active_marker = value + 1;
999}
1000
1001static void rna_Action_active_pose_marker_index_range(
1002 PointerRNA *ptr, int *min, int *max, int * /*softmin*/, int * /*softmax*/)
1003{
1004 bAction *act = (bAction *)ptr->data;
1005
1006 *min = 0;
1007 *max = max_ii(0, BLI_listbase_count(&act->markers) - 1);
1008}
1009
1010static bool rna_Action_is_empty_get(PointerRNA *ptr)
1011{
1012 animrig::Action &action = rna_action(ptr);
1013 return action.is_empty();
1014}
1015static bool rna_Action_is_action_legacy_get(PointerRNA *ptr)
1016{
1017 return rna_action(ptr).is_action_legacy();
1018}
1019static bool rna_Action_is_action_layered_get(PointerRNA *ptr)
1020{
1021 return rna_action(ptr).is_action_layered();
1022}
1023
1024static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values)
1025{
1026 const float2 frame_range = rna_action(ptr).get_frame_range();
1027 r_values[0] = frame_range[0];
1028 r_values[1] = frame_range[1];
1029}
1030
1031static void rna_Action_frame_range_set(PointerRNA *ptr, const float *values)
1032{
1033 bAction *data = (bAction *)ptr->owner_id;
1034
1035 data->flag |= ACT_FRAME_RANGE;
1036 data->frame_start = values[0];
1037 data->frame_end = values[1];
1038 CLAMP_MIN(data->frame_end, data->frame_start);
1039}
1040
1041static void rna_Action_curve_frame_range_get(PointerRNA *ptr, float *values)
1042{ /* don't include modifiers because they too easily can have very large
1043 * ranges: MINAFRAMEF to MAXFRAMEF. */
1044 const float2 frame_range = rna_action(ptr).get_frame_range_of_keys(false);
1045 values[0] = frame_range[0];
1046 values[1] = frame_range[1];
1047}
1048
1049static void rna_Action_use_frame_range_set(PointerRNA *ptr, bool value)
1050{
1051 animrig::Action &action = rna_action(ptr);
1052
1053 if (value) {
1054 /* If the frame range is blank, initialize it by scanning F-Curves. */
1055 if ((action.frame_start == action.frame_end) && (action.frame_start == 0)) {
1056 const float2 frame_range = action.get_frame_range_of_keys(false);
1057 action.frame_start = frame_range[0];
1058 action.frame_end = frame_range[1];
1059 }
1060
1061 action.flag |= ACT_FRAME_RANGE;
1062 }
1063 else {
1064 action.flag &= ~ACT_FRAME_RANGE;
1065 }
1066}
1067
1068static void rna_Action_start_frame_set(PointerRNA *ptr, float value)
1069{
1070 bAction *data = (bAction *)ptr->owner_id;
1071
1072 data->frame_start = value;
1073 CLAMP_MIN(data->frame_end, data->frame_start);
1074}
1075
1076static void rna_Action_end_frame_set(PointerRNA *ptr, float value)
1077{
1078 bAction *data = (bAction *)ptr->owner_id;
1079
1080 data->frame_end = value;
1081 CLAMP_MAX(data->frame_start, data->frame_end);
1082}
1083
1084static void rna_Action_deselect_keys(bAction *act)
1085{
1086 animrig::action_deselect_keys(act->wrap());
1088}
1089
1090static FCurve *rna_Action_fcurve_ensure_for_datablock(bAction *_self,
1091 Main *bmain,
1092 ReportList *reports,
1093 ID *datablock,
1094 const char *data_path,
1095 const int array_index,
1096 const char *group_name)
1097{
1098 /* Precondition checks. */
1099 {
1100 if (blender::animrig::get_action(*datablock) != _self) {
1101 BKE_reportf(reports,
1103 "Assign action \"%s\" to \"%s\" before calling this function",
1104 _self->id.name + 2,
1105 datablock->name + 2);
1106 return nullptr;
1107 }
1108
1109 BLI_assert(data_path != nullptr);
1110 if (data_path[0] == '\0') {
1111 BKE_report(reports, RPT_ERROR_INVALID_INPUT, "F-Curve data path empty, invalid argument");
1112 return nullptr;
1113 }
1114 }
1115
1116 blender::animrig::FCurveDescriptor descriptor = {data_path, array_index};
1117 if (group_name && group_name[0]) {
1118 descriptor.channel_group = group_name;
1119 }
1120
1121 FCurve &fcurve = blender::animrig::action_fcurve_ensure(bmain, *_self, *datablock, descriptor);
1122
1124 return &fcurve;
1125}
1126
1132{
1133 ID *srcId = ptr->owner_id;
1134 bAction *dna_action = (bAction *)value.owner_id;
1135
1136 if (!dna_action) {
1137 return false;
1138 }
1139
1140 animrig::Action &action = dna_action->wrap();
1142 /* there can still be actions that will have undefined id-root
1143 * (i.e. floating "action-library" members) which we will not
1144 * be able to resolve an idroot for automatically, so let these through
1145 */
1146 if (action.idroot == 0) {
1147 return true;
1148 }
1149 if (srcId) {
1150 return GS(srcId->name) == action.idroot;
1151 }
1152 }
1153
1154 /* Layered Actions can always be assigned. */
1155 BLI_assert(action.idroot == 0);
1156 return true;
1157}
1158
1164{
1165 SpaceAction *saction = (SpaceAction *)ptr->data;
1166 bAction *action = (bAction *)value.owner_id;
1167
1168 if (!saction) {
1169 /* Unable to determine what this Action is going to be assigned to, so
1170 * reject it for now. This is mostly to have a non-functional refactor of
1171 * this code; personally I (Sybren) wouldn't mind to always return `true` in
1172 * this case. */
1173 return false;
1174 }
1175
1176 switch (saction->mode) {
1177 case SACTCONT_ACTION:
1179 case SACTCONT_SHAPEKEY:
1181 case SACTCONT_GPENCIL:
1182 case SACTCONT_DOPESHEET:
1183 case SACTCONT_MASK:
1184 case SACTCONT_CACHEFILE:
1185 break;
1186 }
1187
1188 /* Same as above, I (Sybren) wouldn't mind returning `true` here to just
1189 * always show all Actions in an unexpected place. */
1190 return false;
1191}
1192
1197static void reevaluate_fcurve_errors(bAnimContext *ac)
1198{
1199 /* Need to take off the flag before filtering, else the filter code would skip the FCurves, which
1200 * have not yet been validated. */
1201 const bool filtering_enabled = ac->filters.flag & ADS_FILTER_ONLY_ERRORS;
1202 if (filtering_enabled) {
1204 }
1205 ListBase anim_data = {nullptr, nullptr};
1207 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, eAnimCont_Types(ac->datatype));
1208
1209 LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
1210 FCurve *fcu = (FCurve *)ale->key_data;
1212 PropertyRNA *prop;
1213 PointerRNA id_ptr = RNA_id_pointer_create(ale->id);
1214 if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
1215 fcu->flag &= ~FCURVE_DISABLED;
1216 }
1217 else {
1218 fcu->flag |= FCURVE_DISABLED;
1219 }
1220 }
1221
1222 ANIM_animdata_freelist(&anim_data);
1223 if (filtering_enabled) {
1225 }
1226}
1227
1228/* All FCurves need to be validated when the "show_only_errors" button is enabled. */
1229static void rna_Action_show_errors_update(bContext *C, PointerRNA * /*ptr*/)
1230{
1231 bAnimContext ac;
1232
1233 /* Get editor data. */
1234 if (ANIM_animdata_get_context(C, &ac) == 0) {
1235 return;
1236 }
1237
1238 if (!(ac.ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
1239 return;
1240 }
1241
1242 reevaluate_fcurve_errors(&ac);
1243}
1244
1245static std::optional<std::string> rna_DopeSheet_path(const PointerRNA *ptr)
1246{
1247 if (GS(ptr->owner_id->name) == ID_SCR) {
1248 const bScreen *screen = reinterpret_cast<bScreen *>(ptr->owner_id);
1249 const bDopeSheet *ads = static_cast<bDopeSheet *>(ptr->data);
1250 int area_index;
1251 int space_index;
1252 LISTBASE_FOREACH_INDEX (ScrArea *, area, &screen->areabase, area_index) {
1253 LISTBASE_FOREACH_INDEX (SpaceLink *, sl, &area->spacedata, space_index) {
1254 if (sl->spacetype == SPACE_GRAPH) {
1255 SpaceGraph *sipo = reinterpret_cast<SpaceGraph *>(sl);
1256 if (sipo->ads == ads) {
1257 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1258 }
1259 }
1260 else if (sl->spacetype == SPACE_NLA) {
1261 SpaceNla *snla = reinterpret_cast<SpaceNla *>(sl);
1262 if (snla->ads == ads) {
1263 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1264 }
1265 }
1266 else if (sl->spacetype == SPACE_ACTION) {
1267 SpaceAction *saction = reinterpret_cast<SpaceAction *>(sl);
1268 if (&saction->ads == ads) {
1269 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1270 }
1271 }
1272 }
1273 }
1274 }
1275 return "dopesheet";
1276}
1277
1285static const EnumPropertyItem *rna_ActionSlot_target_id_type_itemf(bContext * /* C */,
1286 PointerRNA * /* ptr */,
1287 PropertyRNA * /* prop */,
1288 bool *r_free)
1289{
1290 /* These items don't change, as the ID types are hard-coded. So better to
1291 * cache the list of enum items. */
1292 static EnumPropertyItem *_rna_ActionSlot_target_id_type_items = nullptr;
1293
1294 if (_rna_ActionSlot_target_id_type_items) {
1295 return _rna_ActionSlot_target_id_type_items;
1296 }
1297
1298 int totitem = 0;
1299 EnumPropertyItem *items = nullptr;
1300
1301 int i = 0;
1302 while (rna_enum_id_type_items[i].identifier != nullptr) {
1303 EnumPropertyItem item = {0};
1304 item.value = rna_enum_id_type_items[i].value;
1305 item.name = rna_enum_id_type_items[i].name;
1306 item.identifier = rna_enum_id_type_items[i].identifier;
1307 item.icon = rna_enum_id_type_items[i].icon;
1308 item.description = rna_enum_id_type_items[i].description;
1309 RNA_enum_item_add(&items, &totitem, &item);
1310 i++;
1311 }
1312
1314
1315 RNA_enum_item_end(&items, &totitem);
1316
1317 /* Don't free, but keep a reference to the created list. This is necessary
1318 * because of the PROP_ENUM_NO_CONTEXT flag. Without it, this will make
1319 * Blender use memory after it is freed:
1320 *
1321 * >>> slot = C.object.animation_data.action_slot
1322 * >>> enum_item = s.bl_rna.properties['target_id_type'].enum_items[slot.target_id_type]
1323 * >>> print(enum_item.name)
1324 */
1325 *r_free = false;
1326 _rna_ActionSlot_target_id_type_items = items;
1327
1329
1330 return items;
1331}
1332
1333static void rna_ActionSlot_target_id_type_set(PointerRNA *ptr, int value)
1334{
1335 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
1336 animrig::Slot &slot = reinterpret_cast<ActionSlot *>(ptr->data)->wrap();
1337
1338 if (slot.idtype != 0) {
1339 /* Ignore the assignment. */
1340 printf(
1341 "WARNING: ignoring assignment to target_id_type of Slot '%s' in Action '%s'. A Slot's "
1342 "target_id_type can only be changed when currently 'UNSPECIFIED'.\n",
1343 slot.identifier,
1344 action.id.name);
1345 return;
1346 }
1347
1348 action.slot_idtype_define(slot, ID_Type(value));
1349}
1350
1351#else
1352
1354{
1355 StructRNA *srna;
1356 PropertyRNA *prop;
1357
1358 srna = RNA_def_struct(brna, "DopeSheet", nullptr);
1359 RNA_def_struct_sdna(srna, "bDopeSheet");
1360 RNA_def_struct_path_func(srna, "rna_DopeSheet_path");
1362 srna, "Dope Sheet", "Settings for filtering the channels shown in animation editors");
1363
1364 /* Source of DopeSheet data */
1365 /* XXX: make this obsolete? */
1366 prop = RNA_def_property(srna, "source", PROP_POINTER, PROP_NONE);
1367 RNA_def_property_struct_type(prop, "ID");
1369 prop, "Source", "ID-Block representing source data, usually ID_SCE (i.e. Scene)");
1370
1371 /* Show data-block filters */
1372 prop = RNA_def_property(srna, "show_datablock_filters", PROP_BOOLEAN, PROP_NONE);
1375 prop,
1376 "Show Data-Block Filters",
1377 "Show options for whether channels related to certain types of data are included");
1378 RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1);
1380
1381 /* General Filtering Settings */
1382 prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE);
1383 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLYSEL);
1385 prop, "Only Show Selected", "Only include channels relating to selected objects and data");
1386 RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0);
1388
1389 prop = RNA_def_property(srna, "show_only_slot_of_active_object", PROP_BOOLEAN, PROP_NONE);
1392 prop,
1393 "Only Show Slot of Active Object",
1394 "Only show the slot of the active Object. Otherwise show all the Action's Slots");
1395 RNA_def_property_ui_icon(prop, ICON_ACTION_SLOT, 0);
1397
1398 prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE);
1399 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_INCL_HIDDEN);
1401 prop, "Show Hidden", "Include channels from objects/bone that are not visible");
1402 RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0);
1404
1405 prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE);
1408 "Sort Data-Blocks",
1409 "Alphabetically sorts data-blocks - mainly objects in the scene "
1410 "(disable to increase viewport speed)");
1411 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1413
1414 prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
1416 RNA_def_property_ui_text(prop, "Invert", "Invert filter search");
1417 RNA_def_property_ui_icon(prop, ICON_ZOOM_IN, 0);
1419
1420 /* Debug Filtering Settings */
1421 prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE);
1422 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLY_ERRORS);
1424 "Only Show Errors",
1425 "Only include F-Curves and drivers that are disabled or have errors");
1426 RNA_def_property_ui_icon(prop, ICON_ERROR, 0);
1429 prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, "rna_Action_show_errors_update");
1430
1431 /* Object Collection Filtering Settings */
1432 prop = RNA_def_property(srna, "filter_collection", PROP_POINTER, PROP_NONE);
1433 RNA_def_property_pointer_sdna(prop, nullptr, "filter_grp");
1436 prop, "Filtering Collection", "Collection that included object should be a member of");
1438
1439 /* FCurve Display Name Search Settings */
1440 prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE);
1441 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1442 RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string");
1443 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1446
1447 /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */
1448 prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
1449 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1450 RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string");
1452 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1454
1455 /* Multi-word fuzzy search option for name/text filters */
1456 prop = RNA_def_property(srna, "use_multi_word_filter", PROP_BOOLEAN, PROP_NONE);
1459 "Multi-Word Fuzzy Filter",
1460 "Perform fuzzy/multi-word matching.\n"
1461 "Warning: May be slow");
1462 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1464
1465 /* NLA Specific Settings */
1466 prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE);
1469 "Include Missing NLA",
1470 "Include animation data-blocks with no NLA data (NLA editor only)");
1471 RNA_def_property_ui_icon(prop, ICON_ACTION, 0);
1473
1474 /* Summary Settings (DopeSheet editors only) */
1475 prop = RNA_def_property(srna, "show_summary", PROP_BOOLEAN, PROP_NONE);
1476 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_SUMMARY);
1478 prop, "Display Summary", "Display an additional 'summary' line (Dope Sheet editors only)");
1479 RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0);
1481
1482 prop = RNA_def_property(srna, "show_expanded_summary", PROP_BOOLEAN, PROP_NONE);
1485 prop,
1486 "Collapse Summary",
1487 "Collapse summary when shown, so all other channels get hidden (Dope Sheet editors only)");
1489
1490 /* General DataType Filtering Settings */
1491 prop = RNA_def_property(srna, "show_transforms", PROP_BOOLEAN, PROP_NONE);
1492 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOOBJ);
1494 prop,
1495 "Display Transforms",
1496 "Include visualization of object-level animation data (mostly transforms)");
1497 RNA_def_property_ui_icon(prop, ICON_ORIENTATION_GLOBAL, 0); /* XXX? */
1499
1500 prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE);
1503 prop, "Display Shape Keys", "Include visualization of shape key related animation data");
1504 RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0);
1506
1507 prop = RNA_def_property(srna, "show_modifiers", PROP_BOOLEAN, PROP_NONE);
1510 prop,
1511 "Display Modifier Data",
1512 "Include visualization of animation data related to data-blocks linked to modifiers");
1513 RNA_def_property_ui_icon(prop, ICON_MODIFIER_DATA, 0);
1515
1516 prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE);
1517 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMESH);
1519 prop, "Display Meshes", "Include visualization of mesh related animation data");
1520 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_MESH, 0);
1522
1523 prop = RNA_def_property(srna, "show_lattices", PROP_BOOLEAN, PROP_NONE);
1524 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAT);
1526 prop, "Display Lattices", "Include visualization of lattice related animation data");
1527 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LATTICE, 0);
1529
1530 prop = RNA_def_property(srna, "show_cameras", PROP_BOOLEAN, PROP_NONE);
1531 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCAM);
1533 prop, "Display Camera", "Include visualization of camera related animation data");
1534 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CAMERA, 0);
1536
1537 prop = RNA_def_property(srna, "show_materials", PROP_BOOLEAN, PROP_NONE);
1538 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMAT);
1540 prop, "Display Material", "Include visualization of material related animation data");
1541 RNA_def_property_ui_icon(prop, ICON_MATERIAL_DATA, 0);
1543
1544 prop = RNA_def_property(srna, "show_lights", PROP_BOOLEAN, PROP_NONE);
1545 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAM);
1547 prop, "Display Light", "Include visualization of light related animation data");
1548 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHT, 0);
1550
1551 prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE);
1554 prop, "Display Line Style", "Include visualization of Line Style related Animation data");
1555 RNA_def_property_ui_icon(prop, ICON_LINE_DATA, 0);
1557
1558 prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE);
1559 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOTEX);
1561 prop, "Display Texture", "Include visualization of texture related animation data");
1562 RNA_def_property_ui_icon(prop, ICON_TEXTURE_DATA, 0);
1564
1565 prop = RNA_def_property(srna, "show_curves", PROP_BOOLEAN, PROP_NONE);
1566 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCUR);
1568 prop, "Display Curve", "Include visualization of curve related animation data");
1569 RNA_def_property_ui_icon(prop, ICON_CURVE_DATA, 0);
1571
1572 prop = RNA_def_property(srna, "show_worlds", PROP_BOOLEAN, PROP_NONE);
1573 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOWOR);
1575 prop, "Display World", "Include visualization of world related animation data");
1576 RNA_def_property_ui_icon(prop, ICON_WORLD_DATA, 0);
1578
1579 prop = RNA_def_property(srna, "show_scenes", PROP_BOOLEAN, PROP_NONE);
1580 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSCE);
1582 prop, "Display Scene", "Include visualization of scene related animation data");
1583 RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0);
1585
1586 prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
1587 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOPART);
1589 prop, "Display Particle", "Include visualization of particle related animation data");
1590 RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0);
1592
1593 prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE);
1594 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMBA);
1596 prop, "Display Metaball", "Include visualization of metaball related animation data");
1597 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_META, 0);
1599
1600 prop = RNA_def_property(srna, "show_armatures", PROP_BOOLEAN, PROP_NONE);
1601 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOARM);
1603 prop, "Display Armature", "Include visualization of armature related animation data");
1604 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_ARMATURE, 0);
1606
1607 prop = RNA_def_property(srna, "show_nodes", PROP_BOOLEAN, PROP_NONE);
1608 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NONTREE);
1610 prop, "Display Node", "Include visualization of node related animation data");
1611 RNA_def_property_ui_icon(prop, ICON_NODETREE, 0);
1613
1614 prop = RNA_def_property(srna, "show_speakers", PROP_BOOLEAN, PROP_NONE);
1615 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSPK);
1617 prop, "Display Speaker", "Include visualization of speaker related animation data");
1618 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_SPEAKER, 0);
1620
1621 prop = RNA_def_property(srna, "show_cache_files", PROP_BOOLEAN, PROP_NONE);
1624 prop, "Display Cache Files", "Include visualization of cache file related animation data");
1625 RNA_def_property_ui_icon(prop, ICON_FILE, 0);
1627
1628 prop = RNA_def_property(srna, "show_hair_curves", PROP_BOOLEAN, PROP_NONE);
1629 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOHAIR);
1631 prop, "Display Hair", "Include visualization of hair related animation data");
1632 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CURVES, 0);
1634
1635 prop = RNA_def_property(srna, "show_pointclouds", PROP_BOOLEAN, PROP_NONE);
1638 prop, "Display Point Cloud", "Include visualization of point cloud related animation data");
1639 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_POINTCLOUD, 0);
1641
1642 prop = RNA_def_property(srna, "show_volumes", PROP_BOOLEAN, PROP_NONE);
1643 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOVOLUME);
1645 prop, "Display Volume", "Include visualization of volume related animation data");
1646 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_VOLUME, 0);
1648
1649 prop = RNA_def_property(srna, "show_lightprobes", PROP_BOOLEAN, PROP_NONE);
1652 prop, "Display Light Probe", "Include visualization of lightprobe related animation data");
1653 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHTPROBE, 0);
1655
1656 prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
1659 prop,
1660 "Display Grease Pencil",
1661 "Include visualization of Grease Pencil related animation data and frames");
1662 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_GREASEPENCIL, 0);
1664
1665 prop = RNA_def_property(srna, "show_movieclips", PROP_BOOLEAN, PROP_NONE);
1668 prop, "Display Movie Clips", "Include visualization of movie clip related animation data");
1669 RNA_def_property_ui_icon(prop, ICON_TRACKER, 0);
1671
1672 prop = RNA_def_property(srna, "show_driver_fallback_as_error", PROP_BOOLEAN, PROP_NONE);
1675 prop,
1676 "Variable Fallback As Error",
1677 "Include drivers that relied on any fallback values for their evaluation "
1678 "in the Only Show Errors filter, even if the driver evaluation succeeded");
1679 RNA_def_property_ui_icon(prop, ICON_RNA, 0);
1681}
1682
1683/* =========================== Layered Action interface =========================== */
1684
1686{
1687 StructRNA *srna;
1688 PropertyRNA *prop;
1689
1690 FunctionRNA *func;
1691 PropertyRNA *parm;
1692
1693 RNA_def_property_srna(cprop, "ActionSlots");
1694 srna = RNA_def_struct(brna, "ActionSlots", nullptr);
1695 RNA_def_struct_sdna(srna, "bAction");
1696 RNA_def_struct_ui_text(srna, "Action Slots", "Collection of action slots");
1697
1698 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
1699 RNA_def_property_struct_type(prop, "ActionSlot");
1702 prop, "rna_ActionSlots_active_get", "rna_ActionSlots_active_set", nullptr, nullptr);
1704
1705 RNA_def_property_ui_text(prop, "Active Slot", "Active slot for this action");
1706
1707 /* Animation.slots.new(...) */
1708 func = RNA_def_function(srna, "new", "rna_Action_slots_new");
1709 RNA_def_function_ui_description(func, "Add a slot to the Action");
1711 parm = RNA_def_enum(
1712 func,
1713 "id_type",
1715 ID_OB,
1716 "Data-block Type",
1717 "The data-block type that the slot is intended for. This is combined with the slot name to "
1718 "create the slot's unique identifier, and is also used to limit (on a best-effort basis) "
1719 "which data-blocks the slot can be assigned to.");
1721 parm = RNA_def_string(
1722 func,
1723 "name",
1724 nullptr,
1725 /* Minus 2 for the ID-type prefix. */
1726 sizeof(ActionSlot::identifier) - 2,
1727 "Name",
1728 "Name of the slot. This will be made unique within the Action among slots of the same type");
1730
1731 parm = RNA_def_pointer(func, "slot", "ActionSlot", "", "Newly created action slot");
1732 RNA_def_function_return(func, parm);
1733
1734 /* Animation.slots.remove(layer) */
1735 func = RNA_def_function(srna, "remove", "rna_Action_slots_remove");
1738 "Remove the slot from the Action, including all animation that "
1739 "is associated with that slot");
1740 parm = RNA_def_pointer(func, "action_slot", "ActionSlot", "Action Slot", "The slot to remove");
1742}
1743
1745{
1746 StructRNA *srna;
1747
1748 FunctionRNA *func;
1749 PropertyRNA *parm;
1750
1751 RNA_def_property_srna(cprop, "ActionLayers");
1752 srna = RNA_def_struct(brna, "ActionLayers", nullptr);
1753 RNA_def_struct_sdna(srna, "bAction");
1754 RNA_def_struct_ui_text(srna, "Action Layers", "Collection of animation layers");
1755
1756 /* Animation.layers.new(...) */
1757 func = RNA_def_function(srna, "new", "rna_Action_layers_new");
1760 func,
1761 "Add a layer to the Animation. Currently an Animation can only have at most one layer.");
1762 parm = RNA_def_string(func,
1763 "name",
1764 nullptr,
1765 sizeof(ActionLayer::name) - 1,
1766 "Name",
1767 "Name of the layer, will be made unique within the Action");
1769 parm = RNA_def_pointer(func, "layer", "ActionLayer", "", "Newly created animation layer");
1770 RNA_def_function_return(func, parm);
1771
1772 /* Animation.layers.remove(layer) */
1773 func = RNA_def_function(srna, "remove", "rna_Action_layers_remove");
1775 RNA_def_function_ui_description(func, "Remove the layer from the animation");
1776 parm = RNA_def_pointer(
1777 func, "anim_layer", "ActionLayer", "Animation Layer", "The layer to remove");
1779}
1780
1782{
1783 StructRNA *srna;
1784 PropertyRNA *prop;
1785 PropertyRNA *parm;
1786 FunctionRNA *func;
1787
1788 srna = RNA_def_struct(brna, "ActionSlot", nullptr);
1789 RNA_def_struct_path_func(srna, "rna_ActionSlot_path");
1790 RNA_def_struct_ui_icon(srna, ICON_ACTION_SLOT);
1792 srna,
1793 "Action slot",
1794 "Identifier for a set of channels in this Action, that can be used by a data-block "
1795 "to specify what it gets animated by");
1796
1798
1799 prop = RNA_def_property(srna, "identifier", PROP_STRING, PROP_NONE);
1800 RNA_def_struct_name_property(srna, prop);
1801 RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_ActionSlot_identifier_set");
1803 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_identifier_update");
1805 prop,
1806 "Slot Identifier",
1807 "Used when connecting an Action to a data-block, to find the correct slot handle. This is "
1808 "the display name, prefixed by two characters determined by the slot's ID type");
1809
1810 prop = RNA_def_property(srna, "target_id_type", PROP_ENUM, PROP_NONE);
1811 RNA_def_property_enum_sdna(prop, nullptr, "idtype");
1814 prop, nullptr, "rna_ActionSlot_target_id_type_set", "rna_ActionSlot_target_id_type_itemf");
1815 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_identifier_update");
1818 "Target ID Type",
1819 "Type of data-block that this slot is intended to animate; can be set "
1820 "when 'UNSPECIFIED' but is otherwise read-only");
1822
1823 prop = RNA_def_property(srna, "target_id_type_icon", PROP_INT, PROP_NONE);
1824 RNA_def_property_int_funcs(prop, "rna_ActionSlot_target_id_type_icon_get", nullptr, nullptr);
1826
1827 prop = RNA_def_property(srna, "name_display", PROP_STRING, PROP_NONE);
1829 "rna_ActionSlot_name_display_get",
1830 "rna_ActionSlot_name_display_length",
1831 "rna_ActionSlot_name_display_set");
1834 prop, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, "rna_ActionSlot_identifier_update");
1836 prop,
1837 "Slot Display Name",
1838 "Name of the slot, for display in the user interface. This name combined with the slot's "
1839 "data-block type is unique within its Action");
1840
1841 prop = RNA_def_property(srna, "handle", PROP_INT, PROP_NONE);
1844 "Slot Handle",
1845 "Number specific to this Slot, unique within the Action.\n"
1846 "This is used, for example, on a ActionKeyframeStrip to look up the "
1847 "ActionChannelbag for this Slot");
1848
1849 prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
1850 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Active));
1852 prop,
1853 "Active",
1854 "Whether this is the active slot, can be set by assigning to action.slots.active");
1858
1859 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
1860 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Selected));
1861 RNA_def_property_ui_text(prop, "Select", "Selection state of the slot");
1865
1866 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
1867 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Expanded));
1868 RNA_def_property_ui_text(prop, "Show Expanded", "Expanded state of the slot");
1872
1873 func = RNA_def_function(srna, "users", "rna_ActionSlot_users");
1876 func, "Return the data-blocks that are animated by this slot of this action");
1877 /* Return value. */
1878 parm = RNA_def_property(func, "users", PROP_COLLECTION, PROP_NONE);
1879 RNA_def_property_struct_type(parm, "ID");
1880 RNA_def_function_return(func, parm);
1881
1882 func = RNA_def_function(srna, "duplicate", "rna_ActionSlot_duplicate");
1884 func, "Duplicate this slot, including all the animation data associated with it");
1885 /* Return value. */
1886 parm = RNA_def_property(func, "slot", PROP_POINTER, PROP_NONE);
1888 RNA_def_property_struct_type(parm, "ActionSlot");
1889 RNA_def_property_ui_text(parm, "Duplicated Slot", "The slot created by duplicating this one");
1890 RNA_def_function_return(func, parm);
1891}
1892
1894{
1895 StructRNA *srna;
1896
1897 FunctionRNA *func;
1898 PropertyRNA *parm;
1899
1900 RNA_def_property_srna(cprop, "ActionStrips");
1901 srna = RNA_def_struct(brna, "ActionStrips", nullptr);
1902 RNA_def_struct_sdna(srna, "ActionLayer");
1903 RNA_def_struct_ui_text(srna, "Action Strips", "Collection of animation strips");
1904
1905 /* Layer.strips.new(type='...') */
1906 func = RNA_def_function(srna, "new", "rna_ActionStrips_new");
1908 "Add a new strip to the layer. Currently a layer can only have "
1909 "one strip, with infinite boundaries.");
1911 parm = RNA_def_enum(func,
1912 "type",
1914 int(animrig::Strip::Type::Keyframe),
1915 "Type",
1916 "The type of strip to create");
1917 /* Return value. */
1918 parm = RNA_def_pointer(func, "strip", "ActionStrip", "", "Newly created animation strip");
1919 RNA_def_function_return(func, parm);
1920
1921 /* Layer.strips.remove(strip) */
1922 func = RNA_def_function(srna, "remove", "rna_ActionStrips_remove");
1924 RNA_def_function_ui_description(func, "Remove the strip from the animation layer");
1925 parm = RNA_def_pointer(
1926 func, "anim_strip", "ActionStrip", "Animation Strip", "The strip to remove");
1928}
1929
1931{
1932 StructRNA *srna;
1933 PropertyRNA *prop;
1934
1935 srna = RNA_def_struct(brna, "ActionLayer", nullptr);
1936 RNA_def_struct_ui_text(srna, "Action Layer", "");
1937 RNA_def_struct_path_func(srna, "rna_ActionLayer_path");
1938
1939 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
1940 RNA_def_struct_name_property(srna, prop);
1941
1942 /* Disabled in RNA until layered animation is actually implemented.
1943 *
1944 * The animation evaluation already takes these into account, but there is no guarantee that the
1945 * mixing that is currently implemented is going to be mathematically identical to the eventual
1946 * implementation. */
1947# if 0
1948 prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
1949 RNA_def_property_range(prop, 0.0f, 1.0f);
1951 prop, "Influence", "How much of this layer is used when blending into the lower layers");
1952 RNA_def_property_ui_range(prop, 0.0, 1.0, 3, 2);
1954 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
1955
1956 prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
1957 RNA_def_property_enum_sdna(prop, nullptr, "layer_mix_mode");
1959 prop, "Mix Mode", "How animation of this layer is blended into the lower layers");
1961 RNA_def_property_enum_items(prop, rna_enum_layer_mix_mode_items);
1962 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
1963# endif
1964
1965 /* Collection properties. */
1966 prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
1967 RNA_def_property_struct_type(prop, "ActionStrip");
1969 "rna_iterator_ActionLayer_strips_begin",
1970 "rna_iterator_array_next",
1971 "rna_iterator_array_end",
1972 "rna_iterator_array_dereference_get",
1973 "rna_iterator_ActionLayer_strips_length",
1974 nullptr,
1975 nullptr,
1976 nullptr);
1977 RNA_def_property_ui_text(prop, "Strips", "The list of strips that are on this animation layer");
1978
1979 rna_def_ActionLayer_strips(brna, prop);
1980}
1981
1983{
1984 StructRNA *srna;
1985
1986 FunctionRNA *func;
1987 PropertyRNA *parm;
1988
1989 RNA_def_property_srna(cprop, "ActionChannelbags");
1990 srna = RNA_def_struct(brna, "ActionChannelbags", nullptr);
1991 RNA_def_struct_sdna(srna, "ActionStrip");
1993 srna,
1994 "Animation Channels for Slots",
1995 "For each action slot, a list of animation channels that are meant for that slot");
1996
1997 /* Strip.channelbags.new(slot=...) */
1998 func = RNA_def_function(srna, "new", "rna_Channelbags_new");
2000 func,
2001 "Add a new channelbag to the strip, to contain animation channels for a specific slot");
2003 parm = RNA_def_pointer(func,
2004 "slot",
2005 "ActionSlot",
2006 "Action Slot",
2007 "The slot that should be animated by this channelbag");
2009
2010 /* Return value. */
2011 parm = RNA_def_pointer(func, "channelbag", "ActionChannelbag", "", "Newly created channelbag");
2012 RNA_def_function_return(func, parm);
2013
2014 /* Strip.channelbags.remove(strip) */
2015 func = RNA_def_function(srna, "remove", "rna_Channelbags_remove");
2017 RNA_def_function_ui_description(func, "Remove the channelbag from the strip");
2018 parm = RNA_def_pointer(func, "channelbag", "ActionChannelbag", "", "The channelbag to remove");
2020}
2021
2026{
2027 StructRNA *srna;
2028 PropertyRNA *prop;
2029
2030 srna = RNA_def_struct(brna, "ActionKeyframeStrip", "ActionStrip");
2032 srna, "Keyframe Animation Strip", "Strip with a set of F-Curves for each action slot");
2033 RNA_def_struct_sdna_from(srna, "ActionStrip", nullptr);
2034
2035 prop = RNA_def_property(srna, "channelbags", PROP_COLLECTION, PROP_NONE);
2036 RNA_def_property_struct_type(prop, "ActionChannelbag");
2038 "rna_iterator_keyframestrip_channelbags_begin",
2039 "rna_iterator_array_next",
2040 "rna_iterator_array_end",
2041 "rna_iterator_array_dereference_get",
2042 "rna_iterator_keyframestrip_channelbags_length",
2043 nullptr,
2044 nullptr,
2045 nullptr);
2047
2048 {
2049 FunctionRNA *func;
2050 PropertyRNA *parm;
2051
2052 /* Strip.channelbag(...). */
2053 func = RNA_def_function(srna, "channelbag", "rna_ActionStrip_channelbag");
2055 RNA_def_function_ui_description(func, "Find the ActionChannelbag for a specific Slot");
2056 parm = RNA_def_pointer(
2057 func, "slot", "ActionSlot", "Slot", "The slot for which to find the channelbag");
2059 RNA_def_boolean(func,
2060 "ensure",
2061 false,
2062 "Create if necessary",
2063 "Ensure the channelbag exists for this slot, creating it if necessary");
2064 parm = RNA_def_pointer(func, "channels", "ActionChannelbag", "Channels", "");
2065 RNA_def_function_return(func, parm);
2066
2067 /* Strip.key_insert(...). */
2068
2069 func = RNA_def_function(srna, "key_insert", "rna_ActionStrip_key_insert");
2071 parm = RNA_def_pointer(func,
2072 "slot",
2073 "ActionSlot",
2074 "Slot",
2075 "The slot that identifies which 'thing' should be keyed");
2077
2078 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2080
2081 parm = RNA_def_int(
2082 func,
2083 "array_index",
2084 -1,
2085 -INT_MAX,
2086 INT_MAX,
2087 "Array Index",
2088 "Index of the animated array element, or -1 if the property is not an array",
2089 -1,
2090 4);
2092
2093 parm = RNA_def_float(func,
2094 "value",
2095 0.0,
2096 -FLT_MAX,
2097 FLT_MAX,
2098 "Value to key",
2099 "Value of the animated property",
2100 -FLT_MAX,
2101 FLT_MAX);
2103
2104 parm = RNA_def_float(func,
2105 "time",
2106 0.0,
2107 -FLT_MAX,
2108 FLT_MAX,
2109 "Time of the key",
2110 "Time, in frames, of the key",
2111 -FLT_MAX,
2112 FLT_MAX);
2114
2115 parm = RNA_def_boolean(
2116 func, "success", true, "Success", "Whether the key was successfully inserted");
2117
2118 RNA_def_function_return(func, parm);
2119 }
2120}
2121
2123{
2124 StructRNA *srna;
2125 PropertyRNA *prop;
2126
2127 srna = RNA_def_struct(brna, "ActionStrip", nullptr);
2128 RNA_def_struct_ui_text(srna, "Action Strip", "");
2129 RNA_def_struct_path_func(srna, "rna_ActionStrip_path");
2130 RNA_def_struct_refine_func(srna, "rna_ActionStrip_refine");
2131
2132 static const EnumPropertyItem prop_type_items[] = {
2133 {int(animrig::Strip::Type::Keyframe),
2134 "KEYFRAME",
2135 0,
2136 "Keyframe",
2137 "Strip with a set of F-Curves for each action slot"},
2138 {0, nullptr, 0, nullptr, nullptr},
2139 };
2140
2141 prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
2142 RNA_def_property_enum_sdna(prop, nullptr, "strip_type");
2143 RNA_def_property_enum_items(prop, prop_type_items);
2145
2146 /* Define Strip subtypes. */
2148}
2149
2151{
2152 StructRNA *srna;
2153
2154 FunctionRNA *func;
2155 PropertyRNA *parm;
2156
2157 RNA_def_property_srna(cprop, "ActionChannelbagFCurves");
2158 srna = RNA_def_struct(brna, "ActionChannelbagFCurves", nullptr);
2159 RNA_def_struct_sdna(srna, "ActionChannelbag");
2161 srna, "F-Curves", "Collection of F-Curves for a specific action slot, on a specific strip");
2162
2163 /* Channelbag.fcurves.new(...) */
2164 func = RNA_def_function(srna, "new", "rna_Channelbag_fcurve_new");
2165 RNA_def_function_ui_description(func, "Add an F-Curve to the channelbag");
2167 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2169 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2170 parm = RNA_def_string(
2171 func,
2172 "group_name",
2173 nullptr,
2174 sizeof(bActionGroup::name),
2175 "Group Name",
2176 "Name of the Group for this F-Curve, will be created if it does not exist yet");
2177 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2178 RNA_def_function_return(func, parm);
2179
2180 func = RNA_def_function(srna, "new_from_fcurve", "rna_Channelbag_fcurve_new_from_fcurve");
2182 func, "Copy an F-Curve into the channelbag. The original F-Curve is unchanged");
2184 parm = RNA_def_pointer(func, "source", "FCurve", "Source F-Curve", "The F-Curve to copy");
2186 parm = RNA_def_string(func,
2187 "data_path",
2188 nullptr,
2189 0,
2190 "Data Path",
2191 "F-Curve data path to use. If not provided, this will use the same data "
2192 "path as the given F-Curve");
2193 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2194 RNA_def_function_return(func, parm);
2195
2196 /* Channelbag.fcurves.ensure(...) */
2197 func = RNA_def_function(srna, "ensure", "rna_Channelbag_fcurve_ensure");
2199 func, "Returns the F-Curve if it already exists, and creates it if necessary");
2201 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2203 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2204 parm = RNA_def_string(func,
2205 "group_name",
2206 nullptr,
2207 sizeof(bActionGroup::name),
2208 "Group Name",
2209 "Name of the Group for this F-Curve, will be created if it does not exist "
2210 "yet. This parameter is ignored if the F-Curve already exists");
2211 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Found or newly created F-Curve");
2212 RNA_def_function_return(func, parm);
2213
2214 /* Channelbag.fcurves.find(...) */
2215 func = RNA_def_function(srna, "find", "rna_Channelbag_fcurve_find");
2217 func,
2218 "Find an F-Curve. Note that this function performs a linear scan "
2219 "of all F-Curves in the channelbag.");
2221 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2223 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2224 parm = RNA_def_pointer(
2225 func, "fcurve", "FCurve", "", "The found F-Curve, or None if it does not exist");
2226 RNA_def_function_return(func, parm);
2227
2228 /* Channelbag.fcurves.remove(...) */
2229 func = RNA_def_function(srna, "remove", "rna_Channelbag_fcurve_remove");
2230 RNA_def_function_ui_description(func, "Remove F-Curve");
2232 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove");
2235
2236 /* Channelbag.fcurves.clear() */
2237 func = RNA_def_function(srna, "clear", "rna_Channelbag_fcurve_clear");
2239 RNA_def_function_ui_description(func, "Remove all F-Curves from this channelbag");
2240}
2241
2243{
2244 StructRNA *srna;
2245
2246 FunctionRNA *func;
2247 PropertyRNA *parm;
2248
2249 RNA_def_property_srna(cprop, "ActionChannelbagGroups");
2250 srna = RNA_def_struct(brna, "ActionChannelbagGroups", nullptr);
2251 RNA_def_struct_sdna(srna, "ActionChannelbag");
2252 RNA_def_struct_ui_text(srna, "F-Curve Groups", "Collection of f-curve groups");
2253
2254 func = RNA_def_function(srna, "new", "rna_Channelbag_group_new");
2256 RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
2257 parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
2259 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Newly created action group");
2260 RNA_def_function_return(func, parm);
2261
2262 func = RNA_def_function(srna, "remove", "rna_Channelbag_group_remove");
2263 RNA_def_function_ui_description(func, "Remove action group");
2265 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove");
2268}
2269
2271{
2272 StructRNA *srna;
2273 PropertyRNA *prop;
2274
2275 srna = RNA_def_struct(brna, "ActionChannelbag", nullptr);
2277 srna,
2278 "Animation Channel Bag",
2279 "Collection of animation channels, typically associated with an action slot");
2280 RNA_def_struct_path_func(srna, "rna_Channelbag_path");
2281
2282 prop = RNA_def_property(srna, "slot_handle", PROP_INT, PROP_NONE);
2284
2285 prop = RNA_def_property(srna, "slot", PROP_POINTER, PROP_NONE);
2286 RNA_def_property_struct_type(prop, "ActionSlot");
2287 RNA_def_property_ui_text(prop, "Slot", "The Slot that the Channelbag's animation data is for");
2289 RNA_def_property_pointer_funcs(prop, "rna_Channelbag_slot_get", nullptr, nullptr, nullptr);
2290
2291 /* Channelbag.fcurves */
2292 prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
2294 "rna_iterator_Channelbag_fcurves_begin",
2295 "rna_iterator_array_next",
2296 "rna_iterator_array_end",
2297 "rna_iterator_array_dereference_get",
2298 "rna_iterator_Channelbag_fcurves_length",
2299 nullptr,
2300 nullptr,
2301 nullptr);
2302 RNA_def_property_struct_type(prop, "FCurve");
2303 RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that animate the slot");
2304 rna_def_channelbag_fcurves(brna, prop);
2305
2306 /* Channelbag.groups */
2307 prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
2309 "rna_iterator_Channelbag_groups_begin",
2310 "rna_iterator_array_next",
2311 "rna_iterator_array_end",
2312 "rna_iterator_array_dereference_get",
2313 "rna_iterator_Channelbag_groups_length",
2314 nullptr,
2315 nullptr,
2316 nullptr);
2317 RNA_def_property_struct_type(prop, "ActionGroup");
2319 prop,
2320 "F-Curve Groups",
2321 "Groupings of F-Curves for display purposes, in e.g. the dopesheet and graph editor");
2322 rna_def_channelbag_groups(brna, prop);
2323}
2324
2326{
2327 StructRNA *srna;
2328 PropertyRNA *prop;
2329
2330 srna = RNA_def_struct(brna, "ActionGroup", nullptr);
2331 RNA_def_struct_sdna(srna, "bActionGroup");
2332 RNA_def_struct_ui_text(srna, "Action Group", "Groups of F-Curves");
2333
2334 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
2335 RNA_def_property_ui_text(prop, "Name", "");
2336 RNA_def_struct_name_property(srna, prop);
2338
2339 /* WARNING: be very careful when working with this list, since the endpoint is not
2340 * defined like a standard ListBase. Adding/removing channels from this list needs
2341 * extreme care, otherwise the F-Curve list running through adjacent groups does
2342 * not match up with the one stored in the Action, resulting in curves which do not
2343 * show up in animation editors. In extreme cases, animation may also selectively
2344 * fail to play back correctly.
2345 *
2346 * If such changes are required, these MUST go through the API functions for manipulating
2347 * these F-Curve groupings. Also, note that groups only apply in actions ONLY.
2348 */
2349 prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
2350 RNA_def_property_collection_sdna(prop, nullptr, "channels", nullptr);
2351 RNA_def_property_struct_type(prop, "FCurve");
2353 "rna_ActionGroup_channels_begin",
2354 "rna_ActionGroup_channels_next",
2355 "rna_ActionGroup_channels_end",
2356 "rna_ActionGroup_channels_get",
2357 nullptr,
2358 nullptr,
2359 nullptr,
2360 nullptr);
2361 RNA_def_property_ui_text(prop, "Channels", "F-Curves in this group");
2362
2363 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
2364 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_SELECTED);
2365 RNA_def_property_ui_text(prop, "Select", "Action group is selected");
2367
2368 prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
2369 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_PROTECTED);
2370 RNA_def_property_ui_text(prop, "Lock", "Action group is locked");
2372
2373 prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
2374 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_MUTED);
2375 RNA_def_property_ui_text(prop, "Mute", "Action group is muted");
2377
2378 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
2380 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED);
2381 RNA_def_property_ui_text(prop, "Expanded", "Action group is expanded except in graph editor");
2383
2384 prop = RNA_def_property(srna, "show_expanded_graph", PROP_BOOLEAN, PROP_NONE);
2386 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED_G);
2388 prop, "Expanded in Graph Editor", "Action group is expanded in graph editor");
2390
2391 prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
2394 RNA_def_property_ui_text(prop, "Pin in Graph Editor", "");
2396
2397 /* color set */
2399}
2400
2401/* =========================== Legacy Action interface =========================== */
2402
2404{
2405 StructRNA *srna;
2406 PropertyRNA *prop;
2407
2408 FunctionRNA *func;
2409 PropertyRNA *parm;
2410
2411 RNA_def_property_srna(cprop, "ActionPoseMarkers");
2412 srna = RNA_def_struct(brna, "ActionPoseMarkers", nullptr);
2413 RNA_def_struct_sdna(srna, "bAction");
2414 RNA_def_struct_ui_text(srna, "Action Pose Markers", "Collection of timeline markers");
2415
2416 func = RNA_def_function(srna, "new", "rna_Action_pose_markers_new");
2417 RNA_def_function_ui_description(func, "Add a pose marker to the action");
2418 parm = RNA_def_string(
2419 func, "name", "Marker", 0, nullptr, "New name for the marker (not unique)");
2421 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Newly created marker");
2422 RNA_def_function_return(func, parm);
2423
2424 func = RNA_def_function(srna, "remove", "rna_Action_pose_markers_remove");
2425 RNA_def_function_ui_description(func, "Remove a timeline marker");
2427 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove");
2430
2431 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
2432 RNA_def_property_struct_type(prop, "TimelineMarker");
2435 "rna_Action_active_pose_marker_get",
2436 "rna_Action_active_pose_marker_set",
2437 nullptr,
2438 nullptr);
2439 RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action");
2440
2441 prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
2442 RNA_def_property_int_sdna(prop, nullptr, "active_marker");
2445 "rna_Action_active_pose_marker_index_get",
2446 "rna_Action_active_pose_marker_index_set",
2447 "rna_Action_active_pose_marker_index_range");
2448 RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker");
2449}
2450
2451static void rna_def_action(BlenderRNA *brna)
2452{
2453 StructRNA *srna;
2454 PropertyRNA *prop;
2455
2456 FunctionRNA *func;
2457 PropertyRNA *parm;
2458
2459 srna = RNA_def_struct(brna, "Action", "ID");
2460 RNA_def_struct_sdna(srna, "bAction");
2461 RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation");
2462 RNA_def_struct_ui_icon(srna, ICON_ACTION);
2463
2464 /* Properties. */
2465 prop = RNA_def_property(srna, "is_empty", PROP_BOOLEAN, PROP_NONE);
2468 prop, "Is Empty", "False when there is any Layer, Slot, or legacy F-Curve");
2469 RNA_def_property_boolean_funcs(prop, "rna_Action_is_empty_get", nullptr);
2470
2471 prop = RNA_def_property(srna, "is_action_legacy", PROP_BOOLEAN, PROP_NONE);
2474 prop,
2475 "Is Legacy Action",
2476 "Return whether this is a legacy Action. Legacy Actions have no layers or slots. An "
2477 "empty Action is considered as both a 'legacy' and a 'layered' Action. Since Blender 4.4 "
2478 "actions are automatically updated to layered actions, and thus this will only return True "
2479 "when the action is empty");
2480 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_legacy_get", nullptr);
2481
2482 prop = RNA_def_property(srna, "is_action_layered", PROP_BOOLEAN, PROP_NONE);
2485 prop,
2486 "Is Layered Action",
2487 "Return whether this is a layered Action. An empty Action is considered "
2488 "as both a 'legacy' and a 'layered' Action.");
2489 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_layered_get", nullptr);
2490
2491 /* Collection properties. */
2492 prop = RNA_def_property(srna, "slots", PROP_COLLECTION, PROP_NONE);
2493 RNA_def_property_struct_type(prop, "ActionSlot");
2495 "rna_iterator_animation_slots_begin",
2496 "rna_iterator_array_next",
2497 "rna_iterator_array_end",
2498 "rna_iterator_array_dereference_get",
2499 "rna_iterator_animation_slots_length",
2500 nullptr,
2501 nullptr,
2502 nullptr);
2503 RNA_def_property_ui_text(prop, "Slots", "The list of slots in this Action");
2504 rna_def_action_slots(brna, prop);
2505
2506 prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
2507 RNA_def_property_struct_type(prop, "ActionLayer");
2509 "rna_iterator_action_layers_begin",
2510 "rna_iterator_array_next",
2511 "rna_iterator_array_end",
2512 "rna_iterator_array_dereference_get",
2513 "rna_iterator_action_layers_length",
2514 nullptr,
2515 nullptr,
2516 nullptr);
2517 RNA_def_property_ui_text(prop, "Layers", "The list of layers that make up this Action");
2518 rna_def_action_layers(brna, prop);
2519
2520 prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
2521 RNA_def_property_collection_sdna(prop, nullptr, "markers", nullptr);
2522 RNA_def_property_struct_type(prop, "TimelineMarker");
2523 /* Use lib exception so the list isn't grayed out;
2524 * adding/removing is still banned though, see #45689. */
2527 prop, "Pose Markers", "Markers specific to this action, for labeling poses");
2528 rna_def_action_pose_markers(brna, prop);
2529
2530 /* properties */
2531 prop = RNA_def_property(srna, "use_frame_range", PROP_BOOLEAN, PROP_NONE);
2533 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_FRAME_RANGE);
2534 RNA_def_property_boolean_funcs(prop, nullptr, "rna_Action_use_frame_range_set");
2536 prop,
2537 "Manual Frame Range",
2538 "Manually specify the intended playback frame range for the action "
2539 "(this range is used by some tools, but does not affect animation evaluation)");
2541
2542 prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
2544 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_CYCLIC);
2546 prop,
2547 "Cyclic Animation",
2548 "The action is intended to be used as a cycle looping over its manually set "
2549 "playback frame range (enabling this does not automatically make it loop)");
2551
2552 prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
2554 RNA_def_property_float_sdna(prop, nullptr, "frame_start");
2555 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_start_frame_set", nullptr);
2558 prop, "Start Frame", "The start frame of the manually set intended playback range");
2560
2561 prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME);
2563 RNA_def_property_float_sdna(prop, nullptr, "frame_end");
2564 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_end_frame_set", nullptr);
2567 prop, "End Frame", "The end frame of the manually set intended playback range");
2569
2570 prop = RNA_def_float_vector(
2571 srna,
2572 "frame_range",
2573 2,
2574 nullptr,
2575 0,
2576 0,
2577 "Frame Range",
2578 "The intended playback frame range of this action, using the manually set range "
2579 "if available, or the combined frame range of all F-Curves within this action "
2580 "if not (assigning sets the manual frame range)",
2581 0,
2582 0);
2584 prop, "rna_Action_frame_range_get", "rna_Action_frame_range_set", nullptr);
2586
2587 prop = RNA_def_float_vector(srna,
2588 "curve_frame_range",
2589 2,
2590 nullptr,
2591 0,
2592 0,
2593 "Curve Frame Range",
2594 "The combined frame range of all F-Curves within this action",
2595 0,
2596 0);
2597 RNA_def_property_float_funcs(prop, "rna_Action_curve_frame_range_get", nullptr, nullptr);
2599
2600 func = RNA_def_function(srna, "deselect_keys", "rna_Action_deselect_keys");
2602 func, "Deselects all keys of the Action. The selection status of F-Curves is unchanged.");
2603
2604 /* action.fcurve_ensure_for_datablock() */
2605 func = RNA_def_function(
2606 srna, "fcurve_ensure_for_datablock", "rna_Action_fcurve_ensure_for_datablock");
2608 func,
2609 "Ensure that an F-Curve exists, with the given data path and array index, for the given "
2610 "data-block. This action must already be assigned to the data-block. This function will "
2611 "also create the layer, keyframe strip, and action slot if necessary, and take care of "
2612 "assigning the action slot too");
2614
2615 parm = RNA_def_pointer(func,
2616 "datablock",
2617 "ID",
2618 "",
2619 "The data-block animated by this action, for which to ensure the F-Curve "
2620 "exists. This action must already be assigned to the data-block");
2622 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2624 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2625 RNA_def_string(func,
2626 "group_name",
2627 nullptr,
2628 0,
2629 "Group Name",
2630 "Name of the group for this F-Curve, if any. If the F-Curve already exists, this "
2631 "parameter is ignored");
2632 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "The found or created F-Curve");
2633 RNA_def_function_return(func, parm);
2634
2635 /* API calls */
2636 RNA_api_action(srna);
2637}
2638
2639/* --------- */
2640
2642{
2643 rna_def_action(brna);
2645 rna_def_dopesheet(brna);
2646
2647 rna_def_action_slot(brna);
2651}
2652
2653#endif
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to modify FCurves.
Functions to insert, delete or modify keyframes.
Blender kernel action and pose functionality.
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:490
FCurve * BKE_fcurve_copy(const FCurve *fcu)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR_INVALID_INPUT
Definition BKE_report.hh:40
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#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)
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)
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.cc:30
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:1077
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1176
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_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
eAnimCont_Types
eAnimFilter_Flags
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_FCURVESONLY
#define MEM_SAFE_FREE(v)
ParameterFlag
Definition RNA_types.hh:544
@ PARM_RNAPTR
Definition RNA_types.hh:547
@ PARM_REQUIRED
Definition RNA_types.hh:545
FunctionFlag
Definition RNA_types.hh:884
@ FUNC_USE_REPORTS
Definition RNA_types.hh:914
@ FUNC_USE_MAIN
Definition RNA_types.hh:912
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:913
@ FUNC_USE_SELF_ID
Definition RNA_types.hh:889
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_BOOLEAN
Definition RNA_types.hh:162
@ PROP_ENUM
Definition RNA_types.hh:166
@ PROP_INT
Definition RNA_types.hh:163
@ PROP_STRING
Definition RNA_types.hh:165
@ PROP_POINTER
Definition RNA_types.hh:167
@ PROP_COLLECTION
Definition RNA_types.hh:168
@ PROPOVERRIDE_OVERRIDABLE_LIBRARY
Definition RNA_types.hh:503
PropertyFlag
Definition RNA_types.hh:300
@ PROP_THICK_WRAP
Definition RNA_types.hh:423
@ PROP_CONTEXT_UPDATE
Definition RNA_types.hh:407
@ PROP_ANIMATABLE
Definition RNA_types.hh:319
@ PROP_EDITABLE
Definition RNA_types.hh:306
@ PROP_LIB_EXCEPTION
Definition RNA_types.hh:312
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:430
@ PROP_NEVER_NULL
Definition RNA_types.hh:377
@ PROP_NO_DEG_UPDATE
Definition RNA_types.hh:439
@ PROP_TEXTEDIT_UPDATE
Definition RNA_types.hh:326
@ PROP_TIME
Definition RNA_types.hh:253
@ PROP_NONE
Definition RNA_types.hh:233
@ PROP_FACTOR
Definition RNA_types.hh:251
@ PROP_UNSIGNED
Definition RNA_types.hh:249
#define C
Definition RandGen.cpp:29
int UI_icon_from_idcode(int idcode)
#define NC_ANIMATION
Definition WM_types.hh:388
#define NA_EDITED
Definition WM_types.hh:584
#define NA_RENAME
Definition WM_types.hh:588
#define ND_KEYFRAME
Definition WM_types.hh:494
#define ND_ANIMCHAN
Definition WM_types.hh:496
#define NA_SELECTED
Definition WM_types.hh:589
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)
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)
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 GS(x)
#define filter
#define printf(...)
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
descriptor
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define T
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)
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)
float wrap(float value, float max, float min)
Definition node_math.h:103
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
const char * name
const EnumPropertyItem rna_enum_id_type_items[]
Definition rna_ID.cc:29
const PointerRNA PointerRNA_NULL
void rna_iterator_array_begin(CollectionPropertyIterator *iter, PointerRNA *ptr, void *data, size_t itemsize, int64_t length, bool free_ptr, IteratorSkipFunc skip)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
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_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_ActionLayer_strips(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_channelbag(BlenderRNA *brna)
const EnumPropertyItem default_ActionSlot_target_id_type_items[]
Definition rna_action.cc:77
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:66
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:710
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[258]
union CollectionPropertyIterator::@220100362304005352221007113371015217044252346141 internal
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
const char * description
Definition RNA_types.hh:663
struct FCurve * next
bActionGroup * grp
char * rna_path
int array_index
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
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
float frame_start
ListBase markers
eDopeSheet_FilterFlag flag
eAnimCont_Types datatype
bDopeSheet * ads
struct bAnimContext::@242276144047124000362312251357014355232301013033 filters
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:4238