Cleanup: GPv3: Refactor use of TreeNode
#111177
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue