Fix #117970: Fix RNA checks for animatable properties, add a check for drivable ones.

The `RNA_property_animateable` would check for some conditions, where it
is not valid to add or edit animations (e.g. if using a linked Action
ID...).

Add a new `RNA_property_drivable`, which is essentially a call to
`RNA_property_animateable` with extra checks in liboverride cases, as
drivers are stored directly in the AnimData struct, instead of their own
dedicated ID.

Pull Request: https://projects.blender.org/blender/blender/pulls/118809
This commit is contained in:
Bastien Montagne 2024-02-27 16:32:49 +01:00 committed by Gitea
parent f880cbce93
commit 427eed292d
4 changed files with 47 additions and 9 deletions

View File

@ -891,7 +891,7 @@ static const EnumPropertyItem *driver_mapping_type_itemf(bContext *C,
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
if (ptr.owner_id && ptr.data && prop && RNA_property_drivable(&ptr, prop)) {
const bool is_array = RNA_property_array_check(prop);
while (input->identifier) {
@ -927,7 +927,7 @@ static bool add_driver_button_poll(bContext *C)
if (!(ptr.owner_id && ptr.data && prop)) {
return false;
}
if (!RNA_property_animateable(&ptr, prop)) {
if (!RNA_property_drivable(&ptr, prop)) {
return false;
}
@ -952,7 +952,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
index = -1;
}
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
if (ptr.owner_id && ptr.data && prop && RNA_property_drivable(&ptr, prop)) {
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
@ -1043,7 +1043,7 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
if (ptr.owner_id && ptr.data && prop && RNA_property_drivable(&ptr, prop)) {
/* 1) Create a new "empty" driver for this property */
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
bool changed = false;
@ -1181,7 +1181,7 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
if (ptr.owner_id && ptr.data && prop && RNA_property_drivable(&ptr, prop)) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
/* only copy the driver for the button that this was involved for */
changed = ANIM_copy_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
@ -1220,7 +1220,7 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
if (ptr.owner_id && ptr.data && prop && RNA_property_drivable(&ptr, prop)) {
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
/* only copy the driver for the button that this was involved for */
changed = ANIM_paste_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);

View File

@ -54,8 +54,7 @@ static bool driverdropper_init(bContext *C, wmOperator *op)
uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);
if ((ddr->ptr.data == nullptr) || (ddr->prop == nullptr) ||
(RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
(RNA_property_animateable(&ddr->ptr, ddr->prop) == false) || (but->flag & UI_BUT_DRIVEN))
(RNA_property_drivable(&ddr->ptr, ddr->prop) == false) || (but->flag & UI_BUT_DRIVEN))
{
MEM_freeN(ddr);
return false;

View File

@ -305,6 +305,12 @@ bool RNA_property_editable_flag(const PointerRNA *ptr, PropertyRNA *prop);
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop);
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop);
/**
* With LibOverrides, a property may be animatable, but not drivable (in case the reference data
* already has an animation data, its Action can ba an editable local ID, but the drivers are
* directly stored in the animdata, overriding these is not supported currently).
*/
bool RNA_property_drivable(const PointerRNA *ptr, PropertyRNA *prop);
/**
* \note Does not take into account editable status, this has to be checked separately
* (using #RNA_property_editable_flag() usually).

View File

@ -17,6 +17,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
#include "DNA_anim_types.h"
#include "DNA_constraint_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
@ -2191,13 +2192,45 @@ bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop)
return false;
}
/* Linked or LibOverride Action IDs are not editable at the FCurve level. */
if (ptr->owner_id) {
AnimData *anim_data = BKE_animdata_from_id(ptr->owner_id);
if (anim_data && anim_data->action &&
(ID_IS_LINKED(anim_data->action) || ID_IS_OVERRIDE_LIBRARY(anim_data->action)))
{
return false;
}
}
prop = rna_ensure_property(prop);
if (!(prop->flag & PROP_ANIMATABLE)) {
return false;
}
return (prop->flag & PROP_EDITABLE) != 0;
return RNA_property_editable(const_cast<PointerRNA *>(ptr), prop);
}
bool RNA_property_drivable(const PointerRNA *ptr, PropertyRNA *prop)
{
if (!RNA_property_animateable(ptr, prop)) {
return false;
}
/* LibOverrides can only get drivers if their animdata (if any) was created for the local
* liboverride, and there is none in the linked reference.
*
* See also #rna_AnimaData_override_apply. */
if (ptr->owner_id && ID_IS_OVERRIDE_LIBRARY(ptr->owner_id)) {
IDOverrideLibrary *liboverride = BKE_lib_override_library_get(
nullptr, ptr->owner_id, nullptr, nullptr);
AnimData *linked_reference_anim_data = BKE_animdata_from_id(liboverride->reference);
if (linked_reference_anim_data) {
return false;
}
}
return true;
}
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)