Anim: show animated properties with the appropriate color in the GUI
Use the `Animation` data-block to find F-Curves, for drawing the background color of properties in the GUI (green for 'animated', yellow for 'keyed on this frame', etc.). This assumes (correctly) that the `Animation` is limited to a single layer with a single strip. As such, there is only one set of F-Curves for every animated ID, which means that the correct F-Curve will be found. This will need adjustment when the same property can have multiple F-Curves (due to layers) or when an F-Curve may not be applicable for each point in time (due to the use of finite strips). Pull Request: https://projects.blender.org/blender/blender/pulls/118677
This commit is contained in:
parent
631f72265d
commit
694e5b50f4
@ -10,6 +10,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
|
||||
struct ID;
|
||||
struct Main;
|
||||
|
||||
@ -20,6 +22,8 @@ struct bAction;
|
||||
|
||||
namespace blender::animrig {
|
||||
|
||||
class Animation;
|
||||
|
||||
/**
|
||||
* Get (or add relevant data to be able to do so) the Active Action for the given
|
||||
* Animation Data block, given an ID block where the Animation Data should reside.
|
||||
@ -44,4 +48,27 @@ void reevaluate_fcurve_errors(bAnimContext *ac);
|
||||
*/
|
||||
bool animdata_remove_empty_action(AnimData *adt);
|
||||
|
||||
/**
|
||||
* Compatibility helper function for `BKE_animadata_fcurve_find_by_rna_path()`.
|
||||
*
|
||||
* Searches each layer (top to bottom) to find an FCurve that matches the given
|
||||
* RNA path & index.
|
||||
*
|
||||
* \see BKE_animadata_fcurve_find_by_rna_path
|
||||
*
|
||||
* \note The returned FCurve should NOT be used for keyframe manipulation. Its
|
||||
* existence is an indicator for "this property is animated".
|
||||
*
|
||||
* This function should probably be limited to the active layer (for the given
|
||||
* property, once pinning to layers is there), so that the "this is keyed" color
|
||||
* is more accurate.
|
||||
*
|
||||
* Again, this is just to hook up the new Animation data-block to the old
|
||||
* Blender UI code.
|
||||
*/
|
||||
const FCurve *fcurve_find_by_rna_path(const Animation &anim,
|
||||
const ID &animated_id,
|
||||
StringRefNull rna_path,
|
||||
int array_index);
|
||||
|
||||
} // namespace blender::animrig
|
||||
|
@ -6,6 +6,7 @@
|
||||
* \ingroup animrig
|
||||
*/
|
||||
|
||||
#include "ANIM_animation.hh"
|
||||
#include "ANIM_animdata.hh"
|
||||
|
||||
#include "BKE_action.h"
|
||||
@ -174,4 +175,46 @@ void reevaluate_fcurve_errors(bAnimContext *ac)
|
||||
}
|
||||
}
|
||||
|
||||
const FCurve *fcurve_find_by_rna_path(const Animation &anim,
|
||||
const ID &animated_id,
|
||||
const StringRefNull rna_path,
|
||||
const int array_index)
|
||||
{
|
||||
const Binding *binding = anim.binding_for_id(animated_id);
|
||||
if (!binding) {
|
||||
/* No need to inspect anything if this ID does not have an animation Binding. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Iterate the layers top-down, as higher-up animation overrides (or at least can override)
|
||||
* lower-down animation. */
|
||||
for (int layer_idx = anim.layer_array_num - 1; layer_idx >= 0; layer_idx--) {
|
||||
const Layer *layer = anim.layer(layer_idx);
|
||||
|
||||
/* TODO: refactor this into something nicer once we have different strip types. */
|
||||
for (const Strip *strip : layer->strips()) {
|
||||
switch (strip->type()) {
|
||||
case Strip::Type::Keyframe: {
|
||||
const KeyframeStrip &key_strip = strip->as<KeyframeStrip>();
|
||||
const ChannelBag *channelbag_for_binding = key_strip.channelbag_for_binding(*binding);
|
||||
if (!channelbag_for_binding) {
|
||||
continue;
|
||||
}
|
||||
const FCurve *fcu = channelbag_for_binding->fcurve_find(rna_path, array_index);
|
||||
if (!fcu) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This code assumes that there is only one strip, and that it's infinite. When that
|
||||
* changes, this code needs to be expanded to check for strip boundaries. */
|
||||
return fcu;
|
||||
}
|
||||
}
|
||||
/* Explicit lack of 'default' clause, to get compiler warnings when strip types are added. */
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender::animrig
|
||||
|
@ -292,8 +292,10 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
|
||||
/**
|
||||
* Find an F-Curve from its rna path and index.
|
||||
*
|
||||
* If there is an action assigned to the `animdata`, it will be searched for a matching F-curve
|
||||
* first. Drivers are searched only if no valid action F-curve could be found.
|
||||
* The search order is as follows. The first match will be returned:
|
||||
* - Animation
|
||||
* - Action
|
||||
* - Drivers
|
||||
*
|
||||
* \note Typically, indices in RNA arrays are stored separately in F-curves, so the rna_path
|
||||
* should not include them (e.g. `rna_path='location[0]'` will not match any F-Curve on an Object,
|
||||
@ -301,8 +303,13 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
|
||||
*
|
||||
* \note Return pointer parameters (`r_action`, `r_driven` and `r_special`) are all optional and
|
||||
* may be NULL.
|
||||
*
|
||||
* \note since Animation data-blocks may have multiple layers all containing an F-Curve for this
|
||||
* property, what is returned is a best-effort guess. The topmost layer has priority, and it is
|
||||
* assumed that when it has a strip, it's infinite.
|
||||
*/
|
||||
FCurve *BKE_animadata_fcurve_find_by_rna_path(AnimData *animdata,
|
||||
FCurve *BKE_animadata_fcurve_find_by_rna_path(const ID *id,
|
||||
AnimData *animdata,
|
||||
const char *rna_path,
|
||||
const int rna_index,
|
||||
bAction **r_action,
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "ANIM_animation.hh"
|
||||
#include "ANIM_animdata.hh"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_text_types.h"
|
||||
@ -38,6 +41,7 @@
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_scene.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
@ -247,7 +251,7 @@ FCurve *id_data_find_fcurve(
|
||||
* needs to be re-checked I think?. */
|
||||
bool is_driven = false;
|
||||
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(
|
||||
adt, path->c_str(), index, nullptr, &is_driven);
|
||||
id, adt, path->c_str(), index, nullptr, &is_driven);
|
||||
if (is_driven) {
|
||||
if (r_driven != nullptr) {
|
||||
*r_driven = is_driven;
|
||||
@ -344,8 +348,12 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
|
||||
return matches;
|
||||
}
|
||||
|
||||
FCurve *BKE_animadata_fcurve_find_by_rna_path(
|
||||
AnimData *animdata, const char *rna_path, int rna_index, bAction **r_action, bool *r_driven)
|
||||
FCurve *BKE_animadata_fcurve_find_by_rna_path(const ID *id,
|
||||
AnimData *animdata,
|
||||
const char *rna_path,
|
||||
int rna_index,
|
||||
bAction **r_action,
|
||||
bool *r_driven)
|
||||
{
|
||||
if (r_driven != nullptr) {
|
||||
*r_driven = false;
|
||||
@ -354,11 +362,24 @@ FCurve *BKE_animadata_fcurve_find_by_rna_path(
|
||||
*r_action = nullptr;
|
||||
}
|
||||
|
||||
/* Animation data-block takes priority over Action data-block. */
|
||||
if (animdata->animation) {
|
||||
/* TODO: this branch probably also needs a `Animation *r_anim` parameter for full
|
||||
* compatibility with the Action-based uses. Even better: change to return a
|
||||
* result struct with all the relevant information/data. */
|
||||
BLI_assert(id);
|
||||
const FCurve *fcu = blender::animrig::fcurve_find_by_rna_path(
|
||||
animdata->animation->wrap(), *id, rna_path, rna_index);
|
||||
if (fcu) {
|
||||
/* The new Animation data-block is stricter with const-ness than older code, hence the
|
||||
* const_cast. */
|
||||
return const_cast<FCurve *>(fcu);
|
||||
}
|
||||
}
|
||||
|
||||
/* Action takes priority over drivers. */
|
||||
const bool has_action_fcurves = animdata->action != nullptr &&
|
||||
!BLI_listbase_is_empty(&animdata->action->curves);
|
||||
const bool has_drivers = !BLI_listbase_is_empty(&animdata->drivers);
|
||||
|
||||
/* Animation takes priority over drivers. */
|
||||
if (has_action_fcurves) {
|
||||
FCurve *fcu = BKE_fcurve_find(&animdata->action->curves, rna_path, rna_index);
|
||||
|
||||
@ -371,6 +392,7 @@ FCurve *BKE_animadata_fcurve_find_by_rna_path(
|
||||
}
|
||||
|
||||
/* If not animated, check if driven. */
|
||||
const bool has_drivers = !BLI_listbase_is_empty(&animdata->drivers);
|
||||
if (has_drivers) {
|
||||
FCurve *fcu = BKE_fcurve_find(&animdata->drivers, rna_path, rna_index);
|
||||
|
||||
@ -460,7 +482,7 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext * /*C*/,
|
||||
|
||||
/* Standard F-Curve from animdata - Animation (Action) or Drivers. */
|
||||
FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(
|
||||
adt, rna_path->c_str(), rnaindex, r_action, r_driven);
|
||||
ptr->owner_id, adt, rna_path->c_str(), rnaindex, r_action, r_driven);
|
||||
|
||||
if (fcu != nullptr && r_animdata != nullptr) {
|
||||
*r_animdata = adt;
|
||||
|
@ -360,12 +360,12 @@ bool BKE_lib_override_library_property_is_animated(
|
||||
const char index_token_start_backup = *index_token_start;
|
||||
*index_token_start = '\0';
|
||||
fcurve = BKE_animadata_fcurve_find_by_rna_path(
|
||||
anim_data, liboverride_prop->rna_path, rnaprop_index, nullptr, nullptr);
|
||||
id, anim_data, liboverride_prop->rna_path, rnaprop_index, nullptr, nullptr);
|
||||
*index_token_start = index_token_start_backup;
|
||||
}
|
||||
else {
|
||||
fcurve = BKE_animadata_fcurve_find_by_rna_path(
|
||||
anim_data, liboverride_prop->rna_path, 0, nullptr, nullptr);
|
||||
id, anim_data, liboverride_prop->rna_path, 0, nullptr, nullptr);
|
||||
}
|
||||
if (fcurve != nullptr) {
|
||||
return true;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_mask.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_scene.hh"
|
||||
#include "BKE_screen.hh"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
@ -4576,7 +4577,7 @@ static blender::Vector<FCurve *> get_fcurves_of_property(
|
||||
const int length = RNA_property_array_length(ptr, prop);
|
||||
for (int i = 0; i < length; i++) {
|
||||
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
|
||||
anim_data, path->c_str(), i, nullptr, nullptr);
|
||||
id, anim_data, path->c_str(), i, nullptr, nullptr);
|
||||
if (fcurve != nullptr) {
|
||||
fcurves.append(fcurve);
|
||||
}
|
||||
@ -4584,7 +4585,7 @@ static blender::Vector<FCurve *> get_fcurves_of_property(
|
||||
}
|
||||
else {
|
||||
FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path(
|
||||
anim_data, path->c_str(), index, nullptr, nullptr);
|
||||
id, anim_data, path->c_str(), index, nullptr, nullptr);
|
||||
if (fcurve != nullptr) {
|
||||
fcurves.append(fcurve);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user