Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_stroke.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c165
1 files changed, 93 insertions, 72 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index de01bc3a474..a8cb05c6d2c 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -67,77 +67,6 @@
# include "PIL_time_utildefines.h"
#endif
-typedef struct PaintSample {
- float mouse[2];
- float pressure;
-} PaintSample;
-
-typedef struct PaintStroke {
- void *mode_data;
- void *stroke_cursor;
- wmTimer *timer;
- struct RNG *rng;
-
- /* Cached values */
- ViewContext vc;
- Brush *brush;
- UnifiedPaintSettings *ups;
-
- /* used for lines and curves */
- ListBase line;
-
- /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
- * to smooth the stroke */
- PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
- int num_samples;
- int cur_sample;
- int tot_samples;
-
- float last_mouse_position[2];
- float last_world_space_position[3];
- bool stroke_over_mesh;
- /* space distance covered so far */
- float stroke_distance;
-
- /* Set whether any stroke step has yet occurred
- * e.g. in sculpt mode, stroke doesn't start until cursor
- * passes over the mesh */
- bool stroke_started;
- /* Set when enough motion was found for rake rotation */
- bool rake_started;
- /* event that started stroke, for modal() return */
- int event_type;
- /* check if stroke variables have been initialized */
- bool stroke_init;
- /* check if various brush mapping variables have been initialized */
- bool brush_init;
- float initial_mouse[2];
- /* cached_pressure stores initial pressure for size pressure influence mainly */
- float cached_size_pressure;
- /* last pressure will store last pressure value for use in interpolation for space strokes */
- float last_pressure;
- int stroke_mode;
-
- float last_tablet_event_pressure;
-
- float zoom_2d;
- int pen_flip;
-
- /* Tilt, as read from the event. */
- float x_tilt;
- float y_tilt;
-
- /* line constraint */
- bool constrain_line;
- float constrained_pos[2];
-
- StrokeGetLocation get_location;
- StrokeTestStart test_start;
- StrokeUpdateStep update_step;
- StrokeRedraw redraw;
- StrokeDone done;
-} PaintStroke;
-
/*** Cursors ***/
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
{
@@ -288,6 +217,26 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
return true;
}
+bool paint_stroke_apply_subspacing(struct PaintStroke *stroke,
+ const float spacing,
+ const enum ePaintMode mode,
+ float *state)
+{
+ if (!paint_space_stroke_enabled(stroke->brush, mode)) {
+ return true;
+ }
+
+ const float t = stroke->stroke_distance_t;
+
+ if (t != 0.0f && t < *state + spacing) {
+ return false;
+ }
+ else {
+ *state = t;
+ return true;
+ }
+}
+
/* Initialize the stroke cache variants from operator properties */
static bool paint_brush_update(bContext *C,
Brush *brush,
@@ -430,11 +379,13 @@ static bool paint_brush_update(bContext *C,
ups->anchored_size /= 2.0f;
ups->pixel_radius /= 2.0f;
stroke->stroke_distance = ups->pixel_radius;
+ stroke->stroke_distance_t = 1.0f;
}
else {
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
copy_v2_v2(mouse, stroke->initial_mouse);
stroke->stroke_distance = ups->pixel_radius;
+ stroke->stroke_distance_t = 1.0f;
}
ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
@@ -767,6 +718,58 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor)
return 1.0f / max;
}
+static float paint_space_get_final_size_intern(
+ bContext *C, const Scene *scene, PaintStroke *stroke, float pressure, float dpressure)
+{
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ float size = BKE_brush_size_get(scene, stroke->brush) * pressure;
+
+ if (paint_stroke_use_scene_spacing(stroke->brush, mode)) {
+ if (!BKE_brush_use_locked_size(scene, stroke->brush)) {
+ float last_object_space_position[3];
+ mul_v3_m4v3(
+ last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
+ size = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
+ }
+ else {
+ size = BKE_brush_unprojected_radius_get(scene, stroke->brush) * pressure;
+ }
+ }
+
+ return size;
+}
+
+static float paint_space_get_final_size(bContext *C,
+ const Scene *scene,
+ PaintStroke *stroke,
+ float pressure,
+ float dpressure,
+ float length)
+{
+ if (BKE_brush_use_size_pressure(stroke->brush)) {
+ /* use pressure to modify size. set spacing so that at 100%, the circles
+ * are aligned nicely with no overlap. for this the spacing needs to be
+ * the average of the previous and next size. */
+ float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
+ float q = s * dpressure / (2.0f * length);
+ float pressure_fac = (1.0f + q) / (1.0f - q);
+
+ float last_size_pressure = stroke->last_pressure;
+ float new_size_pressure = stroke->last_pressure * pressure_fac;
+
+ /* average spacing */
+ float last_size = paint_space_get_final_size_intern(
+ C, scene, stroke, last_size_pressure, pressure);
+ float new_size = paint_space_get_final_size_intern(
+ C, scene, stroke, new_size_pressure, pressure);
+
+ return 0.5f * (last_size + new_size);
+ }
+ else {
+ return paint_space_get_final_size_intern(C, scene, stroke, 1.0, 0.0);
+ }
+}
+
static float paint_space_stroke_spacing_variable(bContext *C,
const Scene *scene,
PaintStroke *stroke,
@@ -797,6 +800,8 @@ static float paint_space_stroke_spacing_variable(bContext *C,
return paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
}
+#include "BLI_compiler_attrs.h"
+
/* For brushes with stroke spacing enabled, moves mouse in steps
* towards the final mouse location. */
static int paint_space_stroke(bContext *C,
@@ -866,8 +871,17 @@ static int paint_space_stroke(bContext *C,
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush,
spacing / no_pressure_spacing);
+ if (use_scene_spacing) {
+ float size = paint_space_get_final_size(C, scene, stroke, pressure, dpressure, length);
+
+ stroke->stroke_distance += stroke->ups->pixel_radius * spacing / size;
+ stroke->stroke_distance_t += spacing / size;
+ }
+ else {
+ stroke->stroke_distance += spacing / stroke->zoom_2d;
+ stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
+ }
- stroke->stroke_distance += spacing / stroke->zoom_2d;
paint_brush_stroke_add_step(C, op, mouse, pressure);
length -= spacing;
@@ -1233,6 +1247,8 @@ static void paint_line_strokes_spacing(bContext *C,
length += *length_residue;
*length_residue = 0.0;
+ stroke->spacing = spacing;
+
if (length >= spacing) {
if (use_scene_spacing) {
float final_world_space_position[3];
@@ -1250,6 +1266,8 @@ static void paint_line_strokes_spacing(bContext *C,
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
stroke->stroke_distance += spacing / stroke->zoom_2d;
+ stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
+
paint_brush_stroke_add_step(C, op, mouse, 1.0);
length -= spacing;
@@ -1472,6 +1490,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* one time stroke initialization */
if (!stroke->stroke_started) {
stroke->last_pressure = sample_average.pressure;
+
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
if (paint_stroke_use_scene_spacing(br, mode)) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
@@ -1558,6 +1577,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
float dmouse[2];
sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
stroke->stroke_distance += len_v2(dmouse);
+ stroke->stroke_distance_t += len_v2(dmouse) / stroke->ups->pixel_radius;
+
paint_brush_stroke_add_step(C, op, mouse, pressure);
redraw = true;
}