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:
authorAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-03-09 18:27:24 +0300
commit29f3af95272590d26f610ae828b2eeee89c82a00 (patch)
treea696a58a2561c48f7ec6166e369e22081e0a64d8 /source/blender/editors/gpencil/gpencil_data.c
parentdcb93126876879d969a30a7865700abd072066f8 (diff)
GPencil: Refactor of Draw Engine, Vertex Paint and all internal functions
This commit is a full refactor of the grease pencil modules including Draw Engine, Modifiers, VFX, depsgraph update, improvements in operators and conversion of Sculpt and Weight paint tools to real brushes. Also, a huge code cleanup has been done at all levels. Thanks to @fclem for his work and yo @pepeland and @mendio for the testing and help in the development. Differential Revision: https://developer.blender.org/D6293
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_data.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c571
1 files changed, 493 insertions, 78 deletions
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index a8c3fb02e11..9b33e999a25 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -292,7 +292,7 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl)) {
@@ -309,15 +309,18 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op)
* - if this is the only layer, this naturally becomes NULL
*/
if (gpl->prev) {
- BKE_gpencil_layer_setactive(gpd, gpl->prev);
+ BKE_gpencil_layer_active_set(gpd, gpl->prev);
}
else {
- BKE_gpencil_layer_setactive(gpd, gpl->next);
+ BKE_gpencil_layer_active_set(gpd, gpl->next);
}
/* delete the layer now... */
BKE_gpencil_layer_delete(gpd, gpl);
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort_all(gpd);
+
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -342,7 +345,7 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot)
static bool gp_active_layer_annotation_poll(bContext *C)
{
bGPdata *gpd = ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
return (gpl != NULL);
}
@@ -373,7 +376,7 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
ED_annotation_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
const int direction = RNA_enum_get(op->ptr, "type") * -1;
@@ -384,6 +387,9 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op)
BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort_all(gpd);
+
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
@@ -441,7 +447,7 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *new_layer;
/* sanity checks */
@@ -460,7 +466,7 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
'.',
offsetof(bGPDlayer, info),
sizeof(new_layer->info));
- BKE_gpencil_layer_setactive(gpd, new_layer);
+ BKE_gpencil_layer_active_set(gpd, new_layer);
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -499,7 +505,7 @@ static bool gp_layer_duplicate_object_poll(bContext *C)
}
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl == NULL) {
return false;
@@ -532,7 +538,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
Object *ob_src = CTX_data_active_object(C);
bGPdata *gpd_src = (bGPdata *)ob_src->data;
- bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
+ bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd_src);
/* Sanity checks. */
if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
@@ -568,7 +574,7 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* Make copy of source stroke. */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
/* Check if material is in destination object,
* otherwise add the slot with the material. */
@@ -630,21 +636,21 @@ enum {
static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
Scene *scene = CTX_data_scene(C);
int mode = RNA_enum_get(op->ptr, "mode");
/* sanity checks */
- if (ELEM(NULL, gpd, gpl)) {
+ if (ELEM(NULL, gpd, gpl_active)) {
return OPERATOR_CANCELLED;
}
if (mode == 0) {
- BKE_gpencil_frame_addcopy(gpl, CFRA);
+ BKE_gpencil_frame_addcopy(gpl_active, CFRA);
}
else {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
BKE_gpencil_frame_addcopy(gpl, CFRA);
}
@@ -700,16 +706,13 @@ static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op)
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || (mode == GP_FRAME_CLEAN_FILL_ALL)) {
- bGPDstroke *gps, *gpsn;
if (gpf == NULL) {
continue;
}
/* simply delete strokes which are no fill */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -778,8 +781,6 @@ static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- bGPDstroke *gps = NULL;
- bGPDstroke *gpsn = NULL;
for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
@@ -788,9 +789,7 @@ static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
}
/* simply delete strokes which are no loose */
- for (gps = gpf->strokes.first; gps; gps = gpsn) {
- gpsn = gps->next;
-
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -861,7 +860,7 @@ void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
static int gp_hide_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
bool unselected = RNA_boolean_get(op->ptr, "unselected");
/* sanity checks */
@@ -870,10 +869,8 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
}
if (unselected) {
- bGPDlayer *gpl;
-
/* hide unselected */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl != layer) {
gpl->flag |= GP_LAYER_HIDE;
}
@@ -946,7 +943,6 @@ static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
static int gp_reveal_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
const bool select = RNA_boolean_get(op->ptr, "select");
/* sanity checks */
@@ -954,8 +950,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_HIDE) {
gpl->flag &= ~GP_LAYER_HIDE;
@@ -1008,7 +1003,6 @@ void GPENCIL_OT_reveal(wmOperatorType *ot)
static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1016,7 +1010,7 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers non-editable */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag |= GP_LAYER_LOCKED;
}
@@ -1048,7 +1042,6 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot)
static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl;
/* sanity checks */
if (gpd == NULL) {
@@ -1056,7 +1049,7 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
}
/* make all layers editable again */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
@@ -1087,8 +1080,7 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot)
static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
- bGPDlayer *gpl;
+ bGPDlayer *layer = BKE_gpencil_layer_active_get(gpd);
int flags = GP_LAYER_LOCKED;
bool isolate = false;
@@ -1102,7 +1094,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
/* Test whether to isolate or clear all flags */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* Skip if this is the active layer */
if (gpl == layer) {
continue;
@@ -1121,7 +1113,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
/* TODO: Include onion-skinning on this list? */
if (isolate) {
/* Set flags on all "other" layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl == layer) {
continue;
}
@@ -1132,7 +1124,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
}
else {
/* Clear flags - Restore everything else */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~flags;
}
}
@@ -1172,7 +1164,7 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
static int gp_merge_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_next = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_next = BKE_gpencil_layer_active_get(gpd);
bGPDlayer *gpl_current = gpl_next->prev;
if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
@@ -1191,7 +1183,7 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
/* try to find frame in current layer */
bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, POINTER_FROM_INT(gpf->framenum));
if (!frame) {
- bGPDframe *actframe = BKE_gpencil_layer_getframe(
+ bGPDframe *actframe = BKE_gpencil_layer_frame_get(
gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
/* duplicate strokes of current active frame */
@@ -1203,10 +1195,29 @@ static int gp_merge_layer_exec(bContext *C, wmOperator *op)
BLI_movelisttolist(&frame->strokes, &gpf->strokes);
}
+ /* Add Masks to destination layer. */
+ LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl_next->mask_layers) {
+ /* Don't add merged layers or missing layer names. */
+ if (!BKE_gpencil_layer_named_get(gpd, mask->name) || STREQ(mask->name, gpl_next->info) ||
+ STREQ(mask->name, gpl_current->info)) {
+ continue;
+ }
+ if (!BKE_gpencil_layer_mask_named_get(gpl_current, mask->name)) {
+ bGPDlayer_Mask *mask_new = MEM_dupallocN(mask);
+ BLI_addtail(&gpl_current->mask_layers, mask_new);
+ gpl_current->act_mask++;
+ }
+ }
+ /* Set destination layer as active. */
+ BKE_gpencil_layer_active_set(gpd, gpl_current);
+
/* Now delete next layer */
BKE_gpencil_layer_delete(gpd, gpl_next);
BLI_ghash_free(gh_frames_cur, NULL, NULL);
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl_current);
+
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -1268,7 +1279,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op)
}
/* Set active layer */
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
/* updates */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -1297,6 +1308,49 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot)
RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
}
+static int gp_layer_active_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+ int layer_num = RNA_int_get(op->ptr, "layer");
+
+ /* Try to get layer */
+ bGPDlayer *gpl = BLI_findlink(&gpd->layers, layer_num);
+
+ if (gpl == NULL) {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num);
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Set active layer */
+ BKE_gpencil_layer_active_set(gpd, gpl);
+
+ /* updates */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Active Layer";
+ ot->idname = "GPENCIL_OT_layer_active";
+ ot->description = "Active Grease Pencil layer";
+
+ /* callbacks */
+ ot->exec = gp_layer_active_exec;
+ ot->poll = gp_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* GPencil layer to use. */
+ ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
/* ************************************************ */
/* ******************* Arrange Stroke Up/Down in drawing order ************************** */
@@ -1312,7 +1366,7 @@ static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
- bGPDlayer *gpl_act = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *gpl_act = BKE_gpencil_layer_active_get(gpd);
/* sanity checks */
if (ELEM(NULL, gpd, gpl_act, gpl_act->actframe)) {
@@ -1469,7 +1523,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
}
}
/* try to find slot */
- int idx = BKE_gpencil_object_material_get_index(ob, ma);
+ int idx = BKE_gpencil_object_material_index_get(ob, ma);
if (idx < 0) {
return OPERATOR_CANCELLED;
}
@@ -1494,7 +1548,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
continue;
}
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
@@ -1562,15 +1616,15 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
Material *tmp_ma = BKE_object_material_get(ob, i + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* only if selected */
if (gps->flag & GP_STROKE_SELECT) {
@@ -1581,7 +1635,7 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
/* unlock color */
Material *tmp_ma = BKE_object_material_get(ob, gps->mat_nr + 1);
if (tmp_ma) {
- tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ tmp_ma->gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -1619,28 +1673,273 @@ void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
/* ************************************************ */
/* Drawing Brushes Operators */
-/* ******************* Brush create presets ************************** */
-static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
+/* ******************* Brush resets ************************** */
+static int gp_brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- BKE_brush_gpencil_presets(bmain, ts);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ Brush *brush = NULL;
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ Paint *paint = &ts->gp_paint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ Paint *paint = &ts->gp_sculptpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ Paint *paint = &ts->gp_weightpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ Paint *paint = &ts->gp_vertexpaint->paint;
+ brush = paint->brush;
+ if (brush && brush->gpencil_settings) {
+ BKE_gpencil_brush_preset_set(bmain, brush, brush->gpencil_settings->preset_type);
+ }
+ break;
+ }
+ default:
+ break;
+ }
/* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_brush_reset(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Reset Brush";
+ ot->idname = "GPENCIL_OT_brush_reset";
+ ot->description = "Reset Brush to default parameters";
+
+ /* api callbacks */
+ ot->exec = gp_brush_reset_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static Brush *gp_brush_get_first_by_mode(Main *bmain,
+ Paint *UNUSED(paint),
+ const enum eContextObjectMode mode,
+ char tool)
+{
+ Brush *brush_next = NULL;
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
+ brush_next = brush->id.next;
+
+ if (brush->gpencil_settings == NULL) {
+ continue;
+ }
+
+ if ((mode == CTX_MODE_PAINT_GPENCIL) && (brush->gpencil_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_SCULPT_GPENCIL) && (brush->gpencil_sculpt_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_WEIGHT_GPENCIL) && (brush->gpencil_weight_tool == tool)) {
+ return brush;
+ }
+
+ if ((mode == CTX_MODE_VERTEX_GPENCIL) && (brush->gpencil_vertex_tool == tool)) {
+ return brush;
+ }
+ }
+
+ return NULL;
+}
+
+static void gp_brush_delete_mode_brushes(Main *bmain,
+ Paint *paint,
+ const enum eContextObjectMode mode)
+{
+ Brush *brush_active = paint->brush;
+ Brush *brush_next = NULL;
+ for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
+ brush_next = brush->id.next;
+
+ if ((brush->gpencil_settings == NULL) && (brush->ob_mode != OB_MODE_PAINT_GPENCIL)) {
+ continue;
+ }
+
+ short preset = (brush->gpencil_settings) ? brush->gpencil_settings->preset_type :
+ GP_BRUSH_PRESET_UNKNOWN;
+
+ if (preset != GP_BRUSH_PRESET_UNKNOWN) {
+ /* Verify to delete only the brushes of the current mode. */
+ if (mode == CTX_MODE_PAINT_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_AIRBRUSH) || (preset > GP_BRUSH_PRESET_TINT)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_tool != brush->gpencil_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_SCULPT_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_SMOOTH_STROKE) || (preset > GP_BRUSH_PRESET_CLONE_STROKE)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_sculpt_tool != brush->gpencil_sculpt_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_WEIGHT_GPENCIL) {
+ if (preset != GP_BRUSH_PRESET_DRAW_WEIGHT) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_weight_tool != brush->gpencil_weight_tool)) {
+ continue;
+ }
+ }
+
+ if (mode == CTX_MODE_VERTEX_GPENCIL) {
+ if ((preset < GP_BRUSH_PRESET_VERTEX_DRAW) || (preset > GP_BRUSH_PRESET_VERTEX_REPLACE)) {
+ continue;
+ }
+ if ((brush_active) && (brush_active->gpencil_vertex_tool != brush->gpencil_vertex_tool)) {
+ continue;
+ }
+ }
+ }
+
+ /* Before delete, unpinn any material of the brush. */
+ if ((brush->gpencil_settings) && (brush->gpencil_settings->material != NULL)) {
+ brush->gpencil_settings->material = NULL;
+ brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
+ }
+
+ BKE_brush_delete(bmain, brush);
+ }
+}
+
+static int gp_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ Paint *paint = NULL;
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ paint = &ts->gp_paint->paint;
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ paint = &ts->gp_sculptpaint->paint;
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ paint = &ts->gp_weightpaint->paint;
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ paint = &ts->gp_vertexpaint->paint;
+ break;
+ }
+ default:
+ break;
+ }
+
+ char tool = '0';
+ if (paint) {
+ Brush *brush_active = paint->brush;
+ if (brush_active) {
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ tool = brush_active->gpencil_tool;
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ tool = brush_active->gpencil_sculpt_tool;
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ tool = brush_active->gpencil_weight_tool;
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ tool = brush_active->gpencil_vertex_tool;
+ break;
+ }
+ default: {
+ tool = brush_active->gpencil_tool;
+ break;
+ }
+ }
+ }
+
+ gp_brush_delete_mode_brushes(bmain, paint, mode);
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL: {
+ BKE_brush_gpencil_paint_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_SCULPT_GPENCIL: {
+ BKE_brush_gpencil_sculpt_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_WEIGHT_GPENCIL: {
+ BKE_brush_gpencil_weight_presets(bmain, ts);
+ break;
+ }
+ case CTX_MODE_VERTEX_GPENCIL: {
+ BKE_brush_gpencil_vertex_presets(bmain, ts);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ BKE_paint_toolslots_brush_validate(bmain, paint);
+
+ /* Set Again the first brush of the mode. */
+ Brush *deft_brush = gp_brush_get_first_by_mode(bmain, paint, mode, tool);
+ if (deft_brush) {
+ BKE_paint_brush_set(paint, deft_brush);
+ }
+ /* notifiers */
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, NULL);
+ }
return OPERATOR_FINISHED;
}
-void GPENCIL_OT_brush_presets_create(wmOperatorType *ot)
+void GPENCIL_OT_brush_reset_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create Preset Brushes";
- ot->idname = "GPENCIL_OT_brush_presets_create";
- ot->description = "Create a set of predefined Grease Pencil drawing brushes";
+ ot->name = "Reset All Brushes";
+ ot->idname = "GPENCIL_OT_brush_reset_all";
+ ot->description = "Delete all mode brushes and recreate a default set";
/* api callbacks */
- ot->exec = gp_brush_presets_create_exec;
+ ot->exec = gp_brush_reset_all_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2323,9 +2622,9 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
BKE_object_defgroup_unique_name(vgroup, ob_active);
BLI_addtail(&ob_active->defbase, vgroup);
/* update vertex groups in strokes in original data */
- for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
- for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
MDeformVert *dvert;
int i;
for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
@@ -2372,12 +2671,12 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
float inverse_diff_mat[4][4];
/* recalculate all stroke points */
- ED_gpencil_parent_location(depsgraph, ob_iter, gpd_src, gpl_src, diff_mat);
+ BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
invert_m4_m4(inverse_diff_mat, diff_mat);
Material *ma_src = NULL;
for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* Reassign material. Look old material and try to find in destination. */
ma_src = BKE_gpencil_material(ob_src, gps->mat_nr + 1);
@@ -2468,7 +2767,8 @@ static bool gpencil_active_color_poll(bContext *C)
return false;
}
-/* **************** Lock and hide any color non used in current layer ************************** */
+/* **************** Lock and hide any color non used in current layer **************************
+ */
static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -2491,16 +2791,16 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
+ gp_style->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
/* loop all selected strokes and unlock any color used in active layer */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* only editable and visible layers are considered */
- if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
+ if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
(gpl->flag & GP_LAYER_ACTIVE)) {
for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
/* skip strokes that are invalid for current view */
@@ -2514,8 +2814,8 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
gp_style = ma->gp_style;
/* unlock/unhide color if not unlocked before */
if (gp_style != NULL) {
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
}
}
}
@@ -2555,11 +2855,11 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
MaterialGPencilStyle *active_color = BKE_gpencil_material_settings(ob, ob->actcol);
MaterialGPencilStyle *gp_style;
- int flags = GP_STYLE_COLOR_LOCKED;
+ int flags = GP_MATERIAL_LOCKED;
bool isolate = false;
if (RNA_boolean_get(op->ptr, "affect_visibility")) {
- flags |= GP_STYLE_COLOR_HIDE;
+ flags |= GP_MATERIAL_HIDE;
}
if (ELEM(NULL, gpd, active_color)) {
@@ -2677,7 +2977,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
if (ma) {
color = ma->gp_style;
if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
+ color->flag |= GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2685,7 +2985,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
}
else {
/* hide selected/active */
- active_color->flag |= GP_STYLE_COLOR_HIDE;
+ active_color->flag |= GP_MATERIAL_HIDE;
}
/* updates */
@@ -2739,7 +3039,7 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ gp_style->flag &= ~GP_MATERIAL_HIDE;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2792,7 +3092,7 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2845,7 +3145,7 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_gpencil_material(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ gp_style->flag &= ~GP_MATERIAL_LOCKED;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -2900,7 +3200,7 @@ static int gpencil_color_select_exec(bContext *C, wmOperator *op)
if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
/* verify something to do */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
@@ -3057,3 +3357,118 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C,
return true;
}
+
+/* Masking operators */
+static int gp_layer_mask_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
+ if (gpl_active == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ char name[128];
+ RNA_string_get(op->ptr, "name", name);
+ bGPDlayer *gpl = BKE_gpencil_layer_named_get(gpd, name);
+
+ if (gpl == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to find layer to add");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (gpl == gpl_active) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add active layer as mask");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (BKE_gpencil_layer_mask_named_get(gpl_active, name)) {
+ BKE_report(op->reports, RPT_ERROR, "Layer already added");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (gpl_active->act_mask == 256) {
+ BKE_report(op->reports, RPT_ERROR, "Maximum number of masking layers reached");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_gpencil_layer_mask_add(gpl_active, name);
+
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl_active);
+
+ /* notifiers */
+ if (gpd) {
+ DEG_id_tag_update(&gpd->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ }
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_mask_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add New Mask Layer";
+ ot->idname = "GPENCIL_OT_layer_mask_add";
+ ot->description = "Add new layer as masking";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_mask_add_exec;
+ ot->poll = gp_add_poll;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", NULL, 128, "Layer", "Name of the layer");
+}
+
+static int gp_layer_mask_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+ if (gpl == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if (gpl->act_mask > 0) {
+ bGPDlayer_Mask *mask = BLI_findlink(&gpl->mask_layers, gpl->act_mask - 1);
+ if (mask != NULL) {
+ BKE_gpencil_layer_mask_remove(gpl, mask);
+ if ((gpl->mask_layers.first != NULL) && (gpl->act_mask == 0)) {
+ gpl->act_mask = 1;
+ }
+ }
+ }
+
+ /* Reorder masking. */
+ BKE_gpencil_layer_mask_sort(gpd, gpl);
+
+ /* notifiers */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_layer_mask_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Mask Layer";
+ ot->idname = "GPENCIL_OT_layer_mask_remove";
+ ot->description = "Remove Layer Mask";
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* callbacks */
+ ot->exec = gp_layer_mask_remove_exec;
+ ot->poll = gp_active_layer_poll;
+}