Blender V4.3
node_geo_merge_layers.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "GEO_merge_layers.hh"
8
10
11#include "NOD_rna_define.hh"
12
13#include "UI_interface.hh"
14#include "UI_resources.hh"
15
17
19
20enum class MergeLayerMode {
21 ByName = 0,
22 ByID = 1,
23};
24
26{
27 b.add_input<decl::Geometry>("Grease Pencil")
29 b.add_input<decl::Bool>("Selection").default_value(true).hide_value().field_on_all();
30 auto &group_id = b.add_input<decl::Int>("Group ID").hide_value().field_on_all();
31 b.add_output<decl::Geometry>("Grease Pencil").propagate_all();
32
33 const bNode *node = b.node_or_null();
34 if (node) {
35 const NodeGeometryMergeLayers &storage = node_storage(*node);
36 const MergeLayerMode mode = MergeLayerMode(storage.mode);
37 group_id.available(mode == MergeLayerMode::ByID);
38 }
39}
40
41static void node_init(bNodeTree * /*tree*/, bNode *node)
42{
43 auto *data = MEM_cnew<NodeGeometryMergeLayers>(__func__);
44 data->mode = int8_t(MergeLayerMode::ByName);
45 node->storage = data;
46}
47
48static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
49{
50 uiItemR(layout, ptr, "mode", UI_ITEM_NONE, "", ICON_NONE);
51}
52
55{
56 using namespace bke::greasepencil;
57
58 const int old_layers_num = src_grease_pencil.layers().size();
59
60 const Field<bool> selection_field = params.get_input<Field<bool>>("Selection");
61
62 bke::GreasePencilFieldContext field_context{src_grease_pencil};
63 FieldEvaluator field_evaluator{field_context, old_layers_num};
64 field_evaluator.add(selection_field);
65 field_evaluator.evaluate();
66 const VArray<bool> selection = field_evaluator.get_evaluated<bool>(0);
67
68 Vector<Vector<int>> layers_map;
69 Map<StringRef, int> new_layer_index_by_name;
70
71 for (const int layer_i : IndexRange(old_layers_num)) {
72 const bool is_selected = selection[layer_i];
73 if (!is_selected) {
74 layers_map.append({layer_i});
75 continue;
76 }
77
78 const Layer &layer = src_grease_pencil.layer(layer_i);
79 const int new_layer_index = new_layer_index_by_name.lookup_or_add_cb(
80 layer.name(), [&]() { return layers_map.append_and_get_index_as(); });
81 layers_map[new_layer_index].append(layer_i);
82 }
83 return layers_map;
84}
85
86static Vector<Vector<int>> get_layers_map_by_id(const GreasePencil &src_grease_pencil,
88{
89 using namespace bke::greasepencil;
90
91 const int old_layers_num = src_grease_pencil.layers().size();
92
93 const Field<bool> selection_field = params.get_input<Field<bool>>("Selection");
94 const Field<int> group_id_field = params.get_input<Field<int>>("Group ID");
95
96 bke::GreasePencilFieldContext field_context{src_grease_pencil};
97 FieldEvaluator field_evaluator{field_context, old_layers_num};
98 field_evaluator.add(selection_field);
99 field_evaluator.add(group_id_field);
100 field_evaluator.evaluate();
101 const VArray<bool> selection = field_evaluator.get_evaluated<bool>(0);
102 const VArray<int> group_ids = field_evaluator.get_evaluated<int>(1);
103
104 Vector<Vector<int>> layers_map;
105 Map<int, int> new_layer_index_by_id;
106
107 for (const int layer_i : IndexRange(old_layers_num)) {
108 const bool is_selected = selection[layer_i];
109 if (!is_selected) {
110 layers_map.append({layer_i});
111 continue;
112 }
113 const int group_id = group_ids[layer_i];
114 const int new_layer_index = new_layer_index_by_id.lookup_or_add_cb(
115 group_id, [&]() { return layers_map.append_and_get_index_as(); });
116 layers_map[new_layer_index].append(layer_i);
117 }
118 return layers_map;
119}
120
121static void merge_layers(GeometrySet &geometry,
122 const NodeGeometryMergeLayers &storage,
124 const AttributeFilter &attribute_filter)
125{
126 using namespace bke::greasepencil;
127
128 const GreasePencil *src_grease_pencil = geometry.get_grease_pencil();
129 if (!src_grease_pencil) {
130 return;
131 }
132 const int old_layers_num = src_grease_pencil->layers().size();
133
134 Vector<Vector<int>> layers_map;
135 switch (MergeLayerMode(storage.mode)) {
137 layers_map = get_layers_map_by_name(*src_grease_pencil, params);
138 break;
139 }
141 layers_map = get_layers_map_by_id(*src_grease_pencil, params);
142 break;
143 }
144 }
145
146 const int new_layers_num = layers_map.size();
147 if (old_layers_num == new_layers_num) {
148 return;
149 }
150
151 GreasePencil *new_grease_pencil = geometry::merge_layers(
152 *src_grease_pencil, layers_map, attribute_filter);
153 geometry.replace_grease_pencil(new_grease_pencil);
154}
155
157{
158 GeometrySet main_geometry = params.extract_input<GeometrySet>("Grease Pencil");
159 const bNode &node = params.node();
160 const NodeGeometryMergeLayers &storage = node_storage(node);
161
162 const NodeAttributeFilter attribute_filter = params.get_attribute_filter("Grease Pencil");
163
164 main_geometry.modify_geometry_sets(
165 [&](GeometrySet &geometry) { merge_layers(geometry, storage, params, attribute_filter); });
166
167 params.set_output("Grease Pencil", std::move(main_geometry));
168}
169
170static void node_rna(StructRNA *srna)
171{
172 static const EnumPropertyItem mode_items[] = {
174 "MERGE_BY_NAME",
175 0,
176 "By Name",
177 "Combine all layers which have the same name"},
179 "MERGE_BY_ID",
180 0,
181 "By Group ID",
182 "Provide a custom group ID for each layer and all layers with the same ID will be merged "
183 "into one"},
184 {0, nullptr, 0, nullptr, nullptr},
185 };
186
188 "mode",
189 "Mode",
190 "Determines how to choose which layers are merged",
191 mode_items,
194 nullptr);
195}
196
197static void node_register()
198{
199 static blender::bke::bNodeType ntype;
200
201 geo_node_type_base(&ntype, GEO_NODE_MERGE_LAYERS, "Merge Layers", NODE_CLASS_GEOMETRY);
202 ntype.declare = node_declare;
203 ntype.initfunc = node_init;
207 &ntype, "NodeGeometryMergeLayers", node_free_standard_storage, node_copy_standard_storage);
209
210 node_rna(ntype.rna_ext.srna);
211}
213
214} // namespace blender::nodes::node_geo_merge_layers_cc
Low-level operations for grease pencil.
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1799
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:418
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
#define UI_ITEM_NONE
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:582
int64_t size() const
int add(GField field, GVArray *varray_ptr)
Definition field.cc:756
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
GreasePencil * merge_layers(const GreasePencil &src_grease_pencil, Span< Vector< int > > layers_to_merge, const bke::AttributeFilter &attribute_filter)
static Vector< Vector< int > > get_layers_map_by_name(const GreasePencil &src_grease_pencil, const GeoNodeExecParams &params)
static void merge_layers(GeometrySet &geometry, const NodeGeometryMergeLayers &storage, const GeoNodeExecParams &params, const AttributeFilter &attribute_filter)
static void node_init(bNodeTree *, bNode *node)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static Vector< Vector< int > > get_layers_map_by_id(const GreasePencil &src_grease_pencil, const GeoNodeExecParams &params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
signed char int8_t
Definition stdint.h:75
StructRNA * srna
Definition RNA_types.hh:780
void modify_geometry_sets(ForeachSubGeometryCallback callback)
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:339
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeDeclareFunction declare
Definition BKE_node.hh:347
PointerRNA * ptr
Definition wm_files.cc:4126