36#include "RNA_prototypes.hh"
70constexpr const char *slot_default_name =
"Slot";
71constexpr const char *slot_unbound_prefix =
"XX";
73constexpr const char *layer_default_name =
"Layer";
85template<
typename T>
static void grow_array(T **
array,
int *num,
const int add_num)
88 const int new_array_num = *num + add_num;
89 T *new_array = MEM_cnew_array<T>(new_array_num,
"animrig::action/grow_array");
101 (*array)[*num - 1] = item;
108 const int new_array_num = *num + 1;
109 T *new_array = MEM_cnew_array<T>(new_array_num, __func__);
112 new_array[index] = item;
118 *num = new_array_num;
124 const int new_array_num = *num - shrink_num;
125 T *new_array = MEM_cnew_array<T>(new_array_num, __func__);
131 *num = new_array_num;
137 const int new_array_num = *num - 1;
138 T *new_array = MEM_cnew_array<T>(new_array_num, __func__);
145 *num = new_array_num;
156 const int new_array_num = *num - 1;
157 T *new_array = MEM_cnew_array<T>(new_array_num, __func__);
160 if (index < new_array_num) {
161 new_array[index] = (*array)[new_array_num];
167 *num = new_array_num;
181 T *
array,
const int num,
const int range_start,
const int range_end,
const int to)
185 BLI_assert(to <= num + range_start - range_end);
188 if (
ELEM(range_start, range_end, to)) {
192 if (to < range_start) {
193 T *start =
array + to;
194 T *mid =
array + range_start;
195 T *end =
array + range_end;
196 std::rotate(start, mid, end);
199 T *start =
array + range_start;
200 T *mid =
array + range_end;
201 T *end =
array + to + range_end - range_start;
202 std::rotate(start, mid, end);
252 if (name.has_value()) {
275 Layer &layer = (*dna_layer_ptr)->wrap();
282 if (layer_index < 0) {
302 layer = this->
layer(0);
306 if (layer->
strips().is_empty()) {
307 layer->strip_add(*
this, Strip::Type::Keyframe);
318 for (
const int64_t layer_index : this->
layers().index_range()) {
319 const Layer *visit_layer = this->
layer(layer_index);
320 if (visit_layer == &layer) {
329 for (
const int64_t slot_index : this->
slots().index_range()) {
330 const Slot *visit_slot = this->
slot(slot_index);
331 if (visit_slot == &
slot) {
380 struct DupNameCheckData {
384 DupNameCheckData check_data = {action, slot};
386 auto check_name_is_used = [](
void *arg,
const char *name) ->
bool {
387 DupNameCheckData *data =
static_cast<DupNameCheckData *
>(arg);
388 for (
const Slot *slot : data->action.slots()) {
389 if (slot == &data->slot) {
417 "Action Slots must be large enough for a 2-letter ID code + the display name");
436 if (!adt || adt->
action !=
this) {
463Slot &Action::slot_allocate()
465 Slot &
slot = *MEM_new<Slot>(__func__);
516 Slot &slot = (*dna_slot_ptr)->wrap();
524 if (slot_index < 0) {
530 layer->slot_data_remove(*
this, slot_to_remove.
handle);
565 if (adt && adt->
action ==
this) {
615 for (
const Strip *strip : layer->strips()) {
616 if (strip->type() == Strip::Type::Keyframe && strip->data_index == index) {
623 MEM_delete<StripKeyframeData>(
637 for (
Strip *strip : layer->strips()) {
638 if (strip->type() == Strip::Type::Keyframe && strip->data_index == old_index) {
639 strip->data_index = index;
672 return this->
layer(0);
675void Action::slot_name_ensure_prefix(
Slot &slot)
689 this->slot_name_ensure_prefix(
slot);
714 bool found_key =
false;
715 float found_key_frame = 0.0f;
718 switch (fcu->totvert) {
730 const float this_key_frame = fcu->bezt !=
nullptr ? fcu->bezt[0].vec[1][0] :
734 found_key_frame = this_key_frame;
740 if (!
compare_ff(found_key_frame, this_key_frame, 0.001f)) {
782 fcurves_to_consider = legacy_fcurves;
794 const bool include_modifiers)
796 float min = 999999999.0f, max = -999999999.0f;
797 bool foundvert =
false, foundmod =
false;
799 for (
const FCurve *fcu : fcurves) {
822 if ((include_modifiers) && (fcu->modifiers.last)) {
867 if (foundvert || foundmod) {
871 return float2{0.0f, 0.0f};
883 allocation_name.
c_str());
884 for (
int i : this->
strips().index_range()) {
885 Strip *strip_copy = MEM_new<Strip>(allocation_name.
c_str(), *this->strip(i));
886 copy->strip_array[i] = strip_copy;
889 return &
copy->wrap();
922 Strip &
strip = Strip::create(owning_action, strip_type);
932 Strip &strip = (*dna_strip_ptr)->wrap();
939 if (strip_index < 0) {
943 const Strip::Type strip_type =
strip.
type();
953 switch (strip_type) {
954 case Strip::Type::Keyframe:
964 for (
const int64_t strip_index : this->
strips().index_range()) {
984 memset(
this, 0,
sizeof(*
this));
985 this->
runtime = MEM_new<SlotRuntime>(__func__);
990 memcpy(
this, &other,
sizeof(*
this));
991 this->
runtime = MEM_new<SlotRuntime>(__func__);
1002 this->
runtime = MEM_new<SlotRuntime>(__func__);
1013 const int animated_idtype =
GS(animated_id.
name);
1014 return this->
idtype == animated_idtype;
1019 return this->
idtype != 0;
1074 return this->
runtime->users.as_span();
1086 this->
runtime->users.append_non_duplicates(&animated_id);
1095 if (vector_index < 0) {
1099 users.remove_and_reorder(vector_index);
1110 return slot_unbound_prefix;
1114 *
reinterpret_cast<short *
>(
name) = this->
idtype;
1123 if (this->name[0] ==
'\0' || this->name[1] ==
'\0') {
1126 return this->name + 2;
1135 this->name[2] =
'\0';
1141 this->name[0] = slot_unbound_prefix[0];
1142 this->name[1] = slot_unbound_prefix[1];
1146 *
reinterpret_cast<short *
>(this->
name) = this->
idtype;
1155 return dna_action->wrap();
1171 BKE_report(
nullptr,
RPT_ERROR,
"Cannot change action, as it is still being edited in NLA");
1210 if (adt && adt->
action == &action) {
1252 auto visit_action_use = [&](
const Action &used_action,
slot_handle_t used_slot_handle) ->
bool {
1253 const bool is_used = (&used_action == &action && used_slot_handle == slot_handle);
1258 return !looped_until_end;
1276 "Could not set action '%s' to animate ID '%s', as it does not have suitably rooted "
1277 "paths for this purpose",
1278 action_to_assign->
id.
name + 2,
1285 if (action_ptr_ref) {
1289 nullptr, animated_id, action_ptr_ref, slot_handle_ref, slot_name);
1296 action_ptr_ref =
nullptr;
1299 if (!action_to_assign) {
1305 action_ptr_ref = action_to_assign;
1310 Slot *slot = action_to_assign->wrap().find_suitable_slot_for(animated_id);
1312 slot, animated_id, action_ptr_ref, slot_handle_ref, slot_name);
1326 if (!action_ptr_ref) {
1331 Action &action = action_ptr_ref->wrap();
1334 if (slot_to_assign) {
1335 if (!action.
slots().contains(slot_to_assign)) {
1348 if (slot_to_unassign) {
1364 if (!slot_to_assign) {
1369 slot_handle_ref = slot_to_assign->
handle;
1389 if (!action_ptr_ref) {
1396 Slot *slot = action_ptr_ref->wrap().slot_for_handle(slot_handle_to_assign);
1407 if (dna_action->
idroot == 0) {
1418 return action.
idroot == id_code;
1436 Slot *slot_to_assign,
1456 return &adt->
action->wrap();
1462 if (!adt || !adt->
action) {
1464 return std::nullopt;
1471 return std::nullopt;
1474 return std::make_pair(&action, slot);
1482 ActionStrip *strip = MEM_cnew<ActionStrip>(__func__);
1488 case Strip::Type::Keyframe: {
1500 return strip->wrap();
1503bool Strip::is_infinite()
const
1505 return this->
frame_start == -std::numeric_limits<float>::infinity() &&
1506 this->
frame_end == std::numeric_limits<float>::infinity();
1509bool Strip::contains_frame(
const float frame_time)
const
1514bool Strip::is_last_frame(
const float frame_time)
const
1521void Strip::resize(
const float frame_start,
const float frame_end)
1525 "only the end frame can be at positive infinity");
1527 "only the start frame can be at negative infinity");
1548 switch (this->
type()) {
1558 memcpy(
this, &other,
sizeof(*
this));
1560 this->
channelbag_array = MEM_cnew_array<ActionChannelBag *>(other.channelbag_array_num,
1564 this->
channelbag_array[i] = MEM_new<animrig::ChannelBag>(__func__, *other.channelbag(i));
1598 if (channels->slot_handle == slot_handle) {
1617 return const_cast<ChannelBag *
>(const_channels);
1631 "Cannot add chans-for-slot for already-registered slot");
1633 ChannelBag &channels = MEM_new<ActionChannelBag>(__func__)->wrap();
1645 if (channel_bag !=
nullptr) {
1646 return *channel_bag;
1653 ChannelBag &channelbag = (*dna_channelbag_ptr)->wrap();
1654 MEM_delete(&channelbag);
1660 if (channelbag_index < 0) {
1697 return *existing_fcurve;
1721 const int insert_index = group ? group->fcurve_range_start + group->fcurve_range_length :
1727 group->fcurve_range_length += 1;
1728 this->restore_channel_group_invariants();
1775 const int64_t fcurve_index = this->
fcurves().first_index_try(&fcurve_to_detach);
1776 if (fcurve_index < 0) {
1789 if (group_index != -1) {
1792 group->fcurve_range_length -= 1;
1793 if (group->fcurve_range_length <= 0) {
1794 const int group_index = this->
channel_groups().first_index_try(group);
1795 this->channel_group_remove_raw(group_index);
1800 &this->fcurve_array_num,
1805 this->restore_channel_group_invariants();
1816 const int fcurve_index = this->
fcurves().first_index_try(&fcurve);
1817 BLI_assert_msg(fcurve_index >= 0,
"FCurve not in this channel bag.");
1822 this->restore_channel_group_invariants();
1831 group->fcurve_range_start = 0;
1832 group->fcurve_range_length = 0;
1845 FCurve *fcurve =
nullptr;
1851 if (channels !=
nullptr) {
1852 fcurve = channels->fcurve_find(fcurve_descriptor);
1857 std::fprintf(stderr,
1858 "FCurve %s[%d] for slot %s was not created due to either the Only Insert "
1859 "Available setting or Replace keyframing mode.\n",
1868 std::fprintf(stderr,
1869 "FCurve %s[%d] for slot %s doesn't allow inserting keys.\n",
1877 fcurve, time_value, settings, insert_key_flags);
1880 std::fprintf(stderr,
1881 "Could not insert key into FCurve %s[%d] for slot %s.\n",
1885 return insert_vert_result;
1898 this->
fcurve_array = MEM_cnew_array<FCurve *>(other.fcurve_array_num, __func__);
1899 for (
int i = 0; i < other.fcurve_array_num; i++) {
1900 const FCurve *fcu_src = other.fcurve_array[i];
1905 this->
group_array = MEM_cnew_array<bActionGroup *>(other.group_array_num, __func__);
1906 for (
int i = 0; i < other.group_array_num; i++) {
1914 this->restore_channel_group_invariants();
1996 if (fcurve_array_index >= group->fcurve_range_start &&
1997 fcurve_array_index < (group->fcurve_range_start + group->fcurve_range_length))
2014 int fcurve_index = 0;
2036 if (
STREQ(group->name, name.data())) {
2043 name[0] ==
'\0' ?
DATA_(
"Group") : name);
2064 const int group_index = this->
channel_groups().first_index_try(&group);
2065 if (group_index == -1) {
2074 group.fcurve_range_length;
2078 group.fcurve_range_start + group.fcurve_range_length,
2081 this->channel_group_remove_raw(group_index);
2082 this->restore_channel_group_invariants();
2091 const int group_index = this->
channel_groups().first_index_try(&group);
2092 BLI_assert_msg(group_index >= 0,
"Group not in this channel bag.");
2103 this->restore_channel_group_invariants();
2112 group.fcurve_range_start);
2113 this->restore_channel_group_invariants();
2116void ChannelBag::channel_group_remove_raw(
const int group_index)
2124void ChannelBag::restore_channel_group_invariants()
2128 int start_index = 0;
2130 group->fcurve_range_start = start_index;
2131 start_index += group->fcurve_range_length;
2194 switch (strip->type()) {
2195 case animrig::Strip::Type::Keyframe: {
2213 const_cast<const Action &
>(action), slot_handle);
2241 if (act ==
nullptr) {
2245 Action &action = act->wrap();
2256 Strip *strip = layer->strip(0);
2264 FCurve *fcu = channelbag->fcurve_find(fcurve_descriptor);
2282 if (act ==
nullptr) {
2286 Action &action = act->wrap();
2305 const size_t quoted_name_size = data_name.
size() + 1;
2306 char *quoted_name =
static_cast<char *
>(alloca(quoted_name_size));
2313 fcurve.
rna_path, collection_rna_path.
c_str(), quoted_name, quoted_name_size))
2317 if (quoted_name != data_name) {
2333 if (predicate(fcurve)) {
2334 found.append(&fcurve);
2347 if (act ==
nullptr) {
2368 Action &action = act->wrap();
2401 if (fcu !=
nullptr) {
2406 std::optional<PropertySubType> prop_subtype = std::nullopt;
2407 if (
ptr !=
nullptr) {
2412 &id_ptr, fcurve_descriptor.
rna_path.
c_str(), &resolved_ptr, &resolved_prop);
2419 "Did not expect a prop_subtype to be passed in. This is fine, but does need some "
2420 "changes to action_fcurve_ensure() to deal with it");
2431 if (agrp ==
nullptr) {
2460 for (
Strip *strip : layer->strips()) {
2461 if (!(strip->type() == Strip::Type::Keyframe)) {
2466 const bool removed = bag->fcurve_remove(fcu);
2483 for (
Strip *strip : layer->strips()) {
2484 if (!(strip->type() == Strip::Type::Keyframe)) {
2489 const bool is_detached = bag->fcurve_detach(fcurve_to_detach);
2501 FCurve &fcurve_to_attach,
2502 std::optional<StringRefNull> group_name)
2512 printf(
"Cannot find slot handle %d on Action %s, unable to attach F-Curve %s[%d] to it!\n",
2526 bActionGroup &group = cbag.channel_group_ensure(*group_name);
2527 cbag.fcurve_assign_to_channel_group(fcurve_to_attach, group);
2538 std::optional<std::string> group_name;
2540 group_name = fcurve.
grp->
name;
2552 if (this->channel_groups().first_index_try(&to_group) == -1) {
2556 const int fcurve_index = this->fcurves().first_index_try(&fcurve);
2557 if (fcurve_index == -1) {
2561 if (fcurve.
grp == &to_group) {
2566 if (fcurve.
grp !=
nullptr) {
2569 const int group_index = this->channel_groups().first_index_try(fcurve.
grp);
2570 this->channel_group_remove_raw(group_index);
2572 this->restore_channel_group_invariants();
2576 this->fcurve_array_num,
2582 this->restore_channel_group_invariants();
2587bool ChannelBag::fcurve_ungroup(
FCurve &fcurve)
2589 const int fcurve_index = this->fcurves().first_index_try(&fcurve);
2590 if (fcurve_index == -1) {
2594 if (fcurve.
grp ==
nullptr) {
2601 this->fcurve_array_num,
2604 this->fcurve_array_num - 1);
2608 const int old_group_index = this->channel_groups().first_index_try(old_group);
2609 this->channel_group_remove_raw(old_group_index);
2612 this->restore_channel_group_invariants();
2623 if (primary_id &&
get_action(*primary_id) == &action) {
2630 if (slot ==
nullptr) {
2635 if (
users.size() == 1) {
2644 if (
users.contains(primary_id)) {
2654 if (
users.is_empty()) {
2657 if (
users.contains(primary_id)) {
2665 const Action &action = dna_action.wrap();
2667 return Slot::unassigned;
2677 if (action.
layers().is_empty()) {
2687 if (layer.strips().is_empty()) {
2709 std::string suffix =
"_layered";
2715 const std::string layered_action_name = std::string(legacy_name) + suffix;
2718 Action &converted_action = dna_action->wrap();
2721 Strip &strip = layer.strip_add(converted_action, Strip::Type::Keyframe);
2726 bag->
fcurve_array = MEM_cnew_array<FCurve *>(fcu_count,
"Convert to layered action");
2742 if (fcu->grp != group) {
2752 return &converted_action;
2790 grow_array_and_append<ActionChannelBag *>(
2791 &to_strip_data.channelbag_array, &to_strip_data.channelbag_array_num, channel_bag);
2793 shrink_array_and_remove<ActionChannelBag *>(
2797 for (
ID *user : source_slot.
users(bmain)) {
2798 const auto assign_other_action =
2802 if (action_ptr_ref != &from_action) {
2808 *user, &to_action, action_ptr_ref, slot_handle_ref, slot_name);
2809 BLI_assert_msg(assign_ok,
"Expecting slotted Actions to always be assignable");
2814 &target_slot, *user, action_ptr_ref, slot_handle_ref, slot_name);
2815 BLI_assert(result == ActionSlotAssignmentResult::OK);
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
Functions for backward compatibility with the legacy Action API.
Functions to work with AnimData.
Functions to modify FCurves.
Blender kernel action and pose functionality.
void action_group_colors_set_from_posebone(bActionGroup *grp, const bPoseChannel *pchan)
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
bAction * BKE_action_add(Main *bmain, const char name[])
bActionGroup * action_groups_add_new(bAction *act, const char name[])
bActionGroup * BKE_action_group_find_name(bAction *act, const char name[])
bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
AnimData * BKE_animdata_ensure_id(ID *id)
bool id_can_have_animdata(const ID *id)
bool BKE_animdata_action_editable(const AnimData *adt)
AnimData * BKE_animdata_from_id(const ID *id)
FCurve * BKE_fcurve_copy(const FCurve *fcu)
bool BKE_fcurve_is_keyframable(const FCurve *fcu)
FCurve * BKE_fcurve_find(ListBase *list, const char rna_path[], int array_index)
void BKE_fcurve_free(FCurve *fcu)
bool BKE_fcurve_calc_range(const FCurve *fcu, float *r_min, float *r_max, bool selected_keys_only)
void id_us_clear_real(ID *id)
#define FOREACH_MAIN_LISTBASE_ID_END
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
#define FOREACH_MAIN_LISTBASE_END
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int compare_ff(float a, float b, float max_diff)
bool bool BLI_str_quoted_substr(const char *__restrict str, const char *__restrict prefix, char *result, size_t result_maxncpy)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define STRNCPY_UTF8(dst, src)
size_t void BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_maxncpy) ATTR_NONNULL(1
#define UNUSED_VARS_NDEBUG(...)
void DEG_relations_tag_update(Main *bmain)
struct ActionSlotRuntimeHandle ActionSlotRuntimeHandle
#define DNA_struct_default_get(struct_name)
#define DNA_struct_default_alloc(struct_name)
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
Internal C++ functions to deal with Actions, Slots, and their runtime data.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
static bool visit_strip(NlaStrip *strip, blender::FunctionRef< bool(NlaStrip *)> callback)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
bool add(const Key &key, const Value &value)
const Value & lookup(const Key &key) const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr const char * c_str() const
int64_t first_index_of_try(const T &value) const
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)
void layer_keystrip_ensure()
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
Layer * get_layer_for_keyframing()
const Slot * slot(int64_t index) const
blender::Span< const Layer * > layers() const
bool is_action_legacy() const
bool is_action_layered() 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
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)
void fcurve_move(FCurve &fcurve, int to_fcurve_index)
bActionGroup & channel_group_create(StringRefNull name)
const bActionGroup * channel_group(int64_t index) const
bActionGroup & channel_group_ensure(StringRefNull name)
void channel_group_move(bActionGroup &group, int to_group_index)
const FCurve * fcurve(int64_t index) const
const bActionGroup * channel_group_find(StringRef name) const
bool fcurve_assign_to_channel_group(FCurve &fcurve, bActionGroup &to_group)
FCurve & fcurve_ensure(Main *bmain, FCurveDescriptor fcurve_descriptor)
bool fcurve_detach(FCurve &fcurve_to_detach)
FCurve * fcurve_create_unique(Main *bmain, FCurveDescriptor fcurve_descriptor)
void fcurve_remove_by_index(int64_t fcurve_array_index)
const FCurve * fcurve_find(FCurveDescriptor fcurve_descriptor) const
FCurve & fcurve_create(Main *bmain, FCurveDescriptor fcurve_descriptor)
void fcurve_append(FCurve &fcurve)
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)
void fcurve_detach_by_index(int64_t fcurve_array_index)
int channel_group_containing_index(int fcurve_array_index)
Span< FCurve * > fcurves()
bool strip_remove(Action &owning_action, Strip &strip)
void slot_data_remove(Action &owning_action, slot_handle_t slot_handle)
blender::Span< const Strip * > strips() const
Layer * duplicate_with_shallow_strip_copies(StringRefNull allocation_name) const
const Strip * strip(int64_t index) const
Strip & strip_add(Action &owning_action, Strip::Type strip_type)
int64_t find_strip_index(const Strip &strip) const
std::string name_prefix_for_idtype() const
static void users_invalidate(Main &bmain)
Vector< ID * > runtime_users()
static constexpr int name_length_max
void users_add(ID &animated_id)
void set_active(bool active)
bool is_suitable_for(const ID &animated_id) const
static constexpr int name_length_min
void name_ensure_prefix()
void set_expanded(bool expanded)
StringRefNull name_without_prefix() const
void set_selected(bool selected)
Span< ID * > users(Main &bmain) const
static constexpr slot_handle_t unassigned
void users_remove(ID &animated_id)
const ChannelBag * channelbag(int64_t index) const
ChannelBag & channelbag_for_slot_ensure(const Slot &slot)
SingleKeyingResult keyframe_insert(Main *bmain, const Slot &slot, FCurveDescriptor fcurve_descriptor, float2 time_value, const KeyframeSettings &settings, eInsertKeyFlags insert_key_flags=INSERTKEY_NOFLAGS)
void slot_data_remove(slot_handle_t slot_handle)
bool channelbag_remove(ChannelBag &channelbag_to_remove)
const ChannelBag * channelbag_for_slot(const Slot &slot) const
blender::Span< const ChannelBag * > channelbags() const
static constexpr Strip::Type TYPE
int64_t find_channelbag_index(const ChannelBag &channelbag) const
ChannelBag & channelbag_for_slot_add(const Slot &slot)
StripKeyframeData()=default
void slot_data_remove(Action &owning_action, slot_handle_t slot_handle)
const T & data(const Action &owning_action) const
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const void *vmemh)
void rebuild_slot_user_cache(Main &bmain)
Vector< const FCurve * > fcurves_all(const bAction *action)
bool action_treat_as_legacy(const bAction &action)
void action_fcurve_attach(Action &action, slot_handle_t action_slot, FCurve &fcurve_to_attach, std::optional< StringRefNull > group_name)
void foreach_fcurve_in_action_slot(Action &action, slot_handle_t handle, FunctionRef< void(FCurve &fcurve)> callback)
bool action_fcurve_remove(Action &action, FCurve &fcu)
static void shrink_array_and_swap_remove(T **array, int *num, const int index)
void assert_baklava_phase_1_invariants(const Action &action)
static void strip_ptr_destructor(ActionStrip **dna_strip_ptr)
bool fcurve_matches_collection_path(const FCurve &fcurve, StringRefNull collection_rna_path, StringRefNull data_name)
static bool is_id_using_action_slot(const ID &animated_id, const Action &action, const slot_handle_t slot_handle)
static animrig::Layer & ActionLayer_alloc()
bool foreach_action_slot_use_with_references(ID &animated_id, FunctionRef< bool(bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_name)> callback)
static void slot_ptr_destructor(ActionSlot **dna_slot_ptr)
static void array_shift_range(T *array, const int num, const int range_start, const int range_end, const int to)
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)
static void channelbag_ptr_destructor(ActionChannelBag **dna_channelbag_ptr)
static void layer_ptr_destructor(ActionLayer **dna_layer_ptr)
slot_handle_t first_slot_handle(const ::bAction &dna_action)
static void grow_array_and_append(T **array, int *num, T item)
static float2 get_frame_range_of_fcurves(Span< const FCurve * > fcurves, bool include_modifiers)
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)
SingleKeyingResult insert_vert_fcurve(FCurve *fcu, const float2 position, const KeyframeSettings &settings, eInsertKeyFlags flag)
Main Key-framing API call.
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)
static void shrink_array_and_remove(T **array, int *num, const int index)
bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code) ATTR_WARN_UNUSED_RESULT
static void grow_array_and_insert(T **array, int *num, const int index, T item)
decltype(::ActionSlot::handle) slot_handle_t
Action * get_action(ID &animated_id)
bool assign_tmpaction(bAction *action, OwnedAnimData owned_adt)
static void fcurve_ptr_noop_destructor(FCurve **)
static void fcurve_ptr_destructor(FCurve **fcurve_ptr)
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)
static void grow_array(T **array, int *num, const int add_num)
bool key_insertion_may_create_fcurve(eInsertKeyFlags insert_key_flags)
static void slot_name_ensure_unique(Action &action, Slot &slot)
static void shrink_array(T **array, int *num, const int shrink_num)
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)
bool foreach_action_slot_use(const ID &animated_id, FunctionRef< bool(const Action &action, slot_handle_t slot_handle)> callback)
static void clone_slot(Slot &from, Slot &to)
FCurve * create_fcurve_for_channel(FCurveDescriptor fcurve_descriptor)
@ FCURVE_NOT_KEYFRAMEABLE
ActionSlotAssignmentResult
void remove_index(T **items, int *items_num, int *active_index, const int index, void(*destruct_item)(T *))
void clear(T **items, int *items_num, int *active_index, void(*destruct_item)(T *))
void uninitialized_relocate_n(T *src, int64_t n, T *dst)
void uninitialized_move_n(T *src, int64_t n, T *dst)
float wrap(float value, float max, float min)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
static void unique_name(bNode *node)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
struct FCurve ** fcurve_array
struct bActionGroup ** group_array
struct ActionStrip ** strip_array
ActionSlotRuntimeHandle * runtime
struct ActionChannelBag ** channelbag_array
bool is_action_slot_to_id_map_dirty
struct ActionChannelBag * channel_bag
struct ActionSlot ** slot_array
struct ActionStripKeyframeData ** strip_keyframe_data_array
struct ActionLayer ** layer_array
int strip_keyframe_data_array_num
std::optional< blender::StringRefNull > channel_group
std::optional< PropertySubType > prop_subtype