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:
@@ -891,7 +891,7 @@ static const EnumPropertyItem *driver_mapping_type_itemf(bContext *C,
|
|||||||
|
|
||||||
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
|
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);
|
const bool is_array = RNA_property_array_check(prop);
|
||||||
|
|
||||||
while (input->identifier) {
|
while (input->identifier) {
|
||||||
@@ -927,7 +927,7 @@ static bool add_driver_button_poll(bContext *C)
|
|||||||
if (!(ptr.owner_id && ptr.data && prop)) {
|
if (!(ptr.owner_id && ptr.data && prop)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!RNA_property_animateable(&ptr, prop)) {
|
if (!RNA_property_drivable(&ptr, prop)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,7 +952,7 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
|
|||||||
index = -1;
|
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;
|
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
||||||
|
|
||||||
if (const std::optional<std::string> path = RNA_path_from_ID_to_property(&ptr, prop)) {
|
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);
|
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 */
|
/* 1) Create a new "empty" driver for this property */
|
||||||
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
|
||||||
bool changed = false;
|
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);
|
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)) {
|
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 */
|
/* 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);
|
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);
|
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)) {
|
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 */
|
/* 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);
|
changed = ANIM_paste_driver(op->reports, ptr.owner_id, path->c_str(), index, 0);
|
||||||
|
|||||||
@@ -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);
|
uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);
|
||||||
|
|
||||||
if ((ddr->ptr.data == nullptr) || (ddr->prop == nullptr) ||
|
if ((ddr->ptr.data == nullptr) || (ddr->prop == nullptr) ||
|
||||||
(RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
|
(RNA_property_drivable(&ddr->ptr, ddr->prop) == false) || (but->flag & UI_BUT_DRIVEN))
|
||||||
(RNA_property_animateable(&ddr->ptr, ddr->prop) == false) || (but->flag & UI_BUT_DRIVEN))
|
|
||||||
{
|
{
|
||||||
MEM_freeN(ddr);
|
MEM_freeN(ddr);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -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_animateable(const PointerRNA *ptr, PropertyRNA *prop);
|
||||||
bool RNA_property_animated(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
|
* \note Does not take into account editable status, this has to be checked separately
|
||||||
* (using #RNA_property_editable_flag() usually).
|
* (using #RNA_property_editable_flag() usually).
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_ID.h"
|
#include "DNA_ID.h"
|
||||||
|
#include "DNA_anim_types.h"
|
||||||
#include "DNA_constraint_types.h"
|
#include "DNA_constraint_types.h"
|
||||||
#include "DNA_modifier_types.h"
|
#include "DNA_modifier_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
@@ -2191,13 +2192,45 @@ bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop)
|
|||||||
return false;
|
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);
|
prop = rna_ensure_property(prop);
|
||||||
|
|
||||||
if (!(prop->flag & PROP_ANIMATABLE)) {
|
if (!(prop->flag & PROP_ANIMATABLE)) {
|
||||||
return false;
|
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)
|
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
|
||||||
|
|||||||
Reference in New Issue
Block a user