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/blenkernel/intern
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/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/brush.c1077
-rw-r--r--source/blender/blenkernel/intern/context.c27
-rw-r--r--source/blender/blenkernel/intern/gpencil.c1061
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c358
-rw-r--r--source/blender/blenkernel/intern/lib_query.c9
-rw-r--r--source/blender/blenkernel/intern/material.c5
-rw-r--r--source/blender/blenkernel/intern/object.c15
-rw-r--r--source/blender/blenkernel/intern/object_update.c11
-rw-r--r--source/blender/blenkernel/intern/paint.c270
-rw-r--r--source/blender/blenkernel/intern/paint_toolslots.c9
-rw-r--r--source/blender/blenkernel/intern/scene.c90
11 files changed, 2066 insertions, 866 deletions
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 4a92f439d74..1716439c3fd 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -271,12 +271,10 @@ void BKE_brush_init_gpencil_settings(Brush *brush)
brush->gpencil_settings->draw_smoothlvl = 1;
brush->gpencil_settings->flag = 0;
brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
brush->gpencil_settings->draw_strength = 1.0f;
brush->gpencil_settings->draw_jitter = 0.0f;
brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
- brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
/* curves */
brush->gpencil_settings->curve_sensitivity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
@@ -285,11 +283,32 @@ void BKE_brush_init_gpencil_settings(Brush *brush)
}
/* add a new gp-brush */
-Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name)
+Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name, eObjectMode mode)
{
+ Paint *paint = NULL;
Brush *brush;
- Paint *paint = &ts->gp_paint->paint;
- brush = BKE_brush_add(bmain, name, OB_MODE_PAINT_GPENCIL);
+ switch (mode) {
+ case OB_MODE_PAINT_GPENCIL: {
+ paint = &ts->gp_paint->paint;
+ break;
+ }
+ case OB_MODE_SCULPT_GPENCIL: {
+ paint = &ts->gp_sculptpaint->paint;
+ break;
+ }
+ case OB_MODE_WEIGHT_GPENCIL: {
+ paint = &ts->gp_weightpaint->paint;
+ break;
+ }
+ case OB_MODE_VERTEX_GPENCIL: {
+ paint = &ts->gp_vertexpaint->paint;
+ break;
+ }
+ default:
+ paint = &ts->gp_paint->paint;
+ }
+
+ brush = BKE_brush_add(bmain, name, mode);
BKE_paint_brush_set(paint, brush);
id_us_min(&brush->id);
@@ -303,6 +322,22 @@ Brush *BKE_brush_add_gpencil(Main *bmain, ToolSettings *ts, const char *name)
return brush;
}
+/* Delete a Brush. */
+bool BKE_brush_delete(Main *bmain, Brush *brush)
+{
+ if (brush->id.tag & LIB_TAG_INDIRECT) {
+ return false;
+ }
+ else if (BKE_library_ID_is_indirectly_used(bmain, brush) && ID_REAL_USERS(brush) <= 1 &&
+ ID_EXTRA_USERS(brush) == 0) {
+ return false;
+ }
+
+ BKE_id_delete(bmain, brush);
+
+ return true;
+}
+
/* grease pencil cumapping->preset */
typedef enum eGPCurveMappingPreset {
GPCURVE_PRESET_PENCIL = 0,
@@ -363,442 +398,760 @@ static void brush_gpencil_curvemap_reset(CurveMap *cuma, int tot, int preset)
}
}
-/* create a set of grease pencil presets. */
-void BKE_brush_gpencil_presets(Main *bmain, ToolSettings *ts)
+void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
{
#define SMOOTH_STROKE_RADIUS 40
#define SMOOTH_STROKE_FACTOR 0.9f
+#define ACTIVE_SMOOTH 0.35f
- Paint *paint = &ts->gp_paint->paint;
+ CurveMapping *custom_curve = NULL;
- Brush *brush, *deft;
- CurveMapping *custom_curve;
+ /* Set general defaults at brush level. */
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
- /* Airbrush brush. */
- brush = BLI_findstring(&bmain->brushes, "Airbrush", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Airbrush");
+ brush->rgb[0] = 0.498f;
+ brush->rgb[1] = 1.0f;
+ brush->rgb[2] = 0.498f;
+
+ brush->secondary_rgb[0] = 1.0f;
+ brush->secondary_rgb[1] = 1.0f;
+ brush->secondary_rgb[2] = 1.0f;
+
+ brush->curve_preset = BRUSH_CURVE_SMOOTH;
+
+ if (brush->gpencil_settings == NULL) {
+ return;
}
- brush->size = 300.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ /* Set preset type. */
+ brush->gpencil_settings->preset_type = type;
- brush->gpencil_settings->draw_strength = 0.4f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ /* Set vertex mix factor. */
+ brush->gpencil_settings->vertex_mode = GPPAINT_MODE_STROKE;
+ brush->gpencil_settings->vertex_factor = 1.0f;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.98f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 0.211f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ switch (type) {
+ case GP_BRUSH_PRESET_AIRBRUSH: {
+ brush->size = 300.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.4f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_AIRBRUSH;
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 0.211f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_AIRBRUSH;
- /* Create and link Black Dots material to brush.
- * This material is required because the brush uses the material to define how the stroke is
- * drawn. */
- Material *ma = BLI_findstring(&bmain->materials, "Black Dots", offsetof(ID, name) + 2);
- if (ma == NULL) {
- ma = BKE_gpencil_material_add(bmain, "Black Dots");
- }
- brush->gpencil_settings->material = ma;
- /* Pin the matterial to the brush. */
- brush->gpencil_settings->flag |= GP_BRUSH_MATERIAL_PINNED;
+ /* Create and link Black Dots material to brush.
+ * This material is required because the brush uses the material to define how the stroke is
+ * drawn. */
+ Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
+ if (ma == NULL) {
+ ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
+ }
+ brush->gpencil_settings->material = ma;
+ /* Pin the matterial to the brush. */
+ brush->gpencil_settings->flag |= GP_BRUSH_MATERIAL_PINNED;
- /* Ink Pen brush. */
- brush = BLI_findstring(&bmain->brushes, "Ink Pen", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Ink Pen");
- }
- brush->size = 60.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_INK_PEN: {
- brush->gpencil_settings->draw_strength = 1.0f;
+ brush->size = 60.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.7f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ brush->gpencil_settings->draw_strength = 1.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.1f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.002f;
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.002f;
- /* Curve. */
- custom_curve = brush->gpencil_settings->curve_sensitivity;
- BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
- BKE_curvemapping_initialize(custom_curve);
- brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INK);
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ /* Curve. */
+ custom_curve = brush->gpencil_settings->curve_sensitivity;
+ BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+ BKE_curvemapping_initialize(custom_curve);
+ brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INK);
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
- /* Ink Pen Rough brush. */
- brush = BLI_findstring(&bmain->brushes, "Ink Pen Rough", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Ink Pen Rough");
- }
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_INK_PEN_ROUGH: {
+ brush->size = 60.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 2;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.000f;
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
+ brush->gpencil_settings->draw_random_press = 1.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ /* Curve. */
+ custom_curve = brush->gpencil_settings->curve_sensitivity;
+ BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+ BKE_curvemapping_initialize(custom_curve);
+ brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE);
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_MARKER_BOLD: {
+ brush->size = 150.0f;
+ brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 0.3f;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.002f;
+
+ brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_RANDOM;
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ /* Curve. */
+ custom_curve = brush->gpencil_settings->curve_sensitivity;
+ BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
+ BKE_curvemapping_initialize(custom_curve);
+ brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER);
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_MARKER_CHISEL: {
+ brush->size = 80.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = DEG2RAD(20.0f);
+ brush->gpencil_settings->draw_angle_factor = 1.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.002f;
+
+ brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_RANDOM;
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_CHISEL;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_PEN: {
+ brush->size = 30.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->simplify_f = 0.002f;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_PENCIL_SOFT: {
+ brush->size = 80.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 0.4f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 0.8f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.000f;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_PENCIL: {
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 0.6f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH;
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+
+ brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
+ brush->gpencil_settings->draw_smoothfac = 0.0f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 0;
+ brush->gpencil_settings->simplify_f = 0.002f;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_FILL_AREA: {
+ brush->size = 20.0f;
+
+ brush->gpencil_settings->fill_leak = 3;
+ brush->gpencil_settings->fill_threshold = 0.1f;
+ brush->gpencil_settings->fill_simplylvl = 1;
+ brush->gpencil_settings->fill_factor = 1;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->hardeness = 1.0f;
+ copy_v2_fl(brush->gpencil_settings->aspect_ratio, 1.0f);
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 1;
+
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
+ brush->gpencil_tool = GPAINT_TOOL_FILL;
+ brush->gpencil_settings->vertex_mode = GPPAINT_MODE_FILL;
+
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_ERASER_SOFT: {
+ brush->size = 30.0f;
+ brush->gpencil_settings->draw_strength = 0.5f;
+ brush->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
+ brush->gpencil_settings->era_strength_f = 100.0f;
+ brush->gpencil_settings->era_thickness_f = 10.0f;
- brush->size = 60.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ break;
+ }
+ case GP_BRUSH_PRESET_ERASER_HARD: {
+ brush->size = 30.0f;
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
+ brush->gpencil_settings->era_strength_f = 100.0f;
+ brush->gpencil_settings->era_thickness_f = 50.0f;
- brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.5f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
-
- brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.0f;
- brush->gpencil_settings->draw_smoothlvl = 2;
- brush->gpencil_settings->thick_smoothfac = 0.0f;
- brush->gpencil_settings->thick_smoothlvl = 2;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.000f;
-
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_RANDOM;
- brush->gpencil_settings->draw_random_press = 1.0f;
- brush->gpencil_settings->draw_random_strength = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ break;
+ }
+ case GP_BRUSH_PRESET_ERASER_POINT: {
+ brush->size = 30.0f;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
- /* Curve. */
- custom_curve = brush->gpencil_settings->curve_sensitivity;
- BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
- BKE_curvemapping_initialize(custom_curve);
- brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE);
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ break;
+ }
+ case GP_BRUSH_PRESET_ERASER_STROKE: {
+ brush->size = 30.0f;
+ brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
+ brush->gpencil_tool = GPAINT_TOOL_ERASE;
- /* Marker Bold brush. */
- brush = BLI_findstring(&bmain->brushes, "Marker Bold", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Marker Bold");
- }
- brush->size = 150.0f;
- brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE;
+ break;
+ }
+ case GP_BRUSH_PRESET_TINT: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_TINT;
+ brush->gpencil_tool = GPAINT_TOOL_TINT;
- brush->gpencil_settings->draw_strength = 0.3f;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.6f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.1f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.002f;
-
- brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_RANDOM;
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_random_strength = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_VERTEX_DRAW: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_DRAW;
+ brush->gpencil_vertex_tool = GPVERTEX_TOOL_DRAW;
- /* Curve. */
- custom_curve = brush->gpencil_settings->curve_sensitivity;
- BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f);
- BKE_curvemapping_initialize(custom_curve);
- brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER);
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_VERTEX_BLUR: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_BLUR;
+ brush->gpencil_vertex_tool = GPVERTEX_TOOL_BLUR;
- /* Marker Chisel brush. */
- brush = BLI_findstring(&bmain->brushes, "Marker Chisel", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Marker Chisel");
- }
- brush->size = 80.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.5f;
- brush->gpencil_settings->draw_angle = DEG2RAD(20.0f);
- brush->gpencil_settings->draw_angle_factor = 1.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_VERTEX_AVERAGE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_AVERAGE;
+ brush->gpencil_vertex_tool = GPVERTEX_TOOL_AVERAGE;
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.0f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0;
- brush->gpencil_settings->simplify_f = 0.002f;
-
- brush->gpencil_settings->flag &= ~GP_BRUSH_GROUP_RANDOM;
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_CHISEL;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_VERTEX_SMEAR: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_SMEAR;
+ brush->gpencil_vertex_tool = GPVERTEX_TOOL_SMEAR;
- /* Pen brush. */
- brush = BLI_findstring(&bmain->brushes, "Pen", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Pen");
- }
- brush->size = 30.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_strength = 1.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
-
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.3f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
-
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.0f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 1;
- brush->gpencil_settings->draw_subdivide = 1;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.002f;
-
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_random_strength = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_VERTEX_REPLACE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_VERTEX_REPLACE;
+ brush->gpencil_vertex_tool = GPVERTEX_TOOL_REPLACE;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- /* Pencil Soft brush. */
- brush = BLI_findstring(&bmain->brushes, "Pencil Soft", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Pencil Soft");
- }
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->size = 80.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ zero_v3(brush->secondary_rgb);
+ break;
+ }
+ case GP_BRUSH_PRESET_SMOOTH_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_SMOOTH;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_SMOOTH;
- brush->gpencil_settings->draw_strength = 0.4f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.64f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 0.8f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.3f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.0f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.000f;
-
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_random_strength = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ break;
+ }
+ case GP_BRUSH_PRESET_STRENGTH_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_STRENGTH;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_STRENGTH;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->gpencil_settings->draw_strength = 0.3f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- /* Pencil brush. */
- brush = BLI_findstring(&bmain->brushes, "Pencil", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Pencil");
- }
- deft = brush; /* save default brush. */
+ break;
+ }
+ case GP_BRUSH_PRESET_THICKNESS_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_THICKNESS;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_THICKNESS;
- brush->size = 25.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_strength = 0.6f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->draw_strength = 0.5f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- brush->gpencil_settings->input_samples = 10;
- brush->gpencil_settings->active_smooth = 0.55f;
- brush->gpencil_settings->draw_angle = 0.0f;
- brush->gpencil_settings->draw_angle_factor = 0.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
+ break;
+ }
+ case GP_BRUSH_PRESET_GRAB_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_GRAB;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_GRAB;
+ brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->flag |= GP_BRUSH_GROUP_SETTINGS;
- brush->gpencil_settings->draw_smoothfac = 0.0f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 0;
- brush->gpencil_settings->draw_random_sub = 0.0f;
- brush->gpencil_settings->simplify_f = 0.002f;
+ brush->size = 25.0f;
- brush->gpencil_settings->draw_random_press = 0.0f;
- brush->gpencil_settings->draw_jitter = 0.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.3f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PENCIL;
- brush->gpencil_tool = GPAINT_TOOL_DRAW;
+ break;
+ }
+ case GP_BRUSH_PRESET_PUSH_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_PUSH;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_PUSH;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- /* Fill brush. */
- brush = BLI_findstring(&bmain->brushes, "Fill Area", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
- }
- brush->size = 20.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
+ brush->gpencil_settings->draw_strength = 0.3f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- brush->gpencil_settings->fill_leak = 3;
- brush->gpencil_settings->fill_threshold = 0.1f;
- brush->gpencil_settings->fill_simplylvl = 1;
- brush->gpencil_settings->fill_factor = 1;
+ break;
+ }
+ case GP_BRUSH_PRESET_TWIST_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_TWIST;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_TWIST;
- brush->gpencil_settings->draw_strength = 1.0f;
- brush->gpencil_settings->gradient_f = 1.0f;
- brush->gpencil_settings->gradient_s[0] = 1.0f;
- brush->gpencil_settings->gradient_s[1] = 1.0f;
- brush->gpencil_settings->draw_smoothfac = 0.1f;
- brush->gpencil_settings->draw_smoothlvl = 1;
- brush->gpencil_settings->thick_smoothfac = 1.0f;
- brush->gpencil_settings->thick_smoothlvl = 3;
- brush->gpencil_settings->draw_subdivide = 1;
+ brush->size = 50.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->draw_sensitivity = 1.0f;
+ brush->gpencil_settings->draw_strength = 0.3f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL;
- brush->gpencil_tool = GPAINT_TOOL_FILL;
+ break;
+ }
+ case GP_BRUSH_PRESET_PINCH_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_PINCH;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_PINCH;
- brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
- brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+ brush->size = 50.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- /* Soft Eraser brush. */
- brush = BLI_findstring(&bmain->brushes, "Eraser Soft", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Soft");
+ brush->gpencil_settings->draw_strength = 0.5f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
+
+ break;
+ }
+ case GP_BRUSH_PRESET_RANDOMIZE_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_RANDOMIZE;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_RANDOMIZE;
+
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 0.5f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
+
+ break;
+ }
+ case GP_BRUSH_PRESET_CLONE_STROKE: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_CLONE;
+ brush->gpencil_sculpt_tool = GPSCULPT_TOOL_CLONE;
+ brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE;
+
+ brush->size = 25.0f;
+
+ brush->gpencil_settings->draw_strength = 1.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
+
+ break;
+ }
+ case GP_BRUSH_PRESET_DRAW_WEIGHT: {
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_GPBRUSH_WEIGHT;
+ brush->gpencil_weight_tool = GPWEIGHT_TOOL_DRAW;
+
+ brush->size = 25.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
+
+ brush->gpencil_settings->draw_strength = 0.8f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+ brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION;
+
+ break;
+ }
+ default:
+ break;
}
- brush->size = 30.0f;
- brush->gpencil_settings->draw_strength = 0.5f;
- brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
- brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE;
- brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT;
- brush->gpencil_tool = GPAINT_TOOL_ERASE;
- brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
- brush->gpencil_settings->era_strength_f = 100.0f;
- brush->gpencil_settings->era_thickness_f = 10.0f;
+}
- /* Hard Eraser brush. */
- brush = BLI_findstring(&bmain->brushes, "Eraser Hard", offsetof(ID, name) + 2);
+static Brush *gpencil_brush_ensure(Main *bmain,
+ ToolSettings *ts,
+ const char *brush_name,
+ eObjectMode mode)
+{
+ Brush *brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Hard");
+ brush = BKE_brush_add_gpencil(bmain, ts, brush_name, mode);
}
- brush->size = 30.0f;
- brush->gpencil_settings->draw_strength = 1.0f;
- brush->gpencil_settings->flag |= (GP_BRUSH_ENABLE_CURSOR | GP_BRUSH_DEFAULT_ERASER);
- brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT;
- brush->gpencil_settings->era_strength_f = 100.0f;
- brush->gpencil_settings->era_thickness_f = 50.0f;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
- brush->gpencil_tool = GPAINT_TOOL_ERASE;
-
- /* Point Eraser brush. */
- brush = BLI_findstring(&bmain->brushes, "Eraser Point", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Point");
+ if (brush->gpencil_settings == NULL) {
+ BKE_brush_init_gpencil_settings(brush);
}
- brush->size = 30.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
- brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_HARD;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_HARD;
- brush->gpencil_tool = GPAINT_TOOL_ERASE;
+ return brush;
+}
+
+/* Create a set of grease pencil Drawing presets. */
+void BKE_brush_gpencil_paint_presets(Main *bmain, ToolSettings *ts)
+{
+
+ Paint *paint = &ts->gp_paint->paint;
+
+ Brush *brush, *deft_draw;
+ /* Airbrush brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Airbrush", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_AIRBRUSH);
+
+ /* Ink Pen brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Ink Pen", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN);
+
+ /* Ink Pen Rough brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Ink Pen Rough", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_INK_PEN_ROUGH);
+
+ /* Marker Bold brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Marker Bold", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_BOLD);
+
+ /* Marker Chisel brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Marker Chisel", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_MARKER_CHISEL);
+
+ /* Pen brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Pen", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PEN);
+
+ /* Pencil Soft brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Pencil Soft", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL_SOFT);
+
+ /* Pencil brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Pencil", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PENCIL);
+ deft_draw = brush; /* save default brush. */
+
+ /* Fill brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Fill Area", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_FILL_AREA);
+
+ /* Soft Eraser brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Eraser Soft", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_SOFT);
+
+ /* Hard Eraser brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Eraser Hard", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_HARD);
+
+ /* Point Eraser brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Eraser Point", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_POINT);
/* Stroke Eraser brush. */
- brush = BLI_findstring(&bmain->brushes, "Eraser Stroke", offsetof(ID, name) + 2);
- if (brush == NULL) {
- brush = BKE_brush_add_gpencil(bmain, ts, "Eraser Stroke");
- }
- brush->size = 30.0f;
- brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
- brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_STROKE;
+ brush = gpencil_brush_ensure(bmain, ts, "Eraser Stroke", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_ERASER_STROKE);
+
+ /* Tint brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Tint", OB_MODE_PAINT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TINT);
+
+ /* Set default Draw brush. */
+ BKE_paint_brush_set(paint, deft_draw);
+}
+
+/* Create a set of grease pencil Vertex Paint presets. */
+void BKE_brush_gpencil_vertex_presets(Main *bmain, ToolSettings *ts)
+{
+ Paint *vertexpaint = &ts->gp_vertexpaint->paint;
+
+ Brush *brush, *deft_vertex;
+ /* Vertex Draw brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Vertex Draw", OB_MODE_VERTEX_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_DRAW);
+ deft_vertex = brush; /* save default brush. */
+
+ /* Vertex Blur brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Vertex Blur", OB_MODE_VERTEX_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_BLUR);
+
+ /* Vertex Average brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Vertex Average", OB_MODE_VERTEX_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_AVERAGE);
+
+ /* Vertex Smear brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Vertex Smear", OB_MODE_VERTEX_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_SMEAR);
+
+ /* Vertex Replace brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Vertex Replace", OB_MODE_VERTEX_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_VERTEX_REPLACE);
+
+ /* Set default Vertex brush. */
+ BKE_paint_brush_set(vertexpaint, deft_vertex);
+}
+
+/* Create a set of grease pencil Sculpt Paint presets. */
+void BKE_brush_gpencil_sculpt_presets(Main *bmain, ToolSettings *ts)
+{
+ Paint *sculptpaint = &ts->gp_sculptpaint->paint;
+ Brush *brush, *deft_sculpt;
+
+ /* Smooth brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Smooth Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_SMOOTH_STROKE);
+ deft_sculpt = brush;
+
+ /* Strength brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Strength Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_STRENGTH_STROKE);
+
+ /* Thickness brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Thickness Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_THICKNESS_STROKE);
+
+ /* Grab brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Grab Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_GRAB_STROKE);
+
+ /* Push brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Push Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PUSH_STROKE);
+
+ /* Twist brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Twist Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TWIST_STROKE);
+
+ /* Pinch brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Pinch Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_PINCH_STROKE);
+
+ /* Randomize brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Randomize Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_RANDOMIZE_STROKE);
+
+ /* Clone brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Clone Stroke", OB_MODE_SCULPT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_CLONE_STROKE);
+
+ /* Set default brush. */
+ BKE_paint_brush_set(sculptpaint, deft_sculpt);
+}
+
+/* Create a set of grease pencil Weight Paint presets. */
+void BKE_brush_gpencil_weight_presets(Main *bmain, ToolSettings *ts)
+{
+ Paint *weightpaint = &ts->gp_weightpaint->paint;
- brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_STROKE;
- brush->gpencil_tool = GPAINT_TOOL_ERASE;
+ Brush *brush, *deft_weight;
+ /* Vertex Draw brush. */
+ brush = gpencil_brush_ensure(bmain, ts, "Draw Weight", OB_MODE_WEIGHT_GPENCIL);
+ BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_DRAW_WEIGHT);
+ deft_weight = brush; /* save default brush. */
- /* set default brush. */
- BKE_paint_brush_set(paint, deft);
+ /* Set default brush. */
+ BKE_paint_brush_set(weightpaint, deft_weight);
}
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 48985932d87..b2c551a1752 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1124,6 +1124,9 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
else if (object_mode & OB_MODE_WEIGHT_GPENCIL) {
return CTX_MODE_WEIGHT_GPENCIL;
}
+ else if (object_mode & OB_MODE_VERTEX_GPENCIL) {
+ return CTX_MODE_VERTEX_GPENCIL;
+ }
}
}
@@ -1140,25 +1143,11 @@ enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
/* would prefer if we can use the enum version below over this one - Campbell */
/* must be aligned with above enum */
static const char *data_mode_strings[] = {
- "mesh_edit",
- "curve_edit",
- "surface_edit",
- "text_edit",
- "armature_edit",
- "mball_edit",
- "lattice_edit",
- "posemode",
- "sculpt_mode",
- "weightpaint",
- "vertexpaint",
- "imagepaint",
- "particlemode",
- "objectmode",
- "greasepencil_paint",
- "greasepencil_edit",
- "greasepencil_sculpt",
- "greasepencil_weight",
- NULL,
+ "mesh_edit", "curve_edit", "surface_edit", "text_edit",
+ "armature_edit", "mball_edit", "lattice_edit", "posemode",
+ "sculpt_mode", "weightpaint", "vertexpaint", "imagepaint",
+ "particlemode", "objectmode", "greasepencil_paint", "greasepencil_edit",
+ "greasepencil_sculpt", "greasepencil_weight", "greasepencil_vertex", NULL,
};
BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1,
"Must have a string for each context mode")
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 747ffb92ad5..0b33eaccb6f 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -39,12 +39,16 @@
#include "BLT_translation.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
#include "DNA_anim_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_material_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_userdef_types.h"
#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
#include "DNA_object_types.h"
#include "BKE_action.h"
@@ -55,14 +59,17 @@
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_icons.h"
+#include "BKE_image.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_object.h"
+#include "BKE_paint.h"
#include "BLI_math_color.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
static CLG_LogRef LOG = {"bke.gpencil"};
@@ -139,12 +146,10 @@ void BKE_gpencil_free_stroke(bGPDstroke *gps)
/* Free strokes belonging to a gp-frame */
bool BKE_gpencil_free_strokes(bGPDframe *gpf)
{
- bGPDstroke *gps_next;
bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
/* free strokes */
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
- gps_next = gps->next;
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
BKE_gpencil_free_stroke(gps);
}
BLI_listbase_clear(&gpf->strokes);
@@ -152,24 +157,6 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
return changed;
}
-/* Free strokes and colors belonging to a gp-frame */
-bool BKE_gpencil_free_frame_runtime_data(bGPDframe *gpf_eval)
-{
- bGPDstroke *gps_next;
- if (!gpf_eval) {
- return false;
- }
-
- /* free strokes */
- for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps_next) {
- gps_next = gps->next;
- BKE_gpencil_free_stroke(gps);
- }
- BLI_listbase_clear(&gpf_eval->strokes);
-
- return true;
-}
-
/* Free all of a gp-layer's frames */
void BKE_gpencil_free_frames(bGPDlayer *gpl)
{
@@ -191,6 +178,15 @@ void BKE_gpencil_free_frames(bGPDlayer *gpl)
gpl->actframe = NULL;
}
+void BKE_gpencil_free_layer_masks(bGPDlayer *gpl)
+{
+ /* Free masks.*/
+ bGPDlayer_Mask *mask_next = NULL;
+ for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
+ mask_next = mask->next;
+ BLI_freelinkN(&gpl->mask_layers, mask);
+ }
+}
/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
void BKE_gpencil_free_layers(ListBase *list)
{
@@ -207,6 +203,10 @@ void BKE_gpencil_free_layers(ListBase *list)
/* free layers and their data */
BKE_gpencil_free_frames(gpl);
+
+ /* Free masks.*/
+ BKE_gpencil_free_layer_masks(gpl);
+
BLI_freelinkN(list, gpl);
}
}
@@ -230,6 +230,13 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all)
}
}
+void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
+{
+ BKE_gpencil_free(gpd_eval, true);
+ BKE_libblock_free_data(&gpd_eval->id, false);
+ MEM_freeN(gpd_eval);
+}
+
/* ************************************************** */
/* Container Creation */
@@ -307,7 +314,7 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
/* Find frame to insert it before */
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->framenum > cframe) {
/* Add it here */
BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
@@ -356,7 +363,7 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
/* allocate memory for frame and add to end of list */
gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
- gpl_active = BKE_gpencil_layer_getactive(gpd);
+ gpl_active = BKE_gpencil_layer_active_get(gpd);
/* add to datablock */
if (gpl_active == NULL) {
@@ -386,6 +393,8 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
gpl->opacity = 1.0f;
/* default channel color */
ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
+ /* Default vertex mix. */
+ gpl->vertex_paint_opacity = 1.0f;
}
/* auto-name */
@@ -397,9 +406,11 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
offsetof(bGPDlayer, info),
sizeof(gpl->info));
+ /* Enable always affected by scene lights. */
+ gpl->flag |= GP_LAYER_USE_LIGHTS;
/* make this one the active one */
if (setactive) {
- BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_active_set(gpd, gpl);
}
/* return layer */
@@ -419,7 +430,6 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
/* general flags */
gpd->flag |= GP_DATA_VIEWALIGN;
- gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
/* always enable object onion skin switch */
gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
/* GP object specific settings */
@@ -427,6 +437,8 @@ bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
+ gpd->zdepth_offset = 0.150f;
+
/* grid settings */
ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); /* Color */
ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); /* Scale */
@@ -474,43 +486,59 @@ void BKE_gpencil_stroke_add_points(bGPDstroke *gps,
}
}
-/* Create a new stroke, with pre-allocated data buffers */
-bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
+/* Create a new stroke, with pre-allocated data buffers. */
+bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
{
/* allocate memory for a new stroke */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
gps->thickness = thickness;
- gps->gradient_f = 1.0f;
- gps->gradient_s[0] = 1.0f;
- gps->gradient_s[1] = 1.0f;
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = 1.0f;
+ copy_v2_fl(gps->aspect_ratio, 1.0f);
+
+ gps->uv_scale = 1.0f;
gps->inittime = 0;
- /* enable recalculation flag by default */
- gps->flag = GP_STROKE_RECALC_GEOMETRY | GP_STROKE_3DSPACE;
+ gps->flag = GP_STROKE_3DSPACE;
gps->totpoints = totpoints;
gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
/* initialize triangle memory to dummy data */
gps->triangles = NULL;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->tot_triangles = 0;
gps->mat_nr = mat_idx;
- /* add to frame */
- BLI_addtail(&gpf->strokes, gps);
+ return gps;
+}
+
+/* Create a new stroke and add to frame. */
+bGPDstroke *BKE_gpencil_stroke_add(
+ bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
+{
+ bGPDstroke *gps = BKE_gpencil_stroke_new(mat_idx, totpoints, thickness);
+
+ /* Add to frame. */
+ if ((gps != NULL) && (gpf != NULL)) {
+ if (!insert_at_head) {
+ BLI_addtail(&gpf->strokes, gps);
+ }
+ else {
+ BLI_addhead(&gpf->strokes, gps);
+ }
+ }
return gps;
}
/* Add a stroke and copy the temporary drawing color value from one of the existing stroke */
-bGPDstroke *BKE_gpencil_add_stroke_existing_style(
+bGPDstroke *BKE_gpencil_stroke_add_existing_style(
bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
{
- bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, mat_idx, totpoints, thickness);
+ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, totpoints, thickness, false);
/* Copy run-time color data so that strokes added in the modifier has the style.
* There are depsgraph reference pointers inside,
* change the copy function if interfere with future drawing implementation. */
@@ -533,30 +561,26 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d
}
/* make a copy of a given gpencil stroke */
-bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
+bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points)
{
bGPDstroke *gps_dst = NULL;
gps_dst = MEM_dupallocN(gps_src);
gps_dst->prev = gps_dst->next = NULL;
+ gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
- gps_dst->points = MEM_dupallocN(gps_src->points);
+ if (dup_points) {
+ gps_dst->points = MEM_dupallocN(gps_src->points);
- if (gps_src->dvert != NULL) {
- gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
- BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
- }
- else {
- gps_dst->dvert = NULL;
+ if (gps_src->dvert != NULL) {
+ gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
+ BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
+ }
+ else {
+ gps_dst->dvert = NULL;
+ }
}
- /* Don't clear triangles, so that modifier evaluation can just use
- * this without extra work first. Most places that need to force
- * this data to get recalculated will destroy the data anyway though.
- */
- gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
- /* gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY; */
-
/* return new stroke */
return gps_dst;
}
@@ -580,7 +604,7 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
BLI_listbase_clear(&gpf_dst->strokes);
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke */
- gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
@@ -601,7 +625,7 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds
BLI_listbase_clear(&gpf_dst->strokes);
for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke */
- gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
BLI_addtail(&gpf_dst->strokes, gps_dst);
}
}
@@ -622,6 +646,14 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
gpl_dst = MEM_dupallocN(gpl_src);
gpl_dst->prev = gpl_dst->next = NULL;
+ /* Copy masks. */
+ BLI_listbase_clear(&gpl_dst->mask_layers);
+ LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) {
+ bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src);
+ mask_dst->prev = mask_dst->next = NULL;
+ BLI_addtail(&gpl_dst->mask_layers, mask_dst);
+ }
+
/* copy frames */
BLI_listbase_clear(&gpl_dst->frames);
for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
@@ -658,7 +690,7 @@ void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int U
/* copy layers */
BLI_listbase_clear(&gpd_dst->layers);
- for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
/* make a copy of source layer and its data */
/* TODO here too could add unused flags... */
@@ -766,8 +798,8 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* if frame has no strokes after this, delete it */
if (BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_layer_delframe(gpl, gpf);
- BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
+ BKE_gpencil_layer_frame_delete(gpl, gpf);
+ BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV);
}
}
@@ -775,7 +807,7 @@ void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
/* GP Layer API */
/* Check if the given layer is able to be edited or not */
-bool gpencil_layer_is_editable(const bGPDlayer *gpl)
+bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
{
/* Sanity check */
if (gpl == NULL) {
@@ -797,7 +829,7 @@ bool gpencil_layer_is_editable(const bGPDlayer *gpl)
}
/* Look up the gp-frame on the requested frame number, but don't add a new one */
-bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
+bGPDframe *BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
{
bGPDframe *gpf;
@@ -817,7 +849,7 @@ bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
* - this sets the layer's actframe var (if allowed to)
* - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
*/
-bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
+bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
{
bGPDframe *gpf = NULL;
bool found = false;
@@ -966,7 +998,7 @@ bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_M
}
/* delete the given frame from a layer */
-bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
+bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
{
bool changed = false;
@@ -989,18 +1021,103 @@ bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
return changed;
}
-/* get the active gp-layer for editing */
-bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
+bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
+{
+ if (name[0] == '\0') {
+ return NULL;
+ }
+ return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
+}
+
+bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *name)
+{
+ if (name[0] == '\0') {
+ return NULL;
+ }
+ return BLI_findstring(&gpl->mask_layers, name, offsetof(bGPDlayer_Mask, name));
+}
+
+bGPDlayer_Mask *BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name)
+{
+
+ bGPDlayer_Mask *mask = MEM_callocN(sizeof(bGPDlayer_Mask), "bGPDlayer_Mask");
+ BLI_addtail(&gpl->mask_layers, mask);
+ BLI_strncpy(mask->name, name, sizeof(mask->name));
+ gpl->act_mask++;
+
+ return mask;
+}
+
+void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
+{
+ BLI_freelinkN(&gpl->mask_layers, mask);
+ gpl->act_mask--;
+ CLAMP_MIN(gpl->act_mask, 0);
+}
+
+void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
+{
+ bGPDlayer_Mask *mask_next;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
+ mask_next = mask->next;
+ if (STREQ(mask->name, name)) {
+ BKE_gpencil_layer_mask_remove(gpl, mask);
+ }
+ }
+ }
+}
+
+static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
+{
+ /* sort is inverted as layer list. */
+ const struct bGPDlayer_Mask *mask1 = arg1;
+ const struct bGPDlayer_Mask *mask2 = arg2;
+ int val = 0;
+
+ if (mask1->sort_index < mask2->sort_index) {
+ val = 1;
+ }
+ else if (mask1->sort_index > mask2->sort_index) {
+ val = -1;
+ }
+
+ return val;
+}
+
+void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
+{
+ /* Update sort index. */
+ LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
+ bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
+ if (gpl_mask != NULL) {
+ mask->sort_index = BLI_findindex(&gpd->layers, gpl_mask);
+ }
+ else {
+ mask->sort_index = 0;
+ }
+ }
+ BLI_listbase_sort(&gpl->mask_layers, gpencil_cb_sort_masks);
+}
+
+void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
{
- bGPDlayer *gpl;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ BKE_gpencil_layer_mask_sort(gpd, gpl);
+ }
+}
+/* get the active gp-layer for editing */
+bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
+{
/* error checking */
if (ELEM(NULL, gpd, gpd->layers.first)) {
return NULL;
}
/* loop over layers until found (assume only one active) */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
if (gpl->flag & GP_LAYER_ACTIVE) {
return gpl;
}
@@ -1011,17 +1128,15 @@ bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
}
/* set the active gp-layer */
-void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
+void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
{
- bGPDlayer *gpl;
-
/* error checking */
if (ELEM(NULL, gpd, gpd->layers.first, active)) {
return;
}
/* loop over layers deactivating all */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_ACTIVE;
if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
gpl->flag |= GP_LAYER_LOCKED;
@@ -1040,13 +1155,11 @@ void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
{
BLI_assert(gpd != NULL);
- bGPDlayer *gpl;
-
if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
- bGPDlayer *layer_active = BKE_gpencil_layer_getactive(gpd);
+ bGPDlayer *layer_active = BKE_gpencil_layer_active_get(gpd);
/* Lock all other layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* unlock active layer */
if (gpl == layer_active) {
gpl->flag &= ~GP_LAYER_LOCKED;
@@ -1061,7 +1174,7 @@ void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
* a problem in the UI because the user expects all layers will be unlocked
*/
if (unlock) {
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpl->flag &= ~GP_LAYER_LOCKED;
}
}
@@ -1079,6 +1192,12 @@ void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
/* free layer */
BKE_gpencil_free_frames(gpl);
+ /* Free Masks. */
+ BKE_gpencil_free_layer_masks(gpl);
+
+ /* Remove any reference to that layer in masking lists. */
+ BKE_gpencil_layer_mask_remove_ref(gpd, gpl->info);
+
/* free icon providing preview of icon color */
BKE_icon_delete(gpl->runtime.icon_id);
@@ -1119,7 +1238,7 @@ Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob,
Material *ma = BKE_gpencil_brush_material_get(brush);
/* check if the material is already on object material slots and add it if missing */
- if (ma && BKE_gpencil_object_material_get_index(ob, ma) < 0) {
+ if (ma && BKE_gpencil_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);
}
@@ -1138,7 +1257,7 @@ int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *materi
if (!material) {
return -1;
}
- int index = BKE_gpencil_object_material_get_index(ob, material);
+ int index = BKE_gpencil_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);
@@ -1167,7 +1286,7 @@ Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *n
}
/* Returns the material for a brush with respect to its pinned state. */
-Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
+Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings) &&
(brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
@@ -1183,7 +1302,7 @@ Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
{
if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
- return BKE_gpencil_object_material_get_index(ob, brush->gpencil_settings->material);
+ return BKE_gpencil_object_material_index_get(ob, brush->gpencil_settings->material);
}
else {
return ob->actcol - 1;
@@ -1294,11 +1413,11 @@ bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
return changed;
}
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf != NULL) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
}
}
@@ -1330,6 +1449,13 @@ void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
mul_v3_v3fl(r_centroid, tot, 0.5f);
}
+/* Compute stroke bounding box. */
+void BKE_gpencil_stroke_boundingbox_calc(bGPDstroke *gps)
+{
+ INIT_MINMAX(gps->boundbox_min, gps->boundbox_max);
+ BKE_gpencil_stroke_minmax(gps, false, gps->boundbox_min, gps->boundbox_max);
+}
+
/* create bounding box values */
static void boundbox_gpencil(Object *ob)
{
@@ -1381,7 +1507,7 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
}
const float scalef = mat4_to_scale(mat);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
/* FIXME: For now, we just skip parented layers.
* Otherwise, we have to update each frame to find
* the current parent position/effects.
@@ -1390,8 +1516,8 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
continue;
}
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
bGPDspoint *pt;
int i;
@@ -1400,9 +1526,8 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
pt->pressure *= scalef;
}
- /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Distortion may mean we need to re-triangulate. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
}
@@ -1421,9 +1546,9 @@ void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
/* Remove points data */
if (gpd) {
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->dvert != NULL) {
for (int i = 0; i < gps->totpoints; i++) {
dvert = &gps->dvert[i];
@@ -1537,6 +1662,7 @@ static int stroke_march_next_point(const bGPDstroke *gps,
float *result,
float *pressure,
float *strength,
+ float *vert_color,
float *ratio_result,
int *index_from,
int *index_to)
@@ -1576,6 +1702,7 @@ static int stroke_march_next_point(const bGPDstroke *gps,
copy_v3_v3(result, &pt->x);
*pressure = gps->points[next_point_index].pressure;
*strength = gps->points[next_point_index].strength;
+ memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float) * 4);
*index_from = next_point_index - 1;
*index_to = next_point_index;
@@ -1590,6 +1717,10 @@ static int stroke_march_next_point(const bGPDstroke *gps,
gps->points[next_point_index].pressure, gps->points[next_point_index - 1].pressure, ratio);
*strength = interpf(
gps->points[next_point_index].strength, gps->points[next_point_index - 1].strength, ratio);
+ interp_v4_v4v4(vert_color,
+ gps->points[next_point_index - 1].vert_color,
+ gps->points[next_point_index].vert_color,
+ ratio);
*index_from = next_point_index - 1;
*index_to = next_point_index;
@@ -1673,7 +1804,7 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist)
* \param gps: Stroke to sample
* \param dist: Distance of one segment
*/
-bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool select)
+bool BKE_gpencil_stroke_sample(bGPDstroke *gps, const float dist, const bool select)
{
bGPDspoint *pt = gps->points;
bGPDspoint *pt1 = NULL;
@@ -1701,6 +1832,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
int next_point_index = 1;
i = 0;
float pressure, strength, ratio_result;
+ float vert_color[4];
int index_from, index_to;
float last_coord[3];
@@ -1711,6 +1843,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pt[0].pressure;
new_pt[i].strength = pt[0].strength;
+ memcpy(new_pt[i].vert_color, pt[0].vert_color, sizeof(float) * 4);
if (select) {
new_pt[i].flag |= GP_SPOINT_SELECT;
}
@@ -1728,6 +1861,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
last_coord,
&pressure,
&strength,
+ vert_color,
&ratio_result,
&index_from,
&index_to)) > -1) {
@@ -1735,6 +1869,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
copy_v3_v3(&pt2->x, last_coord);
new_pt[i].pressure = pressure;
new_pt[i].strength = strength;
+ memcpy(new_pt[i].vert_color, vert_color, sizeof(float) * 4);
if (select) {
new_pt[i].flag |= GP_SPOINT_SELECT;
}
@@ -1766,8 +1901,8 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
gps->totpoints = i;
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
return true;
}
@@ -1778,7 +1913,7 @@ bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool sel
* \param dist: Distance of one segment
* \param tip_length: Ignore tip jittering, set zero to use default value.
*/
-bool BKE_gpencil_stretch_stroke(bGPDstroke *gps, const float dist, const float tip_length)
+bool BKE_gpencil_stroke_stretch(bGPDstroke *gps, const float dist, const float tip_length)
{
bGPDspoint *pt = gps->points, *last_pt, *second_last, *next_pt;
int i;
@@ -1829,7 +1964,7 @@ bool BKE_gpencil_stretch_stroke(bGPDstroke *gps, const float dist, const float t
* \param index_from: the index of the first point to be used in the trimmed result
* \param index_to: the index of the last point to be used in the trimmed result
*/
-bool BKE_gpencil_trim_stroke_points(bGPDstroke *gps, const int index_from, const int index_to)
+bool BKE_gpencil_stroke_trim_points(bGPDstroke *gps, const int index_from, const int index_to)
{
bGPDspoint *pt = gps->points, *new_pt;
MDeformVert *dv, *new_dv;
@@ -1879,7 +2014,7 @@ bool BKE_gpencil_trim_stroke_points(bGPDstroke *gps, const int index_from, const
return true;
}
-bool BKE_gpencil_split_stroke(bGPDframe *gpf,
+bool BKE_gpencil_stroke_split(bGPDframe *gpf,
bGPDstroke *gps,
const int before_index,
bGPDstroke **remaining_gps)
@@ -1897,7 +2032,7 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
/* Handle remaining segments first. */
- new_gps = BKE_gpencil_add_stroke_existing_style(
+ new_gps = BKE_gpencil_stroke_add_existing_style(
gpf, gps, gps->mat_nr, new_count, gps->thickness);
new_pt = new_gps->points; /* Allocated from above. */
@@ -1907,13 +2042,14 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
}
if (gps->dvert) {
- new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_remaining");
+ new_dv = MEM_callocN(sizeof(MDeformVert) * new_count,
+ "gp_stroke_dverts_remaining(MDeformVert)");
for (int i = 0; i < new_count; i++) {
dv = &gps->dvert[i + before_index];
new_dv[i].flag = dv->flag;
new_dv[i].totweight = dv->totweight;
new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
- "gp_stroke_dverts_dw_remaining");
+ "gp_stroke_dverts_dw_remaining(MDeformWeight)");
for (int j = 0; j < dv->totweight; j++) {
new_dv[i].dw[j].weight = dv->dw[j].weight;
new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
@@ -1927,8 +2063,8 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
/* Trim the original stroke into a shorter one.
* Keep the end point. */
- BKE_gpencil_trim_stroke_points(gps, 0, old_count);
-
+ BKE_gpencil_stroke_trim_points(gps, 0, old_count);
+ BKE_gpencil_stroke_geometry_update(gps);
return true;
}
@@ -1937,7 +2073,7 @@ bool BKE_gpencil_split_stroke(bGPDframe *gpf,
* \param gps: Stroke to shrink
* \param dist: delta length
*/
-bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
+bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist)
{
bGPDspoint *pt = gps->points, *second_last;
int i;
@@ -1981,7 +2117,7 @@ bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
index_start = index_end = 0; /* no length left to cut */
}
- BKE_gpencil_trim_stroke_points(gps, index_start, index_end);
+ BKE_gpencil_stroke_trim_points(gps, index_start, index_end);
if (gps->totpoints == 0) {
return false;
@@ -2009,7 +2145,7 @@ bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
* \param i: Point index
* \param inf: Amount of smoothing to apply
*/
-bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
+bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf)
{
bGPDspoint *pt = &gps->points[i];
float sco[3] = {0.0f};
@@ -2068,7 +2204,7 @@ bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
/**
* Apply smooth for strength to stroke point */
-bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2128,7 +2264,7 @@ bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float
/**
* Apply smooth for thickness to stroke point (use pressure) */
-bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2188,7 +2324,7 @@ bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float
/**
* Apply smooth for UV rotation to stroke point (use pressure).
*/
-bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influence)
{
bGPDspoint *ptb = &gps->points[point_index];
@@ -2233,12 +2369,12 @@ bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influe
* \param r_initframe: Number of first selected frame
* \param r_endframe: Number of last selected frame
*/
-void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
+void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
{
*r_initframe = gpl->actframe->framenum;
*r_endframe = gpl->actframe->framenum;
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
if (gpf->flag & GP_FRAME_SELECT) {
if (gpf->framenum < *r_initframe) {
*r_initframe = gpf->framenum;
@@ -2291,9 +2427,9 @@ float BKE_gpencil_multiframe_falloff_calc(
/* reassign strokes using a material */
void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* reassign strokes */
if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
gps->mat_nr--;
@@ -2307,9 +2443,9 @@ void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
/* remove strokes using a material */
bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
{
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->mat_nr == index) {
return true;
}
@@ -2333,9 +2469,9 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd,
} \
((void)0)
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
/* reassign strokes */
MAT_NR_REMAP(gps->mat_nr);
}
@@ -2345,6 +2481,102 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd,
#undef MAT_NR_REMAP
}
+/* Load a table with material conversion index for merged materials. */
+bool BKE_gpencil_merge_materials_table_get(Object *ob,
+ const float hue_threshold,
+ const float sat_threshold,
+ const float val_threshold,
+ GHash *r_mat_table)
+{
+ bool changed = false;
+
+ Material *ma_primary = NULL;
+ Material *ma_secondary = NULL;
+ MaterialGPencilStyle *gp_style_primary = NULL;
+ MaterialGPencilStyle *gp_style_secondary = NULL;
+
+ short *totcol = BKE_object_material_len_p(ob);
+ if (totcol == 0) {
+ return changed;
+ }
+
+ for (int idx_primary = 0; idx_primary < *totcol; idx_primary++) {
+ /* Read primary material to compare. */
+ ma_primary = BKE_gpencil_material(ob, idx_primary + 1);
+ if (ma_primary == NULL) {
+ continue;
+ }
+
+ for (int idx_secondary = idx_primary + 1; idx_secondary < *totcol; idx_secondary++) {
+ /* Read secondary material to compare with primary material. */
+ ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1);
+ if ((ma_secondary == NULL) ||
+ (BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary)))) {
+ continue;
+ }
+ gp_style_primary = ma_primary->gp_style;
+ gp_style_secondary = ma_secondary->gp_style;
+
+ if ((gp_style_primary == NULL) || (gp_style_secondary == NULL) ||
+ (gp_style_secondary->flag & GP_MATERIAL_LOCKED)) {
+ continue;
+ }
+
+ /* Check materials have the same mode. */
+ if (gp_style_primary->mode != gp_style_secondary->mode) {
+ continue;
+ }
+
+ /* Check materials have same stroke and fill attributes. */
+ if ((gp_style_primary->flag & GP_MATERIAL_STROKE_SHOW) !=
+ (gp_style_secondary->flag & GP_MATERIAL_STROKE_SHOW)) {
+ continue;
+ }
+
+ if ((gp_style_primary->flag & GP_MATERIAL_FILL_SHOW) !=
+ (gp_style_secondary->flag & GP_MATERIAL_FILL_SHOW)) {
+ continue;
+ }
+
+ /* Check materials have the same type. */
+ if ((gp_style_primary->stroke_style != gp_style_secondary->stroke_style) ||
+ (gp_style_primary->fill_style != gp_style_secondary->fill_style)) {
+ continue;
+ }
+
+ float s_hsv_a[3], s_hsv_b[3], f_hsv_a[3], f_hsv_b[3], col[3];
+ copy_v3_v3(col, gp_style_primary->stroke_rgba);
+ rgb_to_hsv_compat_v(col, s_hsv_a);
+ copy_v3_v3(col, gp_style_secondary->stroke_rgba);
+ rgb_to_hsv_compat_v(col, s_hsv_b);
+
+ copy_v3_v3(col, gp_style_primary->fill_rgba);
+ rgb_to_hsv_compat_v(col, f_hsv_a);
+ copy_v3_v3(col, gp_style_secondary->fill_rgba);
+ rgb_to_hsv_compat_v(col, f_hsv_b);
+
+ /* Check stroke and fill color (only Hue and Saturation). */
+ if ((!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold)) ||
+ (!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold)) ||
+ (!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold)) ||
+ (!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold)) ||
+ (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
+ (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
+ (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
+ (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold))) {
+ continue;
+ }
+
+ /* Save conversion indexes. */
+ BLI_ghash_insert(
+ r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
/* statistics functions */
void BKE_gpencil_stats_update(bGPdata *gpd)
{
@@ -2353,11 +2585,11 @@ void BKE_gpencil_stats_update(bGPdata *gpd)
gpd->totstroke = 0;
gpd->totpoint = 0;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
gpd->totlayer++;
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
gpd->totframe++;
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
gpd->totstroke++;
gpd->totpoint += gps->totpoints;
}
@@ -2366,7 +2598,7 @@ void BKE_gpencil_stats_update(bGPdata *gpd)
}
/* get material index (0-based like mat_nr not actcol) */
-int BKE_gpencil_object_material_get_index(Object *ob, Material *ma)
+int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
{
short *totcol = BKE_object_material_len_p(ob);
Material *read_ma = NULL;
@@ -2524,61 +2756,48 @@ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points,
*r_direction = (int)locy[2];
}
-/* calc bounding box in 2d using flat projection data */
-static void gpencil_calc_2d_bounding_box(const float (*points2d)[2],
- int totpoints,
- float minv[2],
- float maxv[2])
-{
- minv[0] = points2d[0][0];
- minv[1] = points2d[0][1];
- maxv[0] = points2d[0][0];
- maxv[1] = points2d[0][1];
-
- for (int i = 1; i < totpoints; i++) {
- /* min */
- if (points2d[i][0] < minv[0]) {
- minv[0] = points2d[i][0];
- }
- if (points2d[i][1] < minv[1]) {
- minv[1] = points2d[i][1];
- }
- /* max */
- if (points2d[i][0] > maxv[0]) {
- maxv[0] = points2d[i][0];
- }
- if (points2d[i][1] > maxv[1]) {
- maxv[1] = points2d[i][1];
- }
- }
- /* use a perfect square */
- if (maxv[0] > maxv[1]) {
- maxv[1] = maxv[0];
- }
- else {
- maxv[0] = maxv[1];
- }
-}
-
/* calc texture coordinates using flat projected points */
static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2],
- int totpoints,
+ bGPDstroke *gps,
const float minv[2],
float maxv[2],
float (*r_uv)[2])
{
+ const float s = sin(gps->uv_rotation);
+ const float c = cos(gps->uv_rotation);
+
+ /* Calc center for rotation. */
+ float center[2] = {0.5f, 0.5f};
float d[2];
d[0] = maxv[0] - minv[0];
d[1] = maxv[1] - minv[1];
- for (int i = 0; i < totpoints; i++) {
+ for (int i = 0; i < gps->totpoints; i++) {
r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
+
+ /* Apply translation. */
+ add_v2_v2(r_uv[i], gps->uv_translation);
+
+ /* Apply Rotation. */
+ r_uv[i][0] -= center[0];
+ r_uv[i][1] -= center[1];
+
+ float x = r_uv[i][0] * c - r_uv[i][1] * s;
+ float y = r_uv[i][0] * s + r_uv[i][1] * c;
+
+ r_uv[i][0] = x + center[0];
+ r_uv[i][1] = y + center[1];
+
+ /* Apply scale. */
+ if (gps->uv_scale != 0.0f) {
+ mul_v2_fl(r_uv[i], 1.0f / gps->uv_scale);
+ }
}
}
/* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was
* modified) */
-void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
+void BKE_gpencil_stroke_fill_triangulate(bGPDstroke *gps)
{
BLI_assert(gps->totpoints >= 3);
@@ -2600,36 +2819,25 @@ void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
float minv[2];
float maxv[2];
/* first needs bounding box data */
- if (gpd->flag & GP_DATA_UV_ADAPTIVE) {
- gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
- }
- else {
- ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
- ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
- }
+ ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
+ ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
/* calc uv data */
- gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
+ gpencil_calc_stroke_fill_uv(points2d, gps, minv, maxv, uv);
- /* Number of triangles */
- gps->tot_triangles = gps->totpoints - 2;
- /* save triangulation data in stroke cache */
+ /* Save triangulation data. */
if (gps->tot_triangles > 0) {
- if (gps->triangles == NULL) {
- gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
- "GP Stroke triangulation");
- }
- else {
- gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
- }
+ MEM_SAFE_FREE(gps->triangles);
+ gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
+ "GP Stroke triangulation");
for (int i = 0; i < gps->tot_triangles; i++) {
- bGPDtriangle *stroke_triangle = &gps->triangles[i];
memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
- /* copy texture coordinates */
- copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
- copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
- copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
+ }
+
+ /* Copy UVs to bGPDspoint. */
+ for (int i = 0; i < gps->totpoints; i++) {
+ copy_v2_v2(gps->points[i].uv_fill, uv[i]);
}
}
else {
@@ -2641,17 +2849,50 @@ void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
gps->triangles = NULL;
}
- /* disable recalculation flag */
- if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
- gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
- }
-
/* clear memory */
MEM_SAFE_FREE(tmp_triangles);
MEM_SAFE_FREE(points2d);
MEM_SAFE_FREE(uv);
}
+/* texture coordinate utilities */
+void BKE_gpencil_stroke_uv_update(bGPDstroke *gps)
+{
+ if (gps == NULL || gps->totpoints == 0) {
+ return;
+ }
+
+ bGPDspoint *pt = gps->points;
+ float totlen = 0.0f;
+ pt[0].uv_fac = totlen;
+ for (int i = 1; i < gps->totpoints; i++) {
+ totlen += len_v3v3(&pt[i - 1].x, &pt[i].x);
+ pt[i].uv_fac = totlen;
+ }
+}
+
+/* Recalc the internal geometry caches for fill and uvs. */
+void BKE_gpencil_stroke_geometry_update(bGPDstroke *gps)
+{
+ if (gps == NULL) {
+ return;
+ }
+
+ if (gps->totpoints > 2) {
+ BKE_gpencil_stroke_fill_triangulate(gps);
+ }
+ else {
+ gps->tot_triangles = 0;
+ MEM_SAFE_FREE(gps->triangles);
+ }
+
+ /* calc uv data along the stroke */
+ BKE_gpencil_stroke_uv_update(gps);
+
+ /* Calc stroke bounding box. */
+ BKE_gpencil_stroke_boundingbox_calc(gps);
+}
+
float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
{
if (!gps->points || gps->totpoints < 2) {
@@ -2678,7 +2919,7 @@ float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
* Trim stroke to the first intersection or loop
* \param gps: Stroke data
*/
-bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
+bool BKE_gpencil_stroke_trim(bGPDstroke *gps)
{
if (gps->totpoints < 4) {
return false;
@@ -2759,13 +3000,14 @@ bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
}
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
gps->totpoints = newtot;
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
}
+
+ BKE_gpencil_stroke_geometry_update(gps);
+
return intersect;
}
@@ -2773,7 +3015,7 @@ bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
* Close stroke
* \param gps: Stroke to close
*/
-bool BKE_gpencil_close_stroke(bGPDstroke *gps)
+bool BKE_gpencil_stroke_close(bGPDstroke *gps)
{
bGPDspoint *pt1 = NULL;
bGPDspoint *pt2 = NULL;
@@ -2831,6 +3073,7 @@ bool BKE_gpencil_close_stroke(bGPDstroke *gps)
pt->pressure = interpf(pt2->pressure, pt1->pressure, step);
pt->strength = interpf(pt2->strength, pt1->strength, step);
pt->flag = 0;
+ interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
/* Set weights. */
if (gps->dvert != NULL) {
@@ -2933,8 +3176,7 @@ void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short ta
gps->totpoints = tot;
/* triangles cache needs to be recalculated */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
+ BKE_gpencil_stroke_geometry_update(gps);
}
}
@@ -2947,7 +3189,7 @@ void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short ta
* \param threshold: Distance between points
* \param use_unselected: Set to true to analyze all stroke and not only selected points
*/
-void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
+void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf,
bGPDstroke *gps,
const float threshold,
const bool use_unselected)
@@ -3014,6 +3256,9 @@ void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
if (tagged) {
BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG);
}
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* Helper: Check materials with same color. */
@@ -3033,7 +3278,8 @@ static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Mate
float hsv2[4];
rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
hsv2[3] = gp_style->fill_rgba[3];
- if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) && (compare_v4v4(hsv1, hsv2, 0.01f))) {
+ if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) &&
+ (compare_v4v4(hsv1, hsv2, 0.01f))) {
*r_mat = ma;
return i - 1;
}
@@ -3058,24 +3304,24 @@ static Material *gpencil_add_from_curve_material(Main *bmain,
/* Stroke color. */
if (gpencil_lines) {
ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
else {
linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
- gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
}
/* Fill color. */
linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
/* Fill is false if the original curve hasn't material assigned, so enable it. */
if (fill) {
- gp_style->flag |= GP_STYLE_FILL_SHOW;
+ gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
/* Check at least one is enabled. */
- if (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) &&
- ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) &&
+ ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
return mat_gp;
@@ -3140,13 +3386,14 @@ static void gpencil_convert_spline(Main *bmain,
/* Create Stroke. */
bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
gps->thickness = 1.0f;
- gps->gradient_f = 1.0f;
- ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f);
+ gps->fill_opacity_fac = 1.0f;
+ gps->hardeness = 1.0f;
+ gps->uv_scale = 1.0f;
+
+ ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f);
ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
gps->inittime = 0.0f;
- /* Enable recalculation flag by default. */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
gps->flag &= ~GP_STROKE_SELECT;
gps->flag |= GP_STROKE_3DSPACE;
@@ -3165,10 +3412,6 @@ static void gpencil_convert_spline(Main *bmain,
}
totpoints = (resolu * segments) - (segments - 1);
- /* Initialize triangle memory to dummy data. */
- gps->tot_triangles = 0;
- gps->triangles = NULL;
-
/* Materials
* Notice: The color of the material is the color of viewport and not the final shader color.
*/
@@ -3212,7 +3455,6 @@ static void gpencil_convert_spline(Main *bmain,
copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
gp_style_gp->fill_style = gp_style_cur->fill_style;
gp_style_gp->mix_factor = gp_style_cur->mix_factor;
- gp_style_gp->gradient_angle = gp_style_cur->gradient_angle;
}
/* If object has more than 1 material, use second material for stroke color. */
@@ -3228,16 +3470,16 @@ static void gpencil_convert_spline(Main *bmain,
if (ob_cu->totcol > 0) {
mat_curve = BKE_object_material_get(ob_cu, 1);
if (mat_curve) {
- linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
/* Set fill and stroke depending of curve type (3D or 2D). */
if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
- mat_gp->gp_style->flag |= GP_STYLE_STROKE_SHOW;
- mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW;
}
else {
- mat_gp->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
- mat_gp->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW;
}
}
}
@@ -3349,8 +3591,11 @@ static void gpencil_convert_spline(Main *bmain,
}
/* Cyclic curve, close stroke. */
if ((cyclic) && (!do_stroke)) {
- BKE_gpencil_close_stroke(gps);
+ BKE_gpencil_stroke_close(gps);
}
+
+ /* Recalc fill geometry. */
+ BKE_gpencil_stroke_geometry_update(gps);
}
/* Convert a curve object to grease pencil stroke.
@@ -3388,7 +3633,7 @@ void BKE_gpencil_convert_curve(Main *bmain,
if (use_collections) {
Collection *collection = gpencil_get_parent_collection(scene, ob_cu);
if (collection != NULL) {
- gpl = BLI_findstring(&gpd->layers, collection->id.name + 2, offsetof(bGPDlayer, info));
+ gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2);
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true);
}
@@ -3396,14 +3641,14 @@ void BKE_gpencil_convert_curve(Main *bmain,
}
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_getactive(gpd);
+ gpl = BKE_gpencil_layer_active_get(gpd);
if (gpl == NULL) {
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
}
}
/* Check if there is an active frame and add if needed. */
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY);
/* Read all splines of the curve and create a stroke for each. */
for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
@@ -3413,3 +3658,379 @@ void BKE_gpencil_convert_curve(Main *bmain,
/* Tag for recalculation */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
}
+
+/* Create a default palette */
+void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
+{
+ const int totcol = 120;
+ const char *hexcol[] = {
+ "FFFFFF", "F2F2F2", "E6E6E6", "D9D9D9", "CCCCCC", "BFBFBF", "B2B2B2", "A6A6A6", "999999",
+ "8C8C8C", "808080", "737373", "666666", "595959", "4C4C4C", "404040", "333333", "262626",
+ "1A1A1A", "000000", "F2FC24", "FFEA00", "FEA711", "FE8B68", "FB3B02", "FE3521", "D00000",
+ "A81F3D", "780422", "2B0000", "F1E2C5", "FEE4B3", "FEDABB", "FEC28E", "D88F57", "BD6340",
+ "A2402B", "63352D", "6B2833", "34120C", "E7CB8F", "D1B38B", "C1B17F", "D7980B", "FFB100",
+ "FE8B00", "FF6A00", "B74100", "5F3E1D", "3B2300", "FECADA", "FE65CB", "FE1392", "DD3062",
+ "C04A6D", "891688", "4D2689", "441521", "2C1139", "241422", "FFFF7D", "FFFF00", "FF7F00",
+ "FF7D7D", "FF7DFF", "FF00FE", "FF007F", "FF0000", "7F0000", "0A0A00", "F6FDFF", "E9F7FF",
+ "CFE6FE", "AAC7FE", "77B3FE", "1E74FD", "0046AA", "2F4476", "003052", "0E0E25", "EEF5F0",
+ "D6E5DE", "ACD8B9", "6CADC6", "42A9AF", "007F7F", "49675C", "2E4E4E", "1D3239", "0F1C21",
+ "D8FFF4", "B8F4F5", "AECCB5", "76C578", "358757", "409B68", "468768", "1F512B", "2A3C37",
+ "122E1D", "EFFFC9", "E6F385", "BCF51C", "D4DC18", "82D322", "5C7F00", "59932B", "297F00",
+ "004320", "1C3322", "00FF7F", "00FF00", "7DFF7D", "7DFFFF", "00FFFF", "7D7DFF", "7F00FF",
+ "0000FF", "3F007F", "00007F"};
+
+ ToolSettings *ts = scene->toolsettings;
+ GpPaint *gp_paint = ts->gp_paint;
+ Paint *paint = &gp_paint->paint;
+
+ paint->palette = BLI_findstring(&bmain->palettes, "Palette", offsetof(ID, name) + 2);
+ if (paint->palette == NULL) {
+ paint->palette = BKE_palette_add(bmain, "Palette");
+ ts->gp_vertexpaint->paint.palette = paint->palette;
+
+ /* Create Colors. */
+ for (int i = 0; i < totcol; i++) {
+ PaletteColor *palcol = BKE_palette_color_add(paint->palette);
+ if (palcol) {
+ hex_to_rgb((char *)hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
+ }
+ }
+ }
+}
+
+bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size, const bool mask)
+{
+ Image *image = sima->image;
+ bool done = false;
+
+ if (image == NULL) {
+ return false;
+ }
+
+ ImageUser iuser = sima->iuser;
+ void *lock;
+ ImBuf *ibuf;
+
+ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
+
+ if (ibuf->rect) {
+ int img_x = ibuf->x;
+ int img_y = ibuf->y;
+
+ float color[4];
+ bGPDspoint *pt;
+ for (int row = 0; row < img_y; row++) {
+ /* Create new stroke */
+ bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, 0, img_x, size * 1000, false);
+ done = true;
+ for (int col = 0; col < img_x; col++) {
+ IMB_sampleImageAtLocation(ibuf, col, row, true, color);
+ pt = &gps->points[col];
+ pt->pressure = 1.0f;
+ pt->x = col * size;
+ pt->z = row * size;
+ if (!mask) {
+ copy_v3_v3(pt->vert_color, color);
+ pt->vert_color[3] = 1.0f;
+ pt->strength = color[3];
+ }
+ else {
+ zero_v3(pt->vert_color);
+ pt->vert_color[3] = 1.0f;
+ pt->strength = 1.0f - color[3];
+ }
+
+ /* Selet Alpha points. */
+ if (pt->strength < 0.03f) {
+ gps->flag |= GP_STROKE_SELECT;
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ BKE_gpencil_stroke_geometry_update(gps);
+ }
+ }
+
+ /* Free memory. */
+ BKE_image_release_ibuf(image, ibuf, lock);
+
+ return done;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Iterators
+ *
+ * Iterate over all visible stroke of all visible layers inside a gpObject.
+ * Also take into account onion skining.
+ *
+ * \{ */
+
+void BKE_gpencil_visible_stroke_iter(
+ Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
+
+ /* Onion skinning. */
+ const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE);
+ const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED);
+ const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0;
+ const short onion_keytype = gpd->onion_keytype;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+
+ bGPDframe *act_gpf = gpl->actframe;
+ bGPDframe *sta_gpf = act_gpf;
+ bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL;
+
+ if (gpl->flag & GP_LAYER_HIDE) {
+ continue;
+ }
+
+ if (is_multiedit) {
+ sta_gpf = end_gpf = NULL;
+ /* Check the whole range and tag the editable frames. */
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ if (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT)) {
+ gpf->runtime.onion_id = 0;
+ if (sta_gpf == NULL) {
+ sta_gpf = gpf;
+ }
+ end_gpf = gpf->next;
+ }
+ else {
+ gpf->runtime.onion_id = INT_MAX;
+ }
+ }
+ }
+ else if (is_onion && (gpl->onion_flag & GP_LAYER_ONIONSKIN)) {
+ if (act_gpf) {
+ bGPDframe *last_gpf = gpl->frames.last;
+
+ int frame_len = 0;
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ gpf->runtime.frameid = frame_len++;
+ }
+
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ bool is_wrong_keytype = (onion_keytype > -1) && (gpf->key_type != onion_keytype);
+ bool is_in_range;
+ int delta = (onion_mode_abs) ? (gpf->framenum - cfra) :
+ (gpf->runtime.frameid - act_gpf->runtime.frameid);
+
+ if (onion_mode_sel) {
+ is_in_range = (gpf->flag & GP_FRAME_SELECT) != 0;
+ }
+ else {
+ is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
+
+ if (onion_loop && !is_in_range) {
+ /* We wrap the value using the last frame and 0 as reference. */
+ /* FIXME: This might not be good for animations not starting at 0. */
+ int shift = (onion_mode_abs) ? last_gpf->framenum : last_gpf->runtime.frameid;
+ delta += (delta < 0) ? (shift + 1) : -(shift + 1);
+ /* Test again with wrapped value. */
+ is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
+ }
+ }
+ /* Mask frames that have wrong keytype of are not in range. */
+ gpf->runtime.onion_id = (is_wrong_keytype || !is_in_range) ? INT_MAX : delta;
+ }
+ /* Active frame is always shown. */
+ act_gpf->runtime.onion_id = 0;
+ }
+
+ sta_gpf = gpl->frames.first;
+ end_gpf = NULL;
+ }
+ else {
+ /* Bypass multiedit/onion skinning. */
+ end_gpf = sta_gpf = NULL;
+ }
+
+ if (sta_gpf == NULL && act_gpf == NULL) {
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+ continue;
+ }
+
+ /* Draw multiedit/onion skinning first */
+ for (bGPDframe *gpf = sta_gpf; gpf && gpf != end_gpf; gpf = gpf->next) {
+ if (gpf->runtime.onion_id == INT_MAX || gpf == act_gpf) {
+ continue;
+ }
+
+ if (layer_cb) {
+ layer_cb(gpl, gpf, NULL, thunk);
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ stroke_cb(gpl, gpf, gps, thunk);
+ }
+ }
+ /* Draw Active frame on top. */
+ /* Use evaluated frame (with modifiers for active stroke)/ */
+ act_gpf = gpl->actframe;
+ act_gpf->runtime.onion_id = 0;
+ if (act_gpf) {
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
+ stroke_cb(gpl, act_gpf, gps, thunk);
+ }
+ }
+ }
+}
+
+void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
+ const struct bGPDframe *gpf_eval)
+{
+ bGPDstroke *gps_eval = gpf_eval->strokes.first;
+ LISTBASE_FOREACH (bGPDstroke *, gps_orig, &gpf_orig->strokes) {
+
+ /* Assign original stroke pointer. */
+ if (gps_eval != NULL) {
+ gps_eval->runtime.gps_orig = gps_orig;
+
+ /* Assign original point pointer. */
+ for (int i = 0; i < gps_orig->totpoints; i++) {
+ bGPDspoint *pt_eval = &gps_eval->points[i];
+ pt_eval->runtime.pt_orig = &gps_orig->points[i];
+ pt_eval->runtime.idx_orig = i;
+ }
+ /* Increase pointer. */
+ gps_eval = gps_eval->next;
+ }
+ }
+}
+
+void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
+{
+ bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
+ bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
+
+ /* Assign pointers to the original stroke and points to the evaluated data. This must
+ * be done before applying any modifier because at this moment the structure is equals,
+ * so we can assume the layer index is the same in both datablocks.
+ * This data will be used by operators. */
+
+ bGPDlayer *gpl_eval = gpd_eval->layers.first;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
+ if (gpl_eval != NULL) {
+ /* Update layer reference pointers. */
+ gpl_eval->runtime.gpl_orig = (bGPDlayer *)gpl;
+
+ bGPDframe *gpf_eval = gpl_eval->frames.first;
+ LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl->frames) {
+ if (gpf_eval != NULL) {
+ /* Update frame reference pointers. */
+ gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+ gpf_eval = gpf_eval->next;
+ }
+ }
+ gpl_eval = gpl_eval->next;
+ }
+ }
+}
+
+void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
+ Object *obact,
+ bGPDlayer *gpl,
+ float diff_mat[4][4])
+{
+ Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
+ Object *obparent = gpl->parent;
+ Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
+ obparent;
+
+ /* if not layer parented, try with object parented */
+ if (obparent_eval == NULL) {
+ if (ob_eval != NULL) {
+ if (ob_eval->type == OB_GPENCIL) {
+ copy_m4_m4(diff_mat, ob_eval->obmat);
+ return;
+ }
+ }
+ /* not gpencil object */
+ unit_m4(diff_mat);
+ return;
+ }
+ else {
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ return;
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
+ mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ }
+ else {
+ /* if bone not found use object (armature) */
+ mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
+ add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ }
+ return;
+ }
+ else {
+ unit_m4(diff_mat); /* not defined type */
+ }
+ }
+}
+
+void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob)
+{
+ if (ob->type != OB_GPENCIL) {
+ return;
+ }
+
+ bGPdata *gpd = (bGPdata *)ob->data;
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float cur_mat[4][4];
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ if ((gpl->parent != NULL) && (gpl->actframe != NULL)) {
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, gpl->parent);
+
+ /* calculate new matrix */
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ invert_m4_m4(cur_mat, ob_eval->obmat);
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, ob_eval->obmat, pchan->pose_mat);
+ invert_m4_m4(cur_mat, tmp_mat);
+ }
+ }
+ /* only redo if any change */
+ if (!equals_m4m4(gpl->inverse, cur_mat)) {
+
+ /* first apply current transformation to all strokes */
+ BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat);
+ /* undo local object */
+ sub_v3_v3(diff_mat[3], ob->obmat[3]);
+
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(diff_mat, &pt->x);
+ }
+ }
+ /* set new parent matrix */
+ copy_m4_m4(gpl->inverse, cur_mat);
+ }
+ }
+ }
+}
+/** \} */
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index ebb927a7d60..1014db27d84 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -96,7 +96,7 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
* Ramer - Douglas - Peucker algorithm
* by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
*/
-void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
+void BKE_gpencil_stroke_simplify_adaptive(bGPDstroke *gps, float epsilon)
{
bGPDspoint *old_points = MEM_dupallocN(gps->points);
int totpoints = gps->totpoints;
@@ -165,9 +165,6 @@ void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
old_dvert = MEM_dupallocN(gps->dvert);
}
/* resize gps */
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
-
int j = 0;
for (int i = 0; i < totpoints; i++) {
bGPDspoint *pt_src = &old_points[i];
@@ -195,13 +192,16 @@ void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
gps->totpoints = j;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
MEM_SAFE_FREE(marked);
}
/* Simplify alternate vertex of stroke except extremes */
-void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
+void BKE_gpencil_stroke_simplify_fixed(bGPDstroke *gps)
{
if (gps->totpoints < 5) {
return;
@@ -227,8 +227,6 @@ void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
if (gps->dvert != NULL) {
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
int j = 0;
for (int i = 0; i < gps->totpoints; i++) {
@@ -256,6 +254,8 @@ void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
}
gps->totpoints = j;
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
MEM_SAFE_FREE(old_points);
MEM_SAFE_FREE(old_dvert);
@@ -357,73 +357,8 @@ bool BKE_gpencil_has_transform_modifiers(Object *ob)
return false;
}
-/* apply stroke modifiers */
-void BKE_gpencil_stroke_modifiers(Depsgraph *depsgraph,
- Object *ob,
- bGPDlayer *gpl,
- bGPDframe *gpf,
- bGPDstroke *gps,
- bool is_render)
-{
- GpencilModifierData *md;
- bGPdata *gpd = ob->data;
- const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
-
- for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
- if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
-
- if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
- continue;
- }
-
- if (mti && mti->deformStroke) {
- mti->deformStroke(md, depsgraph, ob, gpl, gpf, gps);
- /* subdivide always requires update */
- if (md->type == eGpencilModifierType_Subdiv) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- }
- /* some modifiers could require a recalc of fill triangulation data */
- else if (gpd->flag & GP_DATA_STROKE_FORCE_RECALC) {
- if (ELEM(md->type,
- eGpencilModifierType_Armature,
- eGpencilModifierType_Hook,
- eGpencilModifierType_Lattice,
- eGpencilModifierType_Offset)) {
-
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- }
- }
- }
- }
- }
-}
-
-/* apply stroke geometry modifiers */
-void BKE_gpencil_geometry_modifiers(
- Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bool is_render)
-{
- GpencilModifierData *md;
- bGPdata *gpd = ob->data;
- const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
-
- for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
- if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
-
- if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
- continue;
- }
-
- if (mti->generateStrokes) {
- mti->generateStrokes(md, depsgraph, ob, gpl, gpf);
- }
- }
- }
-}
-
/* apply time modifiers */
-int BKE_gpencil_time_modifier(
+static int gpencil_time_modifier(
Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl, int cfra, bool is_render)
{
GpencilModifierData *md;
@@ -454,14 +389,14 @@ int BKE_gpencil_time_modifier(
}
/* *************************************************** */
-void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *gpd)
+void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd)
{
DEG_debug_print_eval(depsgraph, __func__, gpd->id.name, gpd);
int ctime = (int)DEG_get_ctime(depsgraph);
/* update active frame */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV);
}
if (DEG_is_active(depsgraph)) {
@@ -471,8 +406,8 @@ void BKE_gpencil_eval_geometry(Depsgraph *depsgraph, bGPdata *gpd)
* so that editing tools work with copy-on-write
* when the current frame changes
*/
- for (bGPDlayer *gpl = gpd_orig->layers.first; gpl; gpl = gpl->next) {
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, ctime, GP_GETFRAME_USE_PREV);
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
+ gpl->actframe = BKE_gpencil_layer_frame_get(gpl, ctime, GP_GETFRAME_USE_PREV);
}
}
}
@@ -687,7 +622,7 @@ GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *na
return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name));
}
-void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
+void BKE_gpencil_stroke_subdivide(bGPDstroke *gps, int level, int type)
{
bGPDspoint *temp_points;
MDeformVert *temp_dverts = NULL;
@@ -710,8 +645,6 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
temp_dverts = MEM_dupallocN(gps->dvert);
gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
/* move points from last to first to new place */
i2 = gps->totpoints - 1;
@@ -726,6 +659,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
pt_final->flag = pt->flag;
pt_final->runtime.pt_orig = pt->runtime.pt_orig;
pt_final->runtime.idx_orig = pt->runtime.idx_orig;
+ copy_v4_v4(pt_final->vert_color, pt->vert_color);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -749,6 +683,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->runtime.pt_orig = NULL;
+ interp_v4_v4v4(pt_final->vert_color, pt->vert_color, next->vert_color, 0.5f);
if (gps->dvert != NULL) {
dvert = &temp_dverts[i];
@@ -775,8 +710,8 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
MEM_SAFE_FREE(temp_points);
MEM_SAFE_FREE(temp_dverts);
- /* move points to smooth stroke (not simple flag )*/
- if ((flag & GP_SUBDIV_SIMPLE) == 0) {
+ /* move points to smooth stroke (not simple type )*/
+ if (type != GP_SUBDIV_SIMPLE) {
/* duplicate points in a temp area with the new subdivide data */
temp_points = MEM_dupallocN(gps->points);
@@ -793,145 +728,186 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
MEM_SAFE_FREE(temp_points);
}
}
+
+ /* Calc geometry data. */
+ BKE_gpencil_stroke_geometry_update(gps);
+}
+
+/* Remap frame (Time modifier) */
+static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob, bGPDlayer *gpl)
+{
+ const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
+ int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+ int remap_cfra = cfra_eval;
+ if (time_remap) {
+ remap_cfra = gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
+ }
+
+ return remap_cfra;
}
-/* Copy frame but do not assign new memory */
-static void gpencil_frame_copy_noalloc(Object *ob, bGPDframe *gpf, bGPDframe *gpf_eval)
+/* Get the current frame retimed with time modifiers. */
+bGPDframe *BKE_gpencil_frame_retime_get(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ bGPDlayer *gpl)
{
- gpf_eval->prev = gpf->prev;
- gpf_eval->next = gpf->next;
- gpf_eval->framenum = gpf->framenum;
- gpf_eval->flag = gpf->flag;
- gpf_eval->key_type = gpf->key_type;
- gpf_eval->runtime = gpf->runtime;
- copy_m4_m4(gpf_eval->runtime.parent_obmat, gpf->runtime.parent_obmat);
+ int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl);
+ bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
- /* copy strokes */
- BLI_listbase_clear(&gpf_eval->strokes);
- for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
- /* make copy of source stroke */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+ return gpf;
+}
- /* copy color to temp fields to apply temporal changes in the stroke */
- MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps_src->mat_nr + 1);
- if (gp_style) {
- copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba);
- }
+static void gpencil_assign_object_eval(Object *object)
+{
+ BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE);
- /* Save original pointers for using in edit and select operators. */
- gps_dst->runtime.gps_orig = gps_src;
- for (int i = 0; i < gps_src->totpoints; i++) {
- bGPDspoint *pt_dst = &gps_dst->points[i];
- pt_dst->runtime.pt_orig = &gps_src->points[i];
- pt_dst->runtime.idx_orig = i;
- }
+ bGPdata *gpd_eval = object->runtime.gpd_eval;
+
+ gpd_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
- BLI_addtail(&gpf_eval->strokes, gps_dst);
+ if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) {
+ object->data = gpd_eval;
}
}
-/* Ensure there is a evaluated frame */
-static void gpencil_evaluated_frame_ensure(int idx,
- Object *ob,
- bGPDframe *gpf,
- bGPDframe **gpf_eval)
+/* Helper: Copy active frame from original datablock to evaluated datablock for modifiers. */
+static void gpencil_copy_activeframe_to_eval(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, bGPdata *gpd_orig, bGPdata *gpd_eval)
{
- /* Create evaluated frames array data or expand. */
- bGPDframe *evaluated_frames = ob->runtime.gpencil_evaluated_frames;
- *gpf_eval = &evaluated_frames[idx];
- /* If already exist a evaluated frame create a new one. */
- if (*gpf_eval != NULL) {
- /* first clear temp data */
- BKE_gpencil_free_frame_runtime_data(*gpf_eval);
+ bGPDlayer *gpl_eval = gpd_eval->layers.first;
+ LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) {
+
+ if (gpl_eval != NULL) {
+ int remap_cfra = gpencil_remap_time_get(depsgraph, scene, ob, gpl_orig);
+
+ bGPDframe *gpf_orig = BKE_gpencil_layer_frame_get(
+ gpl_orig, remap_cfra, GP_GETFRAME_USE_PREV);
+
+ if (gpf_orig != NULL) {
+ int gpf_index = BLI_findindex(&gpl_orig->frames, gpf_orig);
+ bGPDframe *gpf_eval = BLI_findlink(&gpl_eval->frames, gpf_index);
+
+ if (gpf_eval != NULL) {
+ /* Delete old strokes. */
+ BKE_gpencil_free_strokes(gpf_eval);
+ /* Copy again strokes. */
+ BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval);
+
+ gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+ }
+ }
+
+ gpl_eval = gpl_eval->next;
+ }
}
- /* Copy data (do not assign new memory). */
- gpencil_frame_copy_noalloc(ob, gpf, *gpf_eval);
}
-/* Calculate gpencil modifiers */
-void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
+static bGPdata *gpencil_copy_for_eval(bGPdata *gpd)
{
- /* use original data to set reference pointers to original data */
- Object *ob_orig = DEG_get_original_object(ob);
- bGPdata *gpd = (bGPdata *)ob_orig->data;
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const bool simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, false);
- const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
- int cfra_eval = (int)DEG_get_ctime(depsgraph);
+ int flags = LIB_ID_COPY_LOCALIZE;
+
+ bGPdata *result;
+ BKE_id_copy_ex(NULL, &gpd->id, (ID **)&result, flags);
+ return result;
+}
- /* Clear any previous evaluated data. */
- if (ob->runtime.gpencil_tot_layers > 0) {
- for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
- bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i];
- BKE_gpencil_free_frame_runtime_data(gpf_eval);
+void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ bGPdata *gpd_eval = (bGPdata *)ob->data;
+ Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
+ bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
+
+ /* Need check if some layer is parented. */
+ bool do_parent = false;
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
+ if (gpl->parent != NULL) {
+ do_parent = true;
+ break;
}
}
- /* Create array of evaluated frames equal to number of layers. */
- ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers);
- CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1);
- if (ob->runtime.gpencil_evaluated_frames == NULL) {
- ob->runtime.gpencil_evaluated_frames = MEM_callocN(
- sizeof(struct bGPDframe) * ob->runtime.gpencil_tot_layers, __func__);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval);
+ const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
+ (!GPENCIL_SIMPLIFY_MODIF(scene)));
+ if ((!do_modifiers) && (!do_parent)) {
+ return;
+ }
+ DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval);
+
+ /* If only one user, don't need a new copy, just update data of the frame. */
+ if (gpd_orig->id.us == 1) {
+ ob->runtime.gpd_eval = NULL;
+ gpencil_copy_activeframe_to_eval(depsgraph, scene, ob, ob_orig->data, gpd_eval);
+ return;
}
- else {
- ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames,
- sizeof(struct bGPDframe) *
- ob->runtime.gpencil_tot_layers);
+
+ /* Copy full Datablock to evaluated version. */
+ ob->runtime.gpd_orig = gpd_orig;
+ if (ob->runtime.gpd_eval != NULL) {
+ BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
+ ob->runtime.gpd_eval = NULL;
+ ob->data = ob->runtime.gpd_orig;
+ }
+ ob->runtime.gpd_eval = gpencil_copy_for_eval(ob->runtime.gpd_orig);
+ gpencil_assign_object_eval(ob);
+ BKE_gpencil_update_orig_pointers(ob_orig, (Object *)ob);
+}
+
+/* Calculate gpencil modifiers */
+void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ const bool is_edit = GPENCIL_ANY_EDIT_MODE(gpd);
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const bool do_modifiers = (bool)((!is_multiedit) && (ob->greasepencil_modifiers.first != NULL) &&
+ (!GPENCIL_SIMPLIFY_MODIF(scene)));
+ if (!do_modifiers) {
+ return;
}
/* Init general modifiers data. */
- if (ob->greasepencil_modifiers.first) {
- BKE_gpencil_lattice_init(ob);
- }
-
- /* *****************************************************************
- * Loop all layers, duplicate data and apply modifiers.
- *
- * ******************************************************************/
- int idx = 0;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* Remap frame (Time modifier) */
- int remap_cfra = cfra_eval;
- if ((time_remap) && (!simplify_modif)) {
- remap_cfra = BKE_gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
- }
- bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+ BKE_gpencil_lattice_init(ob);
- if (gpf == NULL) {
- idx++;
- continue;
- }
+ const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
- /* Create a duplicate data set of stroke to modify. */
- bGPDframe *gpf_eval = NULL;
- gpencil_evaluated_frame_ensure(idx, ob, gpf, &gpf_eval);
+ LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) {
- /* Skip all if some disable flag is enabled. */
- if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
- idx++;
- continue;
- }
+ if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- /* Apply geometry modifiers (create new geometry). */
- if (BKE_gpencil_has_geometry_modifiers(ob)) {
- BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, gpf_eval, is_render);
- }
+ if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) {
+ continue;
+ }
- /* Loop all strokes and deform them. */
- for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps->next) {
- /* Apply modifiers that only deform geometry */
- BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, gpf_eval, gps, is_render);
- }
+ /* Apply geometry modifiers (add new geometry). */
+ if (mti && mti->generateStrokes) {
+ mti->generateStrokes(md, depsgraph, ob);
+ }
- idx++;
+ /* Apply deform modifiers and Time remap (only change geometry). */
+ if ((time_remap) || (mti && mti->deformStroke)) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl);
+ if (gpf == NULL) {
+ continue;
+ }
+
+ if (mti->deformStroke) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ mti->deformStroke(md, depsgraph, ob, gpl, gpf, gps);
+ }
+ }
+ }
+ }
+ }
}
/* Clear any lattice data. */
- if (ob->greasepencil_modifiers.first) {
- BKE_gpencil_lattice_clear(ob);
- }
+ BKE_gpencil_lattice_clear(ob);
}
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index e1868d88351..ee27d0e546d 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -738,6 +738,15 @@ static void library_foreach_ID_link(Main *bmain,
if (toolsett->gp_paint) {
library_foreach_paint(&data, &toolsett->gp_paint->paint);
}
+ if (toolsett->gp_vertexpaint) {
+ library_foreach_paint(&data, &toolsett->gp_vertexpaint->paint);
+ }
+ if (toolsett->gp_sculptpaint) {
+ library_foreach_paint(&data, &toolsett->gp_sculptpaint->paint);
+ }
+ if (toolsett->gp_weightpaint) {
+ library_foreach_paint(&data, &toolsett->gp_weightpaint->paint);
+ }
CALLBACK_INVOKE(toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP);
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 10f32a6b0bc..22d7c505e60 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -168,15 +168,12 @@ void BKE_gpencil_material_attr_init(Material *ma)
/* set basic settings */
gp_style->stroke_rgba[3] = 1.0f;
gp_style->fill_rgba[3] = 1.0f;
- gp_style->pattern_gridsize = 0.1f;
- gp_style->gradient_radius = 0.5f;
ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f);
- ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f);
ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f);
gp_style->texture_opacity = 1.0f;
gp_style->texture_pixsize = 100.0f;
- gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ gp_style->flag |= GP_MATERIAL_STROKE_SHOW;
}
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index e4a3174c908..211cb633881 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -729,8 +729,11 @@ void BKE_object_free_derived_caches(Object *ob)
BKE_object_to_mesh_clear(ob);
BKE_object_free_curve_cache(ob);
- /* clear grease pencil data */
- DRW_gpencil_freecache(ob);
+ /* Clear grease pencil data. */
+ if (ob->runtime.gpd_eval != NULL) {
+ BKE_gpencil_eval_delete(ob->runtime.gpd_eval);
+ ob->runtime.gpd_eval = NULL;
+ }
}
void BKE_object_free_caches(Object *object)
@@ -803,6 +806,9 @@ bool BKE_object_is_in_editmode(const Object *ob)
case OB_SURF:
case OB_CURVE:
return ((Curve *)ob->data)->editnurb != NULL;
+ case OB_GPENCIL:
+ /* Grease Pencil object has no edit mode data. */
+ return GPENCIL_EDIT_MODE((bGPdata *)ob->data);
default:
return false;
}
@@ -1034,6 +1040,10 @@ static void object_init(Object *ob, const short ob_type)
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
+
+ if (ob->type == OB_GPENCIL) {
+ ob->dtx |= OB_USE_GPENCIL_LIGHTS;
+ }
}
void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
@@ -3963,7 +3973,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->data_eval = NULL;
runtime->mesh_deform_eval = NULL;
runtime->curve_cache = NULL;
- runtime->gpencil_cache = NULL;
}
/*
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index c647afdd00a..20b2ab9409f 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -24,6 +24,7 @@
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
+#include "DNA_gpencil_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -150,6 +151,11 @@ void BKE_object_eval_transform_final(Depsgraph *depsgraph, Object *ob)
else {
ob->transflag &= ~OB_NEG_SCALE;
}
+
+ /* Assign evaluated version. */
+ if ((ob->type == OB_GPENCIL) && (ob->runtime.gpd_eval != NULL)) {
+ ob->data = ob->runtime.gpd_eval;
+ }
}
void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
@@ -213,9 +219,12 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_LATTICE:
BKE_lattice_modifiers_calc(depsgraph, scene, ob);
break;
- case OB_GPENCIL:
+ case OB_GPENCIL: {
+ BKE_gpencil_prepare_eval_data(depsgraph, scene, ob);
BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
+ BKE_gpencil_update_layer_parent(depsgraph, ob);
break;
+ }
}
/* particles */
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 35683ca93f4..e6042b6ad4c 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -215,6 +215,15 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
case PAINT_MODE_GPENCIL:
paint_ptr = (Paint **)&ts->gp_paint;
break;
+ case PAINT_MODE_VERTEX_GPENCIL:
+ paint_ptr = (Paint **)&ts->gp_vertexpaint;
+ break;
+ case PAINT_MODE_SCULPT_GPENCIL:
+ paint_ptr = (Paint **)&ts->gp_sculptpaint;
+ break;
+ case PAINT_MODE_WEIGHT_GPENCIL:
+ paint_ptr = (Paint **)&ts->gp_weightpaint;
+ break;
case PAINT_MODE_INVALID:
break;
}
@@ -244,6 +253,12 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode)
return &ts->uvsculpt->paint;
case PAINT_MODE_GPENCIL:
return &ts->gp_paint->paint;
+ case PAINT_MODE_VERTEX_GPENCIL:
+ return &ts->gp_vertexpaint->paint;
+ case PAINT_MODE_SCULPT_GPENCIL:
+ return &ts->gp_sculptpaint->paint;
+ case PAINT_MODE_WEIGHT_GPENCIL:
+ return &ts->gp_weightpaint->paint;
case PAINT_MODE_INVALID:
return NULL;
default:
@@ -270,6 +285,12 @@ const EnumPropertyItem *BKE_paint_get_tool_enum_from_paintmode(ePaintMode mode)
return rna_enum_brush_uv_sculpt_tool_items;
case PAINT_MODE_GPENCIL:
return rna_enum_brush_gpencil_types_items;
+ case PAINT_MODE_VERTEX_GPENCIL:
+ return rna_enum_brush_gpencil_vertex_types_items;
+ case PAINT_MODE_SCULPT_GPENCIL:
+ return rna_enum_brush_gpencil_sculpt_types_items;
+ case PAINT_MODE_WEIGHT_GPENCIL:
+ return rna_enum_brush_gpencil_weight_types_items;
case PAINT_MODE_INVALID:
break;
}
@@ -292,6 +313,12 @@ const char *BKE_paint_get_tool_prop_id_from_paintmode(ePaintMode mode)
return "uv_sculpt_tool";
case PAINT_MODE_GPENCIL:
return "gpencil_tool";
+ case PAINT_MODE_VERTEX_GPENCIL:
+ return "gpencil_vertex_tool";
+ case PAINT_MODE_SCULPT_GPENCIL:
+ return "gpencil_sculpt_tool";
+ case PAINT_MODE_WEIGHT_GPENCIL:
+ return "gpencil_weight_tool";
default:
/* invalid paint mode */
return NULL;
@@ -315,6 +342,12 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
return &ts->imapaint.paint;
case OB_MODE_PAINT_GPENCIL:
return &ts->gp_paint->paint;
+ case OB_MODE_VERTEX_GPENCIL:
+ return &ts->gp_vertexpaint->paint;
+ case OB_MODE_SCULPT_GPENCIL:
+ return &ts->gp_sculptpaint->paint;
+ case OB_MODE_WEIGHT_GPENCIL:
+ return &ts->gp_weightpaint->paint;
case OB_MODE_EDIT:
return &ts->uvsculpt->paint;
default:
@@ -429,6 +462,12 @@ ePaintMode BKE_paintmode_get_from_tool(const struct bToolRef *tref)
return PAINT_MODE_GPENCIL;
case CTX_MODE_PAINT_TEXTURE:
return PAINT_MODE_TEXTURE_3D;
+ case CTX_MODE_VERTEX_GPENCIL:
+ return PAINT_MODE_VERTEX_GPENCIL;
+ case CTX_MODE_SCULPT_GPENCIL:
+ return PAINT_MODE_SCULPT_GPENCIL;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ return PAINT_MODE_WEIGHT_GPENCIL;
}
}
else if (tref->space_type == SPACE_IMAGE) {
@@ -485,6 +524,18 @@ void BKE_paint_runtime_init(const ToolSettings *ts, Paint *paint)
paint->runtime.tool_offset = offsetof(Brush, gpencil_tool);
paint->runtime.ob_mode = OB_MODE_PAINT_GPENCIL;
}
+ else if (paint == &ts->gp_vertexpaint->paint) {
+ paint->runtime.tool_offset = offsetof(Brush, gpencil_vertex_tool);
+ paint->runtime.ob_mode = OB_MODE_VERTEX_GPENCIL;
+ }
+ else if (paint == &ts->gp_sculptpaint->paint) {
+ paint->runtime.tool_offset = offsetof(Brush, gpencil_sculpt_tool);
+ paint->runtime.ob_mode = OB_MODE_SCULPT_GPENCIL;
+ }
+ else if (paint == &ts->gp_weightpaint->paint) {
+ paint->runtime.tool_offset = offsetof(Brush, gpencil_weight_tool);
+ paint->runtime.ob_mode = OB_MODE_WEIGHT_GPENCIL;
+ }
else {
BLI_assert(0);
}
@@ -506,6 +557,12 @@ uint BKE_paint_get_brush_tool_offset_from_paintmode(const ePaintMode mode)
return offsetof(Brush, uv_sculpt_tool);
case PAINT_MODE_GPENCIL:
return offsetof(Brush, gpencil_tool);
+ case PAINT_MODE_VERTEX_GPENCIL:
+ return offsetof(Brush, gpencil_vertex_tool);
+ case PAINT_MODE_SCULPT_GPENCIL:
+ return offsetof(Brush, gpencil_sculpt_tool);
+ case PAINT_MODE_WEIGHT_GPENCIL:
+ return offsetof(Brush, gpencil_weight_tool);
case PAINT_MODE_INVALID:
break; /* We don't use these yet. */
}
@@ -639,6 +696,204 @@ bool BKE_palette_is_empty(const struct Palette *palette)
return BLI_listbase_is_empty(&palette->colors);
}
+/* helper function to sort using qsort */
+static int palettecolor_compare_hsv(const void *a1, const void *a2)
+{
+ const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
+
+ /* Hue */
+ if (ps1->h > ps2->h) {
+ return 1;
+ }
+ else if (ps1->h < ps2->h) {
+ return -1;
+ }
+
+ /* Saturation. */
+ if (ps1->s > ps2->s) {
+ return 1;
+ }
+ else if (ps1->s < ps2->s) {
+ return -1;
+ }
+
+ /* Value. */
+ if (1.0f - ps1->v > 1.0f - ps2->v) {
+ return 1;
+ }
+ else if (1.0f - ps1->v < 1.0f - ps2->v) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* helper function to sort using qsort */
+static int palettecolor_compare_svh(const void *a1, const void *a2)
+{
+ const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
+
+ /* Saturation. */
+ if (ps1->s > ps2->s) {
+ return 1;
+ }
+ else if (ps1->s < ps2->s) {
+ return -1;
+ }
+
+ /* Value. */
+ if (1.0f - ps1->v > 1.0f - ps2->v) {
+ return 1;
+ }
+ else if (1.0f - ps1->v < 1.0f - ps2->v) {
+ return -1;
+ }
+
+ /* Hue */
+ if (ps1->h > ps2->h) {
+ return 1;
+ }
+ else if (ps1->h < ps2->h) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int palettecolor_compare_vhs(const void *a1, const void *a2)
+{
+ const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
+
+ /* Value. */
+ if (1.0f - ps1->v > 1.0f - ps2->v) {
+ return 1;
+ }
+ else if (1.0f - ps1->v < 1.0f - ps2->v) {
+ return -1;
+ }
+
+ /* Hue */
+ if (ps1->h > ps2->h) {
+ return 1;
+ }
+ else if (ps1->h < ps2->h) {
+ return -1;
+ }
+
+ /* Saturation. */
+ if (ps1->s > ps2->s) {
+ return 1;
+ }
+ else if (ps1->s < ps2->s) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int palettecolor_compare_luminance(const void *a1, const void *a2)
+{
+ const tPaletteColorHSV *ps1 = a1, *ps2 = a2;
+
+ float lumi1 = (ps1->rgb[0] + ps1->rgb[1] + ps1->rgb[2]) / 3.0f;
+ float lumi2 = (ps2->rgb[0] + ps2->rgb[1] + ps2->rgb[2]) / 3.0f;
+
+ if (lumi1 > lumi2) {
+ return -1;
+ }
+ else if (lumi1 < lumi2) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void BKE_palette_sort_hsv(tPaletteColorHSV *color_array, const int totcol)
+{
+ /* Sort by Hue , Saturation and Value. */
+ qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_hsv);
+}
+
+void BKE_palette_sort_svh(tPaletteColorHSV *color_array, const int totcol)
+{
+ /* Sort by Saturation, Value and Hue. */
+ qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_svh);
+}
+
+void BKE_palette_sort_vhs(tPaletteColorHSV *color_array, const int totcol)
+{
+ /* Sort by Saturation, Value and Hue. */
+ qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_vhs);
+}
+
+void BKE_palette_sort_luminance(tPaletteColorHSV *color_array, const int totcol)
+{
+ /* Sort by Luminance (calculated with the average, enough for sorting). */
+ qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_luminance);
+}
+
+bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, const bool linear)
+{
+ tPaletteColorHSV *color_array = NULL;
+ tPaletteColorHSV *col_elm = NULL;
+ bool done = false;
+
+ const int totpal = BLI_ghash_len(color_table);
+
+ if (totpal > 0) {
+ color_array = MEM_calloc_arrayN(totpal, sizeof(tPaletteColorHSV), __func__);
+ /* Put all colors in an array. */
+ GHashIterator gh_iter;
+ int t = 0;
+ GHASH_ITER (gh_iter, color_table) {
+ const uint col = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
+ float r, g, b;
+ float h, s, v;
+ cpack_to_rgb(col, &r, &g, &b);
+ rgb_to_hsv(r, g, b, &h, &s, &v);
+
+ col_elm = &color_array[t];
+ col_elm->rgb[0] = r;
+ col_elm->rgb[1] = g;
+ col_elm->rgb[2] = b;
+ col_elm->h = h;
+ col_elm->s = s;
+ col_elm->v = v;
+ t++;
+ }
+ }
+
+ /* Create the Palette. */
+ if (totpal > 0) {
+ /* Sort by Hue and saturation. */
+ BKE_palette_sort_hsv(color_array, totpal);
+
+ Palette *palette = BKE_palette_add(bmain, name);
+ if (palette) {
+ for (int i = 0; i < totpal; i++) {
+ col_elm = &color_array[i];
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, col_elm->rgb);
+ if (linear) {
+ linearrgb_to_srgb_v3_v3(palcol->rgb, palcol->rgb);
+ }
+ }
+ }
+ done = true;
+ }
+ }
+ else {
+ done = false;
+ }
+
+ if (totpal > 0) {
+ MEM_SAFE_FREE(color_array);
+ }
+
+ return done;
+}
+
/* are we in vertex paint or weight paint face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
@@ -720,6 +975,9 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
BLI_assert(ELEM(*r_paint,
/* Cast is annoying, but prevent NULL-pointer access. */
(Paint *)ts->gp_paint,
+ (Paint *)ts->gp_vertexpaint,
+ (Paint *)ts->gp_sculptpaint,
+ (Paint *)ts->gp_weightpaint,
(Paint *)ts->sculpt,
(Paint *)ts->vpaint,
(Paint *)ts->wpaint,
@@ -755,6 +1013,18 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
GpPaint *data = MEM_callocN(sizeof(*data), __func__);
paint = &data->paint;
}
+ else if ((GpVertexPaint **)r_paint == &ts->gp_vertexpaint) {
+ GpVertexPaint *data = MEM_callocN(sizeof(*data), __func__);
+ paint = &data->paint;
+ }
+ else if ((GpSculptPaint **)r_paint == &ts->gp_sculptpaint) {
+ GpSculptPaint *data = MEM_callocN(sizeof(*data), __func__);
+ paint = &data->paint;
+ }
+ else if ((GpWeightPaint **)r_paint == &ts->gp_weightpaint) {
+ GpWeightPaint *data = MEM_callocN(sizeof(*data), __func__);
+ paint = &data->paint;
+ }
else if ((UvSculpt **)r_paint == &ts->uvsculpt) {
UvSculpt *data = MEM_callocN(sizeof(*data), __func__);
paint = &data->paint;
diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c
index e9601109fd5..7e58bf1eb8b 100644
--- a/source/blender/blenkernel/intern/paint_toolslots.c
+++ b/source/blender/blenkernel/intern/paint_toolslots.c
@@ -82,6 +82,15 @@ void BKE_paint_toolslots_init_from_main(struct Main *bmain)
if (ts->gp_paint) {
paint_toolslots_init(bmain, &ts->gp_paint->paint);
}
+ if (ts->gp_vertexpaint) {
+ paint_toolslots_init(bmain, &ts->gp_vertexpaint->paint);
+ }
+ if (ts->gp_sculptpaint) {
+ paint_toolslots_init(bmain, &ts->gp_sculptpaint->paint);
+ }
+ if (ts->gp_weightpaint) {
+ paint_toolslots_init(bmain, &ts->gp_weightpaint->paint);
+ }
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a88f5a4daa4..f7f59687cb7 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -201,72 +201,6 @@ static void scene_init_data(ID *id)
BKE_color_managed_view_settings_init_render(
&scene->r.bake.im_format.view_settings, &scene->r.bake.im_format.display_settings, "Filmic");
- /* GP Sculpt brushes */
- {
- GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
- GP_Sculpt_Data *gp_brush;
- float curcolor_add[3], curcolor_sub[3];
- ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
- ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
- gp_brush->size = 25;
- gp_brush->strength = 0.3f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_SMOOTH_PRESSURE |
- GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_THICKNESS];
- gp_brush->size = 25;
- gp_brush->strength = 0.5f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_STRENGTH];
- gp_brush->size = 25;
- gp_brush->strength = 0.5f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_GRAB];
- gp_brush->size = 50;
- gp_brush->strength = 0.3f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_PUSH];
- gp_brush->size = 25;
- gp_brush->strength = 0.3f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_TWIST];
- gp_brush->size = 50;
- gp_brush->strength = 0.3f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_PINCH];
- gp_brush->size = 50;
- gp_brush->strength = 0.5f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
-
- gp_brush = &gset->brush[GP_SCULPT_TYPE_RANDOMIZE];
- gp_brush->size = 25;
- gp_brush->strength = 0.5f;
- gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
- copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
- copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
- }
-
/* Curve Profile */
scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
@@ -560,6 +494,18 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
ts->gp_paint = MEM_dupallocN(ts->gp_paint);
BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag);
}
+ if (ts->gp_vertexpaint) {
+ ts->gp_vertexpaint = MEM_dupallocN(ts->gp_vertexpaint);
+ BKE_paint_copy(&ts->gp_vertexpaint->paint, &ts->gp_vertexpaint->paint, flag);
+ }
+ if (ts->gp_sculptpaint) {
+ ts->gp_sculptpaint = MEM_dupallocN(ts->gp_sculptpaint);
+ BKE_paint_copy(&ts->gp_sculptpaint->paint, &ts->gp_sculptpaint->paint, flag);
+ }
+ if (ts->gp_weightpaint) {
+ ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint);
+ BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag);
+ }
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
ts->imapaint.paintcursor = NULL;
@@ -602,6 +548,18 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
BKE_paint_free(&toolsettings->gp_paint->paint);
MEM_freeN(toolsettings->gp_paint);
}
+ if (toolsettings->gp_vertexpaint) {
+ BKE_paint_free(&toolsettings->gp_vertexpaint->paint);
+ MEM_freeN(toolsettings->gp_vertexpaint);
+ }
+ if (toolsettings->gp_sculptpaint) {
+ BKE_paint_free(&toolsettings->gp_sculptpaint->paint);
+ MEM_freeN(toolsettings->gp_sculptpaint);
+ }
+ if (toolsettings->gp_weightpaint) {
+ BKE_paint_free(&toolsettings->gp_weightpaint->paint);
+ MEM_freeN(toolsettings->gp_weightpaint);
+ }
BKE_paint_free(&toolsettings->imapaint.paint);
/* free Grease Pencil interpolation curve */