Merge branch 'blender-v4.4-release'

This commit is contained in:
Lukas Tönne
2025-03-05 08:50:10 +01:00
6 changed files with 409 additions and 178 deletions

View File

@@ -30,6 +30,7 @@ set(SRC
intern/grease_pencil_modes.cc
intern/grease_pencil_ops.cc
intern/grease_pencil_primitive.cc
intern/grease_pencil_randomize.cc
intern/grease_pencil_select.cc
intern/grease_pencil_trim.cc
intern/grease_pencil_undo.cc

View File

@@ -40,6 +40,7 @@
#include "BLI_array_utils.hh"
#include "BLI_math_matrix.hh"
#include "BLI_rand.hh"
#include "BLI_vector.hh"
#include "BLT_translation.hh"
@@ -144,6 +145,14 @@ struct PrimitiveToolOperation {
float4x2 texture_space;
float4x4 local_transform;
RandomNumberGenerator rng;
float stroke_random_radius_factor;
float stroke_random_opacity_factor;
float stroke_random_rotation_factor;
float stroke_random_hue_factor;
float stroke_random_sat_factor;
float stroke_random_val_factor;
OperatorMode mode;
float2 start_position_2d;
int active_control_point_index;
@@ -452,6 +461,7 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
{
const bool on_back = ptd.on_back;
const int new_points_num = grease_pencil_primitive_curve_points_number(ptd);
const bool use_random = (ptd.settings->flag & GP_BRUSH_GROUP_RANDOM) != 0;
bke::CurvesGeometry &curves = ptd.drawing->strokes_for_write();
const int target_curve_index = on_back ? 0 : curves.curves_range().last();
@@ -469,10 +479,22 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
MutableSpan<float> new_radii = ptd.drawing->radii_for_write().slice(curve_points);
MutableSpan<float> new_opacities = ptd.drawing->opacities_for_write().slice(curve_points);
MutableSpan<ColorGeometry4f> new_vertex_colors = ptd.drawing->vertex_colors_for_write().slice(
curve_points);
bke::SpanAttributeWriter<float> rotations;
MutableSpan<float> new_rotations;
if (use_random && ptd.settings->uv_random > 0.0f) {
rotations = curves.attributes_for_write().lookup_or_add_for_write_span<float>(
"rotation", bke::AttrDomain::Point);
new_rotations = rotations.span.slice(curve_points);
}
const ToolSettings *ts = ptd.vc.scene->toolsettings;
const GP_Sculpt_Settings *gset = &ts->gp_sculpt;
/* Screen-space length along curve used as randomization parameter. */
Array<float> lengths(new_points_num);
for (const int point : curve_points.index_range()) {
float pressure = 1.0f;
/* Apply pressure curve. */
@@ -491,15 +513,41 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
const float opacity = ed::greasepencil::opacity_from_input_sample(
pressure, ptd.brush, ptd.settings);
new_radii[point] = radius;
new_opacities[point] = opacity;
}
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (point == 0) {
lengths[point] = 0.0f;
}
else {
const float distance_2d = math::distance(positions_2d[point - 1], positions_2d[point]);
lengths[point] = lengths[point - 1] + distance_2d;
}
new_radii[point] = ed::greasepencil::randomize_radius(
*ptd.settings, ptd.stroke_random_radius_factor, lengths[point], radius, pressure);
new_opacities[point] = ed::greasepencil::randomize_opacity(
*ptd.settings, ptd.stroke_random_opacity_factor, lengths[point], opacity, pressure);
if (ptd.vertex_color) {
new_vertex_colors[point] = ed::greasepencil::randomize_color(*ptd.settings,
ptd.stroke_random_hue_factor,
ptd.stroke_random_sat_factor,
ptd.stroke_random_val_factor,
lengths[point],
*ptd.vertex_color,
pressure);
}
if (rotations) {
new_rotations[point] = ed::greasepencil::randomize_rotation(
*ptd.settings, ptd.stroke_random_rotation_factor, lengths[point], pressure);
}
}
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (ptd.vertex_color) {
ptd.drawing->vertex_colors_for_write().slice(curve_points).fill(*ptd.vertex_color);
point_attributes_to_skip.add("vertex_color");
}
if (rotations) {
point_attributes_to_skip.add("rotation");
rotations.finish();
}
/* Initialize the rest of the attributes with default values. */
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
@@ -764,6 +812,17 @@ static int grease_pencil_primitive_invoke(bContext *C, wmOperator *op, const wmE
ptd.texture_space = ed::greasepencil::calculate_texture_space(
vc.scene, ptd.region, ptd.start_position_2d, ptd.placement);
const bool use_random = (ptd.settings->flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (use_random) {
ptd.rng = RandomNumberGenerator::from_random_seed();
ptd.stroke_random_radius_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_opacity_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_rotation_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_hue_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_sat_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_val_factor = ptd.rng.get_float() * 2.0f - 1.0f;
}
BLI_assert(grease_pencil->has_active_layer());
ptd.local_transform = grease_pencil->get_active_layer()->local_transform();
ptd.drawing = grease_pencil->get_editable_drawing_at(*grease_pencil->get_active_layer(),

View File

@@ -0,0 +1,206 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgreasepencil
*/
#include "BLI_noise.hh"
#include "BLI_rand.hh"
#include "BKE_colortools.hh"
#include "ED_grease_pencil.hh"
#include "DNA_brush_types.h"
namespace blender::ed::greasepencil {
float randomize_radius(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float radius,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.draw_random_press > 0.0f)) {
return radius;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_pressure, 0, pressure);
}
const float randomized_radius = math::interpolate(
radius, radius * (1.0f + random_factor), settings.draw_random_press);
return math::max(randomized_radius, 0.0f);
}
float randomize_opacity(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float opacity,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.draw_random_strength > 0.0f)) {
return opacity;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_strength, 0, pressure);
}
const float randomized_opacity = math::interpolate(
opacity, opacity + random_factor, settings.draw_random_strength);
return math::clamp(randomized_opacity, 0.0f, 1.0f);
}
float randomize_rotation(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings.uv_random);
}
float randomize_rotation(const BrushGpencilSettings &settings,
RandomNumberGenerator &rng,
const float stroke_factor,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
random_factor = rng.get_float() * 2.0f - 1.0f;
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings.uv_random);
}
ColorGeometry4f randomize_color(const BrushGpencilSettings &settings,
const float stroke_hue_factor,
const float stroke_saturation_factor,
const float stroke_value_factor,
const float distance,
const ColorGeometry4f color,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.random_hue > 0.0f || settings.random_saturation > 0.0f ||
settings.random_value > 0.0f))
{
return color;
}
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
float random_hue = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
random_hue = noise::perlin_signed(float2(distance * noise_scale, stroke_hue_factor));
}
else {
random_hue = stroke_hue_factor;
}
float random_saturation = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
random_saturation = noise::perlin_signed(
float2(distance * noise_scale, stroke_saturation_factor));
}
else {
random_saturation = stroke_saturation_factor;
}
float random_value = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
random_value = noise::perlin_signed(float2(distance * noise_scale, stroke_value_factor));
}
else {
random_value = stroke_value_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) != 0) {
random_hue *= BKE_curvemapping_evaluateF(settings.curve_rand_hue, 0, pressure);
}
if ((settings.flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) != 0) {
random_saturation *= BKE_curvemapping_evaluateF(settings.curve_rand_saturation, 0, pressure);
}
if ((settings.flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) != 0) {
random_value *= BKE_curvemapping_evaluateF(settings.curve_rand_value, 0, pressure);
}
float3 hsv;
rgb_to_hsv_v(color, hsv);
hsv += float3(random_hue * settings.random_hue,
random_saturation * settings.random_saturation,
random_value * settings.random_value);
/* Wrap hue. */
if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
else if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
hsv[1] = math::clamp(hsv[1], 0.0f, 1.0f);
hsv[2] = math::clamp(hsv[2], 0.0f, 1.0f);
ColorGeometry4f random_color;
hsv_to_rgb_v(hsv, random_color);
random_color.a = color.a;
return random_color;
}
} // namespace blender::ed::greasepencil

