Anim: Add bone collections to the outliner

Add bone collections to the outliner, underneath the Armature.

This basically follows the same approach as the bone groups (which were
removed from the outliner in the previous commit).
This commit is contained in:
Sybren A. Stüvel 2023-09-18 12:10:53 +02:00
parent d7e9497a06
commit c6b553d57c
10 changed files with 152 additions and 0 deletions

View File

@ -49,6 +49,7 @@ set(SRC
tree/tree_element.cc
tree/tree_element_anim_data.cc
tree/tree_element_bone.cc
tree/tree_element_bone_collection.cc
tree/tree_element_collection.cc
tree/tree_element_constraint.cc
tree/tree_element_defgroup.cc
@ -91,6 +92,7 @@ set(SRC
tree/tree_element.hh
tree/tree_element_anim_data.hh
tree/tree_element_bone.hh
tree/tree_element_bone_collection.hh
tree/tree_element_collection.hh
tree/tree_element_constraint.hh
tree/tree_element_defgroup.hh

View File

@ -45,6 +45,8 @@
#include "BKE_particle.h"
#include "BKE_report.h"
#include "ANIM_bone_collections.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@ -880,6 +882,17 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE);
break;
}
case TSE_BONE_COLLECTION: {
bArmature *arm = (bArmature *)tselem->id;
BoneCollection *bcoll = static_cast<BoneCollection *>(te->directdata);
ANIM_armature_bonecoll_name_set(arm, bcoll, bcoll->name);
WM_msg_publish_rna_prop(mbus, &arm->id, bcoll, BoneCollection, name);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_COLLECTION, arm);
DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
break;
}
}
}
tselem->flag &= ~TSE_TEXTBUT;
@ -2798,6 +2811,8 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case TSE_R_LAYER:
data.icon = ICON_RENDER_RESULT;
break;
case TSE_BONE_COLLECTION_BASE:
case TSE_BONE_COLLECTION:
data.icon = ICON_GROUP_BONE;
break;
case TSE_SEQUENCE: {
@ -3179,6 +3194,7 @@ static void outliner_draw_iconrow(bContext *C,
TSE_BONE,
TSE_EBONE,
TSE_POSE_CHANNEL,
TSE_BONE_COLLECTION,
TSE_DEFGROUP))
{
outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1);

View File

