GPv3: Outliner support #111105

Merged
Falk David merged 7 commits from filedescriptor/blender:gpv3-outliner-support into main 2023-08-14 17:40:27 +02:00
12 changed files with 348 additions and 8 deletions

View File

@ -55,11 +55,13 @@ set(SRC
tree/tree_element_edit_bone.cc
tree/tree_element_gpencil_effect.cc
tree/tree_element_gpencil_layer.cc
tree/tree_element_grease_pencil_node.cc
tree/tree_element_id.cc
tree/tree_element_id_armature.cc
tree/tree_element_id_collection.cc
tree/tree_element_id_curve.cc
tree/tree_element_id_gpencil_legacy.cc
tree/tree_element_id_grease_pencil.cc
tree/tree_element_id_library.cc
tree/tree_element_id_linestyle.cc
tree/tree_element_id_mesh.cc
@ -90,12 +92,14 @@ set(SRC
tree/tree_element_driver.hh
tree/tree_element_edit_bone.hh
tree/tree_element_gpencil_layer.hh
tree/tree_element_grease_pencil_node.hh
tree/tree_element_id.hh
tree/tree_element_id_armature.hh
tree/tree_element_id_collection.hh
tree/tree_element_id_curve.hh
tree/tree_element_gpencil_effect.hh
tree/tree_element_id_gpencil_legacy.hh
tree/tree_element_id_grease_pencil.hh
tree/tree_element_id_library.hh
tree/tree_element_id_linestyle.hh
tree/tree_element_id_mesh.hh

View File

@ -31,6 +31,7 @@
#include "BKE_curve.h"
#include "BKE_deform.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_grease_pencil.hh"
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@ -69,6 +70,7 @@
#include "outliner_intern.hh"
#include "tree/tree_display.hh"
#include "tree/tree_element.hh"
#include "tree/tree_element_grease_pencil_node.hh"
#include "tree/tree_element_id.hh"
#include "tree/tree_element_overrides.hh"
#include "tree/tree_element_rna.hh"
@ -850,6 +852,26 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
DEG_id_tag_update(tselem->id, ID_RECALC_COPY_ON_WRITE);
break;
}
case TSE_GREASE_PENCIL_NODE: {
GreasePencil &grease_pencil = *(GreasePencil *)tselem->id;
bke::greasepencil::TreeNode &node =
tree_element_cast<TreeElementGreasePencilNode>(te)->node();
/* The node already has the new name set. To properly rename the node, we need to first
* store the new name, restore the old name in the node, and then call the rename
* function. */
std::string new_name(node.name);
node.name = oldname;
if (node.is_group()) {
grease_pencil.rename_group(node.as_group_for_write(), new_name);
}
else if (node.is_layer()) {
grease_pencil.rename_layer(node.as_layer_for_write(), new_name);
}
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_ID | NA_RENAME, nullptr);
break;
}
case TSE_R_LAYER: {
Scene *scene = (Scene *)tselem->id;
ViewLayer *view_layer = static_cast<ViewLayer *>(te->directdata);
@ -1489,6 +1511,43 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
}
else if (tselem->type == TSE_GREASE_PENCIL_NODE) {
bke::greasepencil::TreeNode &node =
tree_element_cast<TreeElementGreasePencilNode>(te)->node();
PointerRNA ptr;
PropertyRNA *hide_prop;
if (node.is_layer()) {
RNA_pointer_create(tselem->id, &RNA_GreasePencilLayer, &node, &ptr);
hide_prop = RNA_struct_type_find_property(&RNA_GreasePencilLayer, "hide");
}
else if (node.is_group()) {
RNA_pointer_create(tselem->id, &RNA_GreasePencilLayerGroup, &node, &ptr);
hide_prop = RNA_struct_type_find_property(&RNA_GreasePencilLayerGroup, "hide");
}
if (space_outliner->show_restrict_flags & SO_RESTRICT_HIDE) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
int(region->v2d.cur.xmax - restrict_offsets.hide),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
&ptr,
hide_prop,
-1,
0,
0,
-1,
-1,
nullptr);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
if (!node.parent_group()->is_visible()) {
UI_but_flag_enable(bt, UI_BUT_INACTIVE);
}
}
}
else if (outliner_is_collection_tree_element(te)) {
PointerRNA collection_ptr;
PointerRNA layer_collection_ptr;
@ -2468,6 +2527,7 @@ static BIFIconID tree_element_get_icon_from_id(const ID *id)
}
case ID_LS:
return ICON_LINE_DATA;
case ID_GP:
case ID_GD_LEGACY:
return ICON_OUTLINER_DATA_GREASEPENCIL;
case ID_LP: {
@ -2854,6 +2914,17 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.icon = ICON_OUTLINER_DATA_GP_LAYER;
break;
}
case TSE_GREASE_PENCIL_NODE: {
bke::greasepencil::TreeNode &node =
tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (node.is_layer()) {
data.icon = ICON_OUTLINER_DATA_GP_LAYER;
}
else if (node.is_group()) {
data.icon = ICON_FILE_FOLDER;
}
break;
}
case TSE_GPENCIL_EFFECT_BASE:
case TSE_GPENCIL_EFFECT:
data.drag_id = tselem->id;
@ -3039,8 +3110,19 @@ int tree_element_id_type_to_index(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
const int id_index = (tselem->type == TSE_SOME_ID) ? BKE_idtype_idcode_to_index(te->idcode) :
INDEX_ID_GR;
int id_index = 0;
if (tselem->type == TSE_SOME_ID) {
id_index = BKE_idtype_idcode_to_index(te->idcode);
}
else if (tselem->type == TSE_GREASE_PENCIL_NODE) {
/* Use the index of the grease pencil ID for the grease pencil tree nodes (which are not IDs).
* All the Grease Pencil layer tree stats are stored in this index in #MergedIconRow. */
id_index = INDEX_ID_GP;
}
else {
id_index = INDEX_ID_GR;
}
if (id_index < INDEX_ID_OB) {
return id_index;
}
@ -3069,6 +3151,7 @@ static void outliner_draw_iconrow(bContext *C,
int ys,
float alpha_fac,
bool in_bone_hierarchy,
const bool is_grease_pencil_node_hierarchy,
MergedIconRow *merged)
{
eOLDrawState active = OL_DRAWSEL_NONE;
@ -3082,7 +3165,12 @@ static void outliner_draw_iconrow(bContext *C,
* an they are at the root level of a collapsed subtree (e.g. not "hidden" in a collapsed
* collection). */
const bool is_bone = ELEM(tselem->type, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL);
/* The Grease Pencil layer tree is a hierarchy where we merge and count the total number of
* layers in a node. We merge the counts for all the layers and skip counting nodes that are
* layer groups (for less visual clutter in the outliner). */
const bool is_grease_pencil_node = (tselem->type == TSE_GREASE_PENCIL_NODE);
if ((level < 1) || ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) ||
(is_grease_pencil_node_hierarchy && is_grease_pencil_node) ||
(in_bone_hierarchy && is_bone))
{
/* active blocks get white circle */
@ -3107,6 +3195,7 @@ static void outliner_draw_iconrow(bContext *C,
TSE_LAYER_COLLECTION,
TSE_R_LAYER,
TSE_GP_LAYER,
TSE_GREASE_PENCIL_NODE,
TSE_LIBRARY_OVERRIDE_BASE,
TSE_LIBRARY_OVERRIDE,
TSE_LIBRARY_OVERRIDE_OPERATION,
@ -3118,6 +3207,13 @@ static void outliner_draw_iconrow(bContext *C,
{
outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1);
}
else if (tselem->type == TSE_GREASE_PENCIL_NODE &&
tree_element_cast<TreeElementGreasePencilNode>(te)->node().is_group())
{
/* Grease Pencil layer groups are tree nodes, but they shouldn't be counted. We only want
* to keep track of the nodes that are layers and show the total number of layers in a
* node. Adding the count of groups would add a lot of clutter. */
}
else {
const int index = tree_element_id_type_to_index(te);
merged->num_elements[index]++;
@ -3129,12 +3225,17 @@ static void outliner_draw_iconrow(bContext *C,
}
/* TSE_R_LAYER tree element always has same amount of branches, so don't draw. */
/* Also only recurse into bone hierarchies if a direct child of the collapsed element to merge
* into. */
/* Also only recurse into bone hierarchies if a direct child of the collapsed element to
* merge into. */
const bool is_root_level_bone = is_bone && (level == 0);
in_bone_hierarchy |= is_root_level_bone;
/* Recurse into the grease pencil layer tree if we already are in the hierarchy or if we're at
* the root level and find a grease pencil node. */
const bool in_grease_pencil_node_hierarchy = is_grease_pencil_node_hierarchy ||
(is_grease_pencil_node && level == 0);
if (!ELEM(tselem->type, TSE_R_LAYER, TSE_BONE, TSE_EBONE, TSE_POSE_CHANNEL) ||
in_bone_hierarchy) {
in_bone_hierarchy || in_grease_pencil_node_hierarchy)
{
outliner_draw_iconrow(C,
block,
fstyle,
@ -3147,6 +3248,7 @@ static void outliner_draw_iconrow(bContext *C,
ys,
alpha_fac,
in_bone_hierarchy,
in_grease_pencil_node_hierarchy,
merged);
}
}
@ -3217,6 +3319,16 @@ static bool element_should_draw_faded(const TreeViewContext *tvc,
const bool is_excluded = layer_collection->flag & LAYER_COLLECTION_EXCLUDE;
return !is_visible || is_excluded;
}
case TSE_GREASE_PENCIL_NODE: {
bke::greasepencil::TreeNode &node =
tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (node.is_layer()) {
return !node.as_layer().is_visible();
}
if (node.is_group()) {
return !node.as_group().is_visible();
}
}
}
if (te->flag & TE_CHILD_NOT_IN_COLLECTION) {
@ -3412,6 +3524,7 @@ static void outliner_draw_tree_element(bContext *C,
*starty,
alpha_fac,
false,
false,
&merged);
GPU_blend(GPU_BLEND_NONE);
@ -3517,6 +3630,14 @@ static void outliner_draw_hierarchy_lines_recursive(uint pos,
y = *starty;
}
}
else if (tselem->type == TSE_GREASE_PENCIL_NODE) {
bke::greasepencil::TreeNode &node =
tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (node.is_group() && node.as_group().num_direct_nodes() > 0) {
draw_hierarchy_line = true;
y = *starty;
}
}
outliner_draw_hierarchy_lines_recursive(
pos, space_outliner, &te->subtree, startx + UI_UNIT_X, col, draw_grayed_out, starty);

View File

@ -31,6 +31,7 @@
#include "BKE_deform.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_gpencil_modifier_legacy.h"
#include "BKE_grease_pencil.hh"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@ -68,6 +69,7 @@
#include "outliner_intern.hh"
#include "tree/tree_display.hh"
#include "tree/tree_element_grease_pencil_node.hh"
#include "tree/tree_element_seq.hh"
#include "tree/tree_iterator.hh"
@ -484,6 +486,19 @@ static void tree_element_gplayer_activate(bContext *C, TreeElement *te, TreeStor
}
}
static void tree_element_grease_pencil_layer_activate(bContext *C,
TreeElement *te,
TreeStoreElem *tselem)
{
GreasePencil &grease_pencil = *(GreasePencil *)tselem->id;
bke::greasepencil::TreeNode &node = tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (node.is_layer()) {
grease_pencil.set_active_layer(&node.as_layer());
DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
}
}
static void tree_element_posegroup_activate(bContext *C, TreeElement *te, TreeStoreElem *tselem)
{
Object *ob = (Object *)tselem->id;
@ -853,6 +868,9 @@ void tree_element_type_active_set(bContext *C,
case TSE_GP_LAYER:
tree_element_gplayer_activate(C, te, tselem);
break;
case TSE_GREASE_PENCIL_NODE:
tree_element_grease_pencil_layer_activate(C, te, tselem);
break;
case TSE_VIEW_COLLECTION_BASE:
tree_element_master_collection_activate(C);
break;
@ -1013,6 +1031,16 @@ static eOLDrawState tree_element_gplayer_state_get(const TreeElement *te)
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_grease_pencil_node_state_get(const TreeElement *te)
{
GreasePencil &grease_pencil = *(GreasePencil *)te->store_elem->id;
bke::greasepencil::TreeNode &node = tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (node.is_layer() && grease_pencil.is_layer_active(&node.as_layer())) {
return OL_DRAWSEL_NORMAL;
}
return OL_DRAWSEL_NONE;
}
static eOLDrawState tree_element_master_collection_state_get(const bContext *C)
{
const ViewLayer *view_layer = CTX_data_view_layer(C);
@ -1156,6 +1184,8 @@ eOLDrawState tree_element_type_active_state_get(const bContext *C,
return tree_element_sequence_dup_state_get(te);
case TSE_GP_LAYER:
return tree_element_gplayer_state_get(te);
case TSE_GREASE_PENCIL_NODE:
return tree_element_grease_pencil_node_state_get(te);
case TSE_VIEW_COLLECTION_BASE:
return tree_element_master_collection_state_get(C);
case TSE_LAYER_COLLECTION:
@ -1370,6 +1400,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
break;
}
case TSE_GP_LAYER:
case TSE_GREASE_PENCIL_NODE:
RNA_id_pointer_create(tselem->id, &ptr);
context = BCONTEXT_DATA;
break;

View File

@ -45,6 +45,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_grease_pencil.hh"
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@ -86,6 +87,7 @@
#include "SEQ_sequencer.h"
#include "outliner_intern.hh"
#include "tree/tree_element_grease_pencil_node.hh"
#include "tree/tree_element_rna.hh"
#include "tree/tree_element_seq.hh"
#include "tree/tree_iterator.hh"
@ -2207,6 +2209,27 @@ static void gpencil_layer_fn(int event,
}
}
static void grease_pencil_node_fn(int event,
TreeElement *te,
TreeStoreElem * /*tselem*/,
void * /*arg*/)
{
bke::greasepencil::TreeNode &node = tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (event == OL_DOP_SELECT) {
node.flag |= GP_LAYER_TREE_NODE_SELECT;
}
else if (event == OL_DOP_DESELECT) {
node.flag &= ~GP_LAYER_TREE_NODE_SELECT;
}
else if (event == OL_DOP_HIDE) {
node.flag |= GP_LAYER_TREE_NODE_HIDE;
}
else if (event == OL_DOP_UNHIDE) {
node.flag &= ~GP_LAYER_TREE_NODE_HIDE;
}
}
static void data_select_linked_fn(int event,
TreeElement *te,
TreeStoreElem * /*tselem*/,
@ -3529,6 +3552,12 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
break;
}
case TSE_GREASE_PENCIL_NODE: {
outliner_do_data_operation(space_outliner, datalevel, event, grease_pencil_node_fn, nullptr);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, nullptr);
ED_undo_push(C, "Grease Pencil Node operation");
break;
}
case TSE_RNA_STRUCT:
if (event == OL_DOP_SELECT_LINKED) {
outliner_do_data_operation(space_outliner, datalevel, event, data_select_linked_fn, C);

View File

@ -237,6 +237,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* idv is the layer itself */
id = TREESTORE(parent)->id;
}
else if (type == TSE_GREASE_PENCIL_NODE) {
/* idv is the layer itself */
id = TREESTORE(parent)->id;
}
else if (ELEM(type, TSE_GENERIC_LABEL)) {
id = nullptr;
}
@ -310,7 +314,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
else if (ELEM(type, TSE_ANIM_DATA, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE)) {
/* pass */
}
else if (type == TSE_GP_LAYER) {
else if (ELEM(type, TSE_GP_LAYER, TSE_GREASE_PENCIL_NODE)) {
/* pass */
}
else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
@ -399,7 +403,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
TSE_POSEGRP,
TSE_POSEGRP_BASE,
TSE_R_LAYER,
TSE_R_LAYER_BASE))
TSE_R_LAYER_BASE,
TSE_GREASE_PENCIL_NODE))
{
BLI_assert_msg(false, "Element type should already use new AbstractTreeElement design");
}

View File

@ -25,6 +25,7 @@
#include "tree_element_edit_bone.hh"
#include "tree_element_gpencil_effect.hh"
#include "tree_element_gpencil_layer.hh"
#include "tree_element_grease_pencil_node.hh"
#include "tree_element_id.hh"
#include "tree_element_label.hh"
#include "tree_element_nla.hh"
@ -80,6 +81,9 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
return std::make_unique<TreeElementNLAAction>(legacy_te, *static_cast<bAction *>(idv));
case TSE_GP_LAYER:
return std::make_unique<TreeElementGPencilLayer>(legacy_te, *static_cast<bGPDlayer *>(idv));
case TSE_GREASE_PENCIL_NODE:
return std::make_unique<TreeElementGreasePencilNode>(
legacy_te, *static_cast<bke::greasepencil::TreeNode *>(idv));
case TSE_R_LAYER_BASE:
return std::make_unique<TreeElementViewLayerBase>(legacy_te, *static_cast<Scene *>(idv));
case TSE_R_LAYER: {

View File

@ -0,0 +1,43 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#include "BKE_grease_pencil.hh"
#include "DNA_outliner_types.h"
#include "../outliner_intern.hh"
#include "tree_element_grease_pencil_node.hh"
namespace blender::ed::outliner {
TreeElementGreasePencilNode::TreeElementGreasePencilNode(TreeElement &legacy_te,
bke::greasepencil::TreeNode &node)
: AbstractTreeElement(legacy_te), node_(node)
{
BLI_assert(legacy_te.store_elem->type == TSE_GREASE_PENCIL_NODE);
legacy_te.name = node.name;
}
filedescriptor marked this conversation as resolved Outdated

Let's avoid usages of directdata. All necessary data can be stored directly within TreeElementGreasePencilNode. Code that needs access to it can use tree_element_cast() to get this from the TreeElement, and then use accessors to type-safely get the data.

Let's avoid usages of `directdata`. All necessary data can be stored directly within `TreeElementGreasePencilNode`. Code that needs access to it can use `tree_element_cast()` to get this from the `TreeElement`, and then use accessors to type-safely get the data.
void TreeElementGreasePencilNode::expand(SpaceOutliner &space_outliner) const
{
if (!node_.is_group()) {
return;
}
LISTBASE_FOREACH_BACKWARD (GreasePencilLayerTreeNode *, child, &node_.as_group().children) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_GREASE_PENCIL_NODE, 0);
}
}
blender::bke::greasepencil::TreeNode &TreeElementGreasePencilNode::node() const
{
return node_;
filedescriptor marked this conversation as resolved Outdated

I don't see a reason to use the expand option here. It exists because sometimes we just want to display some objects or collections, without expanding their entire hierarchy. It's mostly a performance workaround. Here there just isn't anything to expand, so the expand() function won't add elements anyway.

I don't see a reason to use the `expand` option here. It exists because sometimes we just want to display some objects or collections, without expanding their entire hierarchy. It's mostly a performance workaround. Here there just isn't anything to expand, so the `expand()` function won't add elements anyway.

I tried setting this to false but then I cannot expand groups with a single child. They show up as if they had no child at all.

I tried setting this to `false` but then I cannot expand groups with a single child. They show up as if they had no child at all.

You don't need to set it at all, it has a default parameter value of true.

You don't need to set it at all, it has a default parameter value of `true`.

Ah that explains it, ok.

Ah that explains it, ok.
}
} // namespace blender::ed::outliner

