Files
test/source/blender/animrig/intern/bone_collections_test.cc
Sybren A. Stüvel 42083c8357 Refactor: move ANIM_bone_collections.h into the .hh file
Move the contents of `ANIM_bone_collections.h` into its C++
`ANIM_bone_collections.hh` sibling. Blender is C++ by now that we can do
without the C header.

No functional changes.
2023-12-05 15:10:27 +01:00

265 lines
9.6 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string.h"
#include "BLT_translation.h"
#include "ANIM_bone_collections.hh"
#include "testing/testing.h"
namespace blender::animrig::tests {
TEST(ANIM_bone_collections, bonecoll_new_free)
{
BoneCollection *bcoll = ANIM_bonecoll_new("some name");
EXPECT_NE(nullptr, bcoll);
EXPECT_EQ("some name", std::string(bcoll->name));
EXPECT_TRUE(BLI_listbase_is_empty(&bcoll->bones));
EXPECT_EQ(BONE_COLLECTION_VISIBLE | BONE_COLLECTION_SELECTABLE, bcoll->flags);
ANIM_bonecoll_free(bcoll);
}
TEST(ANIM_bone_collections, bonecoll_default_name)
{
{
BoneCollection *bcoll = ANIM_bonecoll_new("");
EXPECT_EQ(DATA_("Bones"), std::string(bcoll->name));
ANIM_bonecoll_free(bcoll);
}
{
BoneCollection *bcoll = ANIM_bonecoll_new(nullptr);
EXPECT_EQ(DATA_("Bones"), std::string(bcoll->name));
ANIM_bonecoll_free(bcoll);
}
}
class ANIM_armature_bone_collections : public testing::Test {
protected:
bArmature arm;
Bone bone1, bone2, bone3;
void SetUp() override
{
memset(&arm, 0, sizeof(arm));
memset(&bone1, 0, sizeof(Bone));
memset(&bone2, 0, sizeof(Bone));
memset(&bone3, 0, sizeof(Bone));
STRNCPY(bone1.name, "bone1");
STRNCPY(bone2.name, "bone2");
STRNCPY(bone3.name, "bone3");
BLI_addtail(&arm.bonebase, &bone1); /* bone1 is root bone. */
BLI_addtail(&arm.bonebase, &bone2); /* bone2 is root bone. */
BLI_addtail(&bone2.childbase, &bone3); /* bone3 has bone2 as parent. */
BKE_armature_bone_hash_make(&arm);
}
void TearDown() override
{
while (arm.collection_array_num > 0) {
ANIM_armature_bonecoll_remove_from_index(&arm, arm.collection_array_num - 1);
}
if (arm.collection_array) {
MEM_freeN(arm.collection_array);
}
BKE_armature_bone_hash_free(&arm);
}
};
TEST_F(ANIM_armature_bone_collections, armature_owned_collections)
{
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "collection");
EXPECT_EQ(std::string("collection"), std::string(bcoll1->name));
EXPECT_EQ(std::string("collection.001"), std::string(bcoll2->name));
ANIM_armature_bonecoll_remove(&arm, bcoll1);
ANIM_armature_bonecoll_remove(&arm, bcoll2);
}
TEST_F(ANIM_armature_bone_collections, bones_assign_unassign)
{
BoneCollection *bcoll = ANIM_armature_bonecoll_new(&arm, "collection");
ANIM_armature_bonecoll_assign(bcoll, &bone1);
ANIM_armature_bonecoll_assign(bcoll, &bone2);
ASSERT_EQ(2, BLI_listbase_count(&bcoll->bones)) << "expecting two bones in collection";
EXPECT_EQ(&bone1, static_cast<BoneCollectionMember *>(BLI_findlink(&bcoll->bones, 0))->bone);
EXPECT_EQ(&bone2, static_cast<BoneCollectionMember *>(BLI_findlink(&bcoll->bones, 1))->bone);
EXPECT_EQ(bcoll, static_cast<BoneCollectionReference *>(bone1.runtime.collections.first)->bcoll)
<< "expecting back-reference to collection in bone1 runtime data";
EXPECT_EQ(bcoll, static_cast<BoneCollectionReference *>(bone2.runtime.collections.first)->bcoll)
<< "expecting back-reference to collection in bone2 runtime data";
ANIM_armature_bonecoll_unassign(bcoll, &bone1);
ANIM_armature_bonecoll_unassign(bcoll, &bone2);
EXPECT_EQ(0, BLI_listbase_count(&bone1.runtime.collections))
<< "expecting back-references in bone1 runtime data to be cleared when unassigned";
EXPECT_EQ(0, BLI_listbase_count(&bone2.runtime.collections))
<< "expecting back-references in bone2 runtime data to be cleared when unassigned";
ANIM_armature_bonecoll_remove(&arm, bcoll);
}
TEST_F(ANIM_armature_bone_collections, bones_assign_remove)
{
BoneCollection *bcoll = ANIM_armature_bonecoll_new(&arm, "collection");
ANIM_armature_bonecoll_assign(bcoll, &bone1);
ANIM_armature_bonecoll_assign(bcoll, &bone2);
ANIM_armature_bonecoll_remove(&arm, bcoll);
EXPECT_EQ(0, BLI_listbase_count(&bone1.runtime.collections))
<< "expecting back-references in bone1 runtime data to be cleared when the collection is "
"removed";
EXPECT_EQ(0, BLI_listbase_count(&bone2.runtime.collections))
<< "expecting back-references in bone2 runtime data to be cleared when the collection is "
"removed";
}
TEST_F(ANIM_armature_bone_collections, active_set_clear_by_pointer)
{
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "Bones 1");
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "Bones 2");
BoneCollection *bcoll3 = ANIM_bonecoll_new("Alien Bones");
ANIM_armature_bonecoll_active_set(&arm, bcoll1);
EXPECT_EQ(0, arm.runtime.active_collection_index);
EXPECT_EQ(bcoll1, arm.runtime.active_collection);
EXPECT_STREQ(bcoll1->name, arm.active_collection_name);
ANIM_armature_bonecoll_active_set(&arm, nullptr);
EXPECT_EQ(-1, arm.runtime.active_collection_index);
EXPECT_EQ(nullptr, arm.runtime.active_collection);
EXPECT_STREQ("", arm.active_collection_name);
ANIM_armature_bonecoll_active_set(&arm, bcoll2);
EXPECT_EQ(1, arm.runtime.active_collection_index);
EXPECT_EQ(bcoll2, arm.runtime.active_collection);
EXPECT_STREQ(bcoll2->name, arm.active_collection_name);
ANIM_armature_bonecoll_active_set(&arm, bcoll3);
EXPECT_EQ(-1, arm.runtime.active_collection_index);
EXPECT_EQ(nullptr, arm.runtime.active_collection);
EXPECT_STREQ("", arm.active_collection_name);
ANIM_bonecoll_free(bcoll3);
}
TEST_F(ANIM_armature_bone_collections, active_set_clear_by_index)
{
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "Bones 1");
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "Bones 2");
ANIM_armature_bonecoll_active_index_set(&arm, 0);
EXPECT_EQ(0, arm.runtime.active_collection_index);
EXPECT_EQ(bcoll1, arm.runtime.active_collection);
EXPECT_STREQ(bcoll1->name, arm.active_collection_name);
ANIM_armature_bonecoll_active_index_set(&arm, -1);
EXPECT_EQ(-1, arm.runtime.active_collection_index);
EXPECT_EQ(nullptr, arm.runtime.active_collection);
EXPECT_STREQ("", arm.active_collection_name);
ANIM_armature_bonecoll_active_index_set(&arm, 1);
EXPECT_EQ(1, arm.runtime.active_collection_index);
EXPECT_EQ(bcoll2, arm.runtime.active_collection);
EXPECT_STREQ(bcoll2->name, arm.active_collection_name);
ANIM_armature_bonecoll_active_index_set(&arm, 47);
EXPECT_EQ(-1, arm.runtime.active_collection_index);
EXPECT_EQ(nullptr, arm.runtime.active_collection);
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";
}
TEST_F(ANIM_armature_bone_collections, bcoll_insert_copy_after)
{
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll3 = ANIM_armature_bonecoll_new(&arm, "collection");
EXPECT_EQ(arm.collection_array[0], bcoll1);
EXPECT_EQ(arm.collection_array[1], bcoll2);
EXPECT_EQ(arm.collection_array[2], bcoll3);
BoneCollection *bcoll4 = ANIM_armature_bonecoll_insert_copy_after(&arm, bcoll2, bcoll2);
EXPECT_EQ(arm.collection_array[0], bcoll1);
EXPECT_EQ(arm.collection_array[1], bcoll2);
EXPECT_EQ(arm.collection_array[2], bcoll4);
EXPECT_EQ(arm.collection_array[3], bcoll3);
}
TEST_F(ANIM_armature_bone_collections, bcoll_move_to_index)
{
BoneCollection *bcoll1 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll2 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll3 = ANIM_armature_bonecoll_new(&arm, "collection");
BoneCollection *bcoll4 = ANIM_armature_bonecoll_new(&arm, "collection");
EXPECT_EQ(arm.collection_array[0], bcoll1);
EXPECT_EQ(arm.collection_array[1], bcoll2);
EXPECT_EQ(arm.collection_array[2], bcoll3);
EXPECT_EQ(arm.collection_array[3], bcoll4);
ANIM_armature_bonecoll_move_to_index(&arm, 2, 1);
EXPECT_EQ(arm.collection_array[0], bcoll1);
EXPECT_EQ(arm.collection_array[1], bcoll3);
EXPECT_EQ(arm.collection_array[2], bcoll2);
EXPECT_EQ(arm.collection_array[3], bcoll4);
ANIM_armature_bonecoll_move_to_index(&arm, 0, 3);
EXPECT_EQ(arm.collection_array[0], bcoll3);
EXPECT_EQ(arm.collection_array[1], bcoll2);
EXPECT_EQ(arm.collection_array[2], bcoll4);
EXPECT_EQ(arm.collection_array[3], bcoll1);
}
} // namespace blender::animrig::tests