Blender V4.3
ANIM_action.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#pragma once
11
12#include "ANIM_fcurve.hh"
13#include "ANIM_keyframing.hh"
14
15#include "DNA_action_types.h"
16#include "DNA_anim_types.h"
17
18#include "BKE_anim_data.hh"
19
20#include "BLI_math_vector.hh"
21#include "BLI_span.hh"
22#include "BLI_string_ref.hh"
23#include "BLI_vector.hh"
24
25#include "RNA_types.hh"
26
27#include <utility>
28
29struct FCurve;
30struct FCurve;
31struct ID;
32struct Main;
33struct PointerRNA;
34struct Main;
35
37
38/* Forward declarations for the types defined later in this file. */
39class Layer;
40class Strip;
41class Slot;
42
43/* Use an alias for the Slot handle type to help disambiguate function parameters. */
45
68class Action : public ::bAction {
69 public:
70 Action() = default;
75 Action(const Action &other) = delete;
76
77 /* Discriminators for 'legacy' and 'layered' Actions. */
84 bool is_empty() const;
95 bool is_action_legacy() const;
104 bool is_action_layered() const;
105
106 /* Action Layers access. */
109 const Layer *layer(int64_t index) const;
110 Layer *layer(int64_t index);
111
112 Layer &layer_add(std::optional<StringRefNull> name);
113
122 bool layer_remove(Layer &layer_to_remove);
123
131
132 /* Action Slot access. */
135 const Slot *slot(int64_t index) const;
136 Slot *slot(int64_t index);
137
147 const Slot *slot_for_handle(slot_handle_t handle) const;
148
162 void slot_name_set(Main &bmain, Slot &slot, StringRefNull new_name);
163
173 void slot_name_define(Slot &slot, StringRefNull new_name);
174
183 void slot_name_propagate(Main &bmain, const Slot &slot);
184
186
193 Slot &slot_add();
194
201 Slot &slot_add_for_id(const ID &animated_id);
202
214 bool slot_remove(Slot &slot_to_remove);
215
222 void slot_active_set(slot_handle_t slot_handle);
223
236
242
255 Slot *find_suitable_slot_for(const ID &animated_id);
256
262 bool is_slot_animated(slot_handle_t slot_handle) const;
263
269 bool has_keyframes(slot_handle_t action_slot_handle) const ATTR_WARN_UNUSED_RESULT;
270
281
286
295
306
317
325 float2 get_frame_range_of_keys(bool include_modifiers) const ATTR_WARN_UNUSED_RESULT;
326
338 void slot_setup_for_id(Slot &slot, const ID &animated_id);
339
340 protected:
341 /* Friends for the purpose of adding/removing strip data on the action's strip
342 * data arrays. This is needed for the strip creation and removal code in
343 * `Strip` and `Layer`'s methods. */
344 friend Strip;
345 friend Layer;
346
348 int64_t find_layer_index(const Layer &layer) const;
349
351 int64_t find_slot_index(const Slot &slot) const;
352
362
378
379 private:
380 Slot &slot_allocate();
381
390 void slot_name_ensure_prefix(Slot &slot);
391};
392static_assert(sizeof(Action) == sizeof(::bAction),
393 "DNA struct and its C++ wrapper must have the same size");
394
405class Strip : public ::ActionStrip {
406 public:
415 enum class Type : int8_t { Keyframe = 0 };
416
417 /* Strips typically shouldn't be directly constructed or copied, because their
418 * data is actually stored in arrays on the action, and that data also needs
419 * to be created and managed along with the strips. */
420 Strip() = delete;
421
427 explicit Strip(const Strip &other)
428 {
429 memcpy(this, &other, sizeof(*this));
430 }
431
450 static Strip &create(Action &owning_action, const Strip::Type type);
451
458 Type type() const
459 {
460 return Type(this->strip_type);
461 }
462
463 bool is_infinite() const;
464 bool contains_frame(float frame_time) const;
465 bool is_last_frame(float frame_time) const;
466
474 void resize(float frame_start, float frame_end);
475
482 template<typename T> const T &data(const Action &owning_action) const;
483 template<typename T> T &data(Action &owning_action);
484
490 void slot_data_remove(Action &owning_action, slot_handle_t slot_handle);
491};
492static_assert(sizeof(Strip) == sizeof(::ActionStrip),
493 "DNA struct and its C++ wrapper must have the same size");
494
506class Layer : public ::ActionLayer {
507 public:
508 Layer() = default;
509 Layer(const Layer &other) = delete;
510 ~Layer();
511
525 Layer *duplicate_with_shallow_strip_copies(StringRefNull allocation_name) const;
526
527 enum class Flags : uint8_t {
528 /* Set by default, cleared to mute. */
529 Enabled = (1 << 0),
530 /* When adding/removing a flag, also update the ENUM_OPERATORS() invocation below. */
531 };
532
533 Flags flags() const
534 {
535 return static_cast<Flags>(this->layer_flags);
536 }
537
538 enum class MixMode : int8_t {
540 Replace = 0,
542 Offset = 1,
544 Add = 2,
546 Subtract = 3,
548 Multiply = 4,
549 };
550
552 {
553 return static_cast<MixMode>(this->layer_mix_mode);
554 }
555
556 /* Strip access. */
557 blender::Span<const Strip *> strips() const;
558 blender::Span<Strip *> strips();
559 const Strip *strip(int64_t index) const;
560 Strip *strip(int64_t index);
561
565 Strip &strip_add(Action &owning_action, Strip::Type strip_type);
566
575 bool strip_remove(Action &owning_action, Strip &strip);
576
582 void slot_data_remove(Action &owning_action, slot_handle_t slot_handle);
583
584 protected:
586 int64_t find_strip_index(const Strip &strip) const;
587};
588static_assert(sizeof(Layer) == sizeof(::ActionLayer),
589 "DNA struct and its C++ wrapper must have the same size");
590
592
605class Slot : public ::ActionSlot {
606 public:
607 Slot();
608 explicit Slot(const Slot &other);
609 ~Slot();
610
617 void blend_read_post();
618
622 constexpr static slot_handle_t unassigned = 0;
623
628 constexpr static int name_length_min = 3;
629
630 constexpr static int name_length_max = MAX_ID_NAME;
631 static_assert(sizeof(AnimData::slot_name) == name_length_max);
632 static_assert(sizeof(NlaStrip::action_slot_name) == name_length_max);
633
639 std::string name_prefix_for_idtype() const;
640
646 StringRefNull name_without_prefix() const;
647
649 bool is_suitable_for(const ID &animated_id) const;
650
652 bool has_idtype() const;
653
654 /* Flags access. */
655 enum class Flags : uint8_t {
657 Expanded = (1 << 0),
659 Selected = (1 << 1),
661 Active = (1 << 2),
662 /* When adding/removing a flag, also update the ENUM_OPERATORS() invocation,
663 * all the way below the Slot class. */
664 };
665 Flags flags() const;
666 bool is_expanded() const;
667 void set_expanded(bool expanded);
668 bool is_selected() const;
669 void set_selected(bool selected);
670 bool is_active() const;
671
673 Span<ID *> users(Main &bmain) const;
674
685 Vector<ID *> runtime_users();
686
693 void users_add(ID &animated_id);
694
701 void users_remove(ID &animated_id);
702
712 static void users_invalidate(Main &bmain);
713
714 protected:
715 friend Action;
716
723 void name_ensure_prefix();
724
728 void set_active(bool active);
729};
730static_assert(sizeof(Slot) == sizeof(::ActionSlot),
731 "DNA struct and its C++ wrapper must have the same size");
733
738 public:
739 /* Value of `Strip::type()` that corresponds to this type. */
740 static constexpr Strip::Type TYPE = Strip::Type::Keyframe;
741
742 StripKeyframeData() = default;
743 explicit StripKeyframeData(const StripKeyframeData &other);
745
746 /* ChannelBag array access. */
747 blender::Span<const ChannelBag *> channelbags() const;
748 blender::Span<ChannelBag *> channelbags();
749 const ChannelBag *channelbag(int64_t index) const;
750 ChannelBag *channelbag(int64_t index);
751
757 const ChannelBag *channelbag_for_slot(const Slot &slot) const;
758 ChannelBag *channelbag_for_slot(const Slot &slot);
759 const ChannelBag *channelbag_for_slot(slot_handle_t slot_handle) const;
760 ChannelBag *channelbag_for_slot(slot_handle_t slot_handle);
761
767 ChannelBag &channelbag_for_slot_add(const Slot &slot);
768
772 ChannelBag &channelbag_for_slot_ensure(const Slot &slot);
773
781 bool channelbag_remove(ChannelBag &channelbag_to_remove);
782
788 void slot_data_remove(slot_handle_t slot_handle);
789
791 int64_t find_channelbag_index(const ChannelBag &channelbag) const;
792
793 SingleKeyingResult keyframe_insert(Main *bmain,
794 const Slot &slot,
795 FCurveDescriptor fcurve_descriptor,
796 float2 time_value,
797 const KeyframeSettings &settings,
798 eInsertKeyFlags insert_key_flags = INSERTKEY_NOFLAGS);
799};
800static_assert(sizeof(StripKeyframeData) == sizeof(::ActionStripKeyframeData),
801 "DNA struct and its C++ wrapper must have the same size");
802
807 public:
808 ChannelBag() = default;
809 explicit ChannelBag(const ChannelBag &other);
810 ~ChannelBag();
811
812 /* FCurves access. */
813 blender::Span<const FCurve *> fcurves() const;
814 blender::Span<FCurve *> fcurves();
815 const FCurve *fcurve(int64_t index) const;
816 FCurve *fcurve(int64_t index);
817
823 const FCurve *fcurve_find(FCurveDescriptor fcurve_descriptor) const;
824 FCurve *fcurve_find(FCurveDescriptor fcurve_descriptor);
825
836 FCurve &fcurve_ensure(Main *bmain, FCurveDescriptor fcurve_descriptor);
837
849 FCurve *fcurve_create_unique(Main *bmain, FCurveDescriptor fcurve_descriptor);
850
860 void fcurve_append(FCurve &fcurve);
861
875 bool fcurve_remove(FCurve &fcurve_to_remove);
876
885 void fcurve_remove_by_index(int64_t fcurve_array_index);
886
900 bool fcurve_detach(FCurve &fcurve_to_detach);
901
910 void fcurve_detach_by_index(int64_t fcurve_array_index);
911
921 void fcurve_move(FCurve &fcurve, int to_fcurve_index);
922
926 void fcurves_clear();
927
928 /* Channel group access. */
929 blender::Span<const bActionGroup *> channel_groups() const;
930 blender::Span<bActionGroup *> channel_groups();
931 const bActionGroup *channel_group(int64_t index) const;
932 bActionGroup *channel_group(int64_t index);
933
942 const bActionGroup *channel_group_find(StringRef name) const;
943 bActionGroup *channel_group_find(StringRef name);
944
952 int channel_group_containing_index(int fcurve_array_index);
953
965 bActionGroup &channel_group_create(StringRefNull name);
966
975 bActionGroup &channel_group_ensure(StringRefNull name);
976
986 bool channel_group_remove(bActionGroup &group);
987
998 void channel_group_move(bActionGroup &group, int to_group_index);
999
1008 bool fcurve_assign_to_channel_group(FCurve &fcurve, bActionGroup &to_group);
1009
1022 bool fcurve_ungroup(FCurve &fcurve);
1023
1024 protected:
1037 FCurve &fcurve_create(Main *bmain, FCurveDescriptor fcurve_descriptor);
1038
1039 private:
1056 void channel_group_remove_raw(int group_index);
1057
1099 void restore_channel_group_invariants();
1100};
1101
1102static_assert(sizeof(ChannelBag) == sizeof(::ActionChannelBag),
1103 "DNA struct and its C++ wrapper must have the same size");
1104
1117 public:
1123 bool is_legacy() const;
1124
1128 Span<FCurve *> fcurves();
1129 Span<const FCurve *> fcurves() const;
1130};
1131
1132static_assert(sizeof(ChannelGroup) == sizeof(::bActionGroup),
1133 "DNA struct and its C++ wrapper must have the same size");
1134
1143Action &action_add(Main &bmain, StringRefNull name);
1144
1162[[nodiscard]] bool assign_action(bAction *action, ID &animated_id);
1163
1173[[nodiscard]] bool assign_action(bAction *action, OwnedAnimData owned_adt);
1174
1178[[nodiscard]] bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt);
1179
1187[[nodiscard]] bool unassign_action(ID &animated_id);
1188
1196[[nodiscard]] bool unassign_action(OwnedAnimData owned_adt);
1197
1216[[nodiscard]] Slot *assign_action_ensure_slot_for_keying(Action &action, ID &animated_id);
1217
1225[[nodiscard]] bool generic_assign_action(ID &animated_id,
1226 bAction *action_to_assign,
1227 bAction *&action_ptr_ref,
1228 slot_handle_t &slot_handle_ref,
1229 char *slot_name);
1230
1232 OK = 0,
1233 SlotNotFromAction = 1, /* Slot does not belong to the assigned Action. */
1234 SlotNotSuitable = 2, /* Slot is not suitable for the given ID type.*/
1235 MissingAction = 3, /* No Action assigned yet, so cannot assign slot. */
1236};
1237
1245 ID &animated_id,
1246 bAction *&action_ptr_ref,
1247 slot_handle_t &slot_handle_ref,
1248 char *slot_name) ATTR_WARN_UNUSED_RESULT;
1249
1257 ID &animated_id,
1258 bAction *&action_ptr_ref,
1259 slot_handle_t &slot_handle_ref,
1260 char *slot_name)
1262
1269bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code) ATTR_WARN_UNUSED_RESULT;
1270
1271ActionSlotAssignmentResult assign_action_slot(Slot *slot_to_assign, ID &animated_id);
1272
1282 Slot *slot_to_assign,
1283 ID &animated_id);
1284
1288Action *get_action(ID &animated_id);
1289
1299std::optional<std::pair<Action *, Slot *>> get_action_slot_pair(ID &animated_id);
1300
1302 slot_handle_t slot_handle);
1304
1322
1348 bAction *act,
1349 const char group[],
1350 PointerRNA *ptr,
1351 FCurveDescriptor fcurve_descriptor);
1352
1361FCurve *fcurve_find_in_action(bAction *act, FCurveDescriptor fcurve_descriptor);
1362
1369 slot_handle_t slot_handle,
1370 FCurveDescriptor fcurve_descriptor);
1371
1377FCurve *fcurve_find_in_assigned_slot(AnimData &adt, FCurveDescriptor fcurve_descriptor);
1378
1387bool fcurve_matches_collection_path(const FCurve &fcurve,
1388 StringRefNull collection_rna_path,
1389 StringRefNull data_name);
1390
1399 bAction *act, slot_handle_t slot_handle, FunctionRef<bool(const FCurve &fcurve)> predicate);
1400
1409bool action_fcurve_remove(Action &action, FCurve &fcu);
1410
1425bool action_fcurve_detach(Action &action, FCurve &fcurve_to_detach);
1426
1439void action_fcurve_attach(Action &action,
1440 slot_handle_t action_slot,
1441 FCurve &fcurve_to_attach,
1442 std::optional<StringRefNull> group_name);
1443
1461void action_fcurve_move(Action &action_dst,
1462 slot_handle_t action_slot_dst,
1463 Action &action_src,
1464 FCurve &fcurve);
1465
1496 Action &action,
1497 slot_handle_t slot_handle,
1498 ID *primary_id);
1499
1512ID *action_slot_get_id_best_guess(Main &bmain, Slot &slot, ID *primary_id);
1513
1526slot_handle_t first_slot_handle(const ::bAction &dna_action);
1527
1553void assert_baklava_phase_1_invariants(const Action &action);
1555void assert_baklava_phase_1_invariants(const Layer &layer);
1557void assert_baklava_phase_1_invariants(const Strip &strip);
1558
1563Action *convert_to_layered_action(Main &bmain, const Action &legacy_action);
1564
1574void move_slot(Main &bmain, Slot &slot, Action &from_action, Action &to_action);
1575
1580
1584void action_deselect_keys(Action &action);
1585
1586} // namespace blender::animrig
1587
1588/* Wrap functions for the DNA structs. */
1589
1590inline blender::animrig::ChannelGroup &bActionGroup::wrap()
1591{
1592 return *reinterpret_cast<blender::animrig::ChannelGroup *>(this);
1593}
1594inline const blender::animrig::ChannelGroup &bActionGroup::wrap() const
1595{
1596 return *reinterpret_cast<const blender::animrig::ChannelGroup *>(this);
1597}
1598
1599inline blender::animrig::Action &bAction::wrap()
1600{
1601 return *reinterpret_cast<blender::animrig::Action *>(this);
1602}
1603inline const blender::animrig::Action &bAction::wrap() const
1604{
1605 return *reinterpret_cast<const blender::animrig::Action *>(this);
1606}
1607
1608inline blender::animrig::Layer &ActionLayer::wrap()
1609{
1610 return *reinterpret_cast<blender::animrig::Layer *>(this);
1611}
1612inline const blender::animrig::Layer &ActionLayer::wrap() const
1613{
1614 return *reinterpret_cast<const blender::animrig::Layer *>(this);
1615}
1616
1617inline blender::animrig::Slot &ActionSlot::wrap()
1618{
1619 return *reinterpret_cast<blender::animrig::Slot *>(this);
1620}
1621inline const blender::animrig::Slot &ActionSlot::wrap() const
1622{
1623 return *reinterpret_cast<const blender::animrig::Slot *>(this);
1624}
1625
1626inline blender::animrig::Strip &ActionStrip::wrap()
1627{
1628 return *reinterpret_cast<blender::animrig::Strip *>(this);
1629}
1630inline const blender::animrig::Strip &ActionStrip::wrap() const
1631{
1632 return *reinterpret_cast<const blender::animrig::Strip *>(this);
1633}
1634
1635inline blender::animrig::StripKeyframeData &ActionStripKeyframeData::wrap()
1636{
1637 return *reinterpret_cast<blender::animrig::StripKeyframeData *>(this);
1638}
1639inline const blender::animrig::StripKeyframeData &ActionStripKeyframeData::wrap() const
1640{
1641 return *reinterpret_cast<const blender::animrig::StripKeyframeData *>(this);
1642}
1643
1644inline blender::animrig::ChannelBag &ActionChannelBag::wrap()
1645{
1646 return *reinterpret_cast<blender::animrig::ChannelBag *>(this);
1647}
1648inline const blender::animrig::ChannelBag &ActionChannelBag::wrap() const
1649{
1650 return *reinterpret_cast<const blender::animrig::ChannelBag *>(this);
1651}
Functions to modify FCurves.
Functions to insert, delete or modify keyframes.
#define ATTR_WARN_UNUSED_RESULT
#define ENUM_OPERATORS(_type, _max)
#define MAX_ID_NAME
Definition DNA_ID.h:377
ID_Type
eInsertKeyFlags
@ INSERTKEY_NOFLAGS
void slot_active_set(slot_handle_t slot_handle)
Slot & slot_add_for_id(const ID &animated_id)
float2 get_frame_range_of_slot(slot_handle_t slot_handle) const ATTR_WARN_UNUSED_RESULT
void slot_name_define(Slot &slot, StringRefNull new_name)
Slot * slot_find_by_name(StringRefNull slot_name)
float2 get_frame_range() const ATTR_WARN_UNUSED_RESULT
bool is_cyclic() const ATTR_WARN_UNUSED_RESULT
int strip_keyframe_data_append(StripKeyframeData *strip_data)
const Layer * layer(int64_t index) const
void slot_name_propagate(Main &bmain, const Slot &slot)
int64_t find_slot_index(const Slot &slot) const
const Slot * slot(int64_t index) const
blender::Span< const Layer * > layers() const
bool has_keyframes(slot_handle_t action_slot_handle) const ATTR_WARN_UNUSED_RESULT
Slot * find_suitable_slot_for(const ID &animated_id)
void strip_keyframe_data_remove_if_unused(int index)
void slot_name_set(Main &bmain, Slot &slot, StringRefNull new_name)
int64_t find_layer_index(const Layer &layer) const
Action(const Action &other)=delete
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)
Slot * slot_for_handle(slot_handle_t handle)
bool has_single_frame() const ATTR_WARN_UNUSED_RESULT
Span< const StripKeyframeData * > strip_keyframe_data() const
bool is_slot_animated(slot_handle_t slot_handle) const
void slot_setup_for_id(Slot &slot, const ID &animated_id)
Layer & layer_add(std::optional< StringRefNull > name)
MixMode mix_mode() const
Layer(const Layer &other)=delete
Strip(const Strip &other)
T & data(Action &owning_action)
const T & data(const Action &owning_action) const
int users
void action_fcurve_attach(Action &action, slot_handle_t action_slot, FCurve &fcurve_to_attach, std::optional< StringRefNull > group_name)
bool action_fcurve_remove(Action &action, FCurve &fcu)
void assert_baklava_phase_1_invariants(const Action &action)
bool fcurve_matches_collection_path(const FCurve &fcurve, StringRefNull collection_rna_path, StringRefNull data_name)
Vector< FCurve * > fcurves_in_action_slot_filtered(bAction *act, slot_handle_t slot_handle, FunctionRef< bool(const FCurve &fcurve)> predicate)
Slot * assign_action_ensure_slot_for_keying(Action &action, ID &animated_id)
FCurve * action_fcurve_ensure(Main *bmain, bAction *act, const char group[], PointerRNA *ptr, FCurveDescriptor fcurve_descriptor)
FCurve * fcurve_find_in_assigned_slot(AnimData &adt, FCurveDescriptor fcurve_descriptor)
void action_fcurve_move(Action &action_dst, slot_handle_t action_slot_dst, Action &action_src, FCurve &fcurve)
Action & action_add(Main &bmain, StringRefNull name)
void action_deselect_keys(Action &action)
slot_handle_t first_slot_handle(const ::bAction &dna_action)
ID * action_slot_get_id_best_guess(Main &bmain, Slot &slot, ID *primary_id)
const FCurve * fcurve_find(Span< const FCurve * > fcurves, FCurveDescriptor fcurve_descriptor)
ActionSlotAssignmentResult generic_assign_action_slot(Slot *slot_to_assign, ID &animated_id, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name) ATTR_WARN_UNUSED_RESULT
FCurve * fcurve_find_in_action_slot(bAction *act, slot_handle_t slot_handle, FCurveDescriptor fcurve_descriptor)
bool generic_assign_action(ID &animated_id, bAction *action_to_assign, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name)
ActionSlotAssignmentResult assign_action_and_slot(Action *action, Slot *slot_to_assign, ID &animated_id)
Span< FCurve * > fcurves_for_action_slot(Action &action, slot_handle_t slot_handle)
ID * action_slot_get_id_for_keying(Main &bmain, Action &action, slot_handle_t slot_handle, ID *primary_id)
bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code) ATTR_WARN_UNUSED_RESULT
void deselect_keys_actions(blender::Span< bAction * > actions)
decltype(::ActionSlot::handle) slot_handle_t
Action * get_action(ID &animated_id)
bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt)
Action * convert_to_layered_action(Main &bmain, const Action &legacy_action)
bool unassign_action(ID &animated_id)
ActionSlotAssignmentResult generic_assign_action_slot_handle(slot_handle_t slot_handle_to_assign, ID &animated_id, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name) ATTR_WARN_UNUSED_RESULT
bool action_fcurve_detach(Action &action, FCurve &fcurve_to_detach)
bool assign_action(bAction *action, ID &animated_id)
std::optional< std::pair< Action *, Slot * > > get_action_slot_pair(ID &animated_id)
FCurve * fcurve_find_in_action(bAction *act, FCurveDescriptor fcurve_descriptor)
ActionSlotAssignmentResult assign_action_slot(Slot *slot_to_assign, ID &animated_id)
const animrig::ChannelBag * channelbag_for_action_slot(const Action &action, slot_handle_t slot_handle)
void move_slot(Main &bmain, Slot &slot, Action &from_action, Action &to_action)
__int64 int64_t
Definition stdint.h:89
unsigned char uint8_t
Definition stdint.h:78
signed char int8_t
Definition stdint.h:75
char slot_name[66]
Definition DNA_ID.h:413
char action_slot_name[66]
float frame_start
PointerRNA * ptr
Definition wm_files.cc:4126