View File

@@ -40,12 +40,13 @@ struct BVHTree;
struct GreasePencilLineartModifierData;
struct RV3DMatrixStore;
namespace blender::bke {
namespace blender {
struct RandomNumberGenerator;
namespace bke {
enum class AttrDomain : int8_t;
class CurvesGeometry;
namespace crazyspace {
}
} // namespace blender::bke
} // namespace bke
} // namespace blender
enum {
LAYER_REORDER_ABOVE,
@@ -929,4 +930,65 @@ void add_single_curve(bke::CurvesGeometry &curves, bool at_end);
*/
void resize_single_curve(bke::CurvesGeometry &curves, bool at_end, int new_points_num);
/**
* Calculate a randomized radius value for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param radius Base radius to be randomized.
* \param pressure Pressure factor.
*/
float randomize_radius(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float radius,
float pressure);
/**
* Calculate a randomized opacity value for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param opacity Base opacity to be randomized.
* \param pressure Pressure factor.
*/
float randomize_opacity(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float opacity,
float pressure);
/**
* Calculate a randomized rotation for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param pressure Pressure factor.
*/
float randomize_rotation(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float pressure);
/**
* Calculate a randomized rotation for a point.
* \param rng Random number generator instance.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param pressure Pressure factor.
*/
float randomize_rotation(const BrushGpencilSettings &settings,
blender::RandomNumberGenerator &rng,
float stroke_factor,
float pressure);
/**
* Calculate a randomized opacity value for a point.
* \param stroke_hue_factor Random seed value in [-1, 1] per stroke for color hue.
* \param stroke_saturation_factor Random seed value in [-1, 1] per stroke for color saturation.
* \param stroke_value_factor Random seed value in [-1, 1] per stroke for color value.
* \param distance Screen-space length in pixels along the curve.
* \param color Base color to be randomized.
* \param pressure Pressure factor.
*/
ColorGeometry4f randomize_color(const BrushGpencilSettings &settings,
float stroke_hue_factor,
float stroke_saturation_factor,
float stroke_value_factor,
float distance,
ColorGeometry4f color,
float pressure);
} // namespace blender::ed::greasepencil

