Blender V5.0
animrig/intern/nla.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "ANIM_nla.hh"
10
11namespace blender::animrig::nla {
12
13bool assign_action(NlaStrip &strip, Action &action, ID &animated_id)
14{
16 animated_id, &action, strip.act, strip.action_slot_handle, strip.last_slot_identifier))
17 {
18 return false;
19 }
20
21 /* For the NLA, the auto slot selection gets one more fallback option (compared to the generic
22 * code). This is to support the following scenario:
23 *
24 * - Python script creates an Action, and adds some F-Curves via the legacy API.
25 * - This creates a slot 'XXSlot'.
26 * - The script creates multiple NLA strips for that Action.
27 * - The desired result is that these strips get the same Slot assigned as well.
28 *
29 * The generic code doesn't work for this. The first strip assignment would see the slot
30 * `XXSlot`, and because it has never been used, just use it. This would change its name to, for
31 * example, `OBSlot`. The second strip assignment would not see a 'virgin' slot, and thus not
32 * auto-select `OBSlot`. This behavior makes sense when assigning Actions in the Action editor
33 * (it shouldn't automatically pick the first slot of matching ID type), but for the NLA I
34 * (Sybren) feel that it could be a bit more 'enthusiastic' in auto-picking a slot.
35 */
36 if (strip.action_slot_handle == Slot::unassigned && action.slots().size() == 1) {
37 Slot *first_slot = action.slot(0);
38 if (first_slot->is_suitable_for(animated_id)) {
39 const ActionSlotAssignmentResult result = assign_action_slot(strip, first_slot, animated_id);
41 "Assigning a slot that we know is suitable should work");
43 }
44 }
45
46 /* Regardless of slot auto-selection, the Action assignment worked just fine. */
47 return true;
48}
49
50void unassign_action(NlaStrip &strip, ID &animated_id)
51{
52 const bool ok = generic_assign_action(
53 animated_id, nullptr, strip.act, strip.action_slot_handle, strip.last_slot_identifier);
54 BLI_assert_msg(ok, "Un-assigning an Action from an NLA strip should always work.");
56}
57
59 Slot *slot_to_assign,
60 ID &animated_id)
61{
62 BLI_assert(strip.act);
63
64 return generic_assign_action_slot(slot_to_assign,
65 animated_id,
66 strip.act,
69}
70
72 const slot_handle_t slot_handle,
73 ID &animated_id)
74{
75 BLI_assert(strip.act);
76
77 Action &action = strip.act->wrap();
78 Slot *slot_to_assign = action.slot_for_handle(slot_handle);
79
80 return assign_action_slot(strip, slot_to_assign, animated_id);
81}
82
83} // namespace blender::animrig::nla
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define UNUSED_VARS_NDEBUG(...)
const Slot * slot(int64_t index) const
blender::Span< const Slot * > slots() const
Slot * slot_for_handle(slot_handle_t handle)
bool is_suitable_for(const ID &animated_id) const
static constexpr slot_handle_t unassigned
void unassign_action(NlaStrip &strip, ID &animated_id)
ActionSlotAssignmentResult assign_action_slot_handle(NlaStrip &strip, slot_handle_t slot_handle, ID &animated_id)
bool assign_action(NlaStrip &strip, Action &action, ID &animated_id)
ActionSlotAssignmentResult assign_action_slot(NlaStrip &strip, Slot *slot_to_assign, ID &animated_id)
bool generic_assign_action(ID &animated_id, bAction *action_to_assign, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_identifier)
ActionSlotAssignmentResult generic_assign_action_slot(Slot *slot_to_assign, ID &animated_id, bAction *&action_ptr_ref, slot_handle_t &slot_handle_ref, char *slot_identifier)
decltype(::ActionSlot::handle) slot_handle_t
Definition DNA_ID.h:414
char last_slot_identifier[258]
int32_t action_slot_handle
bAction * act