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:
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt1
-rw-r--r--source/blender/editors/gpencil/gpencil_add_blank.c101
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c48
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c156
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c26
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
7 files changed, 253 insertions, 81 deletions
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 47ae90acb74..f7ab72a8a43 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -36,6 +36,7 @@ set(SRC
annotate_paint.c
drawgpencil.c
editaction_gpencil.c
+ gpencil_add_blank.c
gpencil_add_lineart.c
gpencil_add_monkey.c
gpencil_add_stroke.c
diff --git a/source/blender/editors/gpencil/gpencil_add_blank.c b/source/blender/editors/gpencil/gpencil_add_blank.c
new file mode 100644
index 00000000000..3bd61d5c88a
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_add_blank.c
@@ -0,0 +1,101 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup edgpencil
+ */
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_geom.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_gpencil.h"
+
+/* Definition of the most important info from a color */
+typedef struct ColorTemplate {
+ const char *name;
+ float line[4];
+ float fill[4];
+} ColorTemplate;
+
+/* Add color an ensure duplications (matched by name) */
+static int gpencil_stroke_material(Main *bmain, Object *ob, const ColorTemplate *pct)
+{
+ int index;
+ Material *ma = BKE_gpencil_object_material_ensure_by_name(bmain, ob, pct->name, &index);
+
+ copy_v4_v4(ma->gp_style->stroke_rgba, pct->line);
+ srgb_to_linearrgb_v4(ma->gp_style->stroke_rgba, ma->gp_style->stroke_rgba);
+
+ copy_v4_v4(ma->gp_style->fill_rgba, pct->fill);
+ srgb_to_linearrgb_v4(ma->gp_style->fill_rgba, ma->gp_style->fill_rgba);
+
+ return index;
+}
+
+/* ***************************************************************** */
+/* Stroke Geometry */
+
+/* ***************************************************************** */
+/* Color Data */
+
+static const ColorTemplate gp_stroke_material_black = {
+ "Black",
+ {0.0f, 0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+};
+
+/* ***************************************************************** */
+/* Blank API */
+
+/* Add a Simple empty object with one layer and one color. */
+void ED_gpencil_create_blank(bContext *C, Object *ob, float UNUSED(mat[4][4]))
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = (bGPdata *)ob->data;
+
+ /* create colors */
+ int color_black = gpencil_stroke_material(bmain, ob, &gp_stroke_material_black);
+
+ /* set first color as active and in brushes */
+ ob->actcol = color_black + 1;
+
+ /* layers */
+ bGPDlayer *layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true);
+
+ /* frames */
+ BKE_gpencil_frame_addnew(layer, CFRA);
+
+ /* update depsgraph */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+}
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index b269fd84d5f..c93fcb9eb8c 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -3745,3 +3745,51 @@ void GPENCIL_OT_layer_mask_remove(wmOperatorType *ot)
ot->exec = gpencil_layer_mask_remove_exec;
ot->poll = gpencil_active_layer_poll;
}
+
+static int gpencil_layer_mask_move_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd);
+ const int direction = RNA_enum_get(op->ptr, "type");
+
+ /* sanity checks */
+ if (ELEM(NULL, gpd, gpl)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (gpl->act_mask > 0) {
+ bGPDlayer_Mask *mask = BLI_findlink(&gpl->mask_layers, gpl->act_mask - 1);
+ if (mask != NULL) {
+ BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
+ if (BLI_listbase_link_move(&gpl->mask_layers, mask, direction)) {
+ gpl->act_mask += direction;
+ 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_move(wmOperatorType *ot)
+{
+ static const EnumPropertyItem slot_move[] = {
+ {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
+ {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Grease Pencil Layer Mask";
+ ot->idname = "GPENCIL_OT_layer_mask_move";
+ ot->description = "Move the active Grease Pencil mask layer up/down in the list";
+
+ /* api callbacks */
+ ot->exec = gpencil_layer_mask_move_exec;
+ ot->poll = gpencil_active_layer_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index d388e11dc8c..d90f74fbf4f 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1818,18 +1818,13 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = (bGPdata *)ob->data;
- Scene *scene = CTX_data_scene(C);
bGPDlayer *target_layer = NULL;
ListBase strokes = {NULL, NULL};
int layer_num = RNA_int_get(op->ptr, "layer");
const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Operator not supported in multiframe edition");
- return OPERATOR_CANCELLED;
- }
-
- /* if autolock enabled, disabled now */
+ /* If autolock enabled, disabled now. */
if (use_autolock) {
gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS;
}
@@ -1852,53 +1847,59 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- /* Extract all strokes to move to this layer
- * NOTE: We need to do this in a two-pass system to avoid conflicts with strokes
- * getting repeatedly moved
- */
- CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- bGPDframe *gpf = gpl->actframe;
-
- /* skip if no frame with strokes, or if this is the layer we're moving strokes to */
- if ((gpl == target_layer) || (gpf == NULL)) {
+ /* Extract all strokes to move to this layer. */
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl_src, editable_gpencil_layers) {
+ /* Skip if this is the layer we're moving strokes to. */
+ if (gpl_src == target_layer) {
continue;
}
+ bGPDframe *init_gpf = (is_multiedit) ? gpl_src->frames.first : gpl_src->actframe;
+ for (bGPDframe *gpf_src = init_gpf; gpf_src; gpf_src = gpf_src->next) {
+ if ((gpf_src == gpl_src->actframe) ||
+ ((gpf_src->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf_src == NULL) {
+ continue;
+ }
- /* make copies of selected strokes, and deselect these once we're done */
- LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ bGPDstroke *gpsn = NULL;
+ BLI_listbase_clear(&strokes);
+ for (bGPDstroke *gps = gpf_src->strokes.first; gps; gps = gpsn) {
+ gpsn = gps->next;
+ /* Skip strokes that are invalid for current view. */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* Check if the color is editable. */
+ if (ED_gpencil_stroke_material_editable(ob, gpl_src, gps) == false) {
+ continue;
+ }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
+ if (gps->flag & GP_STROKE_SELECT) {
+ BLI_remlink(&gpf_src->strokes, gps);
+ BLI_addtail(&strokes, gps);
+ }
+ }
+ /* Paste them all in one go. */
+ if (strokes.first) {
+ bGPDframe *gpf_dst = BKE_gpencil_layer_frame_get(
+ target_layer, gpf_src->framenum, GP_GETFRAME_ADD_NEW);
- /* Check if the color is editable. */
- if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
- continue;
+ BLI_movelisttolist(&gpf_dst->strokes, &strokes);
+ BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
+ }
}
-
- /* TODO: Don't just move entire strokes - instead, only copy the selected portions... */
- if (gps->flag & GP_STROKE_SELECT) {
- BLI_remlink(&gpf->strokes, gps);
- BLI_addtail(&strokes, gps);
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
}
}
-
- /* if new layer and autolock, lock old layer */
+ /* If new layer and autolock, lock old layer. */
if ((layer_num == -1) && (use_autolock)) {
- gpl->flag |= GP_LAYER_LOCKED;
+ gpl_src->flag |= GP_LAYER_LOCKED;
}
}
CTX_DATA_END;
- /* Paste them all in one go */
- if (strokes.first) {
- bGPDframe *gpf = BKE_gpencil_layer_frame_get(target_layer, CFRA, GP_GETFRAME_ADD_NEW);
-
- BLI_movelisttolist(&gpf->strokes, &strokes);
- BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL));
- }
-
/* back autolock status */
if (use_autolock) {
gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
@@ -3762,6 +3763,7 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
const eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* Init snap context for geometry projection. */
SnapObjectContext *sctx = NULL;
@@ -3774,36 +3776,55 @@ static int gpencil_strokes_reproject_exec(bContext *C, wmOperator *op)
int cfra_prv = INT_MIN;
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
- GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
- bool curve_select = false;
- if (is_curve_edit && gps->editcurve != NULL) {
- curve_select = gps->editcurve->flag & GP_CURVE_SELECT;
- }
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- if (gps->flag & GP_STROKE_SELECT || curve_select) {
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ bool curve_select = false;
+ if (is_curve_edit && gps->editcurve != NULL) {
+ curve_select = gps->editcurve->flag & GP_CURVE_SELECT;
+ }
- /* update frame to get the new location of objects */
- if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) {
- cfra_prv = gpf_->framenum;
- CFRA = gpf_->framenum;
- BKE_scene_graph_update_for_newframe(depsgraph);
- }
+ if (gps->flag & GP_STROKE_SELECT || curve_select) {
- ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf_, gps, mode, keep_original);
+ /* update frame to get the new location of objects */
+ if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf->framenum)) {
+ cfra_prv = gpf->framenum;
+ CFRA = gpf->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph);
+ }
- if (is_curve_edit && gps->editcurve != NULL) {
- BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
- /* Update the selection from the stroke to the curve. */
- BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve);
+ ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf, gps, mode, keep_original);
- gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
- BKE_gpencil_stroke_geometry_update(gpd, gps);
- }
+ if (is_curve_edit && gps->editcurve != NULL) {
+ BKE_gpencil_stroke_editcurve_update(gpd, gpl, gps);
+ /* Update the selection from the stroke to the curve. */
+ BKE_gpencil_editcurve_stroke_sync_selection(gpd, gps, gps->editcurve);
- changed = true;
+ gps->flag |= GP_STROKE_NEEDS_CURVE_UPDATE;
+ BKE_gpencil_stroke_geometry_update(gpd, gps);
+ }
+
+ changed = true;
+ }
+ }
+ }
+ /* If not multi-edit, exit loop. */
+ if (!is_multiedit) {
+ break;
+ }
}
}
- GP_EDITABLE_STROKES_END(gpstroke_iter);
+ CTX_DATA_END;
/* return frame state and DB to original state */
CFRA = oldframe;
@@ -3832,7 +3853,8 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
"VIEW",
0,
"View",
- "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
+ "Reproject the strokes to end up on the same plane, as if drawn from the current "
+ "viewpoint "
"using 'Cursor' Stroke Placement"},
{GP_REPROJECT_SURFACE,
"SURFACE",
@@ -3851,7 +3873,8 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
ot->name = "Reproject Strokes";
ot->idname = "GPENCIL_OT_reproject";
ot->description =
- "Reproject the selected strokes from the current viewpoint as if they had been newly drawn "
+ "Reproject the selected strokes from the current viewpoint as if they had been newly "
+ "drawn "
"(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
"or for matching deforming geometry)";
@@ -4208,7 +4231,8 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
ot->name = "Subdivide Stroke";
ot->idname = "GPENCIL_OT_stroke_subdivide";
ot->description =
- "Subdivide between continuous selected points of the stroke adding a point half way between "
+ "Subdivide between continuous selected points of the stroke adding a point half way "
+ "between "
"them";
/* api callbacks */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index c6f74c39beb..09200125cb7 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -421,6 +421,7 @@ void GPENCIL_OT_layer_duplicate_object(struct wmOperatorType *ot);
void GPENCIL_OT_layer_mask_add(struct wmOperatorType *ot);
void GPENCIL_OT_layer_mask_remove(struct wmOperatorType *ot);
+void GPENCIL_OT_layer_mask_move(struct wmOperatorType *ot);
void GPENCIL_OT_hide(struct wmOperatorType *ot);
void GPENCIL_OT_reveal(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 7ca53779522..0062e363cdf 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -1434,36 +1434,32 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
static void gpencil_interpolate_seq_ui(bContext *C, wmOperator *op)
{
uiLayout *layout = op->layout;
- wmWindowManager *wm = CTX_wm_manager(C);
uiLayout *col, *row;
- PointerRNA ptr;
-
- RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
const eGP_Interpolate_Type type = RNA_enum_get(op->ptr, "type");
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "step", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "step", 0, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "layers", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "layers", 0, NULL, ICON_NONE);
if (CTX_data_mode_enum(C) == CTX_MODE_EDIT_GPENCIL) {
row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "interpolate_selected_only", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "interpolate_selected_only", 0, NULL, ICON_NONE);
}
row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "flip", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "flip", 0, NULL, ICON_NONE);
col = uiLayoutColumn(layout, true);
- uiItemR(col, &ptr, "smooth_factor", 0, NULL, ICON_NONE);
- uiItemR(col, &ptr, "smooth_steps", 0, NULL, ICON_NONE);
+ uiItemR(col, op->ptr, "smooth_factor", 0, NULL, ICON_NONE);
+ uiItemR(col, op->ptr, "smooth_steps", 0, NULL, ICON_NONE);
row = uiLayoutRow(layout, true);
- uiItemR(row, &ptr, "type", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "type", 0, NULL, ICON_NONE);
if (type == GP_IPO_CURVEMAP) {
/* Get an RNA pointer to ToolSettings to give to the custom curve. */
@@ -1477,16 +1473,16 @@ static void gpencil_interpolate_seq_ui(bContext *C, wmOperator *op)
}
else if (type != GP_IPO_LINEAR) {
row = uiLayoutRow(layout, false);
- uiItemR(row, &ptr, "easing", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "easing", 0, NULL, ICON_NONE);
if (type == GP_IPO_BACK) {
row = uiLayoutRow(layout, false);
- uiItemR(row, &ptr, "back", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "back", 0, NULL, ICON_NONE);
}
else if (type == GP_IPO_ELASTIC) {
row = uiLayoutRow(layout, false);
- uiItemR(row, &ptr, "amplitude", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "amplitude", 0, NULL, ICON_NONE);
row = uiLayoutRow(layout, false);
- uiItemR(row, &ptr, "period", 0, NULL, ICON_NONE);
+ uiItemR(row, op->ptr, "period", 0, NULL, ICON_NONE);
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 1a6cb5670c4..7d454eb3be1 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -601,6 +601,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_layer_mask_add);
WM_operatortype_append(GPENCIL_OT_layer_mask_remove);
+ WM_operatortype_append(GPENCIL_OT_layer_mask_move);
WM_operatortype_append(GPENCIL_OT_hide);
WM_operatortype_append(GPENCIL_OT_reveal);