Anim: add checks for system overrides to bone collection operators

Editability checks shouldn't just check for linked data & library
overrides, but also for the type of library override. A "system
override" should still not be editable by users.

This fixes #115310: Bone collections can be added to system-overridden
(i.e. non-user-editable) armatures
This commit is contained in:
Sybren A. Stüvel 2023-12-21 14:58:30 +01:00
parent dea7d65ee7
commit eac4a6c697
2 changed files with 44 additions and 2 deletions

View File

@ -26,6 +26,7 @@
#include "BKE_animsys.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.hh"
#include "ANIM_armature_iter.hh"
#include "ANIM_bone_collections.hh"
@ -287,7 +288,14 @@ bool ANIM_armature_bonecoll_is_editable(const bArmature *armature, const BoneCol
if (ID_IS_LINKED(armature) && !is_override) {
return false;
}
if (is_override && BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
/* A system override is still not editable. */
return false;
}
if (is_override && (bcoll->flags & BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL) == 0) {
/* This particular collection was not added in the local override, so not editable. */
return false;
}
return true;

View File

@ -17,6 +17,7 @@
#include "BKE_action.h"
#include "BKE_context.hh"
#include "BKE_layer.h"
#include "BKE_lib_override.hh"
#include "BKE_report.h"
#include "BLT_translation.h"
@ -63,6 +64,13 @@ static bool bone_collection_add_poll(bContext *C)
return false;
}
if (BKE_lib_override_library_is_system_defined(nullptr, reinterpret_cast<ID *>(ob->data))) {
CTX_wm_operator_poll_msg_set(C,
"Cannot add bone collections to a linked Armature with a system "
"override; explicitly create an override on the Armature");
return false;
}
return true;
}
@ -80,8 +88,14 @@ static bool active_bone_collection_poll(bContext *C)
}
bArmature *armature = static_cast<bArmature *>(ob->data);
BoneCollection *bcoll = armature->runtime.active_collection;
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
CTX_wm_operator_poll_msg_set(C,
"Cannot update a linked Armature with a system override; "
"explicitly create an override on the Armature");
return false;
}
BoneCollection *bcoll = armature->runtime.active_collection;
if (bcoll == nullptr) {
CTX_wm_operator_poll_msg_set(C, "Armature has no active bone collection, select one first");
return false;
@ -387,6 +401,12 @@ static bool bone_collection_assign_poll(bContext *C)
C, "Cannot edit bone collections on linked Armatures without override");
return false;
}
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
CTX_wm_operator_poll_msg_set(C,
"Cannot edit bone collections on a linked Armature with a system "
"override; explicitly create an override on the Armature");
return false;
}
/* The target bone collection can be specified by name in an operator property, but that's not
* available here. So just allow in the poll function, and do the final check in the execute. */
@ -484,6 +504,12 @@ static bool bone_collection_create_and_assign_poll(bContext *C)
C, "Cannot edit bone collections on linked Armatures without override");
return false;
}
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
CTX_wm_operator_poll_msg_set(C,
"Cannot edit bone collections on a linked Armature with a system "
"override; explicitly create an override on the Armature");
return false;
}
return true;
}
@ -951,11 +977,19 @@ static bool move_to_collection_poll(bContext *C)
return false;
}
if (ID_IS_LINKED(ob->data) && !ID_IS_OVERRIDE_LIBRARY(ob->data)) {
const bArmature *armature = static_cast<bArmature *>(ob->data);
if (ID_IS_LINKED(armature) && !ID_IS_OVERRIDE_LIBRARY(armature)) {
CTX_wm_operator_poll_msg_set(C, "This needs a local Armature or an override");
return false;
}
if (BKE_lib_override_library_is_system_defined(nullptr, &armature->id)) {
CTX_wm_operator_poll_msg_set(C,
"Cannot update a linked Armature with a system override; "
"explicitly create an override on the Armature");
return false;
}
/* Ideally this would also check the target bone collection to move/assign to.
* However, that requires access to the operator properties, and those are not
* available in the poll function. */