@ -322,6 +322,7 @@ static void do_item_rename(ARegion *region,
TSE_SCENE_COLLECTION_BASE,
TSE_VIEW_COLLECTION_BASE,
TSE_LIBRARY_OVERRIDE_BASE,
TSE_BONE_COLLECTION_BASE,
TSE_RNA_STRUCT,
TSE_RNA_PROPERTY,
TSE_RNA_ARRAY_ELEM,

View File

@ -506,6 +506,16 @@ static void tree_element_grease_pencil_layer_activate(bContext *C,
}
}
static void tree_element_bonecollection_activate(bContext *C,
TreeElement *te,
TreeStoreElem *tselem)
{
bArmature *arm = reinterpret_cast<bArmature *>(tselem->id);
BoneCollection *bcoll = reinterpret_cast<BoneCollection *>(te->directdata);
ANIM_armature_bonecoll_active_set(arm, bcoll);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_COLLECTION, arm);
}
static void tree_element_posechannel_activate(bContext *C,
const Scene *scene,
ViewLayer *view_layer,
@ -854,6 +864,8 @@ void tree_element_type_active_set(bContext *C,
case TSE_R_LAYER:
tree_element_viewlayer_activate(C, te);
break;
case TSE_BONE_COLLECTION:
tree_element_bonecollection_activate(C, te, tselem);
break;
case TSE_SEQUENCE:
tree_element_sequence_activate(C, tvc->scene, te, set);
@ -980,6 +992,18 @@ static eOLDrawState tree_element_viewlayer_state_get(const bContext *C, const Tr
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_bone_collection_state_get(const TreeElement *te,
const TreeStoreElem *tselem)
{
const bArmature *arm = reinterpret_cast<const bArmature *>(tselem->id);
const BoneCollection *bcoll = reinterpret_cast<const BoneCollection *>(te->directdata);
if (arm->runtime.active_collection == bcoll) {
return OL_DRAWSEL_ACTIVE;
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_sequence_state_get(const Scene *scene, const TreeElement *te)
{
const TreeElementSequence *te_seq = tree_element_cast<TreeElementSequence>(te);
@ -1168,6 +1192,8 @@ eOLDrawState tree_element_type_active_state_get(const bContext *C,
return tree_element_master_collection_state_get(C);
case TSE_LAYER_COLLECTION:
return tree_element_layer_collection_state_get(C, te);
case TSE_BONE_COLLECTION:
return tree_element_bone_collection_state_get(te, tselem);
}
return OL_DRAWSEL_NONE;
}
@ -1373,6 +1399,14 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
ptr = RNA_id_pointer_create(tselem->id);
context = BCONTEXT_DATA;
break;
case TSE_BONE_COLLECTION_BASE:
ptr = RNA_pointer_create(tselem->id, &RNA_Armature, tselem->id);
context = BCONTEXT_DATA;
break;
case TSE_BONE_COLLECTION:
ptr = RNA_pointer_create(tselem->id, &RNA_BoneCollection, te->directdata);
context = BCONTEXT_DATA;
break;
}
}

View File

@ -334,6 +334,9 @@ TreeElement *AbstractTreeDisplay::add_element(ListBase *lb,
else if (ELEM(type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
/* pass */
}
else if (ELEM(type, TSE_BONE_COLLECTION, TSE_BONE_COLLECTION_BASE)) {
/* pass */
}
else if (ELEM(type, TSE_R_LAYER, TSE_R_LAYER_BASE)) {
/* pass */
}

View File

@ -21,6 +21,7 @@
#include "tree_display.hh"
#include "tree_element_anim_data.hh"
#include "tree_element_bone.hh"
#include "tree_element_bone_collection.hh"
#include "tree_element_collection.hh"
#include "tree_element_constraint.hh"
#include "tree_element_defgroup.hh"
@ -191,6 +192,14 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::create_from_type(const
case TSE_LAYER_COLLECTION:
return std::make_unique<TreeElementLayerCollection>(
legacy_te, *static_cast<LayerCollection *>(create_data));
case TSE_BONE_COLLECTION_BASE:
return std::make_unique<TreeElementBoneCollectionBase>(
legacy_te, *reinterpret_cast<bArmature *>(owner_id));
case TSE_BONE_COLLECTION:
return std::make_unique<TreeElementBoneCollection>(
legacy_te, *static_cast<BoneCollection *>(create_data));
default:
break;
}

View File

@ -0,0 +1,48 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#include "DNA_action_types.h"
#include "DNA_object_types.h"
#include "DNA_outliner_types.h"
#include "BLI_listbase.h"
#include "BLT_translation.h"
#include "../outliner_intern.hh"
#include "tree_element_bone_collection.hh"
namespace blender::ed::outliner {
TreeElementBoneCollectionBase::TreeElementBoneCollectionBase(TreeElement &legacy_te,
bArmature &armature)
: AbstractTreeElement(legacy_te), armature_(armature)
{
BLI_assert(legacy_te.store_elem->type == TSE_BONE_COLLECTION_BASE);
legacy_te.name = IFACE_("Bone Collections");
}
void TreeElementBoneCollectionBase::expand(SpaceOutliner & /*space_outliner*/) const
{
int index;
LISTBASE_FOREACH_INDEX (BoneCollection *, bcoll, &armature_.collections, index) {
add_element(
&legacy_te_.subtree, &armature_.id, bcoll, &legacy_te_, TSE_BONE_COLLECTION, index);
}
}
TreeElementBoneCollection::TreeElementBoneCollection(TreeElement &legacy_te, BoneCollection &bcoll)
: AbstractTreeElement(legacy_te), bcoll_(bcoll)
{
BLI_assert(legacy_te.store_elem->type == TSE_BONE_COLLECTION);
legacy_te.name = bcoll_.name;
legacy_te.directdata = &bcoll_;
}
} // namespace blender::ed::outliner

View File

@ -0,0 +1,33 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#pragma once
#include "tree_element.hh"
struct bArmature;
struct BoneCollection;
namespace blender::ed::outliner {
class TreeElementBoneCollectionBase final : public AbstractTreeElement {
bArmature &armature_;
public:
TreeElementBoneCollectionBase(TreeElement &legacy_te, bArmature &armature);
void expand(SpaceOutliner &) const override;
};
class TreeElementBoneCollection final : public AbstractTreeElement {
BoneCollection &bcoll_;
public:
TreeElementBoneCollection(TreeElement &legacy_te, BoneCollection &bcoll);
};
} // namespace blender::ed::outliner

View File

@ -47,6 +47,10 @@ void TreeElementIDArmature::expand(SpaceOutliner &space_outliner) const
expand_bones(space_outliner);
}
}
if (!BLI_listbase_is_empty(&arm_.collections)) {
add_element(&legacy_te_.subtree, &arm_.id, nullptr, &legacy_te_, TSE_BONE_COLLECTION_BASE, 0);
}
}
void TreeElementIDArmature::expand_edit_bones() const

View File

@ -89,6 +89,8 @@ typedef enum eTreeStoreElemType {
/* TSE_LINKED_MAT = 22, */
/* NOTE: is used for light group. */
/* TSE_LINKED_LAMP = 23, */
TSE_BONE_COLLECTION_BASE = 24,
TSE_BONE_COLLECTION = 25,
TSE_SEQUENCE = 26, /* NO ID */
TSE_SEQ_STRIP = 27, /* NO ID */
TSE_SEQUENCE_DUP = 28, /* NO ID */