Cleanup: GPv3: Refactor use of TreeNode #111177

Merged
Falk David merged 8 commits from filedescriptor/blender:gpv3-tree-node-refactor into main 2023-08-16 16:18:33 +02:00
13 changed files with 267 additions and 264 deletions

View File

@ -122,6 +122,67 @@ class Drawing : public ::GreasePencilDrawing {
class LayerGroup;
class Layer;
/* Defines the common functions used by #TreeNode, #Layer, and #LayerGroup.
* Note: Because we cannot mix C-style and C++ inheritance (all of these three classes wrap a
* C-struct that already uses "inheritance"), we define and implement these methods on all these
* classes individually. This just means that we can call `layer->name()` directly instead of
* having to write `layer->as_node().name()`. For #Layer and #LayerGroup the calls are just
* forwarded to #TreeNode. */
#define TREENODE_COMMON_METHODS \
StringRefNull name() const; \
void set_name(StringRefNull new_name); \
bool is_visible() const; \
void set_visible(bool visible); \
bool is_locked() const; \
void set_locked(bool locked); \
bool is_editable() const; \
bool is_selected() const; \
void set_selected(bool selected); \
bool use_onion_skinning() const;
/* Implements the forwarding of the methods defined by #TREENODE_COMMON_METHODS. */
#define TREENODE_COMMON_METHODS_FORWARD_IMPL(class_name) \
inline StringRefNull class_name::name() const \
{ \
return this->as_node().name(); \
} \
inline void class_name::set_name(StringRefNull new_name) \
{ \
return this->as_node().set_name(new_name); \
} \
inline bool class_name::is_visible() const \
{ \
return this->as_node().is_visible(); \
} \
inline void class_name::set_visible(const bool visible) \
{ \
this->as_node().set_visible(visible); \
} \
inline bool class_name::is_locked() const \
{ \
return this->as_node().is_locked(); \
} \
inline void class_name::set_locked(const bool locked) \
{ \
this->as_node().set_locked(locked); \
} \
inline bool class_name::is_editable() const \
{ \
return this->as_node().is_editable(); \
} \
inline bool class_name::is_selected() const \
{ \
return this->as_node().is_selected(); \
} \
inline void class_name::set_selected(const bool selected) \
{ \
this->as_node().set_selected(selected); \
} \
inline bool class_name::use_onion_skinning() const \
{ \
return this->as_node().use_onion_skinning(); \
}
/**
* A TreeNode represents one node in the layer tree.
* It can either be a layer or a group. The node has zero children if it is a layer or zero or
@ -135,50 +196,34 @@ class TreeNode : public ::GreasePencilLayerTreeNode {
TreeNode(const TreeNode &other);
public:
/* Define the common functions for #TreeNode. */
TREENODE_COMMON_METHODS;
/**
* \returns true if this node is a LayerGroup.
* \returns true if this node is a #LayerGroup.
*/
bool is_group() const
{
return this->type == GP_LAYER_TREE_GROUP;
}
bool is_group() const;
/**
* \returns true if this node is a #Layer.
*/
bool is_layer() const;
/**
* \returns true if this node is a Layer.
*/
bool is_layer() const
{
return this->type == GP_LAYER_TREE_LEAF;
}
/**
* \returns this tree node as a LayerGroup.
* \note This results in undefined behavior if the node is not a LayerGroup.
*/
const LayerGroup &as_group() const;
/**
* \returns this tree node as a Layer.
* \note This results in undefined behavior if the node is not a Layer.
* \returns this node as a #Layer.
*/
Layer &as_layer();
const Layer &as_layer() const;
/**
* \returns this tree node as a mutable LayerGroup.
* \note This results in undefined behavior if the node is not a LayerGroup.
* \returns this node as a #LayerGroup.
*/
LayerGroup &as_group_for_write();
/**
* \returns this tree node as a mutable Layer.
* \note This results in undefined behavior if the node is not a Layer.
*/
Layer &as_layer_for_write();
LayerGroup &as_group();
const LayerGroup &as_group() const;
/**
* \returns the parent layer group or nullptr for the root group.
*/
LayerGroup *parent_group() const;
TreeNode *parent_node() const;
};
/**
@ -269,36 +314,27 @@ class Layer : public ::GreasePencilLayer {
Layer(const Layer &other);
~Layer();
/**
* \returns the layer name.
*/
StringRefNull name() const;
void set_name(StringRefNull new_name);
/**
* \returns the parent layer group.
*/
LayerGroup &parent_group() const;
public:
/* Define the common functions for #TreeNode. */
TREENODE_COMMON_METHODS;
/**
* \returns the layer as a `TreeNode`.
*/
const TreeNode &as_node() const;
TreeNode &as_node();
/**
* \returns the parent #LayerGroup of this layer.
*/
LayerGroup &parent_group() const;
/**
* \returns the frames mapping.
*/
const Map<FramesMapKey, GreasePencilFrame> &frames() const;
Map<FramesMapKey, GreasePencilFrame> &frames_for_write();
bool is_visible() const;
bool is_locked() const;
bool is_editable() const;
bool is_empty() const;
bool is_selected() const;
bool use_onion_skinning() const;
/**
* Adds a new frame into the layer frames map.
@ -406,12 +442,8 @@ class LayerGroup : public ::GreasePencilLayerTreeGroup {
~LayerGroup();
public:
StringRefNull name() const;
void set_name(StringRefNull new_name);
bool is_visible() const;
bool is_locked() const;
/* Define the common functions for #TreeNode. */
TREENODE_COMMON_METHODS;
/**
* \returns the group as a `TreeNode`.
*/
@ -520,6 +552,53 @@ inline bool Drawing::has_users() const
{
return this->runtime->user_count.load(std::memory_order_relaxed) > 0;
}
inline bool TreeNode::is_group() const
{
return this->type == GP_LAYER_TREE_GROUP;
}
inline bool TreeNode::is_layer() const
{
return this->type == GP_LAYER_TREE_LEAF;
}
inline bool TreeNode::is_visible() const
{
return ((this->flag & GP_LAYER_TREE_NODE_HIDE) == 0) &&
(!this->parent_group() || this->parent_group()->as_node().is_visible());
}
inline void TreeNode::set_visible(const bool visible)
{
SET_FLAG_FROM_TEST(this->flag, !visible, GP_LAYER_TREE_NODE_HIDE);
}
inline bool TreeNode::is_locked() const
{
return ((this->flag & GP_LAYER_TREE_NODE_LOCKED) != 0) ||
(!this->parent_group() || this->parent_group()->as_node().is_locked());
}
inline void TreeNode::set_locked(const bool locked)
{
SET_FLAG_FROM_TEST(this->flag, locked, GP_LAYER_TREE_NODE_LOCKED);
}
inline bool TreeNode::is_editable() const
{
return this->is_visible() && !this->is_locked();
}
inline bool TreeNode::is_selected() const
{
return (this->flag & GP_LAYER_TREE_NODE_SELECT) != 0;
}
inline void TreeNode::set_selected(const bool selected)
{
SET_FLAG_FROM_TEST(this->flag, selected, GP_LAYER_TREE_NODE_SELECT);
}
inline bool TreeNode::use_onion_skinning() const
{
return ((this->flag & GP_LAYER_TREE_NODE_USE_ONION_SKINNING) != 0);
}
inline StringRefNull TreeNode::name() const
{
return this->name_ptr;
}
inline const TreeNode &LayerGroup::as_node() const
{
return *reinterpret_cast<const TreeNode *>(this);
@ -538,20 +617,17 @@ inline TreeNode &Layer::as_node()
return *reinterpret_cast<TreeNode *>(this);
}
inline StringRefNull Layer::name() const
TREENODE_COMMON_METHODS_FORWARD_IMPL(Layer);
inline bool Layer::is_empty() const
{
return this->base.name;
return (this->frames().size() == 0);
}
inline LayerGroup &Layer::parent_group() const
{
return this->base.parent->wrap();
return *this->as_node().parent_group();
}
inline StringRefNull LayerGroup::name() const
{
return this->base.name;
}
TREENODE_COMMON_METHODS_FORWARD_IMPL(LayerGroup);
namespace convert {

View File

@ -424,7 +424,7 @@ TreeNode::TreeNode()
this->next = this->prev = nullptr;
this->parent = nullptr;
this->name = nullptr;
this->name_ptr = nullptr;
this->flag = 0;
this->color[0] = this->color[1] = this->color[2] = 0;
}
@ -437,19 +437,24 @@ TreeNode::TreeNode(GreasePencilLayerTreeNodeType type) : TreeNode()
TreeNode::TreeNode(GreasePencilLayerTreeNodeType type, StringRefNull name) : TreeNode()
{
this->type = type;
this->name = BLI_strdup(name.c_str());
this->name_ptr = BLI_strdup(name.c_str());
}
TreeNode::TreeNode(const TreeNode &other)
: TreeNode::TreeNode(GreasePencilLayerTreeNodeType(other.type))
{
if (other.name) {
this->name = BLI_strdup(other.name);
if (!other.name().is_empty()) {
this->name_ptr = BLI_strdup(other.name().c_str());
}
this->flag = other.flag;
copy_v3_v3_uchar(this->color, other.color);
}
void TreeNode::set_name(StringRefNull name)
{
this->name_ptr = BLI_strdup(name.c_str());
}
const LayerGroup &TreeNode::as_group() const
{
return *reinterpret_cast<const LayerGroup *>(this);
@ -460,22 +465,24 @@ const Layer &TreeNode::as_layer() const
return *reinterpret_cast<const Layer *>(this);
}
LayerGroup &TreeNode::as_group_for_write()
LayerGroup &TreeNode::as_group()
{
return *reinterpret_cast<LayerGroup *>(this);
}
Layer &TreeNode::as_layer_for_write()
Layer &TreeNode::as_layer()
{
return *reinterpret_cast<Layer *>(this);
}
LayerGroup *TreeNode::parent_group() const
{
if (this->parent) {
return &this->parent->wrap();
}
return nullptr;
return (this->parent) ? &this->parent->wrap() : nullptr;
}
TreeNode *TreeNode::parent_node() const
{
return this->parent_group() ? &this->parent->wrap().as_node() : nullptr;
}
LayerMask::LayerMask()
@ -522,7 +529,7 @@ Layer::Layer()
Layer::Layer(StringRefNull name) : Layer()
{
this->base.name = BLI_strdup(name.c_str());
this->base.name_ptr = BLI_strdup(name.c_str());
}
Layer::Layer(const Layer &other) : Layer()
@ -543,7 +550,7 @@ Layer::Layer(const Layer &other) : Layer()
Layer::~Layer()
{
MEM_SAFE_FREE(this->base.name);
MEM_SAFE_FREE(this->base.name_ptr);
MEM_SAFE_FREE(this->frames_storage.keys);
MEM_SAFE_FREE(this->frames_storage.values);
@ -556,11 +563,6 @@ Layer::~Layer()
this->runtime = nullptr;
}
void Layer::set_name(StringRefNull new_name)
{
this->base.name = BLI_strdup(new_name.c_str());
}
const Map<int, GreasePencilFrame> &Layer::frames() const
{
return this->runtime->frames_;
@ -571,36 +573,6 @@ Map<int, GreasePencilFrame> &Layer::frames_for_write()
return this->runtime->frames_;
}
bool Layer::is_visible() const
{
return this->parent_group().is_visible() && (this->base.flag & GP_LAYER_TREE_NODE_HIDE) == 0;
}
bool Layer::is_locked() const
{
return this->parent_group().is_locked() || (this->base.flag & GP_LAYER_TREE_NODE_LOCKED) != 0;
}
bool Layer::is_editable() const
{
return !this->is_locked() && this->is_visible();
}
bool Layer::is_empty() const
{
return (this->frames().size() == 0);
}
bool Layer::is_selected() const
{
return ((this->base.flag & GP_LAYER_TREE_NODE_SELECT) != 0);
}
bool Layer::use_onion_skinning() const
{
return ((this->base.flag & GP_LAYER_TREE_NODE_USE_ONION_SKINNING) != 0);
}
Layer::SortedKeysIterator Layer::remove_leading_null_frames_in_range(
Layer::SortedKeysIterator begin, Layer::SortedKeysIterator end)
{
@ -795,7 +767,7 @@ LayerGroup::LayerGroup()
LayerGroup::LayerGroup(StringRefNull name) : LayerGroup()
{
this->base.name = BLI_strdup(name.c_str());
this->base.name_ptr = BLI_strdup(name.c_str());
}
LayerGroup::LayerGroup(const LayerGroup &other) : LayerGroup()
@ -822,7 +794,7 @@ LayerGroup::LayerGroup(const LayerGroup &other) : LayerGroup()
LayerGroup::~LayerGroup()
{
MEM_SAFE_FREE(this->base.name);
MEM_SAFE_FREE(this->base.name_ptr);
LISTBASE_FOREACH_MUTABLE (GreasePencilLayerTreeNode *, child, &this->children) {
switch (child->type) {
@ -843,29 +815,6 @@ LayerGroup::~LayerGroup()
this->runtime = nullptr;
}
void LayerGroup::set_name(StringRefNull new_name)
{
this->base.name = BLI_strdup(new_name.c_str());
}
bool LayerGroup::is_visible() const
{
if (this->base.parent) {
return this->base.parent->wrap().is_visible() &&
(this->base.flag & GP_LAYER_TREE_NODE_HIDE) == 0;
}
return (this->base.flag & GP_LAYER_TREE_NODE_HIDE) == 0;
}
bool LayerGroup::is_locked() const
{
if (this->base.parent) {
return this->base.parent->wrap().is_locked() ||
(this->base.flag & GP_LAYER_TREE_NODE_LOCKED) != 0;
}
return (this->base.flag & GP_LAYER_TREE_NODE_LOCKED) != 0;
}
LayerGroup &LayerGroup::add_group(LayerGroup *group)
{
BLI_assert(group != nullptr);
@ -1058,10 +1007,10 @@ void LayerGroup::print_nodes(StringRefNull header) const
std::cout << " ";
}
if (node->is_layer()) {
std::cout << StringRefNull(node->name);
std::cout << node->name();
}
else if (node->is_group()) {
std::cout << StringRefNull(node->name) << ": ";
std::cout << node->name() << ": ";
LISTBASE_FOREACH_BACKWARD (GreasePencilLayerTreeNode *, child_, &node->as_group().children) {
TreeNode *child = reinterpret_cast<TreeNode *>(child_);
next_node.push(std::make_pair(indent + 1, child));
@ -1084,18 +1033,18 @@ void LayerGroup::ensure_nodes_cache() const
this->runtime->nodes_cache_.append(node);
switch (node->type) {
case GP_LAYER_TREE_LEAF: {
this->runtime->layer_cache_.append(&node->as_layer_for_write());
this->runtime->layer_cache_.append(&node->as_layer());
break;
}
case GP_LAYER_TREE_GROUP: {
this->runtime->layer_group_cache_.append(&node->as_group_for_write());
for (TreeNode *child : node->as_group_for_write().nodes_for_write()) {
this->runtime->layer_group_cache_.append(&node->as_group());
for (TreeNode *child : node->as_group().nodes_for_write()) {
this->runtime->nodes_cache_.append(child);
if (child->is_layer()) {
this->runtime->layer_cache_.append(&child->as_layer_for_write());
this->runtime->layer_cache_.append(&child->as_layer());
}
else if (child->is_group()) {
this->runtime->layer_group_cache_.append(&child->as_group_for_write());
this->runtime->layer_group_cache_.append(&child->as_group());
}
}
break;
@ -1853,12 +1802,12 @@ bool GreasePencil::is_layer_active(const blender::bke::greasepencil::Layer *laye
return this->get_active_layer() == layer;
}
static blender::VectorSet<blender::StringRefNull> get_node_names(GreasePencil &grease_pencil)
static blender::VectorSet<blender::StringRefNull> get_node_names(const GreasePencil &grease_pencil)
{
using namespace blender;
VectorSet<StringRefNull> names;
for (const blender::bke::greasepencil::TreeNode *node : grease_pencil.nodes()) {
names.add(node->name);
names.add(node->name());
}
return names;
}
@ -1870,23 +1819,41 @@ static bool check_unique_node_cb(void *arg, const char *name)
return names.contains(name);
}
static bool unique_layer_name(VectorSet<blender::StringRefNull> &names, char *name)
static bool unique_node_name_ex(VectorSet<blender::StringRefNull> &names,
const char *default_name,
char *name)
{
return BLI_uniquename_cb(check_unique_node_cb, &names, "GP_Layer", '.', name, MAX_NAME);
return BLI_uniquename_cb(check_unique_node_cb, &names, default_name, '.', name, MAX_NAME);
}
static bool unique_layer_group_name(VectorSet<blender::StringRefNull> &names, char *name)
static std::string unique_node_name(const GreasePencil &grease_pencil,
const char *default_name,
blender::StringRefNull name)
{
return BLI_uniquename_cb(check_unique_node_cb, &names, "GP_Group", '.', name, MAX_NAME);
using namespace blender;
std::string unique_name(name.c_str());
VectorSet<StringRefNull> names = get_node_names(grease_pencil);
unique_node_name_ex(names, default_name, unique_name.data());
return unique_name;
}
static std::string unique_layer_name(const GreasePencil &grease_pencil,
blender::StringRefNull name)
{
return unique_node_name(grease_pencil, "GP_Layer", name);
}
static std::string unique_layer_group_name(const GreasePencil &grease_pencil,
blender::StringRefNull name)
{
return unique_node_name(grease_pencil, "GP_Group", name);
}
blender::bke::greasepencil::Layer &GreasePencil::add_layer(
blender::bke::greasepencil::LayerGroup &group, const blender::StringRefNull name)
{
using namespace blender;
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(name.c_str());
unique_layer_name(names, unique_name.data());
std::string unique_name = unique_layer_name(*this, name);
return group.add_layer(unique_name);
}
@ -1896,9 +1863,7 @@ blender::bke::greasepencil::Layer &GreasePencil::add_layer_after(
const blender::StringRefNull name)
{
using namespace blender;
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(name.c_str());
unique_layer_name(names, unique_name.data());
std::string unique_name = unique_layer_name(*this, name);
return group.add_layer_after(unique_name, link);
}
@ -1911,9 +1876,7 @@ blender::bke::greasepencil::LayerGroup &GreasePencil::add_layer_group(
blender::bke::greasepencil::LayerGroup &group, const blender::StringRefNull name)
{
using namespace blender;
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(name.c_str());
unique_layer_group_name(names, unique_name.data());
std::string unique_name = unique_layer_group_name(*this, name);
return group.add_group(unique_name);
}
@ -1923,9 +1886,7 @@ blender::bke::greasepencil::LayerGroup &GreasePencil::add_layer_group_after(
const blender::StringRefNull name)
{
using namespace blender;
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(name.c_str());
unique_layer_group_name(names, unique_name.data());
std::string unique_name = unique_layer_group_name(*this, name);
return group.add_group_after(unique_name, node);
}
@ -1959,30 +1920,15 @@ blender::bke::greasepencil::LayerGroup *GreasePencil::find_group_by_name(
return this->root_group().find_group_by_name(name);
}
void GreasePencil::rename_layer(blender::bke::greasepencil::Layer &layer,
blender::StringRefNull new_name)
void GreasePencil::rename_node(blender::bke::greasepencil::TreeNode &node,
blender::StringRefNull new_name)
{
using namespace blender;
if (layer.name() == new_name) {
if (node.name() == new_name) {
return;
}
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(new_name.c_str());
unique_layer_name(names, unique_name.data());
layer.set_name(unique_name);
}
void GreasePencil::rename_group(blender::bke::greasepencil::LayerGroup &group,
blender::StringRefNull new_name)
{
using namespace blender;
if (group.name() == new_name) {
return;
}
VectorSet<StringRefNull> names = get_node_names(*this);
std::string unique_name(new_name.c_str());
unique_layer_group_name(names, unique_name.data());
group.set_name(unique_name);
node.set_name(node.is_layer() ? unique_layer_name(*this, new_name) :
unique_layer_group_name(*this, new_name));
}
void GreasePencil::remove_layer(blender::bke::greasepencil::Layer &layer)
@ -2120,7 +2066,7 @@ static void read_layer(BlendDataReader *reader,
GreasePencilLayer *node,
GreasePencilLayerTreeGroup *parent)
{
BLO_read_data_address(reader, &node->base.name);
BLO_read_data_address(reader, &node->base.name_ptr);
node->base.parent = parent;
/* Read frames storage. */
@ -2145,7 +2091,7 @@ static void read_layer_tree_group(BlendDataReader *reader,
GreasePencilLayerTreeGroup *node,
GreasePencilLayerTreeGroup *parent)
{
BLO_read_data_address(reader, &node->base.name);
BLO_read_data_address(reader, &node->base.name_ptr);
node->base.parent = parent;
/* Read list of children. */
BLO_read_list(reader, &node->children);
@ -2209,7 +2155,7 @@ static void write_layer(BlendWriter *writer, GreasePencilLayer *node)
}
BLO_write_struct(writer, GreasePencilLayer, node);
BLO_write_string(writer, node->base.name);
BLO_write_string(writer, node->base.name_ptr);
BLO_write_int32_array(writer, node->frames_storage.num, node->frames_storage.keys);
BLO_write_struct_array(
@ -2224,7 +2170,7 @@ static void write_layer(BlendWriter *writer, GreasePencilLayer *node)
static void write_layer_tree_group(BlendWriter *writer, GreasePencilLayerTreeGroup *node)
{
BLO_write_struct(writer, GreasePencilLayerTreeGroup, node);
BLO_write_string(writer, node->base.name);
BLO_write_string(writer, node->base.name_ptr);
LISTBASE_FOREACH (GreasePencilLayerTreeNode *, child, &node->children) {
switch (child->type) {
case GP_LAYER_TREE_LEAF: {

View File

@ -190,11 +190,9 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
grease_pencil.root_group(), StringRefNull(gpl->info, BLI_strnlen(gpl->info, 128)));
/* Flags. */
SET_FLAG_FROM_TEST(new_layer.base.flag, (gpl->flag & GP_LAYER_HIDE), GP_LAYER_TREE_NODE_HIDE);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_LOCKED), GP_LAYER_TREE_NODE_LOCKED);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_SELECT), GP_LAYER_TREE_NODE_SELECT);
new_layer.set_visible((gpl->flag & GP_LAYER_HIDE) == 0);
new_layer.set_locked((gpl->flag & GP_LAYER_LOCKED) != 0);
new_layer.set_selected((gpl->flag & GP_LAYER_SELECT) != 0);
SET_FLAG_FROM_TEST(
new_layer.base.flag, (gpl->flag & GP_LAYER_FRAMELOCK), GP_LAYER_TREE_NODE_MUTE);
SET_FLAG_FROM_TEST(

View File

@ -132,7 +132,7 @@ TEST(greasepencil, layer_tree_pre_order_iteration)
Span<const TreeNode *> children = ex.root.nodes();
for (const int i : children.index_range()) {
const TreeNode &child = *children[i];
EXPECT_STREQ(child.name, ex.names[i].data());
EXPECT_STREQ(child.name().data(), ex.names[i].data());
}
}

View File

@ -3658,7 +3658,7 @@ static int click_select_channel_grease_pencil_layer(bContext *C,
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
if (selectmode == SELECT_INVERT) {
layer->base.flag ^= GP_LAYER_TREE_NODE_SELECT;
layer->set_selected(!layer->is_selected());
}
else if (selectmode == SELECT_EXTEND_RANGE) {
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_EXTEND_RANGE);
@ -3666,7 +3666,7 @@ static int click_select_channel_grease_pencil_layer(bContext *C,
}
else {
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
layer->set_selected(true);
}
/* Active channel is not changed during range select. */

View File

@ -295,12 +295,7 @@ void ANIM_sync_animchannels_to_data(const bContext *C)
using namespace blender::bke::greasepencil;
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(ale->id);
Layer *layer = static_cast<Layer *>(ale->data);
if (grease_pencil->is_layer_active(layer)) {
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
}
else {
layer->base.flag &= ~GP_LAYER_TREE_NODE_SELECT;
}
layer->set_selected(grease_pencil->is_layer_active(layer));
break;
}
}

View File

@ -27,7 +27,7 @@ void select_layer_channel(GreasePencil &grease_pencil, bke::greasepencil::Layer
using namespace blender::bke::greasepencil;
if (layer != nullptr) {
layer->base.flag |= GP_LAYER_TREE_NODE_SELECT;
layer->set_selected(true);
}
if (grease_pencil.active_layer != layer) {

View File

@ -57,7 +57,7 @@ class LayerNodeDropTarget : public TreeViewItemDropTarget {
Layer &drag_layer = drag_grease_pencil->layer->wrap();
std::string_view drag_name = drag_layer.name();
std::string_view drop_name = drop_tree_node_.name;
std::string_view drop_name = drop_tree_node_.name();
switch (drag_info.drop_location) {
case DropLocation::Into:
@ -99,7 +99,7 @@ class LayerNodeDropTarget : public TreeViewItemDropTarget {
"Inserting should not be possible for layers, only for groups, because "
"only groups use DropBehavior::Reorder_and_Insert");
LayerGroup &drop_group = drop_tree_node_.as_group_for_write();
LayerGroup &drop_group = drop_tree_node_.as_group();
drag_parent.unlink_node(&drag_layer.as_node());
drop_group.add_layer(&drag_layer);
return true;
@ -202,7 +202,7 @@ class LayerViewItem : public AbstractTreeViewItem {
bool rename(StringRefNull new_name) override
{
grease_pencil_.rename_layer(layer_, new_name);
grease_pencil_.rename_node(layer_.as_node(), new_name);
return true;
}
@ -311,7 +311,7 @@ class LayerGroupViewItem : public AbstractTreeViewItem {
bool rename(StringRefNull new_name) override
{
grease_pencil_.rename_group(group_, new_name);
grease_pencil_.rename_node(group_.as_node(), new_name);
return true;
}
@ -354,12 +354,12 @@ void LayerTreeView::build_tree_node_recursive(TreeViewOrItem &parent, TreeNode &
using namespace blender::bke::greasepencil;
if (node.is_layer()) {
LayerViewItem &item = parent.add_tree_item<LayerViewItem>(this->grease_pencil_,
node.as_layer_for_write());
node.as_layer());
item.set_collapsed(false);
}
else if (node.is_group()) {
LayerGroupViewItem &group_item = parent.add_tree_item<LayerGroupViewItem>(
this->grease_pencil_, node.as_group_for_write());
LayerGroupViewItem &group_item = parent.add_tree_item<LayerGroupViewItem>(this->grease_pencil_,
node.as_group());
group_item.set_collapsed(false);
LISTBASE_FOREACH_BACKWARD (GreasePencilLayerTreeNode *, node_, &node.as_group().children) {
build_tree_node_recursive(group_item, node_->wrap());

View File

@ -864,16 +864,9 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname)
/* 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 = BLI_strdup(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);
}
std::string new_name(node.name());
node.set_name(oldname);
grease_pencil.rename_node(node, 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;
@ -1549,7 +1542,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
-1,
nullptr);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
if (!node.parent_group()->is_visible()) {
if (node.parent_group() && node.parent_group()->is_visible()) {
UI_but_flag_enable(bt, UI_BUT_INACTIVE);
}
}
@ -3328,12 +3321,7 @@ static bool element_should_draw_faded(const TreeViewContext *tvc,
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();
}
return !node.is_visible();
}
}

View File

@ -2217,16 +2217,16 @@ static void grease_pencil_node_fn(int event,
bke::greasepencil::TreeNode &node = tree_element_cast<TreeElementGreasePencilNode>(te)->node();
if (event == OL_DOP_SELECT) {
node.flag |= GP_LAYER_TREE_NODE_SELECT;
node.set_selected(true);
}
else if (event == OL_DOP_DESELECT) {
node.flag &= ~GP_LAYER_TREE_NODE_SELECT;
node.set_selected(false);
}
else if (event == OL_DOP_HIDE) {
node.flag |= GP_LAYER_TREE_NODE_HIDE;
node.set_visible(false);
}
else if (event == OL_DOP_UNHIDE) {
node.flag &= ~GP_LAYER_TREE_NODE_HIDE;
node.set_visible(true);
}
}

View File

@ -21,7 +21,7 @@ TreeElementGreasePencilNode::TreeElementGreasePencilNode(TreeElement &legacy_te,
: AbstractTreeElement(legacy_te), node_(node)
{
BLI_assert(legacy_te.store_elem->type == TSE_GREASE_PENCIL_NODE);
legacy_te.name = node.name;
legacy_te.name = node.name().c_str();
}
void TreeElementGreasePencilNode::expand(SpaceOutliner &space_outliner) const

View File

@ -246,7 +246,7 @@ typedef struct GreasePencilLayerTreeNode {
/**
* Name of the layer/group. Dynamic length.
*/
char *name;
char *name_ptr;
/**
* One of `GreasePencilLayerTreeNodeType`.
* Indicates the type of struct this element is.
@ -475,9 +475,7 @@ typedef struct GreasePencil {
blender::StringRefNull name) const;
blender::bke::greasepencil::LayerGroup *find_group_by_name(blender::StringRefNull name);
void rename_layer(blender::bke::greasepencil::Layer &layer, blender::StringRefNull new_name);
void rename_group(blender::bke::greasepencil::LayerGroup &group,
blender::StringRefNull new_name);
void rename_node(blender::bke::greasepencil::TreeNode &node, blender::StringRefNull new_name);
void remove_layer(blender::bke::greasepencil::Layer &layer);

View File

@ -54,35 +54,50 @@ static int rna_iterator_grease_pencil_layers_length(PointerRNA *ptr)
return grease_pencil->layers().size();
}
static void tree_node_name_get(blender::bke::greasepencil::TreeNode &node, char *dst)
{
if (!node.name().is_empty()) {
strcpy(dst, node.name().c_str());
}
else {
dst[0] = '\0';
}
}
static int tree_node_name_length(blender::bke::greasepencil::TreeNode &node)
{
if (!node.name().is_empty()) {
return node.name().size();
}
return 0;
}
static char *tree_node_name_path(blender::bke::greasepencil::TreeNode &node, const char *prefix)
{
using namespace blender::bke::greasepencil;
BLI_assert(!node.name().is_empty());
const size_t name_length = node.name().size();
std::string name_esc(name_length * 2, '\0');
BLI_str_escape(name_esc.data(), node.name().c_str(), name_length * 2);
return BLI_sprintfN("%s[\"%s\"]", prefix, name_esc.c_str());
}
static char *rna_GreasePencilLayer_path(const PointerRNA *ptr)
{
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ptr->data);
BLI_assert(layer->base.name);
const size_t name_length = strlen(layer->base.name);
std::string name_esc(name_length * 2, '\0');
BLI_str_escape(name_esc.data(), layer->base.name, name_length * 2);
return BLI_sprintfN("layers[\"%s\"]", name_esc.c_str());
return tree_node_name_path(layer->wrap().as_node(), "layers");
}
static void rna_GreasePencilLayer_name_get(PointerRNA *ptr, char *value)
{
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ptr->data);
if (layer->base.name) {
strcpy(value, layer->base.name);
}
else {
value[0] = '\0';
}
tree_node_name_get(layer->wrap().as_node(), value);
}
static int rna_GreasePencilLayer_name_length(PointerRNA *ptr)
{
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ptr->data);
return layer->base.name ? strlen(layer->base.name) : 0;
return tree_node_name_length(layer->wrap().as_node());
}
static void rna_GreasePencilLayer_name_set(PointerRNA *ptr, const char *value)
@ -90,7 +105,7 @@ static void rna_GreasePencilLayer_name_set(PointerRNA *ptr, const char *value)
GreasePencil *grease_pencil = rna_grease_pencil(ptr);
GreasePencilLayer *layer = static_cast<GreasePencilLayer *>(ptr->data);
grease_pencil->rename_layer(layer->wrap(), value);
grease_pencil->rename_node(layer->wrap().as_node(), value);
}
static PointerRNA rna_GreasePencil_active_layer_get(PointerRNA *ptr)
@ -117,32 +132,19 @@ static void rna_GreasePencil_active_layer_set(PointerRNA *ptr,
static char *rna_GreasePencilLayerGroup_path(const PointerRNA *ptr)
{
GreasePencilLayerTreeGroup *group = static_cast<GreasePencilLayerTreeGroup *>(ptr->data);
BLI_assert(group->base.name);
const size_t name_length = strlen(group->base.name);
std::string name_esc(name_length * 2, '\0');
BLI_str_escape(name_esc.data(), group->base.name, name_length * 2);
return BLI_sprintfN("layer_groups[\"%s\"]", name_esc.c_str());
return tree_node_name_path(group->wrap().as_node(), "layer_groups");
}
static void rna_GreasePencilLayerGroup_name_get(PointerRNA *ptr, char *value)
{
GreasePencilLayerTreeGroup *group = static_cast<GreasePencilLayerTreeGroup *>(ptr->data);
if (group->base.name) {
strcpy(value, group->base.name);
}
else {
value[0] = '\0';
}
tree_node_name_get(group->wrap().as_node(), value);
}
static int rna_GreasePencilLayerGroup_name_length(PointerRNA *ptr)
{
GreasePencilLayerTreeGroup *group = static_cast<GreasePencilLayerTreeGroup *>(ptr->data);
return group->base.name ? strlen(group->base.name) : 0;
return tree_node_name_length(group->wrap().as_node());
}
static void rna_GreasePencilLayerGroup_name_set(PointerRNA *ptr, const char *value)
@ -150,7 +152,7 @@ static void rna_GreasePencilLayerGroup_name_set(PointerRNA *ptr, const char *val
GreasePencil *grease_pencil = rna_grease_pencil(ptr);
GreasePencilLayerTreeGroup *group = static_cast<GreasePencilLayerTreeGroup *>(ptr->data);
grease_pencil->rename_group(group->wrap(), value);
grease_pencil->rename_node(group->wrap().as_node(), value);
}
static void rna_iterator_grease_pencil_layer_groups_begin(CollectionPropertyIterator *iter,