Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Ranish <Codec>2022-06-08 22:10:32 +0300
committerJoseph Eagar <joeedh@gmail.com>2022-06-08 22:10:32 +0300
commit9c28f0eb37aebd6e5eae0763b008ef02d5ce081b (patch)
tree65bc5d816ffc13a30ebf9aa454dd6fee7f512ed1
parentf69c565a33ca58bb95a2bd22de0e211799508182 (diff)
D14823: Adds operator to duplicate the active color attribute layer
Fixes T97706 Adds operator to duplicate the active color attribute layer. Adds `"Color Attribute Specials"` menu to color attribute ui to access the `"geometry.color_attribute_duplicate"` operator. Internally adds a function that duplicates a referenced CustomDataLayer - `BKE_id_attribute_duplicate` mostly copies the existing `BKE_id_attribute_new` - but gets the type and domain from the referenced layer - and copies the data from the old layer into the new layer Reviewed By: Joseph Eagar & Hans Goudey & Julien Kaspar Differential Revision: https://developer.blender.org/D14823 Ref D14823
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py18
-rw-r--r--source/blender/blenkernel/BKE_attribute.h7
-rw-r--r--source/blender/blenkernel/intern/attribute.cc53
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc52
-rw-r--r--source/blender/editors/geometry/geometry_intern.hh1
-rw-r--r--source/blender/editors/geometry/geometry_ops.cc1
6 files changed, 129 insertions, 3 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 15d25f71419..764299e7ce3 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -64,6 +64,18 @@ class MESH_MT_shape_key_context_menu(Menu):
layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
+class MESH_MT_color_attribute_context_menu(Menu):
+ bl_label = "Color Attribute Specials"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ props = layout.operator(
+ "geometry.color_attribute_duplicate",
+ icon='DUPLICATE',
+ )
+
+
class MESH_MT_attribute_context_menu(Menu):
bl_label = "Attribute Specials"
@@ -660,12 +672,16 @@ class DATA_PT_vertex_colors(DATA_PT_mesh_attributes, Panel):
col.operator("geometry.color_attribute_add", icon='ADD', text="")
col.operator("geometry.color_attribute_remove", icon='REMOVE', text="")
- self.draw_attribute_warnings(context, layout)
+ col.separator()
+ col.menu("MESH_MT_color_attribute_context_menu", icon='DOWNARROW_HLT', text="")
+
+ self.draw_attribute_warnings(context, layout)
classes = (
MESH_MT_vertex_group_context_menu,
MESH_MT_shape_key_context_menu,
+ MESH_MT_color_attribute_context_menu,
MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index 52a3e01026c..5755ddb3018 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -60,6 +60,13 @@ struct CustomDataLayer *BKE_id_attribute_new(
struct ID *id, const char *name, int type, eAttrDomain domain, struct ReportList *reports);
bool BKE_id_attribute_remove(struct ID *id, const char *name, struct ReportList *reports);
+/**
+ * Creates a duplicate attribute layer.
+ */
+struct CustomDataLayer *BKE_id_attribute_duplicate(struct ID *id,
+ struct CustomDataLayer *layer,
+ struct ReportList *reports);
+
struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id,
const char *name,
int type,
diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc
index eac42d19b52..b2ea8b833b3 100644
--- a/source/blender/blenkernel/intern/attribute.cc
+++ b/source/blender/blenkernel/intern/attribute.cc
@@ -208,6 +208,55 @@ CustomDataLayer *BKE_id_attribute_new(
return (index == -1) ? nullptr : &(customdata->layers[index]);
}
+CustomDataLayer *BKE_id_attribute_duplicate(ID *id, CustomDataLayer *layer, ReportList *reports)
+{
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+
+ eCustomDataType type = (eCustomDataType)layer->type;
+ eAttrDomain domain = BKE_id_attribute_domain(id, layer);
+
+ CustomData *customdata = info[domain].customdata;
+ if (customdata == nullptr) {
+ BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type");
+ return nullptr;
+ }
+
+ char name[MAX_CUSTOMDATA_LAYER_NAME];
+ char uniquename[MAX_CUSTOMDATA_LAYER_NAME];
+
+ /* Make a copy of name in case CustomData API reallocates the layers. */
+ BLI_strncpy(name, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
+ BKE_id_attribute_calc_unique_name(id, layer->name, uniquename);
+
+ switch (GS(id->name)) {
+ case ID_ME: {
+ Mesh *me = (Mesh *)id;
+ BMEditMesh *em = me->edit_mesh;
+ if (em != nullptr) {
+ BM_data_layer_add_named(em->bm, customdata, type, uniquename);
+ }
+ else {
+ CustomData_add_layer_named(
+ customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename);
+ }
+ break;
+ }
+ default: {
+ CustomData_add_layer_named(
+ customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename);
+ break;
+ }
+ }
+
+ int from_index = CustomData_get_named_layer_index(customdata, type, name);
+ int to_index = CustomData_get_named_layer_index(customdata, type, uniquename);
+ CustomData_copy_data_layer(
+ customdata, customdata, from_index, to_index, 0, 0, info[domain].length);
+
+ return (to_index == -1) ? nullptr : &(customdata->layers[to_index]);
+}
+
bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
{
if (BKE_id_attribute_required(id, name)) {
@@ -283,7 +332,7 @@ CustomDataLayer *BKE_id_attribute_search(const ID *id,
}
CustomData *customdata = info[domain].customdata;
- if (customdata == NULL) {
+ if (customdata == nullptr) {
continue;
}
@@ -295,7 +344,7 @@ CustomDataLayer *BKE_id_attribute_search(const ID *id,
}
}
- return NULL;
+ return nullptr;
}
int BKE_id_attributes_length(const ID *id, eAttrDomainMask domain_mask, eCustomDataMask mask)
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 63059a49a9e..37ec7a61bcb 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -498,6 +498,7 @@ static bool geometry_color_attributes_remove_poll(bContext *C)
return false;
}
+
void GEOMETRY_OT_color_attribute_remove(wmOperatorType *ot)
{
/* identifiers */
@@ -513,6 +514,57 @@ void GEOMETRY_OT_color_attribute_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+static int geometry_color_attribute_duplicate_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+ ID *id = static_cast<ID *>(ob->data);
+ CustomDataLayer *layer = BKE_id_attributes_active_color_get(id);
+
+ if (layer == nullptr) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CustomDataLayer *newLayer = BKE_id_attribute_duplicate(id, layer, op->reports);
+
+ BKE_id_attributes_active_color_set(id, newLayer);
+
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool geometry_color_attributes_duplicate_poll(bContext *C)
+{
+ if (!geometry_attributes_poll(C)) {
+ return false;
+ }
+
+ Object *ob = ED_object_context(C);
+ ID *data = ob ? static_cast<ID *>(ob->data) : nullptr;
+
+ if (BKE_id_attributes_active_color_get(data) != nullptr) {
+ return true;
+ }
+
+ return false;
+}
+
+void GEOMETRY_OT_color_attribute_duplicate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Duplicate Color Attribute";
+ ot->description = "Duplicate color attribute";
+ ot->idname = "GEOMETRY_OT_color_attribute_duplicate";
+
+ /* api callbacks */
+ ot->exec = geometry_color_attribute_duplicate_exec;
+ ot->poll = geometry_color_attributes_duplicate_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
static void geometry_attribute_convert_ui(bContext *UNUSED(C), wmOperator *op)
{
uiLayout *layout = op->layout;
diff --git a/source/blender/editors/geometry/geometry_intern.hh b/source/blender/editors/geometry/geometry_intern.hh
index bbcb682d6bf..a1000a5d01f 100644
--- a/source/blender/editors/geometry/geometry_intern.hh
+++ b/source/blender/editors/geometry/geometry_intern.hh
@@ -17,6 +17,7 @@ void GEOMETRY_OT_attribute_remove(struct wmOperatorType *ot);
void GEOMETRY_OT_color_attribute_add(struct wmOperatorType *ot);
void GEOMETRY_OT_color_attribute_remove(struct wmOperatorType *ot);
void GEOMETRY_OT_color_attribute_render_set(struct wmOperatorType *ot);
+void GEOMETRY_OT_color_attribute_duplicate(struct wmOperatorType *ot);
void GEOMETRY_OT_attribute_convert(struct wmOperatorType *ot);
} // namespace blender::ed::geometry
diff --git a/source/blender/editors/geometry/geometry_ops.cc b/source/blender/editors/geometry/geometry_ops.cc
index 23f6e6f29f4..acac757ecf1 100644
--- a/source/blender/editors/geometry/geometry_ops.cc
+++ b/source/blender/editors/geometry/geometry_ops.cc
@@ -22,5 +22,6 @@ void ED_operatortypes_geometry(void)
WM_operatortype_append(GEOMETRY_OT_color_attribute_add);
WM_operatortype_append(GEOMETRY_OT_color_attribute_remove);
WM_operatortype_append(GEOMETRY_OT_color_attribute_render_set);
+ WM_operatortype_append(GEOMETRY_OT_color_attribute_duplicate);
WM_operatortype_append(GEOMETRY_OT_attribute_convert);
}