View File

@@ -258,159 +258,6 @@ struct PaintOperationExecutor {
BLI_assert(drawing_ != nullptr);
}
float randomize_radius(PaintOperation &self,
const float distance,
const float radius,
const float pressure)
{
if (!use_settings_random_ || !(settings_->draw_random_press > 0.0f)) {
return radius;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_radius_factor_));
}
else {
random_factor = self.stroke_random_radius_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_pressure, 0, pressure);
}
const float randomized_radius = math::interpolate(
radius, radius * (1.0f + random_factor), settings_->draw_random_press);
return math::max(randomized_radius, 0.0f);
}
float randomize_opacity(PaintOperation &self,
const float distance,
const float opacity,
const float pressure)
{
if (!use_settings_random_ || !(settings_->draw_random_strength > 0.0f)) {
return opacity;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_opacity_factor_));
}
else {
random_factor = self.stroke_random_opacity_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_strength, 0, pressure);
}
const float randomized_opacity = math::interpolate(
opacity, opacity + random_factor, settings_->draw_random_strength);
return math::clamp(randomized_opacity, 0.0f, 1.0f);
}
float randomize_rotation(PaintOperation &self, const float pressure)
{
if (!use_settings_random_ || !(settings_->uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
random_factor = self.rng_.get_float() * 2.0f - 1.0f;
}
else {
random_factor = self.stroke_random_rotation_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings_->uv_random);
}
ColorGeometry4f randomize_color(PaintOperation &self,
const float distance,
const ColorGeometry4f color,
const float pressure)
{
if (!use_settings_random_ ||
!(settings_->random_hue > 0.0f || settings_->random_saturation > 0.0f ||
settings_->random_value > 0.0f))
{
return color;
}
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
float random_hue = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
random_hue = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_hue_factor_));
}
else {
random_hue = self.stroke_random_hue_factor_;
}
float random_saturation = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
random_saturation = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_sat_factor_));
}
else {
random_saturation = self.stroke_random_sat_factor_;
}
float random_value = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
random_value = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_val_factor_));
}
else {
random_value = self.stroke_random_val_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) != 0) {
random_hue *= BKE_curvemapping_evaluateF(settings_->curve_rand_hue, 0, pressure);
}
if ((settings_->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) != 0) {
random_saturation *= BKE_curvemapping_evaluateF(
settings_->curve_rand_saturation, 0, pressure);
}
if ((settings_->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) != 0) {
random_value *= BKE_curvemapping_evaluateF(settings_->curve_rand_value, 0, pressure);
}
float3 hsv;
rgb_to_hsv_v(color, hsv);
hsv += float3(random_hue * settings_->random_hue,
random_saturation * settings_->random_saturation,
random_value * settings_->random_value);
/* Wrap hue. */
if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
else if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
hsv[1] = math::clamp(hsv[1], 0.0f, 1.0f);
hsv[2] = math::clamp(hsv[2], 0.0f, 1.0f);
ColorGeometry4f random_color;
hsv_to_rgb_v(hsv, random_color);
random_color.a = color.a;
return random_color;
}
void process_start_sample(PaintOperation &self,
const bContext &C,
const InputSample &start_sample,
@@ -442,18 +289,30 @@ struct PaintOperationExecutor {
start_location,
self.placement_.to_world_space(),
settings_);
start_radius = randomize_radius(self, 0.0f, start_radius, start_sample.pressure);
start_radius = ed::greasepencil::randomize_radius(
*settings_, self.stroke_random_radius_factor_, 0.0f, start_radius, start_sample.pressure);
float start_opacity = ed::greasepencil::opacity_from_input_sample(
start_sample.pressure, brush_, settings_);
start_opacity = randomize_opacity(self, 0.0f, start_opacity, start_sample.pressure);
start_opacity = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
0.0f,
start_opacity,
start_sample.pressure);
/* Do not allow pressure opacity when drawing tool was invoked temporarily. */
const float fill_opacity = (!self.temp_draw_) ? start_opacity : 1.0f;
const float start_rotation = randomize_rotation(self, start_sample.pressure);
const float start_rotation = ed::greasepencil::randomize_rotation(
*settings_, self.rng_, self.stroke_random_rotation_factor_, start_sample.pressure);
if (use_vertex_color_) {
vertex_color_ = randomize_color(self, 0.0f, vertex_color_, start_sample.pressure);
vertex_color_ = ed::greasepencil::randomize_color(*settings_,
self.stroke_random_hue_factor_,
self.stroke_random_sat_factor_,
self.stroke_random_val_factor_,
0.0f,
vertex_color_,
start_sample.pressure);
}
Scene *scene = CTX_data_scene(&C);
@@ -825,11 +684,18 @@ struct PaintOperationExecutor {
curves.positions_for_write()[last_active_point] = position;
}
if (use_settings_random_ && settings_->draw_random_press > 0.0f) {
radius = randomize_radius(self, self.accum_distance_, radius, extension_sample.pressure);
radius = ed::greasepencil::randomize_radius(*settings_,
self.stroke_random_radius_factor_,
self.accum_distance_,
radius,
extension_sample.pressure);
}
if (use_settings_random_ && settings_->draw_random_strength > 0.0f) {
opacity = randomize_opacity(
self, self.accum_distance_, opacity, extension_sample.pressure);
opacity = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
self.accum_distance_,
opacity,
extension_sample.pressure);
}
drawing_->radii_for_write()[last_active_point] = math::max(radius, prev_radius);
drawing_->opacities_for_write()[last_active_point] = math::max(opacity, prev_opacity);
@@ -872,8 +738,12 @@ struct PaintOperationExecutor {
/* Randomize radii. */
if (use_settings_random_ && settings_->draw_random_press > 0.0f) {
for (const int i : IndexRange(new_points_num)) {
new_radii[i] = randomize_radius(
self, self.accum_distance_ + max_spacing_px * i, radius, extension_sample.pressure);
new_radii[i] = ed::greasepencil::randomize_radius(*settings_,
self.stroke_random_radius_factor_,
self.accum_distance_ +
max_spacing_px * i,
radius,
extension_sample.pressure);
}
}
else {
@@ -883,8 +753,12 @@ struct PaintOperationExecutor {
/* Randomize opacities. */
if (use_settings_random_ && settings_->draw_random_strength > 0.0f) {
for (const int i : IndexRange(new_points_num)) {
new_opacities[i] = randomize_opacity(
self, self.accum_distance_ + max_spacing_px * i, opacity, extension_sample.pressure);
new_opacities[i] = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
self.accum_distance_ +
max_spacing_px * i,
opacity,
extension_sample.pressure);
}
}
else {
@@ -898,7 +772,11 @@ struct PaintOperationExecutor {
{
const MutableSpan<float> new_rotations = rotations.span.slice(new_points);
for (const int i : IndexRange(new_points_num)) {
new_rotations[i] = randomize_rotation(self, extension_sample.pressure);
new_rotations[i] = ed::greasepencil::randomize_rotation(
*settings_,
self.rng_,
self.stroke_random_rotation_factor_,
extension_sample.pressure);
}
point_attributes_to_skip.add("rotation");
rotations.finish();
@@ -911,10 +789,14 @@ struct PaintOperationExecutor {
new_points);
if (use_settings_random_ || attributes.contains("vertex_color")) {
for (const int i : IndexRange(new_points_num)) {
new_vertex_colors[i] = randomize_color(self,
self.accum_distance_ + max_spacing_px * i,
vertex_color_,
extension_sample.pressure);
new_vertex_colors[i] = ed::greasepencil::randomize_color(*settings_,
self.stroke_random_hue_factor_,
self.stroke_random_sat_factor_,
self.stroke_random_val_factor_,
self.accum_distance_ +
max_spacing_px * i,
vertex_color_,
extension_sample.pressure);
}
}
else {

View File

@@ -1570,6 +1570,27 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
return OPERATOR_CANCELLED;
}
/* Handles shift-key active smooth toggling during a grease pencil stroke. */
if (mode == PaintMode::GPencil) {
if (event->modifier & KM_SHIFT) {
stroke->stroke_mode = BRUSH_STROKE_SMOOTH;
if (!stroke->stroke_cursor) {
stroke->stroke_cursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
paint_brush_cursor_poll,
paint_draw_smooth_cursor,
stroke);
}
}
else {
stroke->stroke_mode = BRUSH_STROKE_NORMAL;
if (stroke->stroke_cursor != nullptr) {
WM_paint_cursor_end(static_cast<wmPaintCursor *>(stroke->stroke_cursor));
stroke->stroke_cursor = nullptr;
}
}
}
float2 mouse;
if (event->type == stroke->event_type && !first_modal) {
if (event->val == KM_RELEASE) {