Blender V4.3
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
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 "MEM_guardedalloc.h"
16
17#include "BLI_utildefines.h"
18
19#include "BLT_translation.hh"
20
21#include "BKE_action.hh"
22#include "BKE_blender.hh"
23
24#include "RNA_access.hh"
25#include "RNA_define.hh"
26#include "RNA_enum_types.hh"
27
28#include "rna_internal.hh"
29
30#include "ANIM_action.hh"
31#include "ANIM_action_legacy.hh"
32
33#include "WM_types.hh"
34
35using namespace blender;
36
37#ifdef WITH_ANIM_BAKLAVA
38const EnumPropertyItem rna_enum_layer_mix_mode_items[] = {
39 {int(animrig::Layer::MixMode::Replace),
40 "REPLACE",
41 0,
42 "Replace",
43 "Channels in this layer override the same channels from underlying layers"},
44 {int(animrig::Layer::MixMode::Offset),
45 "OFFSET",
46 0,
47 "Offset",
48 "Channels in this layer are added to underlying layers as sequential operations"},
49 {int(animrig::Layer::MixMode::Add),
50 "ADD",
51 0,
52 "Add",
53 "Channels in this layer are added to underlying layers on a per-channel basis"},
54 {int(animrig::Layer::MixMode::Subtract),
55 "SUBTRACT",
56 0,
57 "Subtract",
58 "Channels in this layer are subtracted to underlying layers on a per-channel basis"},
59 {int(animrig::Layer::MixMode::Multiply),
60 "MULTIPLY",
61 0,
62 "Multiply",
63 "Channels in this layer are multiplied with underlying layers on a per-channel basis"},
64 {0, nullptr, 0, nullptr, nullptr},
65};
66
67const EnumPropertyItem rna_enum_strip_type_items[] = {
68 {int(animrig::Strip::Type::Keyframe),
69 "KEYFRAME",
70 0,
71 "Keyframe",
72 "Strip containing keyframes on F-Curves"},
73 {0, nullptr, 0, nullptr, nullptr},
74};
75#endif /* WITH_ANIM_BAKLAVA */
76
77/* Cannot use rna_enum_dummy_DEFAULT_items because the UNSPECIFIED entry needs
78 * to exist as it is the default. */
80 {0,
81 "UNSPECIFIED",
82 ICON_NONE,
83 "Unspecified",
84 "Not yet specified. When this slot is first assigned to a data-block, this will be set to "
85 "the type of that data-block"},
86 {0, nullptr, 0, nullptr, nullptr},
87};
88
89#ifdef RNA_RUNTIME
90
91# include <algorithm>
92
93# include "BLI_math_base.h"
94
95# include "BKE_fcurve.hh"
96
97# include "DEG_depsgraph.hh"
98
99# include "ANIM_action.hh"
100# include "ANIM_animdata.hh"
101# include "ED_anim_api.hh"
102
103# include "WM_api.hh"
104
105# include "UI_interface_icons.hh"
106
107# include "DEG_depsgraph.hh"
108
109# include "ANIM_action_legacy.hh"
110# include "ANIM_keyframing.hh"
111
112# include <fmt/format.h>
113
114static animrig::Action &rna_action(const PointerRNA *ptr)
115{
116 return reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
117}
118
119# ifdef WITH_ANIM_BAKLAVA
120
121static animrig::Slot &rna_data_slot(const PointerRNA *ptr)
122{
123 BLI_assert(ptr->type == &RNA_ActionSlot);
124 return reinterpret_cast<ActionSlot *>(ptr->data)->wrap();
125}
126
127static animrig::Layer &rna_data_layer(const PointerRNA *ptr)
128{
129 return reinterpret_cast<ActionLayer *>(ptr->data)->wrap();
130}
131
132static animrig::Strip &rna_data_strip(const PointerRNA *ptr)
133{
134 return reinterpret_cast<ActionStrip *>(ptr->data)->wrap();
135}
136
137static void rna_Action_tag_animupdate(Main *, Scene *, PointerRNA *ptr)
138{
139 animrig::Action &action = rna_action(ptr);
141}
142
143static animrig::ChannelBag &rna_data_channelbag(const PointerRNA *ptr)
144{
145 return reinterpret_cast<ActionChannelBag *>(ptr->data)->wrap();
146}
147
148template<typename T>
150{
151 rna_iterator_array_begin(iter, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
152}
153
154template<typename T>
156{
157 rna_iterator_array_begin(iter, (void *)items.data(), sizeof(T *), items.size(), 0, nullptr);
158}
159
160static PointerRNA rna_ActionSlots_active_get(PointerRNA *ptr)
161{
162 animrig::Action &action = rna_action(ptr);
163 animrig::Slot *active_slot = action.slot_active_get();
164
165 if (!active_slot) {
166 return PointerRNA_NULL;
167 }
168 return RNA_pointer_create(&action.id, &RNA_ActionSlot, active_slot);
169}
170
171static void rna_ActionSlots_active_set(PointerRNA *ptr,
172 PointerRNA value,
173 struct ReportList * /*reports*/)
174{
175 animrig::Action &action = rna_action(ptr);
176
177 if (value.data) {
178 animrig::Slot &slot = rna_data_slot(&value);
179 action.slot_active_set(slot.handle);
180 }
181 else {
183 }
184}
185
186static ActionSlot *rna_Action_slots_new(bAction *dna_action,
187 bContext *C,
188 ReportList *reports,
189 ID *id_for_slot)
190{
191 animrig::Action &action = dna_action->wrap();
192 animrig::Slot *slot;
193
194 if (!action.is_action_layered()) {
195 BKE_reportf(reports,
196 RPT_ERROR,
197 "Cannot add slots to a legacy Action '%s'. Convert it to a layered Action first.",
198 action.id.name + 2);
199 return nullptr;
200 }
201
202 if (id_for_slot) {
203 slot = &action.slot_add_for_id(*id_for_slot);
204 }
205 else {
206 slot = &action.slot_add();
207 }
208
210 return slot;
211}
212
213void rna_Action_slots_remove(bAction *dna_action,
214 bContext *C,
215 ReportList *reports,
216 PointerRNA *slot_ptr)
217{
218 animrig::Action &action = dna_action->wrap();
219 animrig::Slot &slot = rna_data_slot(slot_ptr);
220 if (!action.slot_remove(slot)) {
221 BKE_report(reports, RPT_ERROR, "This slot does not belong to this Action");
222 return;
223 }
224
225 RNA_POINTER_INVALIDATE(slot_ptr);
228}
229
230static void rna_iterator_action_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
231{
232 animrig::Action &action = rna_action(ptr);
233 rna_iterator_array_begin(iter, action.layers());
234}
235
236static int rna_iterator_action_layers_length(PointerRNA *ptr)
237{
238 animrig::Action &action = rna_action(ptr);
239 return action.layers().size();
240}
241
242static ActionLayer *rna_Action_layers_new(bAction *dna_action,
243 bContext *C,
244 ReportList *reports,
245 const char *name)
246{
247 animrig::Action &action = dna_action->wrap();
248
249 if (!action.is_action_layered()) {
250 BKE_reportf(reports,
251 RPT_ERROR,
252 "Cannot add layers to a legacy Action '%s'. Convert it to a layered Action first.",
253 action.id.name + 2);
254 return nullptr;
255 }
256
257 if (action.layers().size() >= 1) {
258 /* Not allowed to have more than one layer, for now. This limitation is in
259 * place until working with multiple animated IDs is fleshed out better. */
260 BKE_report(reports, RPT_ERROR, "An Action may not have more than one layer");
261 return nullptr;
262 }
263
264 animrig::Layer &layer = action.layer_add(name);
265
267 return &layer;
268}
269
270void rna_Action_layers_remove(bAction *dna_action,
271 bContext *C,
272 ReportList *reports,
273 PointerRNA *layer_ptr)
274{
275 animrig::Action &action = dna_action->wrap();
276 animrig::Layer &layer = rna_data_layer(layer_ptr);
277 if (!action.layer_remove(layer)) {
278 BKE_report(reports, RPT_ERROR, "This layer does not belong to this Action");
279 return;
280 }
281
282 RNA_POINTER_INVALIDATE(layer_ptr);
285}
286
287static void rna_iterator_animation_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
288{
289 animrig::Action &action = rna_action(ptr);
290 rna_iterator_array_begin(iter, action.slots());
291}
292
293static int rna_iterator_animation_slots_length(PointerRNA *ptr)
294{
295 animrig::Action &action = rna_action(ptr);
296 return action.slots().size();
297}
298
299static std::optional<std::string> rna_ActionSlot_path(const PointerRNA *ptr)
300{
301 animrig::Slot &slot = rna_data_slot(ptr);
302
303 char name_esc[sizeof(slot.name) * 2];
304 BLI_str_escape(name_esc, slot.name, sizeof(name_esc));
305 return fmt::format("slots[\"{}\"]", name_esc);
306}
307
308int rna_ActionSlot_id_root_icon_get(PointerRNA *ptr)
309{
310 animrig::Slot &slot = rna_data_slot(ptr);
311 return UI_icon_from_idcode(slot.idtype);
312}
313
314/* Name functions that ignore the first two ID characters */
315void rna_ActionSlot_name_display_get(PointerRNA *ptr, char *value)
316{
317 animrig::Slot &slot = rna_data_slot(ptr);
318 slot.name_without_prefix().unsafe_copy(value);
319}
320
321int rna_ActionSlot_name_display_length(PointerRNA *ptr)
322{
323 animrig::Slot &slot = rna_data_slot(ptr);
324 return slot.name_without_prefix().size();
325}
326
327static void rna_ActionSlot_name_display_set(PointerRNA *ptr, const char *name)
328{
329 animrig::Action &action = rna_action(ptr);
330 animrig::Slot &slot = rna_data_slot(ptr);
331 const StringRef name_ref(name);
332
333 if (name_ref.is_empty()) {
334 WM_report(RPT_ERROR, "Action slot display names cannot be empty");
335 return;
336 }
337
338 /* Construct the new internal name, from the slot's type and the given name. */
339 const std::string internal_name = slot.name_prefix_for_idtype() + name_ref;
340 action.slot_name_define(slot, internal_name);
341}
342
343static void rna_ActionSlot_name_set(PointerRNA *ptr, const char *name)
344{
345 animrig::Action &action = rna_action(ptr);
346 animrig::Slot &slot = rna_data_slot(ptr);
347 const StringRef name_ref(name);
348
349 if (name_ref.size() < animrig::Slot::name_length_min) {
350 WM_report(RPT_ERROR, "Action slot names should be at least three characters");
351 return;
352 }
353
354 if (slot.has_idtype()) {
355 /* Check if the new name is going to be compatible with the already-established ID type. */
356 const std::string expect_prefix = slot.name_prefix_for_idtype();
357
358 if (!name_ref.startswith(expect_prefix)) {
359 const std::string new_prefix = name_ref.substr(0, 2);
361 "Action slot renamed to unexpected prefix \"%s\" (expected \"%s\").\n",
362 new_prefix.c_str(),
363 expect_prefix.c_str());
364 }
365 }
366
367 action.slot_name_define(slot, name);
368}
369
370static void rna_ActionSlot_name_update(Main *bmain, Scene *, PointerRNA *ptr)
371{
372 animrig::Action &action = rna_action(ptr);
373 animrig::Slot &slot = rna_data_slot(ptr);
374 action.slot_name_propagate(*bmain, slot);
375}
376
377# ifndef NDEBUG
378static void rna_ActionSlot_debug_log_users(const ID *action_id, ActionSlot *dna_slot, Main *bmain)
379{
380 using namespace blender::animrig;
381 const Action &action = reinterpret_cast<const bAction *>(action_id)->wrap();
382 Slot &slot = dna_slot->wrap();
383
384 printf("\033[38;5;214mAction Slot users of '%s' on Action '%s':\033[0m\n",
385 slot.name,
386 action.id.name + 2);
388 printf(" User map is \033[93mdirty\033[0m, this will trigger a recompute.\n");
389 }
390 else {
391 printf(" User map is \033[92mclean\033[0m.\n");
392 }
393
394 for (const ID *user : slot.users(*bmain)) {
395 printf(" - %s\n", user->name);
396 }
397}
398# endif /* NDEBUG */
399
400static std::optional<std::string> rna_ActionLayer_path(const PointerRNA *ptr)
401{
402 animrig::Layer &layer = rna_data_layer(ptr);
403
404 char name_esc[sizeof(layer.name) * 2];
405 BLI_str_escape(name_esc, layer.name, sizeof(name_esc));
406 return fmt::format("layers[\"{}\"]", name_esc);
407}
408
409static void rna_iterator_ActionLayer_strips_begin(CollectionPropertyIterator *iter,
411{
412 animrig::Layer &layer = rna_data_layer(ptr);
413 rna_iterator_array_begin(iter, layer.strips());
414}
415
416static int rna_iterator_ActionLayer_strips_length(PointerRNA *ptr)
417{
418 animrig::Layer &layer = rna_data_layer(ptr);
419 return layer.strips().size();
420}
421
422static StructRNA *rna_ActionStrip_refine(PointerRNA *ptr)
423{
424 animrig::Strip &strip = static_cast<ActionStrip *>(ptr->data)->wrap();
425
426 switch (strip.type()) {
427 case animrig::Strip::Type::Keyframe:
428 return &RNA_ActionKeyframeStrip;
429 }
430 return &RNA_UnknownType;
431}
432
433ActionStrip *rna_ActionStrips_new(
434 ID *dna_action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, const int type)
435{
436 const animrig::Strip::Type strip_type = animrig::Strip::Type(type);
437
438 animrig::Layer &layer = dna_layer->wrap();
439
440 if (layer.strips().size() >= 1) {
441 /* Not allowed to have more than one strip, for now. This limitation is in
442 * place until working with layers is fleshed out better. */
443 BKE_report(reports, RPT_ERROR, "A layer may not have more than one strip");
444 return nullptr;
445 }
446
447 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
448 animrig::Strip &strip = layer.strip_add(action, strip_type);
449
451 return &strip;
452}
453
454void rna_ActionStrips_remove(
455 ID *action_id, ActionLayer *dna_layer, bContext *C, ReportList *reports, PointerRNA *strip_ptr)
456{
457 animrig::Action &action = reinterpret_cast<bAction *>(action_id)->wrap();
458 animrig::Layer &layer = dna_layer->wrap();
459 animrig::Strip &strip = rna_data_strip(strip_ptr);
460 if (!layer.strip_remove(action, strip)) {
461 BKE_report(reports, RPT_ERROR, "This strip does not belong to this layer");
462 return;
463 }
464
465 RNA_POINTER_INVALIDATE(strip_ptr);
468}
469
470static std::optional<std::string> rna_ActionStrip_path(const PointerRNA *ptr)
471{
472 animrig::Action &action = rna_action(ptr);
473 animrig::Strip &strip_to_find = rna_data_strip(ptr);
474
475 for (animrig::Layer *layer : action.layers()) {
476 Span<animrig::Strip *> strips = layer->strips();
477 const int index = strips.first_index_try(&strip_to_find);
478 if (index < 0) {
479 continue;
480 }
481
482 PointerRNA layer_ptr = RNA_pointer_create(&action.id, &RNA_ActionLayer, layer);
483 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
484 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
485 const std::string strip_path = fmt::format("{}.strips[{}]", *layer_path, index);
486 return strip_path;
487 }
488
489 return std::nullopt;
490}
491
492static void rna_iterator_keyframestrip_channelbags_begin(CollectionPropertyIterator *iter,
494{
495 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
496 animrig::Strip &strip = rna_data_strip(ptr);
498}
499
500static int rna_iterator_keyframestrip_channelbags_length(PointerRNA *ptr)
501{
502 animrig::Action &action = reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
503 animrig::Strip &strip = rna_data_strip(ptr);
504 return strip.data<animrig::StripKeyframeData>(action).channelbags().size();
505}
506
507static ActionChannelBag *rna_ChannelBags_new(ID *dna_action_id,
508 ActionStrip *dna_strip,
509 bContext *C,
510 ReportList *reports,
511 ActionSlot *dna_slot)
512{
513 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
514 animrig::Strip &strip = dna_strip->wrap();
516 animrig::Slot &slot = dna_slot->wrap();
517
518 if (strip_data.channelbag_for_slot(slot) != nullptr) {
519 BKE_report(reports, RPT_ERROR, "A channelbag for this slot already exists");
520 return nullptr;
521 }
522
523 animrig::ChannelBag &channelbag = strip_data.channelbag_for_slot_add(slot);
524
526 /* No need to tag the depsgraph, as there is no new animation yet. */
527
528 return &channelbag;
529}
530
531static void rna_ChannelBags_remove(ID *dna_action_id,
532 ActionStrip *dna_strip,
533 bContext *C,
534 ReportList *reports,
535 PointerRNA *channelbag_ptr)
536{
537 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
538 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
539 action);
540 animrig::ChannelBag &channelbag = rna_data_channelbag(channelbag_ptr);
541
542 if (!strip_data.channelbag_remove(channelbag)) {
543 BKE_report(reports, RPT_ERROR, "This channelbag does not belong to this strip");
544 return;
545 }
546
547 RNA_POINTER_INVALIDATE(channelbag_ptr);
550}
551
552static bool rna_ActionStrip_key_insert(ID *dna_action_id,
553 ActionStrip *dna_strip,
554 Main *bmain,
555 ReportList *reports,
556 ActionSlot *dna_slot,
557 const char *rna_path,
558 const int array_index,
559 const float value,
560 const float time)
561{
562 if (dna_slot == nullptr) {
563 BKE_report(reports, RPT_ERROR, "Slot cannot be None");
564 return false;
565 }
566
567 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
568 animrig::StripKeyframeData &strip_data = dna_strip->wrap().data<animrig::StripKeyframeData>(
569 action);
570 const animrig::Slot &slot = dna_slot->wrap();
572
573 const animrig::SingleKeyingResult result = strip_data.keyframe_insert(
574 bmain, slot, {rna_path, array_index}, {time, value}, settings, INSERTKEY_NOFLAGS);
575
576 const bool ok = result == animrig::SingleKeyingResult::SUCCESS;
577 if (ok) {
578 DEG_id_tag_update_ex(bmain, dna_action_id, ID_RECALC_ANIMATION);
579 }
580
581 return ok;
582}
583
584static std::optional<std::string> rna_ChannelBag_path(const PointerRNA *ptr)
585{
586 animrig::Action &action = rna_action(ptr);
587 animrig::ChannelBag &cbag_to_find = rna_data_channelbag(ptr);
588
589 for (animrig::Layer *layer : action.layers()) {
590 for (int64_t strip_index : layer->strips().index_range()) {
591 const animrig::Strip *strip = layer->strip(strip_index);
592 if (strip->type() != animrig::Strip::Type::Keyframe) {
593 continue;
594 }
595
597 action);
598 const int64_t index = strip_data.find_channelbag_index(cbag_to_find);
599 if (index < 0) {
600 continue;
601 }
602
603 PointerRNA layer_ptr = RNA_pointer_create(&action.id, &RNA_ActionLayer, layer);
604 const std::optional<std::string> layer_path = rna_ActionLayer_path(&layer_ptr);
605 BLI_assert_msg(layer_path, "Every animation layer should have a valid RNA path.");
606 return fmt::format("{}.strips[{}].channelbags[{}]", *layer_path, strip_index, index);
607 }
608 }
609
610 return std::nullopt;
611}
612
613static void rna_iterator_ChannelBag_fcurves_begin(CollectionPropertyIterator *iter,
615{
616 animrig::ChannelBag &bag = rna_data_channelbag(ptr);
618}
619
620static int rna_iterator_ChannelBag_fcurves_length(PointerRNA *ptr)
621{
622 animrig::ChannelBag &bag = rna_data_channelbag(ptr);
623 return bag.fcurves().size();
624}
625
626static FCurve *rna_ChannelBag_fcurve_new(ActionChannelBag *dna_channelbag,
627 Main *bmain,
628 ReportList *reports,
629 const char *data_path,
630 const int index)
631{
632 BLI_assert(data_path != nullptr);
633 if (data_path[0] == '\0') {
634 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
635 return nullptr;
636 }
637
638 animrig::ChannelBag &self = dna_channelbag->wrap();
639 FCurve *fcurve = self.fcurve_create_unique(bmain, {data_path, index});
640 if (!fcurve) {
641 BKE_reportf(reports,
642 RPT_ERROR,
643 "F-Curve '%s[%d]' already exists in this channelbag",
644 data_path,
645 index);
646 return nullptr;
647 }
648 return fcurve;
649}
650
651static FCurve *rna_ChannelBag_fcurve_find(ActionChannelBag *dna_channelbag,
652 ReportList *reports,
653 const char *data_path,
654 const int index)
655{
656 if (data_path[0] == '\0') {
657 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
658 return nullptr;
659 }
660
661 animrig::ChannelBag &self = dna_channelbag->wrap();
662 return self.fcurve_find({data_path, index});
663}
664
665static void rna_ChannelBag_fcurve_remove(ID *dna_action_id,
666 ActionChannelBag *dna_channelbag,
667 bContext *C,
668 ReportList *reports,
669 PointerRNA *fcurve_ptr)
670{
671 animrig::ChannelBag &self = dna_channelbag->wrap();
672 FCurve *fcurve = static_cast<FCurve *>(fcurve_ptr->data);
673
674 if (!self.fcurve_remove(*fcurve)) {
675 BKE_reportf(reports, RPT_ERROR, "F-Curve not found");
676 return;
677 }
678
681}
682
683static void rna_ChannelBag_fcurve_clear(ID *dna_action_id,
684 ActionChannelBag *dna_channelbag,
685 bContext *C)
686{
687 dna_channelbag->wrap().fcurves_clear();
690}
691
692static void rna_iterator_ChannelBag_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
693{
694 animrig::ChannelBag &bag = rna_data_channelbag(ptr);
696}
697
698static int rna_iterator_ChannelBag_groups_length(PointerRNA *ptr)
699{
700 animrig::ChannelBag &bag = rna_data_channelbag(ptr);
701 return bag.channel_groups().size();
702}
703
704static bActionGroup *rna_ChannelBag_group_new(ActionChannelBag *dna_channelbag, const char *name)
705{
706 BLI_assert(name != nullptr);
707
708 animrig::ChannelBag &self = dna_channelbag->wrap();
709 return &self.channel_group_create(name);
710}
711
712static void rna_ChannelBag_group_remove(ActionChannelBag *dna_channelbag,
713 ReportList *reports,
714 PointerRNA *agrp_ptr)
715{
716 animrig::ChannelBag &self = dna_channelbag->wrap();
717
718 bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
719
720 if (!self.channel_group_remove(*agrp)) {
721 BKE_report(reports,
722 RPT_ERROR,
723 "Could not remove the F-Curve Group from the collection because it doesn't exist "
724 "in the collection");
725 return;
726 }
727
728 RNA_POINTER_INVALIDATE(agrp_ptr);
730}
731
732static ActionChannelBag *rna_ActionStrip_channels(ID *dna_action_id,
734 const animrig::slot_handle_t slot_handle)
735{
736 animrig::Action &action = reinterpret_cast<bAction *>(dna_action_id)->wrap();
737 animrig::StripKeyframeData &strip_data = self->wrap().data<animrig::StripKeyframeData>(action);
738 return strip_data.channelbag_for_slot(slot_handle);
739}
740
741# endif // WITH_ANIM_BAKLAVA
742
753struct ActionGroupChannelsIterator {
754 /* Which kind of iterator it is. */
755 enum {
756 ARRAY,
757 LISTBASE,
758 } tag;
759
760 union {
762 ListBaseIterator listbase;
763 };
764};
765
766static void rna_ActionGroup_channels_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
767{
768 bActionGroup *group = (bActionGroup *)ptr->data;
769
770 ActionGroupChannelsIterator *custom_iter = MEM_cnew<ActionGroupChannelsIterator>(__func__);
771
772 iter->internal.custom = custom_iter;
773
774 /* We handle both the listbase (legacy action) and array (layered action)
775 * cases below. The code for each is based on the code in
776 * `rna_iterator_listbase_begin()` and `rna_iterator_array_begin()`,
777 * respectively. */
778
779 /* Group from a legacy action. */
780 if (group->wrap().is_legacy()) {
781 custom_iter->tag = ActionGroupChannelsIterator::LISTBASE;
782 custom_iter->listbase.link = static_cast<Link *>(group->channels.first);
783
784 iter->valid = custom_iter->listbase.link != nullptr;
785 return;
786 }
787
788 /* Group from a layered action. */
789 animrig::ChannelBag &cbag = group->channel_bag->wrap();
790
791 custom_iter->tag = ActionGroupChannelsIterator::ARRAY;
792 custom_iter->array.ptr = reinterpret_cast<char *>(cbag.fcurve_array + group->fcurve_range_start);
793 custom_iter->array.endptr = reinterpret_cast<char *>(
794 cbag.fcurve_array + group->fcurve_range_start + group->fcurve_range_length);
795 custom_iter->array.itemsize = sizeof(FCurve *);
796 custom_iter->array.length = group->fcurve_range_length;
797
798 iter->valid = group->fcurve_range_length > 0;
799}
800
801static void rna_ActionGroup_channels_end(CollectionPropertyIterator *iter)
802{
804}
805
806static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter)
807{
808 BLI_assert(iter->internal.custom != nullptr);
809 BLI_assert(iter->valid);
810
811 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
812 iter->internal.custom);
813
814 /* The code for both cases here is written based on the code in
815 * `rna_iterator_array_next()` and `rna_iterator_listbase_next()`,
816 * respectively. */
817 switch (custom_iter->tag) {
818 case ActionGroupChannelsIterator::ARRAY: {
819 custom_iter->array.ptr += custom_iter->array.itemsize;
820 iter->valid = (custom_iter->array.ptr != custom_iter->array.endptr);
821 break;
822 }
823 case ActionGroupChannelsIterator::LISTBASE: {
824 FCurve *fcurve = (FCurve *)custom_iter->listbase.link;
825 bActionGroup *grp = fcurve->grp;
826 /* Only continue if the next F-Curve (if existent) belongs in the same
827 * group. */
828 if ((fcurve->next) && (fcurve->next->grp == grp)) {
829 custom_iter->listbase.link = custom_iter->listbase.link->next;
830 iter->valid = (custom_iter->listbase.link != nullptr);
831 }
832 else {
833 custom_iter->listbase.link = nullptr;
834 iter->valid = false;
835 }
836 break;
837 }
838 }
839}
840
841static PointerRNA rna_ActionGroup_channels_get(CollectionPropertyIterator *iter)
842{
843 BLI_assert(iter->internal.custom != nullptr);
844 BLI_assert(iter->valid);
845 ActionGroupChannelsIterator *custom_iter = static_cast<ActionGroupChannelsIterator *>(
846 iter->internal.custom);
847
848 FCurve *fcurve;
849 switch (custom_iter->tag) {
850 case ActionGroupChannelsIterator::ARRAY:
851 fcurve = *reinterpret_cast<FCurve **>(custom_iter->array.ptr);
852 break;
853 case ActionGroupChannelsIterator::LISTBASE:
854 fcurve = reinterpret_cast<FCurve *>(custom_iter->listbase.link);
855 break;
856 }
857
858 return rna_pointer_inherit_refine(&iter->parent, &RNA_FCurve, fcurve);
859}
860
861# ifdef WITH_ANIM_BAKLAVA
862/* Use the backward-compatible API only when we're working with the action as a
863 * layered action. */
864static bool use_backward_compatible_api(animrig::Action &action)
865{
867}
868
869static void rna_iterator_Action_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
870{
871 animrig::Action &action = rna_action(ptr);
872
873 if (use_backward_compatible_api(action)) {
875 if (!channelbag) {
876 return;
877 }
878 rna_iterator_array_begin(iter, channelbag->channel_groups());
879 }
880 else {
881 rna_iterator_listbase_begin(iter, &action.groups, nullptr);
882 }
883}
884static void rna_iterator_Action_groups_next(CollectionPropertyIterator *iter)
885{
886 animrig::Action &action = rna_action(&iter->parent);
887 if (use_backward_compatible_api(action)) {
889 }
890 else {
892 }
893}
894static void rna_iterator_Action_groups_end(CollectionPropertyIterator *iter)
895{
896 animrig::Action &action = rna_action(&iter->parent);
897 if (use_backward_compatible_api(action)) {
899 }
900 else {
902 }
903}
904static PointerRNA rna_iterator_Action_groups_get(CollectionPropertyIterator *iter)
905{
906 animrig::Action &action = rna_action(&iter->parent);
907 bActionGroup *group;
908 if (use_backward_compatible_api(action)) {
909 group = static_cast<bActionGroup *>(rna_iterator_array_dereference_get(iter));
910 }
911 else {
912 group = static_cast<bActionGroup *>(rna_iterator_listbase_get(iter));
913 }
914
915 return RNA_pointer_create(&action.id, &RNA_ActionGroup, group);
916}
917static int rna_iterator_Action_groups_length(PointerRNA *ptr)
918{
919 animrig::Action &action = rna_action(ptr);
920 if (use_backward_compatible_api(action)) {
922 if (!channelbag) {
923 return 0;
924 }
925 return channelbag->channel_groups().size();
926 }
927 return BLI_listbase_count(&action.groups);
928}
929
930# endif /* WITH_ANIM_BAKLAVA */
931
932static bActionGroup *rna_Action_groups_new(bAction *act, const char name[])
933{
934 bActionGroup *group;
935
936# ifdef WITH_ANIM_BAKLAVA
937 animrig::Action &action = act->wrap();
938 if (use_backward_compatible_api(action)) {
940 group = &channelbag.channel_group_create(name);
941 }
942 else {
943 group = action_groups_add_new(act, name);
944 }
945# else
946 group = action_groups_add_new(act, name);
947# endif
948
949 /* I (Sybren) expected that the commented-out notifier below was missing.
950 * However, the animation filtering code (`animfilter_act_group()`) hides
951 * empty groups. Because this group is newly created, it's not shown in the
952 * UI, and thus there is no need to send notifiers.
953 *
954 * WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN | NA_ADDED, nullptr); */
955
956 return group;
957}
958
959static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerRNA *agrp_ptr)
960{
961 bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
962 BLI_assert(agrp); /* Ensured by RNA flag PROP_NEVER_NULL. */
963
964# ifdef WITH_ANIM_BAKLAVA
965 animrig::Action &action = act->wrap();
966 if (use_backward_compatible_api(action)) {
968 if (!channelbag || !channelbag->channel_group_remove(*agrp)) {
969 BKE_reportf(reports,
970 RPT_ERROR,
971 "Action group '%s' not found in action '%s'",
972 agrp->name,
973 act->id.name + 2);
974 }
975
976 /* Removing a group also removes its F-Curves. */
979
980 return;
981 }
982# endif
983
984 FCurve *fcu, *fcn;
985
986 /* try to remove the F-Curve from the action */
987 if (BLI_remlink_safe(&act->groups, agrp) == false) {
988 BKE_reportf(reports,
989 RPT_ERROR,
990 "Action group '%s' not found in action '%s'",
991 agrp->name,
992 act->id.name + 2);
993 return;
994 }
995
996 /* Move every one of the group's F-Curves out into the Action again. */
997 for (fcu = static_cast<FCurve *>(agrp->channels.first); (fcu) && (fcu->grp == agrp); fcu = fcn) {
998 fcn = fcu->next;
999
1000 /* remove from group */
1002
1003 /* tack onto the end */
1004 BLI_addtail(&act->curves, fcu);
1005 }
1006
1007 MEM_freeN(agrp);
1008 RNA_POINTER_INVALIDATE(agrp_ptr);
1009
1012}
1013
1014# ifdef WITH_ANIM_BAKLAVA
1015static void rna_iterator_Action_fcurves_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
1016{
1017 animrig::Action &action = rna_action(ptr);
1018
1019 if (use_backward_compatible_api(action)) {
1021 if (!channelbag) {
1022 return;
1023 }
1024 rna_iterator_array_begin(iter, channelbag->fcurves());
1025 }
1026 else {
1027 rna_iterator_listbase_begin(iter, &action.curves, nullptr);
1028 }
1029}
1030static void rna_iterator_Action_fcurves_next(CollectionPropertyIterator *iter)
1031{
1032 animrig::Action &action = rna_action(&iter->parent);
1033 if (use_backward_compatible_api(action)) {
1035 }
1036 else {
1038 }
1039}
1040static void rna_iterator_Action_fcurves_end(CollectionPropertyIterator *iter)
1041{
1042 animrig::Action &action = rna_action(&iter->parent);
1043 if (use_backward_compatible_api(action)) {
1045 }
1046 else {
1048 }
1049}
1050static PointerRNA rna_iterator_Action_fcurves_get(CollectionPropertyIterator *iter)
1051{
1052 animrig::Action &action = rna_action(&iter->parent);
1053 FCurve *fcurve;
1054 if (use_backward_compatible_api(action)) {
1055 fcurve = static_cast<FCurve *>(rna_iterator_array_dereference_get(iter));
1056 }
1057 else {
1058 fcurve = static_cast<FCurve *>(rna_iterator_listbase_get(iter));
1059 }
1060
1061 return RNA_pointer_create(&action.id, &RNA_FCurve, fcurve);
1062}
1063static int rna_iterator_Action_fcurves_length(PointerRNA *ptr)
1064{
1065 animrig::Action &action = rna_action(ptr);
1066 if (use_backward_compatible_api(action)) {
1068 if (!channelbag) {
1069 return 0;
1070 }
1071 return channelbag->fcurves().size();
1072 }
1073 return BLI_listbase_count(&action.curves);
1074}
1075
1076# endif // WITH_ANIM_BAKLAVA
1077
1078static FCurve *rna_Action_fcurve_new(bAction *act,
1079 Main *bmain,
1080 ReportList *reports,
1081 const char *data_path,
1082 int index,
1083 const char *group)
1084{
1085 BLI_assert(data_path != nullptr);
1086 if (data_path[0] == '\0') {
1087 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
1088 return nullptr;
1089 }
1090
1091 animrig::FCurveDescriptor fcurve_descriptor = {data_path, index};
1092 if (group && group[0] != '\0') {
1093 fcurve_descriptor.channel_group = group;
1094 }
1095
1096# ifdef WITH_ANIM_BAKLAVA
1097 animrig::Action &action = act->wrap();
1098 if (use_backward_compatible_api(action)) {
1099 /* Add the F-Curve to the channelbag for the first slot. */
1101 FCurve *fcurve = channelbag.fcurve_create_unique(bmain, fcurve_descriptor);
1102 if (!fcurve) {
1103 /* The only reason fcurve_create_unique() returns nullptr is when the curve
1104 * already exists. */
1105
1106 /* This is using the same error as below, as this is mimicking the legacy API. */
1107 BKE_reportf(reports,
1108 RPT_ERROR,
1109 "F-Curve '%s[%d]' already exists in action '%s'",
1110 data_path,
1111 index,
1112 act->id.name + 2);
1113 return nullptr;
1114 }
1115
1116 return fcurve;
1117 }
1118# endif
1119
1120 /* Annoying, check if this exists. */
1121 if (blender::animrig::fcurve_find_in_action(act, fcurve_descriptor)) {
1122 BKE_reportf(reports,
1123 RPT_ERROR,
1124 "F-Curve '%s[%d]' already exists in action '%s'",
1125 data_path,
1126 index,
1127 act->id.name + 2);
1128 return nullptr;
1129 }
1131 bmain,
1132 act,
1133 fcurve_descriptor.channel_group ? fcurve_descriptor.channel_group->c_str() : nullptr,
1134 nullptr,
1135 fcurve_descriptor);
1136}
1137
1138static FCurve *rna_Action_fcurve_find(bAction *act,
1139 ReportList *reports,
1140 const char *data_path,
1141 int index)
1142{
1143 if (data_path[0] == '\0') {
1144 BKE_report(reports, RPT_ERROR, "F-Curve data path empty, invalid argument");
1145 return nullptr;
1146 }
1147
1148# ifdef WITH_ANIM_BAKLAVA
1149 animrig::Action &action = act->wrap();
1150 if (use_backward_compatible_api(action)) {
1152 if (!channelbag) {
1153 return nullptr;
1154 }
1155 return channelbag->fcurve_find({data_path, index});
1156 }
1157# endif
1158
1159 /* Returns nullptr if not found. */
1160 return animrig::fcurve_find_in_action(act, {data_path, index});
1161}
1162
1163static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerRNA *fcu_ptr)
1164{
1165 FCurve *fcu = static_cast<FCurve *>(fcu_ptr->data);
1166
1167# ifdef WITH_ANIM_BAKLAVA
1168 animrig::Action &action = act->wrap();
1169 if (use_backward_compatible_api(action)) {
1171 if (!channelbag) {
1172 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1173 return;
1174 }
1175 if (!channelbag->fcurve_remove(*fcu)) {
1176 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1177 return;
1178 }
1179 RNA_POINTER_INVALIDATE(fcu_ptr);
1180
1183
1184 return;
1185 }
1186# endif
1187
1188 if (fcu->grp) {
1189 if (BLI_findindex(&act->groups, fcu->grp) == -1) {
1190 BKE_reportf(reports,
1191 RPT_ERROR,
1192 "F-Curve's action group '%s' not found in action '%s'",
1193 fcu->grp->name,
1194 act->id.name + 2);
1195 return;
1196 }
1197
1199 BKE_fcurve_free(fcu);
1200 RNA_POINTER_INVALIDATE(fcu_ptr);
1201 }
1202 else {
1203 if (BLI_findindex(&act->curves, fcu) == -1) {
1204 BKE_reportf(reports, RPT_ERROR, "F-Curve not found in action '%s'", act->id.name + 2);
1205 return;
1206 }
1207
1208 BLI_remlink(&act->curves, fcu);
1209 BKE_fcurve_free(fcu);
1210 RNA_POINTER_INVALIDATE(fcu_ptr);
1211 }
1212
1215}
1216
1217static void rna_Action_fcurve_clear(bAction *act)
1218{
1219# ifdef WITH_ANIM_BAKLAVA
1220 animrig::Action &action = act->wrap();
1221 if (use_backward_compatible_api(action)) {
1223 if (!channelbag) {
1224 /* Nothing to clear, so the post-condition of not having F-Curves is fulfilled. */
1225 return;
1226 }
1227 channelbag->fcurves_clear();
1228 }
1229 else {
1231 }
1232# else
1234# endif
1235
1237}
1238
1239static TimeMarker *rna_Action_pose_markers_new(bAction *act, const char name[])
1240{
1241 TimeMarker *marker = static_cast<TimeMarker *>(MEM_callocN(sizeof(TimeMarker), "TimeMarker"));
1242 marker->flag = SELECT;
1243 marker->frame = 1;
1244 STRNCPY_UTF8(marker->name, name);
1245 BLI_addtail(&act->markers, marker);
1246 return marker;
1247}
1248
1249static void rna_Action_pose_markers_remove(bAction *act,
1250 ReportList *reports,
1251 PointerRNA *marker_ptr)
1252{
1253 TimeMarker *marker = static_cast<TimeMarker *>(marker_ptr->data);
1254 if (!BLI_remlink_safe(&act->markers, marker)) {
1255 BKE_reportf(reports,
1256 RPT_ERROR,
1257 "Timeline marker '%s' not found in action '%s'",
1258 marker->name,
1259 act->id.name + 2);
1260 return;
1261 }
1262
1263 MEM_freeN(marker);
1264 RNA_POINTER_INVALIDATE(marker_ptr);
1265}
1266
1267static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr)
1268{
1269 bAction *act = (bAction *)ptr->data;
1271 ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker - 1));
1272}
1273
1274static void rna_Action_active_pose_marker_set(PointerRNA *ptr,
1275 PointerRNA value,
1276 ReportList * /*reports*/)
1277{
1278 bAction *act = (bAction *)ptr->data;
1279 act->active_marker = BLI_findindex(&act->markers, value.data) + 1;
1280}
1281
1282static int rna_Action_active_pose_marker_index_get(PointerRNA *ptr)
1283{
1284 bAction *act = (bAction *)ptr->data;
1285 return std::max(act->active_marker - 1, 0);
1286}
1287
1288static void rna_Action_active_pose_marker_index_set(PointerRNA *ptr, int value)
1289{
1290 bAction *act = (bAction *)ptr->data;
1291 act->active_marker = value + 1;
1292}
1293
1294static void rna_Action_active_pose_marker_index_range(
1295 PointerRNA *ptr, int *min, int *max, int * /*softmin*/, int * /*softmax*/)
1296{
1297 bAction *act = (bAction *)ptr->data;
1298
1299 *min = 0;
1300 *max = max_ii(0, BLI_listbase_count(&act->markers) - 1);
1301}
1302
1303# ifdef WITH_ANIM_BAKLAVA
1304static bool rna_Action_is_empty_get(PointerRNA *ptr)
1305{
1306 animrig::Action &action = rna_action(ptr);
1307 return action.is_empty();
1308}
1309static bool rna_Action_is_action_legacy_get(PointerRNA *ptr)
1310{
1311 return rna_action(ptr).is_action_legacy();
1312}
1313static bool rna_Action_is_action_layered_get(PointerRNA *ptr)
1314{
1315 return rna_action(ptr).is_action_layered();
1316}
1317# endif // WITH_ANIM_BAKLAVA
1318
1319static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values)
1320{
1321 const float2 frame_range = rna_action(ptr).get_frame_range();
1322 r_values[0] = frame_range[0];
1323 r_values[1] = frame_range[1];
1324}
1325
1326static void rna_Action_frame_range_set(PointerRNA *ptr, const float *values)
1327{
1328 bAction *data = (bAction *)ptr->owner_id;
1329
1330 data->flag |= ACT_FRAME_RANGE;
1331 data->frame_start = values[0];
1332 data->frame_end = values[1];
1333 CLAMP_MIN(data->frame_end, data->frame_start);
1334}
1335
1336static void rna_Action_curve_frame_range_get(PointerRNA *ptr, float *values)
1337{ /* don't include modifiers because they too easily can have very large
1338 * ranges: MINAFRAMEF to MAXFRAMEF. */
1339 const float2 frame_range = rna_action(ptr).get_frame_range_of_keys(false);
1340 values[0] = frame_range[0];
1341 values[1] = frame_range[1];
1342}
1343
1344static void rna_Action_use_frame_range_set(PointerRNA *ptr, bool value)
1345{
1346 animrig::Action &action = rna_action(ptr);
1347
1348 if (value) {
1349 /* If the frame range is blank, initialize it by scanning F-Curves. */
1350 if ((action.frame_start == action.frame_end) && (action.frame_start == 0)) {
1351 const float2 frame_range = action.get_frame_range_of_keys(false);
1352 action.frame_start = frame_range[0];
1353 action.frame_end = frame_range[1];
1354 }
1355
1356 action.flag |= ACT_FRAME_RANGE;
1357 }
1358 else {
1359 action.flag &= ~ACT_FRAME_RANGE;
1360 }
1361}
1362
1363static void rna_Action_start_frame_set(PointerRNA *ptr, float value)
1364{
1365 bAction *data = (bAction *)ptr->owner_id;
1366
1367 data->frame_start = value;
1368 CLAMP_MIN(data->frame_end, data->frame_start);
1369}
1370
1371static void rna_Action_end_frame_set(PointerRNA *ptr, float value)
1372{
1373 bAction *data = (bAction *)ptr->owner_id;
1374
1375 data->frame_end = value;
1376 CLAMP_MAX(data->frame_start, data->frame_end);
1377}
1378
1379static void rna_Action_deselect_keys(bAction *act)
1380{
1381 animrig::action_deselect_keys(act->wrap());
1383}
1384
1385/* Used to check if an action (value pointer)
1386 * is suitable to be assigned to the ID-block that is ptr. */
1388{
1389 ID *srcId = ptr->owner_id;
1390 bAction *dna_action = (bAction *)value.owner_id;
1391
1392 if (!dna_action) {
1393 return false;
1394 }
1395
1396 animrig::Action &action = dna_action->wrap();
1398 /* there can still be actions that will have undefined id-root
1399 * (i.e. floating "action-library" members) which we will not
1400 * be able to resolve an idroot for automatically, so let these through
1401 */
1402 if (action.idroot == 0) {
1403 return 1;
1404 }
1405 else if (srcId) {
1406 return GS(srcId->name) == action.idroot;
1407 }
1408 }
1409
1410 /* Layered Actions can always be assigned. */
1411 BLI_assert(action.idroot == 0);
1412 return true;
1413}
1414
1415/* Used to check if an action (value pointer)
1416 * can be assigned to Action Editor given current mode. */
1418{
1419 SpaceAction *saction = (SpaceAction *)ptr->data;
1420 bAction *action = (bAction *)value.owner_id;
1421
1422 if (!saction) {
1423 /* Unable to determine what this Action is going to be assigned to, so
1424 * reject it for now. This is mostly to have a non-functional refactor of
1425 * this code; personally I (Sybren) wouldn't mind to always return `true` in
1426 * this case. */
1427 return false;
1428 }
1429
1430 switch (saction->mode) {
1431 case SACTCONT_ACTION:
1433 case SACTCONT_SHAPEKEY:
1435 case SACTCONT_GPENCIL:
1436 case SACTCONT_DOPESHEET:
1437 case SACTCONT_MASK:
1438 case SACTCONT_CACHEFILE:
1439 case SACTCONT_TIMELINE:
1440 break;
1441 }
1442
1443 /* Same as above, I (Sybren) wouldn't mind returning `true` here to just
1444 * always show all Actions in an unexpected place. */
1445 return false;
1446}
1447
1448/* All FCurves need to be validated when the "show_only_errors" button is enabled. */
1449static void rna_Action_show_errors_update(bContext *C, PointerRNA * /*ptr*/)
1450{
1451 bAnimContext ac;
1452
1453 /* Get editor data. */
1454 if (ANIM_animdata_get_context(C, &ac) == 0) {
1455 return;
1456 }
1457
1458 if (!(ac.ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
1459 return;
1460 }
1461
1463}
1464
1465static std::optional<std::string> rna_DopeSheet_path(const PointerRNA *ptr)
1466{
1467 if (GS(ptr->owner_id->name) == ID_SCR) {
1468 const bScreen *screen = reinterpret_cast<bScreen *>(ptr->owner_id);
1469 const bDopeSheet *ads = static_cast<bDopeSheet *>(ptr->data);
1470 int area_index;
1471 int space_index;
1472 LISTBASE_FOREACH_INDEX (ScrArea *, area, &screen->areabase, area_index) {
1473 LISTBASE_FOREACH_INDEX (SpaceLink *, sl, &area->spacedata, space_index) {
1474 if (sl->spacetype == SPACE_GRAPH) {
1475 SpaceGraph *sipo = reinterpret_cast<SpaceGraph *>(sl);
1476 if (sipo->ads == ads) {
1477 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1478 }
1479 }
1480 else if (sl->spacetype == SPACE_NLA) {
1481 SpaceNla *snla = reinterpret_cast<SpaceNla *>(sl);
1482 if (snla->ads == ads) {
1483 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1484 }
1485 }
1486 else if (sl->spacetype == SPACE_ACTION) {
1487 SpaceAction *saction = reinterpret_cast<SpaceAction *>(sl);
1488 if (&saction->ads == ads) {
1489 return fmt::format("areas[{}].spaces[{}].dopesheet", area_index, space_index);
1490 }
1491 }
1492 }
1493 }
1494 }
1495 return "dopesheet";
1496}
1497
1498static const EnumPropertyItem *rna_ActionSlot_id_root_itemf(bContext * /* C */,
1499 PointerRNA * /* ptr */,
1500 PropertyRNA * /* prop */,
1501 bool *r_free)
1502{
1503 /* These items don't change, as the ID types are hard-coded. So better to
1504 * cache the list of enum items. */
1505 static EnumPropertyItem *_rna_ActionSlot_id_root_items = nullptr;
1506
1507 if (_rna_ActionSlot_id_root_items) {
1508 return _rna_ActionSlot_id_root_items;
1509 }
1510
1511 int totitem = 0;
1512 EnumPropertyItem *items = nullptr;
1513
1514 int i = 0;
1515 while (rna_enum_id_type_items[i].identifier != nullptr) {
1516 EnumPropertyItem item = {0};
1522 RNA_enum_item_add(&items, &totitem, &item);
1523 i++;
1524 }
1525
1527
1528 RNA_enum_item_end(&items, &totitem);
1529
1530 /* Don't free, but keep a reference to the created list. This is necessary
1531 * because of the PROP_ENUM_NO_CONTEXT flag. Without it, this will make
1532 * Blender use memory after it is freed:
1533 *
1534 * >>> slot = C.object.animation_data.action_slot
1535 * >>> enum_item = s.bl_rna.properties['id_root'].enum_items[slot.id_root]
1536 * >>> print(enum_item.name)
1537 */
1538 *r_free = false;
1539 _rna_ActionSlot_id_root_items = items;
1540
1542
1543 return items;
1544}
1545
1546#else
1547
1549{
1550 StructRNA *srna;
1551 PropertyRNA *prop;
1552
1553 srna = RNA_def_struct(brna, "DopeSheet", nullptr);
1554 RNA_def_struct_sdna(srna, "bDopeSheet");
1555 RNA_def_struct_path_func(srna, "rna_DopeSheet_path");
1557 srna, "Dope Sheet", "Settings for filtering the channels shown in animation editors");
1558
1559 /* Source of DopeSheet data */
1560 /* XXX: make this obsolete? */
1561 prop = RNA_def_property(srna, "source", PROP_POINTER, PROP_NONE);
1562 RNA_def_property_struct_type(prop, "ID");
1564 prop, "Source", "ID-Block representing source data, usually ID_SCE (i.e. Scene)");
1565
1566 /* Show data-block filters */
1567 prop = RNA_def_property(srna, "show_datablock_filters", PROP_BOOLEAN, PROP_NONE);
1570 prop,
1571 "Show Data-Block Filters",
1572 "Show options for whether channels related to certain types of data are included");
1573 RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1);
1575
1576 /* General Filtering Settings */
1577 prop = RNA_def_property(srna, "show_only_selected", PROP_BOOLEAN, PROP_NONE);
1578 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLYSEL);
1580 prop, "Only Show Selected", "Only include channels relating to selected objects and data");
1581 RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0);
1583
1584 prop = RNA_def_property(srna, "show_all_slots", PROP_BOOLEAN, PROP_NONE);
1585 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ALL_SLOTS);
1586 RNA_def_property_ui_text(prop, "Show All Slots", "Show all the Action's Slots");
1587 RNA_def_property_ui_icon(prop, ICON_ACTION_SLOT, 0);
1589
1590 prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE);
1591 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_INCL_HIDDEN);
1593 prop, "Show Hidden", "Include channels from objects/bone that are not visible");
1594 RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0);
1596
1597 prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE);
1600 "Sort Data-Blocks",
1601 "Alphabetically sorts data-blocks - mainly objects in the scene "
1602 "(disable to increase viewport speed)");
1603 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1605
1606 prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
1608 RNA_def_property_ui_text(prop, "Invert", "Invert filter search");
1609 RNA_def_property_ui_icon(prop, ICON_ZOOM_IN, 0);
1611
1612 /* Debug Filtering Settings */
1613 prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE);
1614 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_ONLY_ERRORS);
1616 "Only Show Errors",
1617 "Only include F-Curves and drivers that are disabled or have errors");
1618 RNA_def_property_ui_icon(prop, ICON_ERROR, 0);
1621 prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, "rna_Action_show_errors_update");
1622
1623 /* Object Collection Filtering Settings */
1624 prop = RNA_def_property(srna, "filter_collection", PROP_POINTER, PROP_NONE);
1625 RNA_def_property_pointer_sdna(prop, nullptr, "filter_grp");
1628 prop, "Filtering Collection", "Collection that included object should be a member of");
1630
1631 /* FCurve Display Name Search Settings */
1632 prop = RNA_def_property(srna, "filter_fcurve_name", PROP_STRING, PROP_NONE);
1633 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1634 RNA_def_property_ui_text(prop, "F-Curve Name Filter", "F-Curve live filtering string");
1635 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1638
1639 /* NLA Name Search Settings (Shared with FCurve setting, but with different labels) */
1640 prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
1641 RNA_def_property_string_sdna(prop, nullptr, "searchstr");
1642 RNA_def_property_ui_text(prop, "Name Filter", "Live filtering string");
1644 RNA_def_property_ui_icon(prop, ICON_VIEWZOOM, 0);
1646
1647 /* Multi-word fuzzy search option for name/text filters */
1648 prop = RNA_def_property(srna, "use_multi_word_filter", PROP_BOOLEAN, PROP_NONE);
1651 "Multi-Word Fuzzy Filter",
1652 "Perform fuzzy/multi-word matching.\n"
1653 "Warning: May be slow");
1654 RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1656
1657 /* NLA Specific Settings */
1658 prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE);
1661 "Include Missing NLA",
1662 "Include animation data-blocks with no NLA data (NLA editor only)");
1663 RNA_def_property_ui_icon(prop, ICON_ACTION, 0);
1665
1666 /* Summary Settings (DopeSheet editors only) */
1667 prop = RNA_def_property(srna, "show_summary", PROP_BOOLEAN, PROP_NONE);
1668 RNA_def_property_boolean_sdna(prop, nullptr, "filterflag", ADS_FILTER_SUMMARY);
1670 prop, "Display Summary", "Display an additional 'summary' line (Dope Sheet editors only)");
1671 RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0);
1673
1674 prop = RNA_def_property(srna, "show_expanded_summary", PROP_BOOLEAN, PROP_NONE);
1677 prop,
1678 "Collapse Summary",
1679 "Collapse summary when shown, so all other channels get hidden (Dope Sheet editors only)");
1681
1682 /* General DataType Filtering Settings */
1683 prop = RNA_def_property(srna, "show_transforms", PROP_BOOLEAN, PROP_NONE);
1684 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOOBJ);
1686 prop,
1687 "Display Transforms",
1688 "Include visualization of object-level animation data (mostly transforms)");
1689 RNA_def_property_ui_icon(prop, ICON_ORIENTATION_GLOBAL, 0); /* XXX? */
1691
1692 prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE);
1695 prop, "Display Shape Keys", "Include visualization of shape key related animation data");
1696 RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0);
1698
1699 prop = RNA_def_property(srna, "show_modifiers", PROP_BOOLEAN, PROP_NONE);
1702 prop,
1703 "Display Modifier Data",
1704 "Include visualization of animation data related to data-blocks linked to modifiers");
1705 RNA_def_property_ui_icon(prop, ICON_MODIFIER_DATA, 0);
1707
1708 prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE);
1709 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMESH);
1711 prop, "Display Meshes", "Include visualization of mesh related animation data");
1712 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_MESH, 0);
1714
1715 prop = RNA_def_property(srna, "show_lattices", PROP_BOOLEAN, PROP_NONE);
1716 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAT);
1718 prop, "Display Lattices", "Include visualization of lattice related animation data");
1719 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LATTICE, 0);
1721
1722 prop = RNA_def_property(srna, "show_cameras", PROP_BOOLEAN, PROP_NONE);
1723 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCAM);
1725 prop, "Display Camera", "Include visualization of camera related animation data");
1726 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CAMERA, 0);
1728
1729 prop = RNA_def_property(srna, "show_materials", PROP_BOOLEAN, PROP_NONE);
1730 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMAT);
1732 prop, "Display Material", "Include visualization of material related animation data");
1733 RNA_def_property_ui_icon(prop, ICON_MATERIAL_DATA, 0);
1735
1736 prop = RNA_def_property(srna, "show_lights", PROP_BOOLEAN, PROP_NONE);
1737 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOLAM);
1739 prop, "Display Light", "Include visualization of light related animation data");
1740 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_LIGHT, 0);
1742
1743 prop = RNA_def_property(srna, "show_linestyles", PROP_BOOLEAN, PROP_NONE);
1746 prop, "Display Line Style", "Include visualization of Line Style related Animation data");
1747 RNA_def_property_ui_icon(prop, ICON_LINE_DATA, 0);
1749
1750 prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE);
1751 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOTEX);
1753 prop, "Display Texture", "Include visualization of texture related animation data");
1754 RNA_def_property_ui_icon(prop, ICON_TEXTURE_DATA, 0);
1756
1757 prop = RNA_def_property(srna, "show_curves", PROP_BOOLEAN, PROP_NONE);
1758 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOCUR);
1760 prop, "Display Curve", "Include visualization of curve related animation data");
1761 RNA_def_property_ui_icon(prop, ICON_CURVE_DATA, 0);
1763
1764 prop = RNA_def_property(srna, "show_worlds", PROP_BOOLEAN, PROP_NONE);
1765 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOWOR);
1767 prop, "Display World", "Include visualization of world related animation data");
1768 RNA_def_property_ui_icon(prop, ICON_WORLD_DATA, 0);
1770
1771 prop = RNA_def_property(srna, "show_scenes", PROP_BOOLEAN, PROP_NONE);
1772 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSCE);
1774 prop, "Display Scene", "Include visualization of scene related animation data");
1775 RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0);
1777
1778 prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
1779 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOPART);
1781 prop, "Display Particle", "Include visualization of particle related animation data");
1782 RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0);
1784
1785 prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE);
1786 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOMBA);
1788 prop, "Display Metaball", "Include visualization of metaball related animation data");
1789 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_META, 0);
1791
1792 prop = RNA_def_property(srna, "show_armatures", PROP_BOOLEAN, PROP_NONE);
1793 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOARM);
1795 prop, "Display Armature", "Include visualization of armature related animation data");
1796 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_ARMATURE, 0);
1798
1799 prop = RNA_def_property(srna, "show_nodes", PROP_BOOLEAN, PROP_NONE);
1800 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NONTREE);
1802 prop, "Display Node", "Include visualization of node related animation data");
1803 RNA_def_property_ui_icon(prop, ICON_NODETREE, 0);
1805
1806 prop = RNA_def_property(srna, "show_speakers", PROP_BOOLEAN, PROP_NONE);
1807 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag", ADS_FILTER_NOSPK);
1809 prop, "Display Speaker", "Include visualization of speaker related animation data");
1810 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_SPEAKER, 0);
1812
1813 prop = RNA_def_property(srna, "show_cache_files", PROP_BOOLEAN, PROP_NONE);
1816 prop, "Display Cache Files", "Include visualization of cache file related animation data");
1817 RNA_def_property_ui_icon(prop, ICON_FILE, 0);
1819
1820 prop = RNA_def_property(srna, "show_hair_curves", PROP_BOOLEAN, PROP_NONE);
1821 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOHAIR);
1823 prop, "Display Hair", "Include visualization of hair related animation data");
1824 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CURVES, 0);
1826
1827 prop = RNA_def_property(srna, "show_pointclouds", PROP_BOOLEAN, PROP_NONE);
1830 prop, "Display Point Cloud", "Include visualization of point cloud related animation data");
1831 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_POINTCLOUD, 0);
1833
1834 prop = RNA_def_property(srna, "show_volumes", PROP_BOOLEAN, PROP_NONE);
1835 RNA_def_property_boolean_negative_sdna(prop, nullptr, "filterflag2", ADS_FILTER_NOVOLUME);
1837 prop, "Display Volume", "Include visualization of volume related animation data");
1838 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_VOLUME, 0);
1840
1841 prop = RNA_def_property(srna, "show_gpencil", PROP_BOOLEAN, PROP_NONE);
1844 prop,
1845 "Display Grease Pencil",
1846 "Include visualization of Grease Pencil related animation data and frames");
1847 RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_GREASEPENCIL, 0);
1849
1850 prop = RNA_def_property(srna, "show_movieclips", PROP_BOOLEAN, PROP_NONE);
1853 prop, "Display Movie Clips", "Include visualization of movie clip related animation data");
1854 RNA_def_property_ui_icon(prop, ICON_TRACKER, 0);
1856
1857 prop = RNA_def_property(srna, "show_driver_fallback_as_error", PROP_BOOLEAN, PROP_NONE);
1860 prop,
1861 "Variable Fallback As Error",
1862 "Include drivers that relied on any fallback values for their evaluation "
1863 "in the Only Show Errors filter, even if the driver evaluation succeeded");
1864 RNA_def_property_ui_icon(prop, ICON_RNA, 0);
1866}
1867
1868/* =========================== Layered Action interface =========================== */
1869
1870# ifdef WITH_ANIM_BAKLAVA
1871
1872static void rna_def_action_slots(BlenderRNA *brna, PropertyRNA *cprop)
1873{
1874 StructRNA *srna;
1875 PropertyRNA *prop;
1876
1877 FunctionRNA *func;
1878 PropertyRNA *parm;
1879
1880 RNA_def_property_srna(cprop, "ActionSlots");
1881 srna = RNA_def_struct(brna, "ActionSlots", nullptr);
1882 RNA_def_struct_sdna(srna, "bAction");
1883 RNA_def_struct_ui_text(srna, "Action Slots", "Collection of action slots");
1884
1885 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
1886 RNA_def_property_struct_type(prop, "ActionSlot");
1889 prop, "rna_ActionSlots_active_get", "rna_ActionSlots_active_set", nullptr, nullptr);
1891
1892 RNA_def_property_ui_text(prop, "Active Slot", "Active slot for this action");
1893
1894 /* Animation.slots.new(...) */
1895 func = RNA_def_function(srna, "new", "rna_Action_slots_new");
1896 RNA_def_function_ui_description(func, "Add a slot to the Action");
1898 parm = RNA_def_pointer(
1899 func,
1900 "for_id",
1901 "ID",
1902 "Data-Block",
1903 "If given, the new slot will be named after this data-block, and limited to animating "
1904 "data-blocks of its type. If ommitted, limiting the ID type will happen as soon as the "
1905 "slot is assigned.");
1906 /* Clear out the PARM_REQUIRED flag, which is set by default for pointer parameters. */
1908
1909 parm = RNA_def_pointer(func, "slot", "ActionSlot", "", "Newly created action slot");
1910 RNA_def_function_return(func, parm);
1911
1912 /* Animation.slots.remove(layer) */
1913 func = RNA_def_function(srna, "remove", "rna_Action_slots_remove");
1916 "Remove the slot from the Action, including all animation that "
1917 "is associated with that slot");
1918 parm = RNA_def_pointer(func, "action_slot", "ActionSlot", "Action Slot", "The slot to remove");
1920}
1921
1922static void rna_def_action_layers(BlenderRNA *brna, PropertyRNA *cprop)
1923{
1924 StructRNA *srna;
1925
1926 FunctionRNA *func;
1927 PropertyRNA *parm;
1928
1929 RNA_def_property_srna(cprop, "ActionLayers");
1930 srna = RNA_def_struct(brna, "ActionLayers", nullptr);
1931 RNA_def_struct_sdna(srna, "bAction");
1932 RNA_def_struct_ui_text(srna, "Action Layers", "Collection of animation layers");
1933
1934 /* Animation.layers.new(...) */
1935 func = RNA_def_function(srna, "new", "rna_Action_layers_new");
1938 func,
1939 "Add a layer to the Animation. Currently an Animation can only have at most one layer.");
1940 parm = RNA_def_string(func,
1941 "name",
1942 nullptr,
1943 sizeof(ActionLayer::name) - 1,
1944 "Name",
1945 "Name of the layer, will be made unique within the Action");
1947 parm = RNA_def_pointer(func, "layer", "ActionLayer", "", "Newly created animation layer");
1948 RNA_def_function_return(func, parm);
1949
1950 /* Animation.layers.remove(layer) */
1951 func = RNA_def_function(srna, "remove", "rna_Action_layers_remove");
1953 RNA_def_function_ui_description(func, "Remove the layer from the animation");
1954 parm = RNA_def_pointer(
1955 func, "anim_layer", "ActionLayer", "Animation Layer", "The layer to remove");
1957}
1958
1959static void rna_def_action_slot(BlenderRNA *brna)
1960{
1961 StructRNA *srna;
1962 PropertyRNA *prop;
1963
1964 srna = RNA_def_struct(brna, "ActionSlot", nullptr);
1965 RNA_def_struct_path_func(srna, "rna_ActionSlot_path");
1966 RNA_def_struct_ui_icon(srna, ICON_ACTION_SLOT);
1968 srna,
1969 "Action slot",
1970 "Identifier for a set of channels in this Action, that can be used by a data-block "
1971 "to specify what it gets animated by");
1972
1974
1975 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
1976 RNA_def_struct_name_property(srna, prop);
1977 RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_ActionSlot_name_set");
1979 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_name_update");
1981 prop,
1982 "Slot Name",
1983 "Used when connecting an Action to a data-block, to find the correct slot handle. This is "
1984 "the display name, prefixed by two characters determined by the slot's ID type");
1985
1986 prop = RNA_def_property(srna, "id_root", PROP_ENUM, PROP_NONE);
1987 RNA_def_property_enum_sdna(prop, nullptr, "idtype");
1989 RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_ActionSlot_id_root_itemf");
1993 prop, "ID Root Type", "Type of data-block that can be animated by this slot");
1995
1996 prop = RNA_def_property(srna, "id_root_icon", PROP_INT, PROP_NONE);
1997 RNA_def_property_int_funcs(prop, "rna_ActionSlot_id_root_icon_get", nullptr, nullptr);
1999
2000 prop = RNA_def_property(srna, "name_display", PROP_STRING, PROP_NONE);
2002 "rna_ActionSlot_name_display_get",
2003 "rna_ActionSlot_name_display_length",
2004 "rna_ActionSlot_name_display_set");
2006 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_ActionSlot_name_update");
2008 prop,
2009 "Slot Display Name",
2010 "Name of the slot, for display in the user interface. This name combined with the slot's "
2011 "data-block type is unique within its Action");
2012
2013 prop = RNA_def_property(srna, "handle", PROP_INT, PROP_NONE);
2016 "Slot Handle",
2017 "Number specific to this Slot, unique within the Action"
2018 "This is used, for example, on a ActionKeyframeStrip to look up the "
2019 "ActionChannelBag for this Slot");
2020
2021 prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
2022 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Active));
2024 prop,
2025 "Active",
2026 "Whether this is the active slot, can be set by assigning to action.slots.active");
2030
2031 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
2032 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Selected));
2033 RNA_def_property_ui_text(prop, "Select", "Selection state of the slot");
2037
2038 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
2039 RNA_def_property_boolean_sdna(prop, nullptr, "slot_flags", int(animrig::Slot::Flags::Expanded));
2040 RNA_def_property_ui_text(prop, "Show Expanded", "Expanded state of the slot");
2044
2045# ifndef NDEBUG
2046 /* Slot.debug_log_users() */
2047 {
2048 FunctionRNA *func;
2049
2050 func = RNA_def_function(srna, "debug_log_users", "rna_ActionSlot_debug_log_users");
2052 }
2053# endif
2054}
2055
2056static void rna_def_ActionLayer_strips(BlenderRNA *brna, PropertyRNA *cprop)
2057{
2058 StructRNA *srna;
2059
2060 FunctionRNA *func;
2061 PropertyRNA *parm;
2062
2063 RNA_def_property_srna(cprop, "ActionStrips");
2064 srna = RNA_def_struct(brna, "ActionStrips", nullptr);
2065 RNA_def_struct_sdna(srna, "ActionLayer");
2066 RNA_def_struct_ui_text(srna, "Action Strips", "Collection of animation strips");
2067
2068 /* Layer.strips.new(type='...') */
2069 func = RNA_def_function(srna, "new", "rna_ActionStrips_new");
2071 "Add a new strip to the layer. Currently a layer can only have "
2072 "one strip, with infinite boundaries.");
2074 parm = RNA_def_enum(func,
2075 "type",
2076 rna_enum_strip_type_items,
2077 int(animrig::Strip::Type::Keyframe),
2078 "Type",
2079 "The type of strip to create");
2080 /* Return value. */
2081 parm = RNA_def_pointer(func, "strip", "ActionStrip", "", "Newly created animation strip");
2082 RNA_def_function_return(func, parm);
2083
2084 /* Layer.strips.remove(strip) */
2085 func = RNA_def_function(srna, "remove", "rna_ActionStrips_remove");
2087 RNA_def_function_ui_description(func, "Remove the strip from the animation layer");
2088 parm = RNA_def_pointer(
2089 func, "anim_strip", "ActionStrip", "Animation Strip", "The strip to remove");
2091}
2092
2093static void rna_def_action_layer(BlenderRNA *brna)
2094{
2095 StructRNA *srna;
2096 PropertyRNA *prop;
2097
2098 srna = RNA_def_struct(brna, "ActionLayer", nullptr);
2099 RNA_def_struct_ui_text(srna, "Action Layer", "");
2100 RNA_def_struct_path_func(srna, "rna_ActionLayer_path");
2101
2102 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
2103 RNA_def_struct_name_property(srna, prop);
2104
2105 prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_FACTOR);
2106 RNA_def_property_range(prop, 0.0f, 1.0f);
2108 prop, "Influence", "How much of this layer is used when blending into the lower layers");
2109 RNA_def_property_ui_range(prop, 0.0, 1.0, 3, 2);
2111 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
2112
2113 prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
2114 RNA_def_property_enum_sdna(prop, nullptr, "layer_mix_mode");
2116 prop, "Mix Mode", "How animation of this layer is blended into the lower layers");
2118 RNA_def_property_enum_items(prop, rna_enum_layer_mix_mode_items);
2119 RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_Action_tag_animupdate");
2120
2121 /* Collection properties .*/
2122 prop = RNA_def_property(srna, "strips", PROP_COLLECTION, PROP_NONE);
2123 RNA_def_property_struct_type(prop, "ActionStrip");
2125 "rna_iterator_ActionLayer_strips_begin",
2126 "rna_iterator_array_next",
2127 "rna_iterator_array_end",
2128 "rna_iterator_array_dereference_get",
2129 "rna_iterator_ActionLayer_strips_length",
2130 nullptr,
2131 nullptr,
2132 nullptr);
2133 RNA_def_property_ui_text(prop, "Strips", "The list of strips that are on this animation layer");
2134
2135 rna_def_ActionLayer_strips(brna, prop);
2136}
2137
2138static void rna_def_keyframestrip_channelbags(BlenderRNA *brna, PropertyRNA *cprop)
2139{
2140 StructRNA *srna;
2141
2142 FunctionRNA *func;
2143 PropertyRNA *parm;
2144
2145 RNA_def_property_srna(cprop, "ActionChannelBags");
2146 srna = RNA_def_struct(brna, "ActionChannelBags", nullptr);
2147 RNA_def_struct_sdna(srna, "ActionStrip");
2149 srna,
2150 "Animation Channels for Slots",
2151 "For each action slot, a list of animation channels that are meant for that slot");
2152
2153 /* Strip.channelbags.new(slot=...) */
2154 func = RNA_def_function(srna, "new", "rna_ChannelBags_new");
2156 func,
2157 "Add a new channelbag to the strip, to contain animation channels for a specific slot");
2159 parm = RNA_def_pointer(func,
2160 "slot",
2161 "ActionSlot",
2162 "Action Slot",
2163 "The slot that should be animated by this channelbag");
2165
2166 /* Return value. */
2167 parm = RNA_def_pointer(func, "channelbag", "ActionChannelBag", "", "Newly created channelbag");
2168 RNA_def_function_return(func, parm);
2169
2170 /* Strip.channelbags.remove(strip) */
2171 func = RNA_def_function(srna, "remove", "rna_ChannelBags_remove");
2173 RNA_def_function_ui_description(func, "Remove the channelbag from the strip");
2174 parm = RNA_def_pointer(func, "channelbag", "ActionChannelBag", "", "The channelbag to remove");
2176}
2177
2181static void rna_def_action_keyframe_strip(BlenderRNA *brna)
2182{
2183 StructRNA *srna;
2184 PropertyRNA *prop;
2185
2186 srna = RNA_def_struct(brna, "ActionKeyframeStrip", "ActionStrip");
2188 srna, "Keyframe Animation Strip", "Strip with a set of F-Curves for each action slot");
2189 RNA_def_struct_sdna_from(srna, "ActionStrip", nullptr);
2190
2191 prop = RNA_def_property(srna, "channelbags", PROP_COLLECTION, PROP_NONE);
2192 RNA_def_property_struct_type(prop, "ActionChannelBag");
2194 "rna_iterator_keyframestrip_channelbags_begin",
2195 "rna_iterator_array_next",
2196 "rna_iterator_array_end",
2197 "rna_iterator_array_dereference_get",
2198 "rna_iterator_keyframestrip_channelbags_length",
2199 nullptr,
2200 nullptr,
2201 nullptr);
2202 rna_def_keyframestrip_channelbags(brna, prop);
2203
2204 {
2205 FunctionRNA *func;
2206 PropertyRNA *parm;
2207
2208 /* Strip.channels(...). */
2209 func = RNA_def_function(srna, "channels", "rna_ActionStrip_channels");
2211 RNA_def_function_ui_description(func, "Find the ActionChannelBag for a specific Slot");
2212 parm = RNA_def_int(func,
2213 "slot_handle",
2214 0,
2215 0,
2216 INT_MAX,
2217 "Slot Handle",
2218 "Number that identifies a specific action slot",
2219 0,
2220 INT_MAX);
2222 parm = RNA_def_pointer(func, "channels", "ActionChannelBag", "Channels", "");
2223 RNA_def_function_return(func, parm);
2224
2225 /* Strip.key_insert(...). */
2226
2227 func = RNA_def_function(srna, "key_insert", "rna_ActionStrip_key_insert");
2229 parm = RNA_def_pointer(func,
2230 "slot",
2231 "ActionSlot",
2232 "Slot",
2233 "The slot that identifies which 'thing' should be keyed");
2235
2236 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2238
2239 parm = RNA_def_int(
2240 func,
2241 "array_index",
2242 -1,
2243 -INT_MAX,
2244 INT_MAX,
2245 "Array Index",
2246 "Index of the animated array element, or -1 if the property is not an array",
2247 -1,
2248 4);
2250
2251 parm = RNA_def_float(func,
2252 "value",
2253 0.0,
2254 -FLT_MAX,
2255 FLT_MAX,
2256 "Value to key",
2257 "Value of the animated property",
2258 -FLT_MAX,
2259 FLT_MAX);
2261
2262 parm = RNA_def_float(func,
2263 "time",
2264 0.0,
2265 -FLT_MAX,
2266 FLT_MAX,
2267 "Time of the key",
2268 "Time, in frames, of the key",
2269 -FLT_MAX,
2270 FLT_MAX);
2272
2273 parm = RNA_def_boolean(
2274 func, "success", true, "Success", "Whether the key was successfully inserted");
2275
2276 RNA_def_function_return(func, parm);
2277 }
2278}
2279
2280static void rna_def_action_strip(BlenderRNA *brna)
2281{
2282 StructRNA *srna;
2283 PropertyRNA *prop;
2284
2285 srna = RNA_def_struct(brna, "ActionStrip", nullptr);
2286 RNA_def_struct_ui_text(srna, "Action Strip", "");
2287 RNA_def_struct_path_func(srna, "rna_ActionStrip_path");
2288 RNA_def_struct_refine_func(srna, "rna_ActionStrip_refine");
2289
2290 static const EnumPropertyItem prop_type_items[] = {
2291 {int(animrig::Strip::Type::Keyframe),
2292 "KEYFRAME",
2293 0,
2294 "Keyframe",
2295 "Strip with a set of F-Curves for each action slot"},
2296 {0, nullptr, 0, nullptr, nullptr},
2297 };
2298
2299 prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
2300 RNA_def_property_enum_sdna(prop, nullptr, "strip_type");
2301 RNA_def_property_enum_items(prop, prop_type_items);
2303
2304 /* Define Strip subtypes. */
2305 rna_def_action_keyframe_strip(brna);
2306}
2307
2308static void rna_def_channelbag_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
2309{
2310 StructRNA *srna;
2311
2312 FunctionRNA *func;
2313 PropertyRNA *parm;
2314
2315 RNA_def_property_srna(cprop, "ActionChannelBagFCurves");
2316 srna = RNA_def_struct(brna, "ActionChannelBagFCurves", nullptr);
2317 RNA_def_struct_sdna(srna, "ActionChannelBag");
2319 srna, "F-Curves", "Collection of F-Curves for a specific action slot, on a specific strip");
2320
2321 /* ChannelBag.fcurves.new(...) */
2322 extern FCurve *ActionChannelBagFCurves_new_func(ID * _selfid,
2323 ActionChannelBag * _self,
2324 Main * bmain,
2325 ReportList * reports,
2326 const char *data_path,
2327 int index);
2328
2329 func = RNA_def_function(srna, "new", "rna_ChannelBag_fcurve_new");
2330 RNA_def_function_ui_description(func, "Add an F-Curve to the channelbag");
2332 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2334 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2335
2336 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2337 RNA_def_function_return(func, parm);
2338
2339 /* ChannelBag.fcurves.find(...) */
2340 func = RNA_def_function(srna, "find", "rna_ChannelBag_fcurve_find");
2342 func,
2343 "Find an F-Curve. Note that this function performs a linear scan "
2344 "of all F-Curves in the channelbag.");
2346 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2348 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2349 parm = RNA_def_pointer(
2350 func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
2351 RNA_def_function_return(func, parm);
2352
2353 /* ChannelBag.fcurves.remove(...) */
2354 func = RNA_def_function(srna, "remove", "rna_ChannelBag_fcurve_remove");
2355 RNA_def_function_ui_description(func, "Remove F-Curve");
2357 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove");
2360
2361 /* ChannelBag.fcurves.clear() */
2362 func = RNA_def_function(srna, "clear", "rna_ChannelBag_fcurve_clear");
2364 RNA_def_function_ui_description(func, "Remove all F-Curves from this channelbag");
2365}
2366
2367static void rna_def_channelbag_groups(BlenderRNA *brna, PropertyRNA *cprop)
2368{
2369 StructRNA *srna;
2370
2371 FunctionRNA *func;
2372 PropertyRNA *parm;
2373
2374 RNA_def_property_srna(cprop, "ActionChannelBagGroups");
2375 srna = RNA_def_struct(brna, "ActionChannelBagGroups", nullptr);
2376 RNA_def_struct_sdna(srna, "ActionChannelBag");
2377 RNA_def_struct_ui_text(srna, "F-Curve Groups", "Collection of f-curve groups");
2378
2379 func = RNA_def_function(srna, "new", "rna_ChannelBag_group_new");
2381 RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
2382 parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
2384 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Newly created action group");
2385 RNA_def_function_return(func, parm);
2386
2387 func = RNA_def_function(srna, "remove", "rna_ChannelBag_group_remove");
2388 RNA_def_function_ui_description(func, "Remove action group");
2390 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove");
2393}
2394
2395static void rna_def_action_channelbag(BlenderRNA *brna)
2396{
2397 StructRNA *srna;
2398 PropertyRNA *prop;
2399
2400 srna = RNA_def_struct(brna, "ActionChannelBag", nullptr);
2402 srna,
2403 "Animation Channel Bag",
2404 "Collection of animation channels, typically associated with an action slot");
2405 RNA_def_struct_path_func(srna, "rna_ChannelBag_path");
2406
2407 prop = RNA_def_property(srna, "slot_handle", PROP_INT, PROP_NONE);
2409
2410 /* ChannelBag.fcurves */
2411 prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
2413 "rna_iterator_ChannelBag_fcurves_begin",
2414 "rna_iterator_array_next",
2415 "rna_iterator_array_end",
2416 "rna_iterator_array_dereference_get",
2417 "rna_iterator_ChannelBag_fcurves_length",
2418 nullptr,
2419 nullptr,
2420 nullptr);
2421 RNA_def_property_struct_type(prop, "FCurve");
2422 RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that animate the slot");
2423 rna_def_channelbag_fcurves(brna, prop);
2424
2425 /* ChannelBag.groups */
2426 prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
2428 "rna_iterator_ChannelBag_groups_begin",
2429 "rna_iterator_array_next",
2430 "rna_iterator_array_end",
2431 "rna_iterator_array_dereference_get",
2432 "rna_iterator_ChannelBag_groups_length",
2433 nullptr,
2434 nullptr,
2435 nullptr);
2436 RNA_def_property_struct_type(prop, "ActionGroup");
2438 prop,
2439 "F-Curve Groups",
2440 "Groupings of F-Curves for display purposes, in e.g. the dopesheet and graph editor");
2441 rna_def_channelbag_groups(brna, prop);
2442}
2443# endif // WITH_ANIM_BAKLAVA
2444
2446{
2447 StructRNA *srna;
2448 PropertyRNA *prop;
2449
2450 srna = RNA_def_struct(brna, "ActionGroup", nullptr);
2451 RNA_def_struct_sdna(srna, "bActionGroup");
2452 RNA_def_struct_ui_text(srna, "Action Group", "Groups of F-Curves");
2453
2454 prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
2455 RNA_def_property_ui_text(prop, "Name", "");
2456 RNA_def_struct_name_property(srna, prop);
2458
2459 /* WARNING: be very careful when working with this list, since the endpoint is not
2460 * defined like a standard ListBase. Adding/removing channels from this list needs
2461 * extreme care, otherwise the F-Curve list running through adjacent groups does
2462 * not match up with the one stored in the Action, resulting in curves which do not
2463 * show up in animation editors. In extreme cases, animation may also selectively
2464 * fail to play back correctly.
2465 *
2466 * If such changes are required, these MUST go through the API functions for manipulating
2467 * these F-Curve groupings. Also, note that groups only apply in actions ONLY.
2468 */
2469 prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
2470 RNA_def_property_collection_sdna(prop, nullptr, "channels", nullptr);
2471 RNA_def_property_struct_type(prop, "FCurve");
2473 "rna_ActionGroup_channels_begin",
2474 "rna_ActionGroup_channels_next",
2475 "rna_ActionGroup_channels_end",
2476 "rna_ActionGroup_channels_get",
2477 nullptr,
2478 nullptr,
2479 nullptr,
2480 nullptr);
2481 RNA_def_property_ui_text(prop, "Channels", "F-Curves in this group");
2482
2483 prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
2484 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_SELECTED);
2485 RNA_def_property_ui_text(prop, "Select", "Action group is selected");
2487
2488 prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE);
2489 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_PROTECTED);
2490 RNA_def_property_ui_text(prop, "Lock", "Action group is locked");
2492
2493 prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
2494 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_MUTED);
2495 RNA_def_property_ui_text(prop, "Mute", "Action group is muted");
2497
2498 prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
2500 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED);
2501 RNA_def_property_ui_text(prop, "Expanded", "Action group is expanded except in graph editor");
2503
2504 prop = RNA_def_property(srna, "show_expanded_graph", PROP_BOOLEAN, PROP_NONE);
2506 RNA_def_property_boolean_sdna(prop, nullptr, "flag", AGRP_EXPANDED_G);
2508 prop, "Expanded in Graph Editor", "Action group is expanded in graph editor");
2510
2511 prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
2514 RNA_def_property_ui_text(prop, "Pin in Graph Editor", "");
2516
2517 /* color set */
2519}
2520
2521/* =========================== Legacy Action interface =========================== */
2522
2523/* fcurve.keyframe_points */
2525{
2526 StructRNA *srna;
2527
2528 FunctionRNA *func;
2529 PropertyRNA *parm;
2530
2531 RNA_def_property_srna(cprop, "ActionGroups");
2532 srna = RNA_def_struct(brna, "ActionGroups", nullptr);
2533 RNA_def_struct_sdna(srna, "bAction");
2534 RNA_def_struct_ui_text(srna, "Action Groups", "Collection of action groups");
2535# ifdef WITH_ANIM_BAKLAVA
2537 "rna_iterator_Action_groups_begin",
2538 "rna_iterator_Action_groups_next",
2539 "rna_iterator_Action_groups_end",
2540 "rna_iterator_Action_groups_get",
2541 "rna_iterator_Action_groups_length",
2542 nullptr,
2543 nullptr,
2544 nullptr);
2545# endif
2546
2547 func = RNA_def_function(srna, "new", "rna_Action_groups_new");
2548 RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
2549 parm = RNA_def_string(func, "name", "Group", 0, "", "New name for the action group");
2551 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Newly created action group");
2552 RNA_def_function_return(func, parm);
2553
2554 func = RNA_def_function(srna, "remove", "rna_Action_groups_remove");
2555 RNA_def_function_ui_description(func, "Remove action group");
2557 parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove");
2560}
2561
2563{
2564 StructRNA *srna;
2565
2566 FunctionRNA *func;
2567 PropertyRNA *parm;
2568
2569 RNA_def_property_srna(cprop, "ActionFCurves");
2570 srna = RNA_def_struct(brna, "ActionFCurves", nullptr);
2571 RNA_def_struct_sdna(srna, "bAction");
2572 RNA_def_struct_ui_text(srna, "Action F-Curves", "Collection of action F-Curves");
2573# ifdef WITH_ANIM_BAKLAVA
2575 "rna_iterator_Action_fcurves_begin",
2576 "rna_iterator_Action_fcurves_next",
2577 "rna_iterator_Action_fcurves_end",
2578 "rna_iterator_Action_fcurves_get",
2579 "rna_iterator_Action_fcurves_length",
2580 nullptr,
2581 nullptr,
2582 nullptr);
2583# endif
2584
2585 /* Action.fcurves.new(...) */
2586 func = RNA_def_function(srna, "new", "rna_Action_fcurve_new");
2587 RNA_def_function_ui_description(func, "Add an F-Curve to the action");
2589 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
2591 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2593 func, "action_group", nullptr, 0, "Action Group", "Acton group to add this F-Curve into");
2594
2595 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "Newly created F-Curve");
2596 RNA_def_function_return(func, parm);
2597
2598 /* Action.fcurves.find(...) */
2599 func = RNA_def_function(srna, "find", "rna_Action_fcurve_find");
2601 func,
2602 "Find an F-Curve. Note that this function performs a linear scan "
2603 "of all F-Curves in the action.");
2605 parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path");
2607 RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
2608 parm = RNA_def_pointer(
2609 func, "fcurve", "FCurve", "", "The found F-Curve, or None if it doesn't exist");
2610 RNA_def_function_return(func, parm);
2611
2612 /* Action.fcurves.remove(...) */
2613 func = RNA_def_function(srna, "remove", "rna_Action_fcurve_remove");
2614 RNA_def_function_ui_description(func, "Remove F-Curve");
2616 parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove");
2619
2620 /* Action.fcurves.clear() */
2621 func = RNA_def_function(srna, "clear", "rna_Action_fcurve_clear");
2622 RNA_def_function_ui_description(func, "Remove all F-Curves");
2623}
2624
2626{
2627 StructRNA *srna;
2628 PropertyRNA *prop;
2629
2630 FunctionRNA *func;
2631 PropertyRNA *parm;
2632
2633 RNA_def_property_srna(cprop, "ActionPoseMarkers");
2634 srna = RNA_def_struct(brna, "ActionPoseMarkers", nullptr);
2635 RNA_def_struct_sdna(srna, "bAction");
2636 RNA_def_struct_ui_text(srna, "Action Pose Markers", "Collection of timeline markers");
2637
2638 func = RNA_def_function(srna, "new", "rna_Action_pose_markers_new");
2639 RNA_def_function_ui_description(func, "Add a pose marker to the action");
2640 parm = RNA_def_string(
2641 func, "name", "Marker", 0, nullptr, "New name for the marker (not unique)");
2643 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Newly created marker");
2644 RNA_def_function_return(func, parm);
2645
2646 func = RNA_def_function(srna, "remove", "rna_Action_pose_markers_remove");
2647 RNA_def_function_ui_description(func, "Remove a timeline marker");
2649 parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove");
2652
2653 prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
2654 RNA_def_property_struct_type(prop, "TimelineMarker");
2657 "rna_Action_active_pose_marker_get",
2658 "rna_Action_active_pose_marker_set",
2659 nullptr,
2660 nullptr);
2661 RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action");
2662
2663 prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
2664 RNA_def_property_int_sdna(prop, nullptr, "active_marker");
2667 "rna_Action_active_pose_marker_index_get",
2668 "rna_Action_active_pose_marker_index_set",
2669 "rna_Action_active_pose_marker_index_range");
2670 RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker");
2671}
2672
2673/* Access to 'legacy' Action features, like the top-level F-Curves, the corresponding F-Curve
2674 * groups, and the top-level id_root. */
2676{
2677 PropertyRNA *prop;
2678
2679 /* collections */
2680 prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE);
2681 RNA_def_property_collection_sdna(prop, nullptr, "curves", nullptr);
2682 RNA_def_property_struct_type(prop, "FCurve");
2683 RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that make up the action");
2684 rna_def_action_fcurves(brna, prop);
2685
2686 prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE);
2687 RNA_def_property_collection_sdna(prop, nullptr, "groups", nullptr);
2688 RNA_def_property_struct_type(prop, "ActionGroup");
2689 RNA_def_property_ui_text(prop, "Groups", "Convenient groupings of F-Curves");
2690 rna_def_action_groups(brna, prop);
2691
2692 /* special "type" limiter - should not really be edited in general,
2693 * but is still available/editable in 'emergencies' */
2694 prop = RNA_def_property(srna, "id_root", PROP_ENUM, PROP_NONE);
2695 RNA_def_property_enum_sdna(prop, nullptr, "idroot");
2697 RNA_def_property_enum_funcs(prop, nullptr, nullptr, "rna_ActionSlot_id_root_itemf");
2700 "ID Root Type",
2701 "Type of ID block that action can be used on - "
2702 "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING");
2704}
2705
2706static void rna_def_action(BlenderRNA *brna)
2707{
2708 StructRNA *srna;
2709 PropertyRNA *prop;
2710
2711 srna = RNA_def_struct(brna, "Action", "ID");
2712 RNA_def_struct_sdna(srna, "bAction");
2713 RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation");
2714 RNA_def_struct_ui_icon(srna, ICON_ACTION);
2715
2716# ifdef WITH_ANIM_BAKLAVA
2717 /* Properties. */
2718 prop = RNA_def_property(srna, "is_empty", PROP_BOOLEAN, PROP_NONE);
2721 prop, "Is Empty", "False when there is any Layer, Slot, or legacy F-Curve");
2722 RNA_def_property_boolean_funcs(prop, "rna_Action_is_empty_get", nullptr);
2723
2724 prop = RNA_def_property(srna, "is_action_legacy", PROP_BOOLEAN, PROP_NONE);
2727 prop,
2728 "Is Legacy Action",
2729 "Return whether this is a legacy Action. Legacy Actions have no layers or slots. An "
2730 "empty Action considered as both a 'legacy' and a 'layered' Action.");
2731 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_legacy_get", nullptr);
2732
2733 prop = RNA_def_property(srna, "is_action_layered", PROP_BOOLEAN, PROP_NONE);
2736 "Is Layered Action",
2737 "Return whether this is a layered Action. An empty Action considered "
2738 "as both a 'layered' and a 'layered' Action.");
2739 RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_layered_get", nullptr);
2740# endif // WITH_ANIM_BAKLAVA
2741
2742 /* Collection properties. */
2743
2744# ifdef WITH_ANIM_BAKLAVA
2745 prop = RNA_def_property(srna, "slots", PROP_COLLECTION, PROP_NONE);
2746 RNA_def_property_struct_type(prop, "ActionSlot");
2748 "rna_iterator_animation_slots_begin",
2749 "rna_iterator_array_next",
2750 "rna_iterator_array_end",
2751 "rna_iterator_array_dereference_get",
2752 "rna_iterator_animation_slots_length",
2753 nullptr,
2754 nullptr,
2755 nullptr);
2756 RNA_def_property_ui_text(prop, "Slots", "The list of slots in this Action");
2757 rna_def_action_slots(brna, prop);
2758
2759 prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
2760 RNA_def_property_struct_type(prop, "ActionLayer");
2762 "rna_iterator_action_layers_begin",
2763 "rna_iterator_array_next",
2764 "rna_iterator_array_end",
2765 "rna_iterator_array_dereference_get",
2766 "rna_iterator_action_layers_length",
2767 nullptr,
2768 nullptr,
2769 nullptr);
2770 RNA_def_property_ui_text(prop, "Layers", "The list of layers that make up this Action");
2771 rna_def_action_layers(brna, prop);
2772# endif // WITH_ANIM_BAKLAVA
2773
2774 prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
2775 RNA_def_property_collection_sdna(prop, nullptr, "markers", nullptr);
2776 RNA_def_property_struct_type(prop, "TimelineMarker");
2777 /* Use lib exception so the list isn't grayed out;
2778 * adding/removing is still banned though, see #45689. */
2781 prop, "Pose Markers", "Markers specific to this action, for labeling poses");
2782 rna_def_action_pose_markers(brna, prop);
2783
2784 /* properties */
2785 prop = RNA_def_property(srna, "use_frame_range", PROP_BOOLEAN, PROP_NONE);
2787 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_FRAME_RANGE);
2788 RNA_def_property_boolean_funcs(prop, nullptr, "rna_Action_use_frame_range_set");
2790 prop,
2791 "Manual Frame Range",
2792 "Manually specify the intended playback frame range for the action "
2793 "(this range is used by some tools, but does not affect animation evaluation)");
2795
2796 prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE);
2798 RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACT_CYCLIC);
2800 prop,
2801 "Cyclic Animation",
2802 "The action is intended to be used as a cycle looping over its manually set "
2803 "playback frame range (enabling this doesn't automatically make it loop)");
2805
2806 prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
2808 RNA_def_property_float_sdna(prop, nullptr, "frame_start");
2809 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_start_frame_set", nullptr);
2812 prop, "Start Frame", "The start frame of the manually set intended playback range");
2814
2815 prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_TIME);
2817 RNA_def_property_float_sdna(prop, nullptr, "frame_end");
2818 RNA_def_property_float_funcs(prop, nullptr, "rna_Action_end_frame_set", nullptr);
2821 prop, "End Frame", "The end frame of the manually set intended playback range");
2823
2824 prop = RNA_def_float_vector(
2825 srna,
2826 "frame_range",
2827 2,
2828 nullptr,
2829 0,
2830 0,
2831 "Frame Range",
2832 "The intended playback frame range of this action, using the manually set range "
2833 "if available, or the combined frame range of all F-Curves within this action "
2834 "if not (assigning sets the manual frame range)",
2835 0,
2836 0);
2838 prop, "rna_Action_frame_range_get", "rna_Action_frame_range_set", nullptr);
2840
2841 prop = RNA_def_float_vector(srna,
2842 "curve_frame_range",
2843 2,
2844 nullptr,
2845 0,
2846 0,
2847 "Curve Frame Range",
2848 "The combined frame range of all F-Curves within this action",
2849 0,
2850 0);
2851 RNA_def_property_float_funcs(prop, "rna_Action_curve_frame_range_get", nullptr, nullptr);
2853
2854 FunctionRNA *func = RNA_def_function(srna, "deselect_keys", "rna_Action_deselect_keys");
2856 func, "Deselects all keys of the Action. The selection status of F-Curves is unchanged.");
2857
2858 rna_def_action_legacy(brna, srna);
2859
2860 /* API calls */
2861 RNA_api_action(srna);
2862}
2863
2864/* --------- */
2865
2867{
2868 rna_def_action(brna);
2870 rna_def_dopesheet(brna);
2871
2872# ifdef WITH_ANIM_BAKLAVA
2873 rna_def_action_slot(brna);
2874 rna_def_action_layer(brna);
2875 rna_def_action_strip(brna);
2876 rna_def_action_channelbag(brna);
2877# endif
2878}
2879
2880#endif
Functions and classes to work with Actions.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to insert, delete or modify keyframes.
Blender kernel action and pose functionality.
void BKE_action_fcurves_clear(bAction *act)
void action_groups_remove_channel(bAction *act, FCurve *fcu)
bActionGroup * action_groups_add_new(bAction *act, const char name[])
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:466
void BKE_fcurve_free(FCurve *fcu)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:153
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
#define CLAMP_MAX(a, c)
#define CLAMP_MIN(a, b)
#define BLT_I18NCONTEXT_ID_ID
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_ex(Main *bmain, ID *id, unsigned int flags)
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:1044
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition DNA_ID.h:1143
@ ID_KE
@ ID_SCR
@ ID_OB
@ 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_ALL_SLOTS
@ ADS_FILTER_NOSCE
@ ADS_FILTER_NOLAM
@ ADS_FILTER_NOMODIFIERS
@ ADS_FILTER_NOLINESTYLE
@ ADS_FILTER_SUMMARY
@ ADS_FILTER_NOGPENCIL
@ ADS_FILTER_NOOBJ
@ ADS_FILTER_NOCUR
@ ADS_FILTER_NOPART
@ ADS_FILTER_NOSPK
@ ADS_FILTER_NOMESH
@ ADS_FILTER_NOWOR
@ ADS_FILTER_INCL_HIDDEN
@ ADS_FILTER_NOMBA
@ ADS_FILTER_NOLAT
@ AGRP_SELECTED
@ AGRP_EXPANDED_G
@ AGRP_EXPANDED
@ AGRP_PROTECTED
@ AGRP_MUTED
@ ACT_FRAME_RANGE
@ ACT_CYCLIC
@ ADS_FLAG_SHOW_DBFILTERS
@ ADS_FLAG_SUMMARY_COLLAPSED
@ ADS_FLAG_INVERT_FILTER
@ ADS_FLAG_NO_DB_SORT
@ ADS_FLAG_FUZZY_NAMES
@ SACTCONT_GPENCIL
@ SACTCONT_ACTION
@ SACTCONT_TIMELINE
@ SACTCONT_DOPESHEET
@ SACTCONT_SHAPEKEY
@ SACTCONT_MASK
@ SACTCONT_CACHEFILE
@ ADT_CURVES_ALWAYS_VISIBLE
@ INSERTKEY_NOFLAGS
#define MAXFRAMEF
#define MINAFRAMEF
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_GRAPH
Read Guarded memory(de)allocation.
#define RNA_POINTER_INVALIDATE(ptr)
ParameterFlag
Definition RNA_types.hh:396
@ PARM_RNAPTR
Definition RNA_types.hh:399
@ PARM_REQUIRED
Definition RNA_types.hh:397
FunctionFlag
Definition RNA_types.hh:662
@ FUNC_USE_REPORTS
Definition RNA_types.hh:680
@ FUNC_USE_MAIN
Definition RNA_types.hh:678
@ FUNC_USE_CONTEXT
Definition RNA_types.hh:679
@ FUNC_USE_SELF_ID
Definition RNA_types.hh:667
@ PROP_FLOAT
Definition RNA_types.hh:67
@ PROP_BOOLEAN
Definition RNA_types.hh:65
@ PROP_ENUM
Definition RNA_types.hh:69
@ PROP_INT
Definition RNA_types.hh:66
@ PROP_STRING
Definition RNA_types.hh:68
@ PROP_POINTER
Definition RNA_types.hh:70
@ PROP_COLLECTION
Definition RNA_types.hh:71
@ PROPOVERRIDE_OVERRIDABLE_LIBRARY
Definition RNA_types.hh:355
PropertyFlag
Definition RNA_types.hh:201
@ PROP_THICK_WRAP
Definition RNA_types.hh:312
@ PROP_CONTEXT_UPDATE
Definition RNA_types.hh:296
@ PROP_ANIMATABLE
Definition RNA_types.hh:220
@ PROP_EDITABLE
Definition RNA_types.hh:207
@ PROP_LIB_EXCEPTION
Definition RNA_types.hh:213
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:319
@ PROP_NEVER_NULL
Definition RNA_types.hh:266
@ PROP_NO_DEG_UPDATE
Definition RNA_types.hh:328
@ PROP_TEXTEDIT_UPDATE
Definition RNA_types.hh:227
@ PROP_TIME
Definition RNA_types.hh:156
@ PROP_NONE
Definition RNA_types.hh:136
@ PROP_FACTOR
Definition RNA_types.hh:154
@ PROP_UNSIGNED
Definition RNA_types.hh:152
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
int UI_icon_from_idcode(int idcode)
#define NC_ANIMATION
Definition WM_types.hh:355
#define NA_EDITED
Definition WM_types.hh:550
#define ND_KEYFRAME
Definition WM_types.hh:461
#define ND_ANIMCHAN
Definition WM_types.hh:463
#define NA_SELECTED
Definition WM_types.hh:555
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
PyObject * self
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr T * data() const
Definition BLI_span.hh:540
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t first_index_try(const T &search_value) const
Definition BLI_span.hh:388
constexpr int64_t size() const
Definition BLI_span.hh:253
void unsafe_copy(char *dst) const
constexpr int64_t size() const
void slot_active_set(slot_handle_t slot_handle)
Slot & slot_add_for_id(const ID &animated_id)
void slot_name_define(Slot &slot, StringRefNull new_name)
void slot_name_propagate(Main &bmain, const Slot &slot)
blender::Span< const Layer * > layers() const
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
bool slot_remove(Slot &slot_to_remove)
Layer & layer_add(std::optional< StringRefNull > name)
bActionGroup & channel_group_create(StringRefNull name)
FCurve * fcurve_create_unique(Main *bmain, FCurveDescriptor fcurve_descriptor)
const FCurve * fcurve_find(FCurveDescriptor fcurve_descriptor) const
bool channel_group_remove(bActionGroup &group)
blender::Span< const bActionGroup * > channel_groups() const
blender::Span< const FCurve * > fcurves() const
bool fcurve_remove(FCurve &fcurve_to_remove)
std::string name_prefix_for_idtype() const
static constexpr int name_length_min
StringRefNull name_without_prefix() const
static constexpr slot_handle_t unassigned
SingleKeyingResult keyframe_insert(Main *bmain, const Slot &slot, FCurveDescriptor fcurve_descriptor, float2 time_value, const KeyframeSettings &settings, eInsertKeyFlags insert_key_flags=INSERTKEY_NOFLAGS)
bool channelbag_remove(ChannelBag &channelbag_to_remove)
const ChannelBag * channelbag_for_slot(const Slot &slot) const
blender::Span< const ChannelBag * > channelbags() const
int64_t find_channelbag_index(const ChannelBag &channelbag) const
ChannelBag & channelbag_for_slot_add(const Slot &slot)
const T & data(const Action &owning_action) const
#define printf
#define SELECT
double time
int users
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define GS(x)
Definition iris.cc:202
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ChannelBag & channelbag_ensure(Action &action)
ChannelBag * channelbag_get(Action &action)
bool action_treat_as_legacy(const bAction &action)
KeyframeSettings get_keyframe_settings(bool from_userprefs)
FCurve * action_fcurve_ensure(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, FCurveDescriptor fcurve_descriptor)
void action_deselect_keys(Action &action)
bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code) ATTR_WARN_UNUSED_RESULT
decltype(::ActionSlot::handle) slot_handle_t
void reevaluate_fcurve_errors(bAnimContext *ac)
Definition animdata.cc:334
FCurve * fcurve_find_in_action(bAction *act, FCurveDescriptor fcurve_descriptor)
float wrap(float value, float max, float min)
Definition node_math.h:71
const EnumPropertyItem rna_enum_id_type_items[]
Definition rna_ID.cc:35
void rna_iterator_array_end(CollectionPropertyIterator *iter)
void rna_iterator_listbase_end(CollectionPropertyIterator *)
void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length, bool free_ptr, IteratorSkipFunc skip)
void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
PointerRNA rna_pointer_inherit_refine(const PointerRNA *ptr, StructRNA *type, void *data)
void rna_iterator_array_next(CollectionPropertyIterator *iter)
void * rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
void * rna_iterator_listbase_get(CollectionPropertyIterator *iter)
static void rna_def_action_legacy(BlenderRNA *brna, StructRNA *srna)
static void rna_def_action(BlenderRNA *brna)
const EnumPropertyItem default_ActionSlot_id_root_items[]
Definition rna_action.cc:79
static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop)
static void rna_def_dopesheet(BlenderRNA *brna)
void RNA_def_action(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_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_property_boolean_sdna(PropertyRNA *prop, const char *structname, const char *propname, int64_t bit)
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)
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:665
bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
__int64 int64_t
Definition stdint.h:89
struct FCurve ** fcurve_array
union CollectionPropertyIterator::@1329 internal
const char * identifier
Definition RNA_types.hh:506
const char * name
Definition RNA_types.hh:510
const char * description
Definition RNA_types.hh:512
struct FCurve * next
bActionGroup * grp
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
void * first
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:205
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
struct bDopeSheet * ads
struct bDopeSheet * ads
unsigned int flag
ListBase curves
float frame_start
ListBase groups
ListBase markers
bDopeSheet * ads
std::optional< blender::StringRefNull > channel_group
void WM_report(eReportType type, const char *message)
void WM_main_add_notifier(uint type, void *reference)
void WM_reportf(eReportType type, const char *format,...)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126