View File

@ -0,0 +1,29 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#pragma once
#include "tree_element.hh"
namespace blender::bke::greasepencil {
class TreeNode;
filedescriptor marked this conversation as resolved Outdated

Should be class, otherwise MSVC won't build.

Should be `class`, otherwise MSVC won't build.
} // namespace blender::bke::greasepencil
namespace blender::ed::outliner {
class TreeElementGreasePencilNode final : public AbstractTreeElement {
blender::bke::greasepencil::TreeNode &node_;
public:
TreeElementGreasePencilNode(TreeElement &legacy_te, blender::bke::greasepencil::TreeNode &node);
void expand(SpaceOutliner &) const override;
blender::bke::greasepencil::TreeNode &node() const;
};
} // namespace blender::ed::outliner

View File

@ -25,6 +25,7 @@
#include "tree_element_id_collection.hh"
#include "tree_element_id_curve.hh"
#include "tree_element_id_gpencil_legacy.hh"
#include "tree_element_id_grease_pencil.hh"
#include "tree_element_id_library.hh"
#include "tree_element_id_linestyle.hh"
#include "tree_element_id_mesh.hh"
@ -61,6 +62,8 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
return std::make_unique<TreeElementIDLineStyle>(legacy_te, (FreestyleLineStyle &)id);
case ID_GD_LEGACY:
return std::make_unique<TreeElementIDGPLegacy>(legacy_te, (bGPdata &)id);
case ID_GP:
return std::make_unique<TreeElementIDGreasePencil>(legacy_te, (GreasePencil &)id);
case ID_GR:
return std::make_unique<TreeElementIDCollection>(legacy_te, (Collection &)id);
case ID_AR:
@ -94,7 +97,6 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
case ID_PAL:
case ID_PC:
case ID_CF:
case ID_GP:
return std::make_unique<TreeElementID>(legacy_te, id);
case ID_IP:
BLI_assert_unreachable();

View File

@ -0,0 +1,42 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#include "BKE_grease_pencil.hh"
#include "DNA_outliner_types.h"
#include "../outliner_intern.hh"
#include "tree_element_id_grease_pencil.hh"
namespace blender::ed::outliner {
TreeElementIDGreasePencil::TreeElementIDGreasePencil(TreeElement &legacy_te,
GreasePencil &grease_pencil)
: TreeElementID(legacy_te, grease_pencil.id), grease_pencil_(grease_pencil)
{
}
void TreeElementIDGreasePencil::expand(SpaceOutliner &space_outliner) const
{
expand_animation_data(space_outliner, grease_pencil_.adt);
expand_layer_tree(space_outliner);
}
void TreeElementIDGreasePencil::expand_layer_tree(SpaceOutliner &space_outliner) const
{
LISTBASE_FOREACH_BACKWARD (
GreasePencilLayerTreeNode *, child, &grease_pencil_.root_group().children)
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_GREASE_PENCIL_NODE, 0);
}
}
} // namespace blender::ed::outliner

View File

@ -0,0 +1,29 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spoutliner
*/
#pragma once
#include "tree_element_id.hh"
struct GreasePencil;
namespace blender::ed::outliner {
class TreeElementIDGreasePencil final : public TreeElementID {
GreasePencil &grease_pencil_;
public:
TreeElementIDGreasePencil(TreeElement &legacy_te, GreasePencil &grease_pencil_);
void expand(SpaceOutliner &) const override;
private:
void expand_layer_tree(SpaceOutliner &) const;
};
} // namespace blender::ed::outliner

View File

@ -117,6 +117,7 @@ typedef enum eTreeStoreElemType {
TSE_LIBRARY_OVERRIDE = 45,
TSE_LIBRARY_OVERRIDE_OPERATION = 46,
TSE_GENERIC_LABEL = 47, /* No ID */
TSE_GREASE_PENCIL_NODE = 48,
filedescriptor marked this conversation as resolved Outdated

The comment says this is not an ID, but TreeStoreElem.id actually points to a valid ID. Checking above, it seems like the ID is needed, so the comment can be removed. Otherwise (if it wouldn't actually point to an ID), TSE_IS_REAL_ID() would have to be updated.

The comment says this is not an ID, but `TreeStoreElem.id` actually points to a valid ID. Checking above, it seems like the ID is needed, so the comment can be removed. Otherwise (if it wouldn't actually point to an ID), `TSE_IS_REAL_ID()` would have to be updated.
} eTreeStoreElemType;
/** Check whether given #TreeStoreElem should have a real ID in #TreeStoreElem.id member. */