diff --git a/scripts/startup/bl_ui/properties_material_gpencil.py b/scripts/startup/bl_ui/properties_material_gpencil.py index 53246ef8b57..70cd6088912 100644 --- a/scripts/startup/bl_ui/properties_material_gpencil.py +++ b/scripts/startup/bl_ui/properties_material_gpencil.py @@ -27,6 +27,13 @@ class GPENCIL_MT_material_context_menu(Menu): layout.operator("grease_pencil.material_unlock_all", icon='UNLOCKED', text="Unlock All") layout.operator("grease_pencil.material_lock_unselected", text="Lock Unselected") layout.operator("grease_pencil.material_lock_unused", text="Lock Unused") + + layout.separator() + + layout.operator("grease_pencil.material_copy_to_object", text="Copy Material to Selected").only_active = True + layout.operator("grease_pencil.material_copy_to_object", + text="Copy All Materials to Selected").only_active = False + else: layout.operator("gpencil.material_reveal", icon='RESTRICT_VIEW_OFF', text="Show All") layout.operator("gpencil.material_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True diff --git a/source/blender/blenkernel/BKE_grease_pencil.hh b/source/blender/blenkernel/BKE_grease_pencil.hh index 6cfce30a4b0..8bb5aac8b3f 100644 --- a/source/blender/blenkernel/BKE_grease_pencil.hh +++ b/source/blender/blenkernel/BKE_grease_pencil.hh @@ -818,7 +818,6 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil_src, GreasePencil *grease_pencil_dst); -int BKE_grease_pencil_object_material_index_get(Object *ob, Material *ma); int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name); Material *BKE_grease_pencil_object_material_new(Main *bmain, Object *ob, diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 6bf78e69673..90a90ce31fb 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -114,6 +114,9 @@ bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_used(struct Object *object, short actcol); +int BKE_object_material_index_get(Object *ob, Material *ma); +int BKE_object_material_ensure(Main *bmain, Object *ob, Material *material); + struct Material *BKE_gpencil_material(struct Object *ob, short act); struct MaterialGPencilStyle *BKE_gpencil_material_settings(struct Object *ob, short act); diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 283bb9b4ebf..4e02c53c941 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -1223,19 +1223,6 @@ void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil /** \name Grease Pencil material functions * \{ */ -int BKE_grease_pencil_object_material_index_get(Object *ob, Material *ma) -{ - short *totcol = BKE_object_material_len_p(ob); - Material *read_ma = nullptr; - for (short i = 0; i < *totcol; i++) { - read_ma = BKE_object_material_get(ob, i + 1); - if (ma == read_ma) { - return i; - } - } - return -1; -} - int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name) { short *totcol = BKE_object_material_len_p(ob); @@ -1311,7 +1298,7 @@ Material *BKE_grease_pencil_object_material_ensure_from_brush(Main *bmain, Material *ma = BKE_grease_pencil_brush_material_get(brush); /* check if the material is already on object material slots and add it if missing */ - if (ma && BKE_grease_pencil_object_material_index_get(ob, ma) < 0) { + if (ma && BKE_object_material_index_get(ob, ma) < 0) { BKE_object_material_slot_add(bmain, ob); BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); } diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 9051f075b53..4c263ca3b4e 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -823,6 +823,33 @@ void BKE_id_material_eval_ensure_default_slot(ID *id) } } +int BKE_object_material_index_get(Object *ob, Material *ma) +{ + short *totcol = BKE_object_material_len_p(ob); + Material *read_ma = nullptr; + for (short i = 0; i < *totcol; i++) { + read_ma = BKE_object_material_get(ob, i + 1); + if (ma == read_ma) { + return i; + } + } + return -1; +} + +int BKE_object_material_ensure(Main *bmain, Object *ob, Material *material) +{ + if (!material) { + return -1; + } + int index = BKE_object_material_index_get(ob, material); + if (index < 0) { + BKE_object_material_slot_add(bmain, ob); + BKE_object_material_assign(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF); + return ob->totcol - 1; + } + return index; +} + Material *BKE_gpencil_material(Object *ob, short act) { Material *ma = BKE_object_material_get(ob, act); diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc index d8106bb7c3c..7b1214ee25b 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc @@ -334,6 +334,76 @@ static void GREASE_PENCIL_OT_material_lock_unselected(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Copy Materials to Selected Objects + * \{ */ + +static int grease_pencil_material_copy_to_object_exec(bContext *C, wmOperator *op) +{ + using namespace blender; + using namespace blender::bke; + + Main *bmain = CTX_data_main(C); + const bool only_active = RNA_boolean_get(op->ptr, "only_active"); + Object *ob_src = CTX_data_active_object(C); + Material *ma_active = BKE_object_material_get(ob_src, ob_src->actcol); + if (ma_active == nullptr) { + return OPERATOR_CANCELLED; + } + + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + if ((ob == ob_src) || (ob->type != OB_GREASE_PENCIL)) { + continue; + } + /* Duplicate materials. */ + for (const int i : IndexRange(ob_src->totcol)) { + Material *ma_src = BKE_object_material_get(ob_src, i + 1); + if (only_active && ma_src != ma_active) { + continue; + } + + if (ma_src == nullptr) { + continue; + } + + BKE_object_material_ensure(bmain, ob, ma_src); + } + + DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, nullptr); + + return OPERATOR_FINISHED; +} + +static void GREASE_PENCIL_OT_material_copy_to_object(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* Identifiers. */ + ot->name = "Copy Materials to Selected Object"; + ot->idname = "GREASE_PENCIL_OT_material_copy_to_object"; + ot->description = "Append Materials of the active Grease Pencil to other object"; + + /* Callbacks. */ + ot->exec = grease_pencil_material_copy_to_object_exec; + ot->poll = active_grease_pencil_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + prop = RNA_def_boolean(ot->srna, + "only_active", + true, + "Only Active", + "Append only active material, uncheck to append all materials"); + + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + +/** \} */ + } // namespace blender::ed::greasepencil void ED_operatortypes_grease_pencil_material() @@ -345,4 +415,5 @@ void ED_operatortypes_grease_pencil_material() WM_operatortype_append(GREASE_PENCIL_OT_material_unlock_all); WM_operatortype_append(GREASE_PENCIL_OT_material_lock_unused); WM_operatortype_append(GREASE_PENCIL_OT_material_lock_unselected); + WM_operatortype_append(GREASE_PENCIL_OT_material_copy_to_object); } diff --git a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc index 2fae6f022a5..b6cdffd9c64 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc @@ -453,7 +453,7 @@ void PaintOperation::on_stroke_begin(const bContext &C, const InputSample &start Material *material = BKE_grease_pencil_object_material_ensure_from_active_input_brush( CTX_data_main(&C), object, brush); - const int material_index = BKE_grease_pencil_object_material_index_get(object, material); + const int material_index = BKE_object_material_index_get(object, material); PaintOperationExecutor executor{C}; executor.process_start_sample(*this, C, start_sample, material_index);