Refactor to prepare for slotted action support to the evaluation of
quaternion F-Curves.
Since slotted Actions store F-Curves in an array, you cannot iterate over
them any more via the `ListBase` pointer `fcurve.next`. Quaternion
evaluation code has been refactored to work on a span of F-Curves instead
of just getting the first one.
For now, slotted Actions just evaluate their first slot only. A future
commit will add a slot handle parameter to evaluate the correct slot.
Properly track Action and Slot assignment when entering/exiting NLA
tweak mode.
This doesn't properly sync the length of the NLA strip when exiting
tweak mode. This and more NLA work is tracked at #127489.
Pull Request: https://projects.blender.org/blender/blender/pulls/127498
For an NLA strip to use a slotted Action, it needs to specify which slot
to use in that action. This is now handled by two new properties on the
strip in DNA & RNA: `action_slot_handle` and `action_slot_name`.
These serve the same purpose as their counterparts on the `AnimData`
struct.
Note that this commit does NOT add NLA evaluation support for slotted
Actions. It merely allows assigning them. Evaluation, tweak mode
support, etc. will be implemented in future commits.
Pull Request: https://projects.blender.org/blender/blender/pulls/127359
When converting a legacy Action to a layered Action,
also convert group memberships.
This is important for bones to retain their structure in
the Channel Box.
Pull Request: https://projects.blender.org/blender/blender/pulls/127188
This adds layered animation support to the following operators, allowing users to manage the grouping and arrangement of fcurves in the channel list:
- "Group Channels"
- "Ungroup Channels"
- "Move Channels"
Pull Request: https://projects.blender.org/blender/blender/pulls/127080
The cause was simple: I missed this operator in the initial layered-action
channel group implementation, so deletion was using the legacy action code
even for layered actions.
This implements the needed code in the deletion operator to handle layered
actions.
Pull Request: https://projects.blender.org/blender/blender/pulls/127242
Add a method to remove a slot from an Action. This is also exposed as
`Action.slots.remove(slot)` to RNA/Python.
Removing a slot deletes all its associated animation data in the Action.
It also un-assigns the slot from any ID that was animated by it. The
Action reference is left untouched.
Pull Request: https://projects.blender.org/blender/blender/pulls/127112
Move the functions
* `BKE_pose_apply_action_selected_bones`
* `BKE_pose_apply_action_all_bones`
* and `BKE_pose_apply_action_blend`
out of the blender kernel and into animrig.
This will allow solving #126969 without having to include
animrig code in the blender kernel.
Pull Request: https://projects.blender.org/blender/blender/pulls/126978
It's possible for the `bArmature.collection_array` to be null if Bone
Collections were never added after armature creation. This could trip up
undo processing later when we call `MEM_freeN` on the collection.
Use a `MEM_SAFE_FREE` call instead which handles checking for null, as
well as setting to null when complete.
Pull Request: https://projects.blender.org/blender/blender/pulls/126945
This issue only applied to layered actions.
The issue was that the `restore_channel_group_invariants()` method was
being called too early in the remove fcurve function, and thus fcurves'
group pointers could end up inconsistent with the membership specified
in the groups.
This commit fixes the issue by moving the call to
`restore_channel_group_invariants()` to the end of the function, where
it belongs.
Pull Request: https://projects.blender.org/blender/blender/pulls/127075
The issue was that the forward compatibility writing code for channel groups in
layered actions was building a temporary legacy listbase, but was not clearing
it properly afterwards. This was then getting caught by an assert that ensured
that layered-action groups didn't have legacy data in them.
The reason the listbase wasn't getting cleared properly is because the
prev/next listbase pointers were getting cleared using a `LISTBASE_FOREACH`
loop, and thus the loop never progressed past the first item.
Additionally, this mistake wasn't just in the channel groups writing code, but
also the forward compatibility writing code for fcurves.
This fixes the issue in both places by switching the loops to
use`LISTBASE_FOREACH_MUTABLE`.
Based on discussion with @dr.sybren, this also removes the assert that caught
the issue. The situation it guards against is actually completely benign, and
the existence of the assert is contrary to the comments in the forward-compat
writing code explaining why its approach is okay.
Pull Request: https://projects.blender.org/blender/blender/pulls/126970
In layered actions, the channel groups in a channel bag hold a
non-owning pointer to the channel bag they belong to, to allow looking
up the fcurves in the group. However, when a duplicate was made of a
channel bag, those pointers in the (also duplicated) channel groups
weren't updated to point at it, and thus were still pointing at the
original channel bag.
This commit adds the code to properly update those pointers when
duplicating channel bags.
Pull Request: https://projects.blender.org/blender/blender/pulls/126923
Fix an issue that was caused by common code used for both these flows:
- 'ensure a slot exists for an ID so keys for it can be inserted' and
- 'assign an Action to an ID'
Both flows search for suitable slots for the ID, but should do so in
subtly different ways. Most importantly, the first case should _not_
search a slot by name (when an Action is already assigned but not a
slot). This is relevant in the following flow:
- Assign an Action to an Object. This auto-selects the most appropriate
slot (by name).
- Un-assign the slot (for whatever reason it's not desired).
- Insert a key.
- This should create a new slot, and not re-assign the slot just
un-assigned above.
Pull Request: https://projects.blender.org/blender/blender/pulls/126850
The functions were allocating arrays of `T *` rather than `T`, and
then were reinterpret-casting to the correct type afterwards. This
coincidentally worked at the current call sites because `T` was always
a pointer type anyway, but the code was logically incorrect and wouldn't
work if anyone tried to use them with a non-pointer `T`.
This commit fixes this by correctly allocating an array of `T` instead,
and removing the unnecessary cast.
Pull Request: https://projects.blender.org/blender/blender/pulls/126656
This PR adds channel groups (also known as fcurve groups or action groups) to
layered actions. For layered actions, these groups belong to the `ChannelBag`s
and can vary by bag.
From a user perspective, the goal is for these to function just like channel
groups from legacy actions. However, internally they are implemented a little
differently: legacy actions store both channel groups and fcurves in a listbase,
and groups indicate what fcurves are in them with a listbase that points
directly into the larger fcurve listbase. Layered actions, on the other hand,
store both fcurves and channel groups in an array, and groups indicate what
fcurves are in them by indexing into the fcurve array.
Despite taking this different approach, we still reuse the `bActionGroup` struct
for the new channel groups, just adding the necessary fields for index-based
fcurve membership as described above.
This PR does not implement all of the functionality needed to reach feature
parity with legacy action channel groups, but implements the main core and gets
them basically working.
It's easier to list the things that *haven't* been implemented yet:
- Operators for letting the user manually create/remove/move channel groups.
- Keyframe selection in the action/dopesheet editor on channel group rows
themselves are not yet working correctly.
- Handling channel groups in legacy/layered action conversion operators.
- Making the legacy `action.groups` property work on single-layer-single-strip
layered actions.
Those are left for future PRs. Other than that, in theory everything should be
working now.
Pull Request: https://projects.blender.org/blender/blender/pulls/125774
The issue was that the code path for layered actions never hit the
function `remap_cyclic_keyframe_location`.
The solution is to move that logic into `insert_vert_fcurve`.
My reason for why this is the correct solution is that
the remapping happens on a per FCurve basis, so it should be within `fcurve.cc`.
Doing so ensures that the layered actions also hit that code.
Pull Request: https://projects.blender.org/blender/blender/pulls/126399
The issues was that the `get_item_transform_flags` iterated over the `curves`
list of the action, ignoring the new structure.
Fixed by using the `action_foreach_fcurve` and modifying that to work on legacy actions as well.
Pull Request: https://projects.blender.org/blender/blender/pulls/126357
This changes the behavior when deleting the last key of an FCurve on layered actions.
Previously the FCurve would continue to exist, whereas now it is deleted.
This makes it consistent with legacy actions.
I modified the "Clear Keyframes" operator in this PR as well to make it work with layered actions.
Pull Request: https://projects.blender.org/blender/blender/pulls/125327
Match function and declaration names, picking names based on
consistency with related code & clarity.
Also changes for old conventions, missed in previous cleanups:
- name -> filepath
- tname -> newname
- maxlen -> maxncpy
No functional changes intended.
The function `clear_keyframe` had more arguments than needed:
* The `bAction *` was always a nullptr
* the unused parameter `eInsertKeyFlags` was removed
* the rna path and the array index were merged with the `RNAPath` struct
Pull Request: https://projects.blender.org/blender/blender/pulls/125487
No functional changes intended.
This simplifies the arguments for the `delete_keyframe` function.
The `bAction *` was always a `nullptr` so I just removed it.
The rna path char array and the array index were merged into the `RNAPath` struct.
Pull Request: https://projects.blender.org/blender/blender/pulls/125479
Add an Action Slot selector to the Action editor's header, next to the
Action selector. The selector shows all slots in the action that are
suitable for animating objects (as the Action editor itself is limited
to showing the Action of the active object).
This also considerably simplifies the 'Animation Debug' panel, as some
debugging code has been removed, as well as the display of any animation
layers. The latter can be reintroduced (if necessary) when multi-layer
animation support is added. Most importantly, it removes the
WindowManager property that was used as a hack to assign layered Actions
to objects.
API change: the RNA property `AnimData.slot` is now a pointer property
that reflects the actual slot (it used to be an enum property).
Some small changes to the UI code were necessary to make the selector
show the slot's display name (and not their internal name).
Pull Request: https://projects.blender.org/blender/blender/pulls/125416
When the setting "Only Insert Available" is enabled and there is no action yet,
we can exit early because we know that it will not be possible to insert a keyframe.
This prevents an action from being created.
Co-authored by: Pratik Borhade
Pull Request: https://projects.blender.org/blender/blender/pulls/125408
These functions can now be called on layered Actions:
- `action.fcurves.new(data_path, array_index)`
- `action.fcurves.find(data_path, array_index)`
- `action.fcurves.remove(fcurve)`
- `action.fcurves.clear()`
These will operate on the first keyframe strip (searching layers bottom
to top), and then its channelbag for the first slot.
If necessary, `fcurves.new()` will create the layer, keyframe strip,
channelbag, and slot.
This backward compatibility layer only kicks in if either of these is
true:
- The Action is empty AND the experimental flag is enabled, or
- The Action already has a layer or a slot (i.e. is already considered
'layered').
If none of these conditions hold, `action.fcurves` just gives access to
the legacy data.
Ref: #124714
Pull Request: https://projects.blender.org/blender/blender/pulls/124996
Rename leftover references to action 'bindings' to 'slot':
- Two comments, and
- bunch of `bind_` variable prefixes, renamed to `slot_`.
No functional changes.
When a new F-Curve is created on a layered Action, tag the dependency
graph for rebuilding its relationships. This is necessary as the F-Curve
may be animating a depsgraph component that was previously not animated,
and thus that relation needs to be constructed.
This was already in place for legacy Actions, and simply overlooked for
the new layered ones.
Pull Request: https://projects.blender.org/blender/blender/pulls/125236