Anim: add support for renaming bone collections added by overrides
Add a flag `BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL` that's only set on bone collections that have been overridden locally.
This commit is contained in:
parent
89aee9defb
commit
347ffd6262
|
@ -89,6 +89,16 @@ class DATA_UL_bone_collections(UIList):
|
|||
|
||||
layout.prop(bcoll, "name", text="", emboss=False,
|
||||
icon='DOT' if has_active_bone else 'BLANK1')
|
||||
|
||||
if armature.override_library:
|
||||
icon = 'LIBRARY_DATA_OVERRIDE' if bcoll.is_local_override else 'BLANK1'
|
||||
layout.prop(
|
||||
bcoll,
|
||||
"is_local_override",
|
||||
text="",
|
||||
emboss=False,
|
||||
icon=icon)
|
||||
|
||||
layout.prop(bcoll, "is_visible", text="", emboss=False,
|
||||
icon='HIDE_OFF' if bcoll.is_visible else 'HIDE_ON')
|
||||
|
||||
|
|
|
@ -108,6 +108,15 @@ void ANIM_armature_bonecoll_active_set(struct bArmature *armature, struct BoneCo
|
|||
void ANIM_armature_bonecoll_active_index_set(struct bArmature *armature,
|
||||
int bone_collection_index);
|
||||
|
||||
/**
|
||||
* Determine whether the given bone collection is editable.
|
||||
*
|
||||
* Bone collections are editable when they are local, so either on a local Armature or added to a
|
||||
* linked Armature via a library override in the local file.
|
||||
*/
|
||||
bool ANIM_armature_bonecoll_is_editable(const struct bArmature *armature,
|
||||
const struct BoneCollection *bcoll);
|
||||
|
||||
/**
|
||||
* Move the bone collection by \a step places up/down.
|
||||
*
|
||||
|
|
|
@ -111,6 +111,12 @@ static void bonecoll_ensure_name_unique(bArmature *armature, BoneCollection *bco
|
|||
BoneCollection *ANIM_armature_bonecoll_new(bArmature *armature, const char *name)
|
||||
{
|
||||
BoneCollection *bcoll = ANIM_bonecoll_new(name);
|
||||
|
||||
if (!ID_IS_LINKED(&armature->id) && ID_IS_OVERRIDE_LIBRARY(&armature->id)) {
|
||||
/* Mark this bone collection as local override, so that certain operations can be allowed. */
|
||||
bcoll->flags |= BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL;
|
||||
}
|
||||
|
||||
bonecoll_ensure_name_unique(armature, bcoll);
|
||||
BLI_addtail(&armature->collections, bcoll);
|
||||
return bcoll;
|
||||
|
@ -187,6 +193,18 @@ void ANIM_armature_bonecoll_active_index_set(bArmature *armature, const int bone
|
|||
armature->runtime.active_collection = bcoll;
|
||||
}
|
||||
|
||||
bool ANIM_armature_bonecoll_is_editable(const bArmature *armature, const BoneCollection *bcoll)
|
||||
{
|
||||
const bool is_override = ID_IS_OVERRIDE_LIBRARY(armature);
|
||||
if (ID_IS_LINKED(armature) && !is_override) {
|
||||
return false;
|
||||
}
|
||||
if (is_override && (bcoll->flags & BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ANIM_armature_bonecoll_move(bArmature *armature, BoneCollection *bcoll, const int step)
|
||||
{
|
||||
if (bcoll == nullptr) {
|
||||
|
|
|
@ -174,4 +174,38 @@ TEST_F(ANIM_armature_bone_collections, active_set_clear_by_index)
|
|||
EXPECT_STREQ("", arm.active_collection_name);
|
||||
}
|
||||
|
||||
TEST_F(ANIM_armature_bone_collections, bcoll_is_editable)
|
||||
{
|
||||
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "Bones 1");
|
||||
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "Bones 2");
|
||||
|
||||
EXPECT_EQ(0, bcoll1->flags & BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL);
|
||||
EXPECT_EQ(0, bcoll2->flags & BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL);
|
||||
|
||||
EXPECT_TRUE(ANIM_armature_bonecoll_is_editable(&arm, bcoll1))
|
||||
<< "Expecting local armature to be editable";
|
||||
|
||||
/* Fake that the armature is linked from another blend file. */
|
||||
Library fake_lib;
|
||||
arm.id.lib = &fake_lib;
|
||||
EXPECT_FALSE(ANIM_armature_bonecoll_is_editable(&arm, bcoll1))
|
||||
<< "Expecting local armature to not be editable";
|
||||
|
||||
/* Fake that the armature is an override, but linked from another blend file. */
|
||||
IDOverrideLibrary fake_override;
|
||||
bArmature fake_reference;
|
||||
fake_override.reference = &fake_reference.id;
|
||||
arm.id.override_library = &fake_override;
|
||||
EXPECT_FALSE(ANIM_armature_bonecoll_is_editable(&arm, bcoll1))
|
||||
<< "Expecting linked armature override to not be editable";
|
||||
|
||||
/* Fake that the armature is a local override. */
|
||||
arm.id.lib = nullptr;
|
||||
bcoll2->flags |= BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL;
|
||||
EXPECT_FALSE(ANIM_armature_bonecoll_is_editable(&arm, bcoll1))
|
||||
<< "Expecting linked bone collection on local armature override to not be editable";
|
||||
EXPECT_TRUE(ANIM_armature_bonecoll_is_editable(&arm, bcoll2))
|
||||
<< "Expecting local bone collection on local armature override to be editable";
|
||||
}
|
||||
|
||||
} // namespace blender::animrig::tests
|
||||
|
|
|
@ -350,10 +350,18 @@ static void armature_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
}
|
||||
|
||||
BLO_read_list(reader, &arm->collections);
|
||||
|
||||
/* Bone collections added via an override can be edited, but ones that already exist in another
|
||||
* blend file (so on the linked Armature) should not be touched. */
|
||||
const bool reset_bcoll_override_flag = ID_IS_LINKED(&arm->id);
|
||||
LISTBASE_FOREACH (BoneCollection *, bcoll, &arm->collections) {
|
||||
direct_link_bone_collection(reader, bcoll);
|
||||
if (reset_bcoll_override_flag) {
|
||||
/* The linked Armature may have overrides in the library file already, and
|
||||
* those should *not* be editable here. */
|
||||
bcoll->flags &= ~BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL;
|
||||
}
|
||||
}
|
||||
BLO_read_data_address(reader, &arm->active_collection);
|
||||
|
||||
BLO_read_data_address(reader, &arm->act_bone);
|
||||
arm->act_edbone = nullptr;
|
||||
|
|
|
@ -53,6 +53,7 @@ static bool bone_collection_poll(bContext *C)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* TODO: double-check these two conditions, I'm not sure they are correct: */
|
||||
if (ID_IS_OVERRIDE_LIBRARY(ob->data)) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Cannot edit bone collections for library overrides");
|
||||
return false;
|
||||
|
@ -87,22 +88,32 @@ static bool bone_collection_add_poll(bContext *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Allow edits of local bone collection only (full local or local override). */
|
||||
static bool active_bone_collection_poll(bContext *C)
|
||||
{
|
||||
if (!bone_collection_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object *ob = ED_object_context(C);
|
||||
if (ob == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ob->type != OB_ARMATURE) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Bone collections can only be edited on an Armature");
|
||||
return false;
|
||||
}
|
||||
|
||||
bArmature *armature = static_cast<bArmature *>(ob->data);
|
||||
if (armature->runtime.active_collection == nullptr) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (!ANIM_armature_bonecoll_is_editable(armature, bcoll)) {
|
||||
CTX_wm_operator_poll_msg_set(
|
||||
C, "Cannot edit bone collections that are linked from another blend file");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -424,8 +424,9 @@ typedef enum eBone_BBoneHandleFlag {
|
|||
typedef enum eBoneCollection_Flag {
|
||||
BONE_COLLECTION_VISIBLE = (1 << 0),
|
||||
BONE_COLLECTION_SELECTABLE = (1 << 1), /* Intended to be implemented in the not-so-far future. */
|
||||
BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL = (1 << 2), /* Added by a local library override. */
|
||||
} eBoneCollection_Flag;
|
||||
ENUM_OPERATORS(eBoneCollection_Flag, BONE_COLLECTION_SELECTABLE)
|
||||
ENUM_OPERATORS(eBoneCollection_Flag, BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
|
|
@ -157,6 +157,12 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (RNA_struct_is_a(ptr->type, &RNA_BoneCollection)) {
|
||||
BoneCollection *bcoll = static_cast<BoneCollection *>(ptr->data);
|
||||
if (bcoll->flags & BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* If this is a RNA-defined property (real or 'virtual' IDProp),
|
||||
* we want to use RNA prop flag. */
|
||||
return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
|
||||
|
|
|
@ -334,8 +334,13 @@ static bool rna_Armature_collections_override_apply(Main *bmain,
|
|||
bArmature *arm_dst = (bArmature *)ptr_dst->owner_id;
|
||||
BoneCollection *bcoll_anchor = static_cast<BoneCollection *>(ptr_item_dst->data);
|
||||
BoneCollection *bcoll_src = static_cast<BoneCollection *>(ptr_item_src->data);
|
||||
BoneCollection *bcoll = ANIM_armature_bonecoll_insert_copy_after(
|
||||
arm_dst, bcoll_anchor, bcoll_src);
|
||||
|
||||
ANIM_armature_bonecoll_insert_copy_after(arm_dst, bcoll_anchor, bcoll_src);
|
||||
if (!ID_IS_LINKED(&arm_dst->id)) {
|
||||
/* Mark this bone collection as local override, so that certain operations can be allowed. */
|
||||
bcoll->flags |= BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL;
|
||||
}
|
||||
|
||||
RNA_property_update_main(bmain, nullptr, ptr_dst, prop_dst);
|
||||
return true;
|
||||
|
@ -2061,7 +2066,6 @@ static void rna_def_bonecollection(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Name", "Unique within the Armature");
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_BoneCollection_name_set");
|
||||
// RNA_def_property_update(prop, 0, "rna_Bone_update_renamed");
|
||||
|
||||
prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flags", BONE_COLLECTION_VISIBLE);
|
||||
|
@ -2072,6 +2076,14 @@ static void rna_def_bonecollection(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, nullptr);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "is_local_override", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flags", BONE_COLLECTION_OVERRIDE_LIBRARY_LOCAL);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Is Local Override",
|
||||
"This collection was added via a library override in the current blend file");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "Bone");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
|
|
Loading…
Reference in New Issue