Cleanup: Various non-functional changes for paint_stroke.cc

This commit applies the following changes:
* Use c++ math types instead of float / int arrays where possible
* Use c++ math library where c++ math types are used
* Use const where possible
* Reduces scope of variables where possible
* Clarifies some variable naming (e.g. d prefix to _delta suffix)

The main areas left untouched are anything that is part of a public
function signature to avoid making changes in many different files at
once.

Pull Request: https://projects.blender.org/blender/blender/pulls/129576
This commit is contained in:
Sean Kim
2024-10-31 21:11:59 +01:00
committed by Sean Kim
parent 3ff2733279
commit dd7064b2e1

View File

@@ -13,6 +13,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math_matrix.h"
#include "BLI_math_matrix.hh"
#include "BLI_rand.hh"
#include "BLI_utildefines.h"
@@ -126,19 +127,20 @@ struct PaintStroke {
};
/*** Cursors ***/
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
static void paint_draw_smooth_cursor(bContext *C, const int x, const int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
const Paint *paint = BKE_paint_get_active_from_context(C);
const Brush *brush = BKE_paint_brush_for_read(paint);
PaintStroke *stroke = static_cast<PaintStroke *>(customdata);
if (stroke && brush) {
GPU_line_smooth(true);
GPU_blend(GPU_BLEND_ALPHA);
ARegion *region = stroke->vc.region;
const ARegion *region = stroke->vc.region;
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
const uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4ubv(paint->paint_cursor_col);
@@ -157,19 +159,19 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
}
}
static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
static void paint_draw_line_cursor(bContext *C, const int x, const int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
const Paint *paint = BKE_paint_get_active_from_context(C);
PaintStroke *stroke = static_cast<PaintStroke *>(customdata);
GPU_line_smooth(true);
uint shdr_pos = GPU_vertformat_attr_add(
const uint shdr_pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
float4 viewport_size;
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
@@ -182,7 +184,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
immBegin(GPU_PRIM_LINES, 2);
ARegion *region = stroke->vc.region;
const ARegion *region = stroke->vc.region;
if (stroke->constrain_line) {
immVertex2f(shdr_pos,
@@ -286,11 +288,11 @@ static bool image_paint_brush_type_require_inbetween_mouse_events(const Brush &b
/* Initialize the stroke cache variants from operator properties */
bool paint_brush_update(bContext *C,
const Brush &brush,
PaintMode mode,
const PaintMode mode,
PaintStroke *stroke,
const float mouse_init[2],
float mouse[2],
float pressure,
const float pressure,
float r_location[3],
bool *r_location_is_set)
{
@@ -376,7 +378,7 @@ bool paint_brush_update(bContext *C,
if (brush.flag & BRUSH_ANCHORED) {
bool hit = false;
float halfway[2];
float2 halfway;
const float dx = mouse[0] - stroke->initial_mouse[0];
const float dy = mouse[1] - stroke->initial_mouse[1];
@@ -422,13 +424,8 @@ bool paint_brush_update(bContext *C,
ups.draw_anchored = true;
}
else {
/* here we are using the initial mouse coordinate because we do not want the rake
* result to depend on jittering */
if (!stroke->brush_init) {
copy_v2_v2(ups.last_rake, mouse_init);
}
/* curve strokes do their own rake calculation */
else if (!(brush.flag & BRUSH_CURVE)) {
if (!(brush.flag & BRUSH_CURVE)) {
if (!paint_calculate_rake_rotation(ups, brush, mouse_init, mode, stroke->rake_started)) {
/* Not enough motion to define an angle. */
if (!stroke->rake_started) {
@@ -477,7 +474,7 @@ bool paint_brush_update(bContext *C,
}
}
return location_success && (is_dry_run == false);
return location_success && !is_dry_run;
}
static bool paint_stroke_use_dash(const Brush &brush)
@@ -486,16 +483,16 @@ static bool paint_stroke_use_dash(const Brush &brush)
return brush.flag & BRUSH_SPACE || brush.flag & BRUSH_LINE || brush.flag & BRUSH_CURVE;
}
static bool paint_stroke_use_jitter(PaintMode mode, const Brush &brush, bool invert)
static bool paint_stroke_use_jitter(const PaintMode mode, const Brush &brush, const bool invert)
{
bool use_jitter = (brush.flag & BRUSH_ABSOLUTE_JITTER) ? (brush.jitter_absolute != 0) :
(brush.jitter != 0);
bool use_jitter = brush.flag & BRUSH_ABSOLUTE_JITTER ? brush.jitter_absolute != 0 :
brush.jitter != 0;
/* jitter-ed brush gives weird and unpredictable result for this
* kinds of stroke, so manually disable jitter usage (sergey) */
use_jitter &= (brush.flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
use_jitter &= (!ELEM(mode, PaintMode::Texture2D, PaintMode::Texture3D) ||
!(invert && brush.image_brush_type == IMAGE_PAINT_BRUSH_TYPE_CLONE));
use_jitter &= !ELEM(mode, PaintMode::Texture2D, PaintMode::Texture3D) ||
!(invert && brush.image_brush_type == IMAGE_PAINT_BRUSH_TYPE_CLONE);
return use_jitter;
}
@@ -509,7 +506,6 @@ void paint_stroke_jitter_pos(Scene &scene,
float r_mouse_out[2])
{
if (paint_stroke_use_jitter(mode, brush, stroke.stroke_mode == BRUSH_STROKE_INVERT)) {
float delta[2];
float factor = stroke.zoom_2d;
if (brush.flag & BRUSH_JITTER_PRESSURE) {
@@ -522,6 +518,7 @@ void paint_stroke_jitter_pos(Scene &scene,
* BKE_brush_jitter_pos isn't written in the best way to
* be reused here */
if (factor != 1.0f) {
float2 delta;
sub_v2_v2v2(delta, r_mouse_out, mval);
mul_v2_fl(delta, factor);
add_v2_v2v2(r_mouse_out, mval, delta);
@@ -534,16 +531,13 @@ void paint_stroke_jitter_pos(Scene &scene,
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
static void paint_brush_stroke_add_step(
bContext *C, wmOperator *op, PaintStroke *stroke, const float mval[2], float pressure)
bContext *C, wmOperator *op, PaintStroke *stroke, const float2 mval, float pressure)
{
Scene &scene = *CTX_data_scene(C);
Paint &paint = *BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
const Paint &paint = *BKE_paint_get_active_from_context(C);
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
const Brush &brush = *BKE_paint_brush_for_read(&paint);
UnifiedPaintSettings *ups = stroke->ups;
float mouse_out[2];
PointerRNA itemptr;
float location[3];
/* the following code is adapted from texture paint. It may not be needed but leaving here
* just in case for reference (code in texpaint removed as part of refactoring).
@@ -574,26 +568,28 @@ static void paint_brush_stroke_add_step(
/* copy last position -before- jittering, or space fill code
* will create too many dabs */
copy_v2_v2(stroke->last_mouse_position, mval);
stroke->last_mouse_position = mval;
stroke->last_pressure = pressure;
if (paint_stroke_use_scene_spacing(brush, mode)) {
float world_space_position[3];
float3 world_space_position;
if (SCULPT_stroke_get_location(
C, world_space_position, stroke->last_mouse_position, stroke->original))
{
copy_v3_v3(stroke->last_world_space_position, world_space_position);
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), stroke->last_world_space_position);
stroke->last_world_space_position = math::transform_point(
stroke->vc.obact->object_to_world(), world_space_position);
}
else {
add_v3_v3(stroke->last_world_space_position, stroke->last_scene_spacing_delta);
stroke->last_world_space_position += stroke->last_scene_spacing_delta;
}
}
float2 mouse_out;
/* Get jitter position (same as mval if no jitter is used). */
paint_stroke_jitter_pos(scene, *stroke, mode, brush, pressure, mval, mouse_out);
float3 location;
bool is_location_is_set;
ups->last_hit = paint_brush_update(
C, brush, mode, stroke, mval, mouse_out, pressure, location, &is_location_is_set);
@@ -607,8 +603,8 @@ static void paint_brush_stroke_add_step(
/* Dash */
bool add_step = true;
if (paint_stroke_use_dash(brush)) {
int dash_samples = stroke->tot_samples % brush.dash_samples;
float dash = float(dash_samples) / float(brush.dash_samples);
const int dash_samples = stroke->tot_samples % brush.dash_samples;
const float dash = float(dash_samples) / float(brush.dash_samples);
if (dash > brush.dash_ratio) {
add_step = false;
}
@@ -616,6 +612,7 @@ static void paint_brush_stroke_add_step(
/* Add to stroke */
if (add_step) {
PointerRNA itemptr;
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set(&itemptr, "size", ups->pixel_radius);
RNA_float_set_array(&itemptr, "location", location);
@@ -641,49 +638,47 @@ static void paint_brush_stroke_add_step(
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static bool paint_smooth_stroke(PaintStroke *stroke,
const PaintSample *sample,
PaintMode mode,
float r_mouse[2],
float *r_pressure)
const PaintMode mode,
float2 &r_mouse,
float &r_pressure)
{
if (paint_supports_smooth_stroke(stroke, *stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
float u = stroke->brush->smooth_stroke_factor;
const float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
const float u = stroke->brush->smooth_stroke_factor;
/* If the mouse is moving within the radius of the last move,
* don't update the mouse position. This allows sharp turns. */
if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < square_f(radius)) {
if (math::distance_squared(stroke->last_mouse_position, sample->mouse) < square_f(radius)) {
return false;
}
interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
*r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
r_mouse = math::interpolate(sample->mouse, stroke->last_mouse_position, u);
r_pressure = math::interpolate(sample->pressure, stroke->last_pressure, u);
}
else {
r_mouse[0] = sample->mouse[0];
r_mouse[1] = sample->mouse[1];
*r_pressure = sample->pressure;
r_mouse = sample->mouse;
r_pressure = sample->pressure;
}
return true;
}
static float paint_space_stroke_spacing(bContext *C,
static float paint_space_stroke_spacing(const bContext *C,
const Scene *scene,
PaintStroke *stroke,
float size_pressure,
float spacing_pressure)
const float size_pressure,
const float spacing_pressure)
{
Paint *paint = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
const Paint *paint = BKE_paint_get_active_from_context(C);
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
const Brush &brush = *BKE_paint_brush_for_read(paint);
const float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
float size_clamp = 0.0f;
float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (!BKE_brush_use_locked_size(scene, &brush)) {
float last_object_space_position[3];
mul_v3_m4v3(last_object_space_position,
stroke->vc.obact->world_to_object().ptr(),
stroke->last_world_space_position);
const float3 last_object_space_position = math::transform_point(
stroke->vc.obact->world_to_object(), stroke->last_world_space_position);
size_clamp = paint_calc_object_space_radius(stroke->vc, last_object_space_position, size);
}
else {
@@ -721,23 +716,21 @@ static float paint_space_stroke_spacing(bContext *C,
return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
}
static float paint_stroke_overlapped_curve(const Brush &br, float x, float spacing)
static float paint_stroke_overlapped_curve(const Brush &br, const float x, const float spacing)
{
/* Avoid division by small numbers, can happen
* on some pen setups. See #105341.
*/
spacing = max_ff(spacing, 0.1f);
const float clamped_spacing = max_ff(spacing, 0.1f);
const int n = 100 / spacing;
const float h = spacing / 50.0f;
const int n = 100 / clamped_spacing;
const float h = clamped_spacing / 50.0f;
const float x0 = x - 1;
float sum = 0;
for (int i = 0; i < n; i++) {
float xx;
xx = fabsf(x0 + i * h);
float xx = fabsf(x0 + i * h);
if (xx < 1.0f) {
sum += BKE_brush_curve_strength(&br, xx, 1);
@@ -747,23 +740,21 @@ static float paint_stroke_overlapped_curve(const Brush &br, float x, float spaci
return sum;
}
static float paint_stroke_integrate_overlap(const Brush &br, float factor)
static float paint_stroke_integrate_overlap(const Brush &br, const float factor)
{
float spacing = br.spacing * factor;
const float spacing = br.spacing * factor;
if (!(br.flag & BRUSH_SPACE_ATTEN && (br.spacing < 100))) {
return 1.0;
}
int m = 10;
constexpr int m = 10;
float g = 1.0f / m;
float max = 0;
for (int i = 0; i < m; i++) {
float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
const float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
if (overlap > max) {
max = overlap;
}
max = std::max(overlap, max);
}
if (max == 0.0f) {
@@ -775,25 +766,26 @@ static float paint_stroke_integrate_overlap(const Brush &br, float factor)
static float paint_space_stroke_spacing_variable(bContext *C,
const Scene *scene,
PaintStroke *stroke,
float pressure,
float dpressure,
float length)
const float pressure,
const float pressure_delta,
const 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);
const float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
const float q = s * pressure_delta / (2.0f * length);
const 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;
const float last_size_pressure = stroke->last_pressure;
const float new_size_pressure = stroke->last_pressure * pressure_fac;
/* average spacing */
float last_spacing = paint_space_stroke_spacing(
const float last_spacing = paint_space_stroke_spacing(
C, scene, stroke, last_size_pressure, pressure);
float new_spacing = paint_space_stroke_spacing(C, scene, stroke, new_size_pressure, pressure);
const float new_spacing = paint_space_stroke_spacing(
C, scene, stroke, new_size_pressure, pressure);
return 0.5f * (last_spacing + new_spacing);
}
@@ -807,69 +799,65 @@ static float paint_space_stroke_spacing_variable(bContext *C,
static int paint_space_stroke(bContext *C,
wmOperator *op,
PaintStroke *stroke,
const float final_mouse[2],
float final_pressure)
const float2 final_mouse,
const float final_pressure)
{
const Scene *scene = CTX_data_scene(C);
ARegion *region = CTX_wm_region(C);
const ARegion *region = CTX_wm_region(C);
UnifiedPaintSettings *ups = stroke->ups;
const Paint &paint = *BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
const Brush &brush = *BKE_paint_brush_for_read(&paint);
int count = 0;
float2 mouse_delta = final_mouse - stroke->last_mouse_position;
float length = normalize_v2(mouse_delta);
float3 world_space_position_delta;
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
float d_world_space_position[3] = {0.0f};
float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
float pressure = stroke->last_pressure;
float dpressure = final_pressure - stroke->last_pressure;
float dmouse[2];
sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
float length = normalize_v2(dmouse);
if (use_scene_spacing) {
float world_space_position[3];
bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse, stroke->original);
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), world_space_position);
float3 world_space_position;
const bool hit = SCULPT_stroke_get_location(
C, world_space_position, final_mouse, stroke->original);
world_space_position = math::transform_point(stroke->vc.obact->object_to_world(),
world_space_position);
if (hit && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position);
length = len_v3(d_world_space_position);
world_space_position_delta = world_space_position - stroke->last_world_space_position;
length = math::length(world_space_position_delta);
stroke->stroke_over_mesh = true;
}
else {
length = 0.0f;
zero_v3(d_world_space_position);
world_space_position_delta = {0.0f, 0.0f, 0.0f};
stroke->stroke_over_mesh = hit;
if (stroke->stroke_over_mesh) {
copy_v3_v3(stroke->last_world_space_position, world_space_position);
stroke->last_world_space_position = world_space_position;
}
}
}
float pressure = stroke->last_pressure;
float pressure_delta = final_pressure - stroke->last_pressure;
const float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
int count = 0;
while (length > 0.0f) {
float spacing = paint_space_stroke_spacing_variable(
C, scene, stroke, pressure, dpressure, length);
float mouse[2];
const float spacing = paint_space_stroke_spacing_variable(
C, scene, stroke, pressure, pressure_delta, length);
if (length >= spacing) {
float2 mouse;
if (use_scene_spacing) {
float final_world_space_position[3];
normalize_v3(d_world_space_position);
mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing);
add_v3_v3v3(final_world_space_position,
stroke->last_world_space_position,
final_world_space_position);
float3 final_world_space_position;
world_space_position_delta = math::normalize(world_space_position_delta);
final_world_space_position = world_space_position_delta * spacing +
stroke->last_world_space_position;
ED_view3d_project_v2(region, final_world_space_position, mouse);
mul_v3_v3fl(stroke->last_scene_spacing_delta, d_world_space_position, spacing);
stroke->last_scene_spacing_delta = world_space_position_delta * spacing;
}
else {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
mouse = stroke->last_mouse_position + mouse_delta * spacing;
}
pressure = stroke->last_pressure + (spacing / length) * dpressure;
pressure = stroke->last_pressure + (spacing / length) * pressure_delta;
ups->overlap_factor = paint_stroke_integrate_overlap(*stroke->brush,
spacing / no_pressure_spacing);
@@ -879,7 +867,7 @@ static int paint_space_stroke(bContext *C,
length -= spacing;
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
pressure_delta = final_pressure - stroke->last_pressure;
count++;
}
@@ -895,12 +883,12 @@ static int paint_space_stroke(bContext *C,
PaintStroke *paint_stroke_new(bContext *C,
wmOperator *op,
StrokeGetLocation get_location,
StrokeTestStart test_start,
StrokeUpdateStep update_step,
StrokeRedraw redraw,
StrokeDone done,
int event_type)
const StrokeGetLocation get_location,
const StrokeTestStart test_start,
const StrokeUpdateStep update_step,
const StrokeRedraw redraw,
const StrokeDone done,
const int event_type)
{
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
PaintStroke *stroke = MEM_new<PaintStroke>(__func__);
@@ -909,7 +897,6 @@ PaintStroke *paint_stroke_new(bContext *C,
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *br = stroke->brush = BKE_paint_brush(paint);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float zoomx, zoomy;
stroke->vc = ED_view3d_viewcontext_init(C, depsgraph);
@@ -925,8 +912,10 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->original = image_paint_brush_type_raycast_original(
*br, BKE_paintmode_get_active_from_context(C));
float zoomx;
float zoomy;
get_imapaint_zoom(C, &zoomx, &zoomy);
stroke->zoom_2d = max_ff(zoomx, zoomy);
stroke->zoom_2d = std::max(zoomx, zoomy);
/* Check here if color sampling the main brush should do color conversion. This is done here
* to avoid locking up to get the image buffer during sampling. */
@@ -979,8 +968,7 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_free(bContext *C, wmOperator * /*op*/, PaintStroke *stroke)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d) {
if (RegionView3D *rv3d = CTX_wm_region_view3d(C)) {
rv3d->rflag &= ~RV3D_PAINTING;
}
@@ -1036,7 +1024,7 @@ static bool curves_sculpt_brush_uses_spacing(const eBrushCurvesSculptType tool)
return ELEM(tool, CURVES_SCULPT_BRUSH_TYPE_ADD, CURVES_SCULPT_BRUSH_TYPE_DENSITY);
}
bool paint_space_stroke_enabled(const Brush &br, PaintMode mode)
bool paint_space_stroke_enabled(const Brush &br, const PaintMode mode)
{
if ((br.flag & BRUSH_SPACE) == 0) {
return false;
@@ -1081,7 +1069,7 @@ static bool sculpt_is_grab_tool(const Brush &br)
SCULPT_BRUSH_TYPE_SNAKE_HOOK);
}
bool paint_supports_dynamic_size(const Brush &br, PaintMode mode)
bool paint_supports_dynamic_size(const Brush &br, const PaintMode mode)
{
if (br.flag & BRUSH_ANCHORED) {
return false;
@@ -1107,7 +1095,7 @@ bool paint_supports_dynamic_size(const Brush &br, PaintMode mode)
return true;
}
bool paint_supports_smooth_stroke(PaintStroke *stroke, const Brush &brush, PaintMode mode)
bool paint_supports_smooth_stroke(PaintStroke *stroke, const Brush &brush, const PaintMode mode)
{
/* The grease pencil draw tool needs to enable this when the `stroke_mode` is set to
* `BRUSH_STROKE_SMOOTH`. */
@@ -1135,14 +1123,14 @@ bool paint_supports_smooth_stroke(PaintStroke *stroke, const Brush &brush, Paint
return true;
}
bool paint_supports_texture(PaintMode mode)
bool paint_supports_texture(const PaintMode mode)
{
/* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
return ELEM(
mode, PaintMode::Sculpt, PaintMode::Vertex, PaintMode::Texture3D, PaintMode::Texture2D);
}
bool paint_supports_dynamic_tex_coords(const Brush &br, PaintMode mode)
bool paint_supports_dynamic_tex_coords(const Brush &br, const PaintMode mode)
{
if (br.flag & BRUSH_ANCHORED) {
return false;
@@ -1180,11 +1168,14 @@ wmKeyMap *paint_stroke_modal_keymap(wmKeyConfig *keyconf)
return keymap;
}
static void paint_stroke_add_sample(
PaintStroke *stroke, int input_samples, float x, float y, float pressure)
static void paint_stroke_add_sample(PaintStroke *stroke,
const int input_samples,
const float x,
const float y,
const float pressure)
{
PaintSample *sample = &stroke->samples[stroke->cur_sample];
int max_samples = std::clamp(input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
const int max_samples = std::clamp(input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
sample->mouse[0] = x;
sample->mouse[1] = y;
@@ -1206,11 +1197,11 @@ static void paint_stroke_sample_average(const PaintStroke *stroke, PaintSample *
BLI_assert(stroke->num_samples > 0);
for (int i = 0; i < stroke->num_samples; i++) {
add_v2_v2(average->mouse, stroke->samples[i].mouse);
average->mouse += stroke->samples[i].mouse;
average->pressure += stroke->samples[i].pressure;
}
mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
average->mouse /= stroke->num_samples;
average->pressure /= stroke->num_samples;
// printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);
@@ -1223,50 +1214,55 @@ static void paint_stroke_sample_average(const PaintStroke *stroke, PaintSample *
static void paint_line_strokes_spacing(bContext *C,
wmOperator *op,
PaintStroke *stroke,
float spacing,
const float spacing,
float *length_residue,
const float old_pos[2],
const float new_pos[2])
const float2 old_pos,
const float2 new_pos)
{
UnifiedPaintSettings *ups = stroke->ups;
Paint *paint = BKE_paint_get_active_from_context(C);
Brush &brush = *BKE_paint_brush(paint);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
ARegion *region = CTX_wm_region(C);
const Brush &brush = *BKE_paint_brush(paint);
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
const ARegion *region = CTX_wm_region(C);
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
float mouse[2], dmouse[2];
float2 mouse_delta;
float length;
float d_world_space_position[3] = {0.0f};
float world_space_position_old[3], world_space_position_new[3];
float3 world_space_position_delta;
float3 world_space_position_old;
copy_v2_v2(stroke->last_mouse_position, old_pos);
stroke->last_mouse_position = old_pos;
if (use_scene_spacing) {
bool hit_old = SCULPT_stroke_get_location(
const bool hit_old = SCULPT_stroke_get_location(
C, world_space_position_old, old_pos, stroke->original);
bool hit_new = SCULPT_stroke_get_location(
float3 world_space_position_new;
const bool hit_new = SCULPT_stroke_get_location(
C, world_space_position_new, new_pos, stroke->original);
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), world_space_position_old);
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), world_space_position_new);
world_space_position_old = math::transform_point(stroke->vc.obact->object_to_world(),
world_space_position_old);
world_space_position_new = math::transform_point(stroke->vc.obact->object_to_world(),
world_space_position_new);
if (hit_old && hit_new && stroke->stroke_over_mesh) {
sub_v3_v3v3(d_world_space_position, world_space_position_new, world_space_position_old);
length = len_v3(d_world_space_position);
world_space_position_delta = world_space_position_new - world_space_position_old;
length = math::length(world_space_position_delta);
stroke->stroke_over_mesh = true;
}
else {
length = 0.0f;
zero_v3(d_world_space_position);
world_space_position_delta = {0.0f, 0.0f, 0.0f};
stroke->stroke_over_mesh = hit_new;
if (stroke->stroke_over_mesh) {
copy_v3_v3(stroke->last_world_space_position, world_space_position_old);
stroke->last_world_space_position = world_space_position_old;
}
}
}
else {
sub_v2_v2v2(dmouse, new_pos, old_pos);
length = normalize_v2(dmouse);
mouse_delta = new_pos - old_pos;
mouse_delta = math::normalize_and_get_length(mouse_delta, length);
}
BLI_assert(length >= 0.0f);
@@ -1275,6 +1271,7 @@ static void paint_line_strokes_spacing(bContext *C,
return;
}
float2 mouse;
while (length > 0.0f) {
float spacing_final = spacing - *length_residue;
length += *length_residue;
@@ -1282,16 +1279,13 @@ static void paint_line_strokes_spacing(bContext *C,
if (length >= spacing) {
if (use_scene_spacing) {
float final_world_space_position[3];
normalize_v3(d_world_space_position);
mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing_final);
add_v3_v3v3(
final_world_space_position, world_space_position_old, final_world_space_position);
world_space_position_delta = math::normalize(world_space_position_delta);
const float3 final_world_space_position = world_space_position_delta * spacing_final +
world_space_position_old;
ED_view3d_project_v2(region, final_world_space_position, mouse);
}
else {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
mouse = stroke->last_mouse_position + mouse_delta * spacing_final;
}
ups->overlap_factor = paint_stroke_integrate_overlap(*stroke->brush, 1.0);
@@ -1313,7 +1307,7 @@ static void paint_line_strokes_spacing(bContext *C,
static void paint_stroke_line_end(bContext *C,
wmOperator *op,
PaintStroke *stroke,
const float mouse[2])
const float2 mouse)
{
Brush *br = stroke->brush;
if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
@@ -1335,9 +1329,6 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
const Scene *scene = CTX_data_scene(C);
const float spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
const PaintCurve *pc = br.paint_curve;
const PaintCurvePoint *pcp;
float length_residue = 0.0f;
int i;
if (!pc) {
return true;
@@ -1347,17 +1338,17 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
TIMEIT_START_AVERAGED(whole_stroke);
#endif
pcp = pc->points;
const PaintCurvePoint *pcp = pc->points;
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
int j;
float length_residue = 0.0f;
for (int i = 0; i < pc->tot_points - 1; i++, pcp++) {
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
const PaintCurvePoint *pcp_next = pcp + 1;
bool do_rake = false;
for (j = 0; j < 2; j++) {
for (int j = 0; j < 2; j++) {
BKE_curve_forward_diff_bezier(pcp->bez.vec[1][j],
pcp->bez.vec[2][j],
pcp_next->bez.vec[0][j],
@@ -1371,7 +1362,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
(br.mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
{
do_rake = true;
for (j = 0; j < 2; j++) {
for (int j = 0; j < 2; j++) {
BKE_curve_forward_diff_tangent_bezier(pcp->bez.vec[1][j],
pcp->bez.vec[2][j],
pcp_next->bez.vec[0][j],
@@ -1382,9 +1373,9 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
}
}
for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
for (int j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
if (do_rake) {
float rotation = atan2f(tangents[2 * j + 1], tangents[2 * j]) + float(0.5f * M_PI);
const float rotation = atan2f(tangents[2 * j + 1], tangents[2 * j]) + float(0.5f * M_PI);
paint_update_brush_rake_rotation(ups, br, rotation);
}
@@ -1422,21 +1413,18 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
return true;
}
static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
static void paint_stroke_line_constrain(PaintStroke *stroke, float2 &mouse)
{
if (stroke->constrain_line) {
float line[2];
float angle, len, res;
sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
angle = atan2f(line[1], line[0]);
len = len_v2(line);
float2 line = mouse - stroke->last_mouse_position;
float angle = atan2f(line[1], line[0]);
const float len = math::length(line);
/* divide angle by PI/4 */
angle = 4.0f * angle / float(M_PI);
/* now take residue */
res = angle - floorf(angle);
const float res = angle - floorf(angle);
/* residue decides how close we are at a certain angle */
if (res <= 0.5f) {
@@ -1453,13 +1441,11 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke **stroke_p)
{
Scene *scene = CTX_data_scene(C);
const Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
PaintStroke *stroke = *stroke_p;
Brush *br = stroke->brush = BKE_paint_brush(paint);
PaintSample sample_average;
float mouse[2];
const Brush *br = stroke->brush = BKE_paint_brush(paint);
bool first_dab = false;
bool first_modal = false;
bool redraw = false;
@@ -1484,8 +1470,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
stroke->last_tablet_event_pressure = pressure;
}
int input_samples = BKE_brush_input_samples_get(scene, br);
const int input_samples = BKE_brush_input_samples_get(scene, br);
paint_stroke_add_sample(stroke, input_samples, event->mval[0], event->mval[1], pressure);
PaintSample sample_average;
paint_stroke_sample_average(stroke, &sample_average);
/* Tilt. */
@@ -1518,11 +1506,12 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
/* one time stroke initialization */
if (!stroke->stroke_started) {
stroke->last_pressure = sample_average.pressure;
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
stroke->last_mouse_position = sample_average.mouse;
if (paint_stroke_use_scene_spacing(*br, mode)) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, sample_average.mouse, stroke->original);
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), stroke->last_world_space_position);
stroke->last_world_space_position = math::transform_point(
stroke->vc.obact->object_to_world(), stroke->last_world_space_position);
}
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
@@ -1564,9 +1553,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
return OPERATOR_CANCELLED;
}
float2 mouse;
if (event->type == stroke->event_type && !first_modal) {
if (event->val == KM_RELEASE) {
copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
mouse = {float(event->mval[0]), float(event->mval[1])};
paint_stroke_line_constrain(stroke, mouse);
paint_stroke_line_end(C, op, stroke, mouse);
stroke_done(C, op, stroke);
@@ -1588,7 +1578,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
stroke->constrain_line = false;
}
copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
mouse = {float(event->mval[0]), float(event->mval[1])};
paint_stroke_line_constrain(stroke, mouse);
if (stroke->stroke_started && (first_modal || ISMOUSE_MOTION(event->type))) {
@@ -1607,7 +1597,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER &&
event->customdata == stroke->timer))
{
if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, pressure)) {
if (stroke->stroke_started) {
if (paint_space_stroke_enabled(*br, mode)) {
if (paint_space_stroke(C, op, stroke, mouse, pressure)) {
@@ -1615,9 +1605,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
}
}
else {
float dmouse[2];
sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
stroke->stroke_distance += len_v2(dmouse);
const float2 mouse_delta = mouse - stroke->last_mouse_position;
stroke->stroke_distance += math::length(mouse_delta);
paint_brush_stroke_add_step(C, op, stroke, mouse, pressure);
redraw = true;
}
@@ -1657,13 +1646,11 @@ int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
{
/* only when executed for the first time */
if (stroke->stroke_started == 0) {
PropertyRNA *strokeprop;
PointerRNA firstpoint;
float mouse[2];
strokeprop = RNA_struct_find_property(op->ptr, "stroke");
PropertyRNA *strokeprop = RNA_struct_find_property(op->ptr, "stroke");
if (RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
float2 mouse;
RNA_float_get_array(&firstpoint, "mouse", mouse);
stroke->stroke_started = stroke->test_start(C, op, mouse);
}
@@ -1676,7 +1663,7 @@ int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
RNA_END;
}
bool ok = (stroke->stroke_started != 0);
const bool ok = stroke->stroke_started != 0;
stroke_done(C, op, stroke);
@@ -1726,9 +1713,9 @@ bool paint_stroke_started(PaintStroke *stroke)
static const bToolRef *brush_tool_get(const bContext *C)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Object *ob = CTX_data_active_object(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
const Object *ob = CTX_data_active_object(C);
const ScrArea *area = CTX_wm_area(C);
const ARegion *region = CTX_wm_region(C);
if (paint && ob && BKE_paint_brush(paint) &&
(area && ELEM(area->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&