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
This commit is contained in:
parent
f69c565a33
commit
9c28f0eb37
Notes:
blender-bot
2023-05-29 09:17:12 +02:00
Referenced by issue #97706, Duplicate active color attribute
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue