From 310ccbdc33ad8fe2e7b31da6cdd82dc68f0b2f49 Mon Sep 17 00:00:00 2001 From: Falk David Date: Mon, 14 Aug 2023 17:40:18 +0200 Subject: [PATCH] GPv3: Initial outliner support This PR adds support for displaying the content of the GPv3 object in the outliner. * Displays the grease pencil data, layers and layer groups. * Data and layer groups have the total layer count displayed next to them. Layer groups also have hierarchy lines. * Active layer is highlighted and can be changed by clicking on a layer. * The visibility of layers and layer groups can be toggled by clicking the eye icon. Note: The icon for layer groups is temporary. Pull Request: https://projects.blender.org/blender/blender/pulls/111105 --- .../editors/space_outliner/CMakeLists.txt | 4 + .../editors/space_outliner/outliner_draw.cc | 131 +++++++++++++++++- .../editors/space_outliner/outliner_select.cc | 31 +++++ .../editors/space_outliner/outliner_tools.cc | 29 ++++ .../editors/space_outliner/outliner_tree.cc | 9 +- .../space_outliner/tree/tree_element.cc | 4 + .../tree/tree_element_grease_pencil_node.cc | 43 ++++++ .../tree/tree_element_grease_pencil_node.hh | 29 ++++ .../space_outliner/tree/tree_element_id.cc | 4 +- .../tree/tree_element_id_grease_pencil.cc | 42 ++++++ .../tree/tree_element_id_grease_pencil.hh | 29 ++++ source/blender/makesdna/DNA_outliner_types.h | 1 + 12 files changed, 348 insertions(+), 8 deletions(-) create mode 100644 source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.cc create mode 100644 source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.hh create mode 100644 source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.cc create mode 100644 source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.hh diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index f8c5b7896cc..70c9d52cb4d 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -56,11 +56,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 @@ -92,12 +94,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 diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index 714cca60c09..ec5ab137d5f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -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" @@ -854,6 +856,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(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(te->directdata); @@ -1493,6 +1515,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(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; @@ -2472,6 +2531,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: { @@ -2858,6 +2918,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(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; @@ -3043,8 +3114,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; } @@ -3073,6 +3155,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; @@ -3086,7 +3169,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 */ @@ -3111,6 +3199,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, @@ -3122,6 +3211,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(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]++; @@ -3133,12 +3229,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, @@ -3151,6 +3252,7 @@ static void outliner_draw_iconrow(bContext *C, ys, alpha_fac, in_bone_hierarchy, + in_grease_pencil_node_hierarchy, merged); } } @@ -3221,6 +3323,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(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) { @@ -3416,6 +3528,7 @@ static void outliner_draw_tree_element(bContext *C, *starty, alpha_fac, false, + false, &merged); GPU_blend(GPU_BLEND_NONE); @@ -3521,6 +3634,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(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); diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index e6009487cd7..8eef93b011b 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -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(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(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; diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc index a03fa14b0dc..9a6adcd907a 100644 --- a/source/blender/editors/space_outliner/outliner_tools.cc +++ b/source/blender/editors/space_outliner/outliner_tools.cc @@ -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(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); diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 97f6927dc50..ded8edf1a86 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -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; } @@ -313,7 +317,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)) { @@ -407,7 +411,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"); } diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index 5f7f5918736..0b5318a6b20 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -26,6 +26,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" @@ -81,6 +82,9 @@ std::unique_ptr AbstractTreeElement::createFromType(const i return std::make_unique(legacy_te, *static_cast(idv)); case TSE_GP_LAYER: return std::make_unique(legacy_te, *static_cast(idv)); + case TSE_GREASE_PENCIL_NODE: + return std::make_unique( + legacy_te, *static_cast(idv)); case TSE_R_LAYER_BASE: return std::make_unique(legacy_te, *static_cast(idv)); case TSE_R_LAYER: { diff --git a/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.cc b/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.cc new file mode 100644 index 00000000000..47ac74d91b0 --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.cc @@ -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; +} + +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_; +} + +} // namespace blender::ed::outliner \ No newline at end of file diff --git a/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.hh b/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.hh new file mode 100644 index 00000000000..77b3081b90d --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_grease_pencil_node.hh @@ -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; +} // 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 diff --git a/source/blender/editors/space_outliner/tree/tree_element_id.cc b/source/blender/editors/space_outliner/tree/tree_element_id.cc index 9a10fe2b60b..b1e339c13ea 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_id.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_id.cc @@ -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::createFromID(TreeElement &legacy_t return std::make_unique(legacy_te, (FreestyleLineStyle &)id); case ID_GD_LEGACY: return std::make_unique(legacy_te, (bGPdata &)id); + case ID_GP: + return std::make_unique(legacy_te, (GreasePencil &)id); case ID_GR: return std::make_unique(legacy_te, (Collection &)id); case ID_AR: @@ -94,7 +97,6 @@ std::unique_ptr TreeElementID::createFromID(TreeElement &legacy_t case ID_PAL: case ID_PC: case ID_CF: - case ID_GP: return std::make_unique(legacy_te, id); case ID_IP: BLI_assert_unreachable(); diff --git a/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.cc b/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.cc new file mode 100644 index 00000000000..d62fff1444f --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.cc @@ -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 diff --git a/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.hh b/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.hh new file mode 100644 index 00000000000..d81ee8cffad --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_id_grease_pencil.hh @@ -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 \ No newline at end of file diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index 455e483234a..d278647625c 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -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, } eTreeStoreElemType; /** Check whether given #TreeStoreElem should have a real ID in #TreeStoreElem.id member. */