diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 5f2ac7e7123..bb059d6befc 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -832,6 +832,11 @@ class GreasePencilMaterialsPanel: layout = self.layout show_full_ui = (self.bl_space_type == 'PROPERTIES') + is_view3d = (self.bl_space_type == 'VIEW_3D') + tool_settings = context.scene.tool_settings + gpencil_paint = tool_settings.gpencil_paint + brush = gpencil_paint.brush + ob = context.object row = layout.row() @@ -841,6 +846,12 @@ class GreasePencilMaterialsPanel: row.template_list("GPENCIL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows) + # if topbar popover and brush pinned, disable + if is_view3d and brush is not None: + gp_settings = brush.gpencil_settings + if gp_settings.use_material_pin: + row.enabled = False + col = row.column(align=True) if show_full_ui: col.operator("object.material_slot_add", icon='ADD', text="") diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 0e687452e5c..7b9b324066a 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -316,7 +316,8 @@ class _draw_left_context_mode: def draw_color_selector(): ma = gp_settings.material row = layout.row(align=True) - + if not gp_settings.use_material_pin: + ma = context.object.active_material icon_id = 0 if ma: icon_id = ma.id_data.preview.icon_id diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 212427dead9..17dd35d9fc4 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1679,7 +1679,15 @@ class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel): gp_settings = brush.gpencil_settings if brush.gpencil_tool in {'DRAW', 'FILL'}: - layout.row(align=True).template_ID(gp_settings, "material") + row = layout.row(align=True) + row_mat = row.row() + if gp_settings.use_material_pin: + row_mat.template_ID(gp_settings, "material", live_icon=True) + else: + row_mat.template_ID(context.active_object, "active_material", live_icon=True) + row_mat.enabled = False # will otherwise allow to change material in active slot + + row.prop(gp_settings, "use_material_pin", text="") if not self.is_popover: from .properties_paint_common import ( diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 9360962317c..30746af0b53 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -56,7 +56,6 @@ void BKE_brush_free(struct Brush *brush); void BKE_brush_sculpt_reset(struct Brush *brush); void BKE_brush_gpencil_presets(struct bContext *C); -void BKE_brush_update_material(struct Main *bmain, struct Material *ma, struct Brush *exclude_brush); /* image icon function */ struct ImBuf *get_brush_icon(struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 353ba61b70d..e94ba27a8ea 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -132,6 +132,21 @@ void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active); void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); struct Material *BKE_gpencil_get_material_from_brush(struct Brush *brush); +void BKE_gpencil_brush_set_material(struct Brush *brush, struct Material *material); + +struct Material *BKE_gpencil_handle_brush_material(struct Main *bmain, struct Object *ob, struct Brush *brush); +int BKE_gpencil_handle_material(struct Main *bmain, struct Object *ob, struct Material *material); + +struct Material *BKE_gpencil_handle_new_material(struct Main *bmain, struct Object *ob, const char *name, int *r_index); + +struct Material *BKE_gpencil_get_material_for_brush(struct Object *ob, struct Brush *brush); +int BKE_gpencil_get_material_index_for_brush(struct Object *ob, struct Brush *brush); + +struct Material *BKE_gpencil_current_input_toolsettings_material(struct Main *bmain, struct Object *ob, struct ToolSettings *ts); +struct Material *BKE_gpencil_current_input_brush_material(struct Main *bmain, struct Object *ob, struct Brush *brush); +struct Material *BKE_gpencil_current_input_material(struct Main *bmain, struct Object *ob); + + struct Material *BKE_gpencil_material_ensure(struct Main *bmain, struct Object *ob); /* object boundbox */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index c959504f84f..ea5605d8ed1 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -540,24 +540,6 @@ void BKE_brush_gpencil_presets(bContext *C) } -void BKE_brush_update_material(Main *bmain, Material *ma, Brush *exclude_brush) -{ - for (Brush *brush = bmain->brushes.first; brush; brush = brush->id.next) { - if ((exclude_brush != NULL) && (brush == exclude_brush)) { - continue; - } - - if (brush->gpencil_settings != NULL) { - BrushGpencilSettings *gpencil_settings = brush->gpencil_settings; - if (((gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) == 0) && - (gpencil_settings->material != ma)) - { - gpencil_settings->material = ma; - } - } - } -} - struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode) { Brush *brush; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index eb6fc9ceeeb..263bf4e57e2 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -996,6 +996,136 @@ Material *BKE_gpencil_get_material_from_brush(Brush *brush) return ma; } +void BKE_gpencil_brush_set_material(Brush *brush, Material *ma) +{ + BLI_assert(brush); + BLI_assert(brush->gpencil_settings); + if (brush->gpencil_settings->material != ma) { + if (brush->gpencil_settings->material) { + id_us_min(&brush->gpencil_settings->material->id); + } + if (ma) { + id_us_plus(&ma->id); + } + brush->gpencil_settings->material = ma; + } +} + +/* Adds the pinned material to the object if necessary. */ +Material *BKE_gpencil_handle_brush_material(Main *bmain, Object *ob, Brush *brush) +{ + if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { + Material *ma = BKE_gpencil_get_material_from_brush(brush); + + /* check if the material is already on object material slots and add it if missing */ + if (ma && BKE_gpencil_get_material_index(ob, ma) < 0) { + BKE_object_material_slot_add(bmain, ob); + assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); + } + + return ma; + } + else { + /* using active material instead */ + return give_current_material(ob, ob->actcol); + } +} + +/* Assigns the material to object (if not already present) and returns its index (mat_nr). */ +int BKE_gpencil_handle_material(Main *bmain, Object *ob, Material *material) +{ + if (!material) { + return -1; + } + int index = BKE_gpencil_get_material_index(ob, material); + if (index < 0) { + BKE_object_material_slot_add(bmain, ob); + assign_material(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF); + return ob->totcol - 1; + } + return index; +} + +/** Creates a new gpencil material and assigns it to object. + * + * \param *r_index: value is set to zero based index of the new material if r_index is not NULL + */ +Material *BKE_gpencil_handle_new_material(Main *bmain, Object *ob, const char *name, int *r_index) +{ + Material *ma = BKE_material_add_gpencil(bmain, name); + id_us_min(&ma->id); /* no users yet */ + + BKE_object_material_slot_add(bmain, ob); + assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); + + if (r_index) { + *r_index = ob->actcol - 1; + } + return ma; +} + +/* Returns the material for a brush with respect to its pinned state. */ +Material *BKE_gpencil_get_material_for_brush(Object *ob, Brush *brush) +{ + if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { + Material *ma = BKE_gpencil_get_material_from_brush(brush); + return ma; + } + else { + return give_current_material(ob, ob->actcol); + } +} + +/* Returns the material index for a brush with respect to its pinned state. */ +int BKE_gpencil_get_material_index_for_brush(Object *ob, Brush *brush) +{ + if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { + return BKE_gpencil_get_material_index(ob, brush->gpencil_settings->material); + } + else { + return ob->actcol - 1; + } +} + +/* Guaranteed to return a material assigned to object. Returns never NULL. */ +Material *BKE_gpencil_current_input_toolsettings_material(Main *bmain, Object *ob, ToolSettings *ts) +{ + if (ts && ts->gp_paint && ts->gp_paint->paint.brush) { + return BKE_gpencil_current_input_brush_material(bmain, ob, ts->gp_paint->paint.brush); + } + else { + return BKE_gpencil_current_input_brush_material(bmain, ob, NULL); + } +} + +/* Guaranteed to return a material assigned to object. Returns never NULL. */ +Material *BKE_gpencil_current_input_brush_material(Main *bmain, Object *ob, Brush *brush) +{ + Material *ma; + if (brush) { + ma = BKE_gpencil_handle_brush_material(bmain, ob, brush); + if (!ma && brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { + /* it is easier to just unpin a NULL material, instead of setting a new one */ + brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED; + } + } + if (ma) { + return ma; + } + return BKE_gpencil_current_input_material(bmain, ob); +} + +/* Guaranteed to return a material assigned to object. Returns never NULL. Only use this for materials unrelated to user input */ +Material *BKE_gpencil_current_input_material(Main *bmain, Object *ob) +{ + Material *ma; + ma = give_current_material(ob, ob->actcol); + if (ma) { + return ma; + } + return BKE_gpencil_handle_new_material(bmain, ob, "Material", NULL); +} + /* Get active color, and add all default settings if we don't find anything */ Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob) { @@ -1005,15 +1135,8 @@ Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob) if (ELEM(NULL, bmain, ob)) return NULL; - ma = give_current_material(ob, ob->actcol); - if (ma == NULL) { - if (ob->totcol == 0) { - BKE_object_material_slot_add(bmain, ob); - } - ma = BKE_material_add_gpencil(bmain, DATA_("Material")); - assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); - } - else if (ma->gp_style == NULL) { + ma = BKE_gpencil_current_input_material(bmain, ob); + if (ma->gp_style == NULL) { BKE_material_init_gpencil_settings(ma); } @@ -1538,7 +1661,7 @@ void BKE_gpencil_stats_update(bGPdata *gpd) } -/* get material index */ +/* get material index (0-based like mat_nr not actcol) */ int BKE_gpencil_get_material_index(Object *ob, Material *ma) { short *totcol = give_totcolp(ob); @@ -1546,11 +1669,11 @@ int BKE_gpencil_get_material_index(Object *ob, Material *ma) for (short i = 0; i < *totcol; i++) { read_ma = give_current_material(ob, i + 1); if (ma == read_ma) { - return i + 1; + return i; } } - return 0; + return -1; } /* Get points of stroke always flat to view not affected by camera view or view position */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 88a96ff098e..f708984e51f 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -164,7 +164,6 @@ Material *BKE_material_add_gpencil(Main *bmain, const char *name) /* grease pencil settings */ if (ma != NULL) { BKE_material_init_gpencil_settings(ma); - BKE_brush_update_material(bmain, ma, NULL); } return ma; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3c5a0f136ba..190b07991e5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2617,8 +2617,19 @@ static void lib_link_brush(FileData *fd, Main *main) brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve); /* link default grease pencil palette */ - if (brush->gpencil_settings != NULL) { - brush->gpencil_settings->material = newlibadr_us(fd, brush->id.lib, brush->gpencil_settings->material); + if (brush->gpencil_settings != NULL) + { + if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) + { + brush->gpencil_settings->material = newlibadr_us(fd, brush->id.lib, brush->gpencil_settings->material); + + if (!brush->gpencil_settings->material) { + brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED; + } + } + else { + brush->gpencil_settings->material = NULL; + } } brush->id.tag &= ~LIB_TAG_NEED_LINK; diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 2710ecc5e5b..475a083ac97 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1355,7 +1355,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T float obscale = mat4_to_scale(ob->obmat); /* use the brush material */ - Material *ma = BKE_gpencil_get_material_from_brush(brush); + Material *ma = BKE_gpencil_get_material_for_brush(ob, brush); if (ma != NULL) { gp_style = ma->gp_style; } diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index a4fbd4002fa..cd28043a6fe 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -60,11 +60,10 @@ static int gpencil_monkey_color( } } + int idx; + /* create a new one */ - BKE_object_material_slot_add(bmain, ob); - ma = BKE_material_add_gpencil(bmain, pct->name); - assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); - id_us_min(&ma->id); + ma = BKE_gpencil_handle_new_material(bmain, ob, pct->name, &idx); copy_v4_v4(ma->gp_style->stroke_rgba, pct->line); copy_v4_v4(ma->gp_style->fill_rgba, pct->fill); @@ -80,7 +79,7 @@ static int gpencil_monkey_color( ma->gp_style->flag |= GP_STYLE_FILL_SHOW; } - return BKE_gpencil_get_material_index(ob, ma) - 1; + return idx; } /* ***************************************************************** */ @@ -1447,10 +1446,6 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) /* set first color as active */ ob->actcol = color_Black + 1; - Material *ma = give_current_material(ob, ob->actcol); - if (ma != NULL) { - BKE_brush_update_material(bmain, ma, NULL); - } /* layers */ /* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */ diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 8b261bf798b..c56cb94c58d 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -60,11 +60,10 @@ static int gp_stroke_material( } } + int idx; + /* create a new one */ - BKE_object_material_slot_add(bmain, ob); - ma = BKE_material_add_gpencil(bmain, pct->name); - assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); - id_us_min(&ma->id); + ma = BKE_gpencil_handle_new_material(bmain, ob, pct->name, &idx); copy_v4_v4(ma->gp_style->stroke_rgba, pct->line); copy_v4_v4(ma->gp_style->fill_rgba, pct->fill); @@ -73,7 +72,7 @@ static int gp_stroke_material( ma->gp_style->flag |= GP_STYLE_FILL_SHOW; } - return BKE_gpencil_get_material_index(ob, ma) - 1; + return idx; } /* ***************************************************************** */ @@ -231,10 +230,6 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) /* set first color as active and in brushes */ ob->actcol = color_black + 1; - Material *ma = give_current_material(ob, ob->actcol); - if (ma != NULL) { - BKE_brush_update_material(bmain, ma, NULL); - } /* layers */ bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false); diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 6e8dd11ee2f..6b646566996 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -1101,14 +1101,10 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) /* Fix color references */ Material *ma = BLI_ghash_lookup(data->new_colors, &new_stroke->mat_nr); - if ((ma) && (BKE_gpencil_get_material_index(ob, ma) > 0)) { - gps->mat_nr = BKE_gpencil_get_material_index(ob, ma) - 1; - CLAMP_MIN(gps->mat_nr, 0); + gps->mat_nr = BKE_gpencil_get_material_index(ob, ma); + if (!ma || gps->mat_nr) { + gps->mat_nr = 0; } - else { - gps->mat_nr = 0; /* only if the color is not found */ - } - /* Adjust all the stroke's points, so that the strokes * get pasted relative to where the cursor is now */ diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 2cdd772f726..a8b31b20182 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -514,15 +514,10 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op) * otherwise add the slot with the material */ Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1); - int idx = BKE_gpencil_get_material_index(ob_dst, ma_src); - if (idx == 0) { - BKE_object_material_slot_add(bmain, ob_dst); - assign_material(bmain, ob_dst, ma_src, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF); - idx = ob_dst->totcol; - } + int idx = BKE_gpencil_handle_material(bmain, ob_dst, ma_src); /* reasign the stroke material to the right slot in destination object */ - gps_dst->mat_nr = idx - 1; + gps_dst->mat_nr = idx; /* add new stroke to frame */ BLI_addtail(&gpf_dst->strokes, gps_dst); @@ -1377,7 +1372,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op) } } /* try to find slot */ - int idx = BKE_gpencil_get_material_index(ob, ma) - 1; + int idx = BKE_gpencil_get_material_index(ob, ma); if (idx < 0) { return OPERATOR_CANCELLED; } @@ -2052,10 +2047,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) for (short i = 0; i < *totcol; i++) { Material *tmp_ma = give_current_material(ob_src, i + 1); - if (BKE_gpencil_get_material_index(ob_dst, tmp_ma) == 0) { - BKE_object_material_slot_add(bmain, ob_dst); - assign_material(bmain, ob_dst, tmp_ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF); - } + BKE_gpencil_handle_material(bmain, ob_dst, tmp_ma); } /* duplicate bGPDlayers */ @@ -2085,24 +2077,12 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) invert_m4_m4(inverse_diff_mat, diff_mat); Material *ma_src = NULL; - int idx; for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* reasign material. Look old material and try to find in dst */ ma_src = give_current_material(ob_src, gps->mat_nr + 1); - if (ma_src != NULL) { - idx = BKE_gpencil_get_material_index(ob_dst, ma_src); - if (idx > 0) { - gps->mat_nr = idx - 1; - } - else { - gps->mat_nr = 0; - } - } - else { - gps->mat_nr = 0; - } + gps->mat_nr = BKE_gpencil_handle_material(bmain, ob_dst, ma_src); bGPDspoint *pt; int i; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index a6b6fc2cbe7..259c9468e76 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1074,10 +1074,7 @@ GHash *gp_copybuf_validate_colormap(bContext *C) char *ma_name = BLI_ghashIterator_getValue(&gh_iter); Material *ma = BLI_ghash_lookup(name_to_ma, ma_name); - if (ma != NULL && BKE_gpencil_get_material_index(ob, ma) == 0) { - BKE_object_material_slot_add(bmain, ob); - assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); - } + BKE_gpencil_handle_material(bmain, ob, ma); /* Store this mapping (for use later when pasting) */ if (!BLI_ghash_haskey(new_colors, POINTER_FROM_INT(*key))) { @@ -1331,14 +1328,8 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) /* Remap material */ Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr)); - if ((ma) && (BKE_gpencil_get_material_index(ob, ma) > 0)) { - new_stroke->mat_nr = BKE_gpencil_get_material_index(ob, ma) - 1; - CLAMP_MIN(new_stroke->mat_nr, 0); - } - else { - new_stroke->mat_nr = 0; /* only if the color is not found */ - } - + new_stroke->mat_nr = BKE_gpencil_get_material_index(ob, ma); + BLI_assert(new_stroke >= 0); /* have to add the material first */ } } } @@ -3914,10 +3905,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) /* create new grease pencil datablock */ gpd_dst = BKE_gpencil_data_addnew(bmain, gpd_src->id.name + 2); ob_dst->data = (bGPdata *)gpd_dst; - - int totslots = ob_dst->totcol; - int totadd = 0; - + /* loop old datablock and separate parts */ if ((mode == GP_SEPARATE_POINT) || (mode == GP_SEPARATE_STROKE)) { CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) @@ -3962,21 +3950,8 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) } /* add duplicate materials */ - ma = give_current_material(ob, gps->mat_nr + 1); - idx = BKE_gpencil_get_material_index(ob_dst, ma); - if (idx == 0) { - - totadd++; - ob_dst->actcol = totadd; - ob_dst->totcol = totadd; - - if (totadd > totslots) { - BKE_object_material_slot_add(bmain, ob_dst); - } - - assign_material(bmain, ob_dst, ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF); - idx = totadd; - } + ma = give_current_material(ob, gps->mat_nr + 1); /* XXX same material can be in multiple slots */ + idx = BKE_gpencil_handle_material(bmain, ob_dst, ma); /* selected points mode */ if (mode == GP_SEPARATE_POINT) { @@ -3984,7 +3959,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps); /* reasign material */ - gps_dst->mat_nr = idx - 1; + gps_dst->mat_nr = idx; /* link to destination frame */ BLI_addtail(&gpf_dst->strokes, gps_dst); @@ -4010,7 +3985,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) /* relink to destination frame */ BLI_addtail(&gpf_dst->strokes, gps); /* reasign material */ - gps->mat_nr = idx - 1; + gps->mat_nr = idx; } } } @@ -4048,21 +4023,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) continue; } ma = give_current_material(ob, gps->mat_nr + 1); - idx = BKE_gpencil_get_material_index(ob_dst, ma); - if (idx == 0) { - totadd++; - ob_dst->actcol = totadd; - ob_dst->totcol = totadd; - - if (totadd > totslots) { - BKE_object_material_slot_add(bmain, ob_dst); - } - - assign_material(bmain, ob_dst, ma, ob_dst->totcol, BKE_MAT_ASSIGN_USERPREF); - idx = totadd; - } - /* reasign material */ - gps->mat_nr = idx - 1; + gps->mat_nr = BKE_gpencil_handle_material(bmain, ob_dst, ma); } } } diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index c8c57c8ffbf..a4b4b699e5e 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1017,12 +1017,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) gps->flag |= GP_STROKE_CYCLIC; gps->flag |= GP_STROKE_3DSPACE; - gps->mat_nr = BKE_gpencil_get_material_index(tgpf->ob, tgpf->mat) - 1; - if (gps->mat_nr < 0) { - BKE_object_material_slot_add(tgpf->bmain, tgpf->ob); - assign_material(tgpf->bmain, tgpf->ob, tgpf->mat, tgpf->ob->totcol, BKE_MAT_ASSIGN_USERPREF); - gps->mat_nr = tgpf->ob->totcol - 1; - } + gps->mat_nr = BKE_gpencil_handle_material(tgpf->bmain, tgpf->ob, tgpf->mat); /* allocate memory for storage points */ gps->totpoints = tgpf->sbuffer_size; @@ -1215,17 +1210,18 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode; tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8)); + int totcol = tgpf->ob->totcol; + /* get color info */ - Material *ma = BKE_gpencil_get_material_from_brush(brush); - /* if no brush defaults, get material and color info */ - if ((ma == NULL) || (ma->gp_style == NULL)) { - ma = BKE_gpencil_material_ensure(bmain, tgpf->ob); - /* assign always the first material to the brush */ - brush->gpencil_settings->material = give_current_material(tgpf->ob, 1); - } + Material *ma = BKE_gpencil_current_input_brush_material(bmain, tgpf->ob, brush); tgpf->mat = ma; + /* check whether the material was newly added */ + if (totcol != tgpf->ob->totcol) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL); + } + /* init undo */ gpencil_undo_init(tgpf->gpd); diff --git a/source/blender/editors/gpencil/gpencil_old.c b/source/blender/editors/gpencil/gpencil_old.c index 5d6abb594ce..47654b69da4 100644 --- a/source/blender/editors/gpencil/gpencil_old.c +++ b/source/blender/editors/gpencil/gpencil_old.c @@ -112,9 +112,7 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *UNUSED(op)) for (bGPDpalettecolor *palcolor = palette->colors.first; palcolor; palcolor = palcolor->next) { /* create material slot */ - BKE_object_material_slot_add(bmain, ob); - Material *ma = BKE_material_add_gpencil(bmain, palcolor->info); - assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF); + Material *ma = BKE_gpencil_handle_new_material(bmain, ob, palcolor->info, NULL); /* copy color settings */ MaterialGPencilStyle *gp_style = ma->gp_style; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index dd949b21743..cd17f7dc640 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -302,6 +302,12 @@ static bool gpencil_draw_poll(bContext *C) return false; } + ToolSettings *ts = CTX_data_scene(C)->toolsettings; + if (!ts->gp_paint->paint.brush) { + CTX_wm_operator_poll_msg_set(C, "Grease Pencil has no active paint tool"); + return false; + } + return true; } else { @@ -1217,7 +1223,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } /* Save material index */ - gps->mat_nr = BKE_gpencil_get_material_index(p->ob, p->material) - 1; + gps->mat_nr = BKE_gpencil_get_material_index_for_brush(p->ob, p->brush); /* calculate UVs along the stroke */ ED_gpencil_calc_stroke_uv(obact, gps); @@ -1834,31 +1840,10 @@ static void gp_init_colors(tGPsdata *p) bGPdata *gpd = p->gpd; Brush *brush = p->brush; - Material *ma = NULL; MaterialGPencilStyle *gp_style = NULL; /* use brush material */ - ma = BKE_gpencil_get_material_from_brush(brush); - - /* if no brush defaults, get material and color info - * NOTE: Ensures that everything we need will exist... - */ - if ((ma == NULL) || (ma->gp_style == NULL)) { - BKE_gpencil_material_ensure(p->bmain, p->ob); - - /* assign always the first material to the brush */ - p->material = give_current_material(p->ob, 1); - brush->gpencil_settings->material = p->material; - } - else { - p->material = ma; - } - - /* check if the material is already on object material slots and add it if missing */ - if (BKE_gpencil_get_material_index(p->ob, p->material) == 0) { - BKE_object_material_slot_add(p->bmain, p->ob); - assign_material(p->bmain, p->ob, ma, p->ob->totcol, BKE_MAT_ASSIGN_USERPREF); - } + p->material = BKE_gpencil_current_input_brush_material(p->bmain, p->ob, brush); /* assign color information to temp tGPsdata */ gp_style = p->material->gp_style; @@ -1996,7 +1981,14 @@ static bool gp_session_initdata(bContext *C, wmOperator *op, tGPsdata *p) /* NOTE: This is only done for 3D view, as Materials aren't used for * annotations in 2D editors */ + int totcol = p->ob->totcol; + gp_init_colors(p); + + /* check whether the material was newly added */ + if (totcol != p->ob->totcol) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL); + } } /* lock axis (in some modes, disable) */ diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 9c4836c5d33..ddfbbded64b 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -137,29 +137,10 @@ static void gp_init_colors(tGPDprimitive *p) bGPdata *gpd = p->gpd; Brush *brush = p->brush; - Material *ma = NULL; MaterialGPencilStyle *gp_style = NULL; /* use brush material */ - ma = BKE_gpencil_get_material_from_brush(brush); - - /* if no brush defaults, get material and color info */ - if ((ma == NULL) || (ma->gp_style == NULL)) { - BKE_gpencil_material_ensure(p->bmain, p->ob); - - /* assign always the first material to the brush */ - p->mat = give_current_material(p->ob, 1); - brush->gpencil_settings->material = p->mat; - } - else { - p->mat = ma; - } - - /* check if the material is already on object material slots and add it if missing */ - if (BKE_gpencil_get_material_index(p->ob, p->mat) == 0) { - BKE_object_material_slot_add(p->bmain, p->ob); - assign_material(p->bmain, p->ob, ma, p->ob->totcol, BKE_MAT_ASSIGN_USERPREF); - } + p->mat = BKE_gpencil_current_input_brush_material(p->bmain,p->ob, brush); /* assign color information to temp data */ gp_style = p->mat->gp_style; @@ -350,7 +331,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) gps->flag |= GP_STROKE_3DSPACE; - gps->mat_nr = BKE_gpencil_get_material_index(tgpi->ob, tgpi->mat) - 1; + gps->mat_nr = BKE_gpencil_get_material_index(tgpi->ob, tgpi->mat); /* allocate memory for storage points, but keep empty */ gps->totpoints = 0; @@ -1130,7 +1111,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) tgpi->gpd->runtime.tot_cp_points = 0; /* getcolor info */ - tgpi->mat = BKE_gpencil_material_ensure(bmain, tgpi->ob); + tgpi->mat = BKE_gpencil_current_input_toolsettings_material(bmain, tgpi->ob, ts); /* set parameters */ tgpi->type = RNA_enum_get(op->ptr, "type"); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 79a92c5a8de..ab116f115cc 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1341,17 +1341,6 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) Main *bmain = CTX_data_main(C); ToolSettings *ts = CTX_data_tool_settings(C); - /* first try to reuse default material */ - if (ob->actcol > 0) { - Material *ma = give_current_material(ob, ob->actcol); - if ((ma) && (ma->gp_style == NULL)) { - BKE_material_init_gpencil_settings(ma); - } - } - - /* ensure color exist */ - BKE_gpencil_material_ensure(bmain, ob); - BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ @@ -1360,6 +1349,9 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) BKE_brush_gpencil_presets(C); } + /* ensure a color exists and is assigned to object */ + BKE_gpencil_current_input_toolsettings_material(bmain, ob, ts); + /* ensure multiframe falloff curve */ if (ts->gp_sculpt.cur_falloff == NULL) { ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -1728,30 +1720,27 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata) } /* get current drawing color */ - ma = BKE_gpencil_get_material_from_brush(brush); - if (ma == NULL) { - BKE_gpencil_material_ensure(bmain, ob); - /* assign the first material to the brush */ - ma = give_current_material(ob, 1); - brush->gpencil_settings->material = ma; - } - gp_style = ma->gp_style; + ma = BKE_gpencil_get_material_for_brush(ob, brush); - /* after some testing, display the size of the brush is not practical because - * is too disruptive and the size of cursor does not change with zoom factor. - * The decision was to use a fix size, instead of brush->thickness value. - */ - if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && - ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && - (brush->gpencil_tool == GPAINT_TOOL_DRAW)) - { - radius = 2.0f; - copy_v3_v3(color, gp_style->stroke_rgba); - } - else { - radius = 5.0f; - copy_v3_v3(color, brush->add_col); + if (ma) { + gp_style = ma->gp_style; + + /* after some testing, display the size of the brush is not practical because + * is too disruptive and the size of cursor does not change with zoom factor. + * The decision was to use a fix size, instead of brush->thickness value. + */ + if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && + ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) && + (brush->gpencil_tool == GPAINT_TOOL_DRAW)) + { + radius = 2.0f; + copy_v3_v3(color, gp_style->stroke_rgba); + } + else { + radius = 5.0f; + copy_v3_v3(color, brush->add_col); + } } } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 0d4a8b8a71f..d78f71bb976 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -559,11 +559,6 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) Material *new_ma = NULL; BKE_id_copy_ex(bmain, &ma->id, (ID **)&new_ma, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); ma = new_ma; - - if (ob != NULL && ob->type == OB_GPENCIL) { - BKE_brush_update_material(bmain, new_ma, NULL); - } - } else { const char *name = DATA_("Material"); diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 7e4482790af..1a35fd8d0fb 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -159,6 +159,7 @@ static EnumPropertyItem rna_enum_gpencil_brush_icons_items[] = { #include "BKE_icons.h" #include "BKE_gpencil.h" #include "BKE_paint.h" +#include "BKE_material.h" #include "WM_api.h" @@ -444,27 +445,8 @@ static void rna_Brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR static void rna_Brush_material_update(bContext *C, PointerRNA *ptr) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Brush *br = (Brush *)ptr->id.data; - int index; - - /* set material slot to same material */ - if ((ob) && (ob->type == OB_GPENCIL) && (br->gpencil_settings != NULL)) { - BrushGpencilSettings *gpencil_settings = br->gpencil_settings; - if (gpencil_settings->material != NULL) { - - index = BKE_gpencil_get_material_index(ob, gpencil_settings->material); - if ((index > 0) && (ob->actcol != index)) { - ob->actcol = index; - /* update other brushes to keep all synchro */ - BKE_brush_update_material(bmain, gpencil_settings->material, br); - } - - } - WM_main_add_notifier(NC_SPACE | ND_SPACE_PROPERTIES, NULL); - } + /* number of material users changed */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_PROPERTIES, NULL); } static void rna_Brush_main_tex_update(bContext *C, PointerRNA *ptr) @@ -723,6 +705,24 @@ static void rna_BrushGpencilSettings_default_eraser_update(Main *bmain, Scene *s } } +static void rna_BrushGpencilSettings_use_material_pin_update(bContext *C, PointerRNA *ptr) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Brush *brush = ptr->id.data; + + if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) { + Material *material = give_current_material(ob, ob->actcol); + BKE_gpencil_brush_set_material(brush, material); + } + else { + BKE_gpencil_brush_set_material(brush, NULL); + } + + /* number of material users changed */ + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_PROPERTIES, NULL); +} + static void rna_BrushGpencilSettings_eraser_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) { ToolSettings *ts = scene->toolsettings; @@ -1337,9 +1337,11 @@ static void rna_def_gpencil_options(BlenderRNA *brna) prop = RNA_def_property(srna, "use_material_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_MATERIAL_PINNED); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_icon(prop, ICON_UNPINNED, 1); RNA_def_property_ui_text(prop, "Pin Material", "Keep material assigned to brush"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_use_material_pin_update"); prop = RNA_def_property(srna, "show_lasso", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_BRUSH_DISSABLE_LASSO); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 53bcb7e0bca..0eaddf0c44e 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -277,14 +277,10 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA static void rna_MaterialIndex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - /* update the material of all brushes not pinned */ Object *ob = (Object *)ptr->id.data; if (ob && ob->type == OB_GPENCIL) { - Material *ma = give_current_material(ob, ob->actcol); - if (ma != NULL) { - BKE_brush_update_material(bmain, ma, NULL); - WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); - } + /* notifying material property in topbar */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); } } @@ -821,6 +817,11 @@ static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value) BLI_assert(BKE_id_is_in_global_main(&ob->id)); BLI_assert(BKE_id_is_in_global_main(value.data)); assign_material(G_MAIN, ob, value.data, ob->actcol, BKE_MAT_ASSIGN_EXISTING); + + if (ob && ob->type == OB_GPENCIL) { + /* notifying material property in topbar */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL); + } } static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNUSED(r_info))