Fix #127856: GPv3 sculpt mode delta projection (lock axis) without DrawingPlacement
Sculpt mode in Grease Pencil should not use the origin point of `DrawingPlacement` and only apply the plane projection to relative offsets. A new variant of the `foreach_editable_drawing` function is introduced that provides a `DeltaProjectionFunc` instead of `DrawingPlacement`. This projection callback takes a layer-space position and a screen-space delta and returns a layer-space position with the constrained delta applied. The projection function is based on the tools settings' "lock axis", like `DrawingPlacement`, but ignores the origin point. Exception is the smoothing tool, which does not restrict movement along the lock axis. This can be implemented if desired, but for a non-directional tool it seems the lock axis isn't very meaningful. Pull Request: https://projects.blender.org/blender/blender/pulls/128022
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
@@ -29,6 +31,14 @@ struct GeometryDeformation;
|
||||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
|
||||
/**
|
||||
* Projects a screen-space displacement vector into layer space.
|
||||
* Current position (in layer space) is used to compute the perspective distance (zfac).
|
||||
* Returns the new layer space position with the projected delta applied.
|
||||
*/
|
||||
using DeltaProjectionFunc =
|
||||
std::function<float3(const float3 position, const float2 &screen_delta)>;
|
||||
|
||||
struct InputSample {
|
||||
float2 mouse_position;
|
||||
float pressure;
|
||||
@@ -85,6 +95,8 @@ bool is_brush_inverted(const Brush &brush, BrushStrokeMode stroke_mode);
|
||||
struct GreasePencilStrokeParams {
|
||||
const ToolSettings &toolsettings;
|
||||
const ARegion ®ion;
|
||||
const RegionView3D &rv3d;
|
||||
const Scene &scene;
|
||||
Object &ob_orig;
|
||||
Object &ob_eval;
|
||||
const bke::greasepencil::Layer &layer;
|
||||
@@ -98,6 +110,7 @@ struct GreasePencilStrokeParams {
|
||||
static GreasePencilStrokeParams from_context(const Scene &scene,
|
||||
Depsgraph &depsgraph,
|
||||
ARegion ®ion,
|
||||
RegionView3D &rv3d,
|
||||
Object &object,
|
||||
int layer_index,
|
||||
int frame_number,
|
||||
@@ -125,6 +138,12 @@ Array<float2> calculate_view_positions(const GreasePencilStrokeParams ¶ms,
|
||||
Array<float> calculate_view_radii(const GreasePencilStrokeParams ¶ms,
|
||||
const IndexMask &selection);
|
||||
|
||||
/* Get an appropriate projection function from screen space to layer space.
|
||||
* This is an alternative to using the DrawingPlacement. */
|
||||
DeltaProjectionFunc get_screen_projection_fn(const GreasePencilStrokeParams ¶ms,
|
||||
const Object &object,
|
||||
const bke::greasepencil::Layer &layer);
|
||||
|
||||
bool do_vertex_color_points(const Brush &brush);
|
||||
bool do_vertex_color_fill(const Brush &brush);
|
||||
|
||||
@@ -158,9 +177,10 @@ class GreasePencilStrokeOperationCommon : public GreasePencilStrokeOperation {
|
||||
const bContext &C,
|
||||
GrainSize grain_size,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms)> fn) const;
|
||||
void foreach_editable_drawing(const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const DrawingPlacement &placement)> fn) const;
|
||||
void foreach_editable_drawing(
|
||||
const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const DeltaProjectionFunc &projection_fn)> fn) const;
|
||||
};
|
||||
|
||||
/* Operations */
|
||||
|
||||
@@ -194,10 +194,80 @@ bool is_brush_inverted(const Brush &brush, const BrushStrokeMode stroke_mode)
|
||||
return bool(brush.flag & BRUSH_DIR_IN) ^ (stroke_mode == BrushStrokeMode::BRUSH_STROKE_INVERT);
|
||||
}
|
||||
|
||||
DeltaProjectionFunc get_screen_projection_fn(const GreasePencilStrokeParams ¶ms,
|
||||
const Object &object,
|
||||
const bke::greasepencil::Layer &layer)
|
||||
{
|
||||
const float4x4 view_to_world = float4x4(params.rv3d.viewinv);
|
||||
const float4x4 layer_to_world = layer.to_world_space(object);
|
||||
const float4x4 world_to_layer = math::invert(layer_to_world);
|
||||
|
||||
auto screen_to_world = [=](const float3 &world_pos, const float2 &screen_delta) {
|
||||
const float zfac = ED_view3d_calc_zfac(¶ms.rv3d, world_pos);
|
||||
float3 world_delta;
|
||||
ED_view3d_win_to_delta(¶ms.region, screen_delta, zfac, world_delta);
|
||||
return world_delta;
|
||||
};
|
||||
|
||||
switch (params.toolsettings.gp_sculpt.lock_axis) {
|
||||
case GP_LOCKAXIS_VIEW: {
|
||||
const float3 world_normal = view_to_world.z_axis();
|
||||
return [=](const float3 &position, const float2 &screen_delta) {
|
||||
const float3 world_pos = math::transform_point(layer_to_world, position);
|
||||
const float3 world_delta = screen_to_world(world_pos, screen_delta);
|
||||
const float3 layer_delta = math::transform_direction(
|
||||
world_to_layer, world_delta - world_normal * math::dot(world_delta, world_normal));
|
||||
return position + layer_delta;
|
||||
};
|
||||
}
|
||||
case GP_LOCKAXIS_X: {
|
||||
return [=](const float3 &position, const float2 &screen_delta) {
|
||||
const float3 world_pos = math::transform_point(layer_to_world, position);
|
||||
const float3 world_delta = screen_to_world(world_pos, screen_delta);
|
||||
const float3 layer_delta = math::transform_direction(
|
||||
world_to_layer, float3(0.0f, world_delta.y, world_delta.z));
|
||||
return position + layer_delta;
|
||||
};
|
||||
}
|
||||
case GP_LOCKAXIS_Y: {
|
||||
return [=](const float3 &position, const float2 &screen_delta) {
|
||||
const float3 world_pos = math::transform_point(layer_to_world, position);
|
||||
const float3 world_delta = screen_to_world(world_pos, screen_delta);
|
||||
const float3 layer_delta = math::transform_direction(
|
||||
world_to_layer, float3(world_delta.x, 0.0f, world_delta.z));
|
||||
return position + layer_delta;
|
||||
};
|
||||
}
|
||||
case GP_LOCKAXIS_Z: {
|
||||
return [=](const float3 &position, const float2 &screen_delta) {
|
||||
const float3 world_pos = math::transform_point(layer_to_world, position);
|
||||
const float3 world_delta = screen_to_world(world_pos, screen_delta);
|
||||
const float3 layer_delta = math::transform_direction(
|
||||
world_to_layer, float3(world_delta.x, world_delta.y, 0.0f));
|
||||
return position + layer_delta;
|
||||
};
|
||||
}
|
||||
case GP_LOCKAXIS_CURSOR: {
|
||||
const float3 world_normal = params.scene.cursor.matrix<float3x3>().z_axis();
|
||||
return [=](const float3 &position, const float2 &screen_delta) {
|
||||
const float3 world_pos = math::transform_point(layer_to_world, position);
|
||||
const float3 world_delta = screen_to_world(world_pos, screen_delta);
|
||||
const float3 layer_delta = math::transform_direction(
|
||||
world_to_layer, world_delta - world_normal * math::dot(world_delta, world_normal));
|
||||
return position + layer_delta;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return [](const float3 &, const float2 &) { return float3(); };
|
||||
}
|
||||
|
||||
GreasePencilStrokeParams GreasePencilStrokeParams::from_context(
|
||||
const Scene &scene,
|
||||
Depsgraph &depsgraph,
|
||||
ARegion ®ion,
|
||||
RegionView3D &rv3d,
|
||||
Object &object,
|
||||
const int layer_index,
|
||||
const int frame_number,
|
||||
@@ -210,6 +280,8 @@ GreasePencilStrokeParams GreasePencilStrokeParams::from_context(
|
||||
const bke::greasepencil::Layer &layer = grease_pencil.layer(layer_index);
|
||||
return {*scene.toolsettings,
|
||||
region,
|
||||
rv3d,
|
||||
scene,
|
||||
object,
|
||||
ob_eval,
|
||||
layer,
|
||||
@@ -327,6 +399,7 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
|
||||
ARegion ®ion = *CTX_wm_region(&C);
|
||||
RegionView3D &rv3d = *CTX_wm_region_view3d(&C);
|
||||
Object &object = *CTX_data_active_object(&C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
|
||||
@@ -338,6 +411,7 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
scene,
|
||||
depsgraph,
|
||||
region,
|
||||
rv3d,
|
||||
object,
|
||||
info.layer_index,
|
||||
info.frame_number,
|
||||
@@ -364,6 +438,7 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
|
||||
ARegion ®ion = *CTX_wm_region(&C);
|
||||
RegionView3D &rv3d = *CTX_wm_region_view3d(&C);
|
||||
Object &object = *CTX_data_active_object(&C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
|
||||
@@ -376,6 +451,7 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
scene,
|
||||
depsgraph,
|
||||
region,
|
||||
rv3d,
|
||||
object,
|
||||
info.layer_index,
|
||||
info.frame_number,
|
||||
@@ -395,15 +471,15 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
|
||||
void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms, const DrawingPlacement &placement)>
|
||||
fn) const
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const DeltaProjectionFunc &projection_fn)> fn) const
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
|
||||
View3D &view3d = *CTX_wm_view3d(&C);
|
||||
ARegion ®ion = *CTX_wm_region(&C);
|
||||
RegionView3D &rv3d = *CTX_wm_region_view3d(&C);
|
||||
Object &object = *CTX_data_active_object(&C);
|
||||
Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
@@ -413,25 +489,18 @@ void GreasePencilStrokeOperationCommon::foreach_editable_drawing(
|
||||
threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) {
|
||||
const Layer &layer = grease_pencil.layer(info.layer_index);
|
||||
|
||||
DrawingPlacement placement(scene, region, view3d, object_eval, &layer);
|
||||
if (placement.use_project_to_surface()) {
|
||||
placement.cache_viewport_depths(&depsgraph, ®ion, &view3d);
|
||||
}
|
||||
else if (placement.use_project_to_nearest_stroke()) {
|
||||
placement.cache_viewport_depths(&depsgraph, ®ion, &view3d);
|
||||
placement.set_origin_to_nearest_stroke(this->start_mouse_position);
|
||||
}
|
||||
|
||||
GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context(
|
||||
const GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context(
|
||||
scene,
|
||||
depsgraph,
|
||||
region,
|
||||
rv3d,
|
||||
object,
|
||||
info.layer_index,
|
||||
info.frame_number,
|
||||
info.multi_frame_falloff,
|
||||
info.drawing);
|
||||
if (fn(params, placement)) {
|
||||
const DeltaProjectionFunc projection_fn = get_screen_projection_fn(params, object_eval, layer);
|
||||
if (fn(params, projection_fn)) {
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,15 +47,14 @@ void CloneOperation::on_stroke_begin(const bContext &C, const InputSample &start
|
||||
*
|
||||
* Here we only have the GPv2 behavior that actually works for now. */
|
||||
this->foreach_editable_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement) {
|
||||
C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) {
|
||||
const IndexRange pasted_curves = ed::greasepencil::clipboard_paste_strokes(
|
||||
bmain, object, params.drawing, false);
|
||||
if (pasted_curves.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
const OffsetIndices<int> pasted_points_by_curve = curves.points_by_curve().slice(
|
||||
pasted_curves);
|
||||
@@ -73,7 +72,7 @@ void CloneOperation::on_stroke_begin(const bContext &C, const InputSample &start
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
threading::parallel_for(pasted_points, 4096, [&](const IndexRange range) {
|
||||
for (const int point_i : range) {
|
||||
positions[point_i] = placement.project(view_positions[point_i] + mouse_delta);
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i], mouse_delta);
|
||||
}
|
||||
});
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
@@ -31,7 +31,6 @@ class GrabOperation : public GreasePencilStrokeOperationCommon {
|
||||
public:
|
||||
using GreasePencilStrokeOperationCommon::GreasePencilStrokeOperationCommon;
|
||||
using MutableDrawingInfo = blender::ed::greasepencil::MutableDrawingInfo;
|
||||
using DrawingPlacement = ed::greasepencil::DrawingPlacement;
|
||||
|
||||
/* Cached point mask and influence for a particular drawing. */
|
||||
struct PointWeights {
|
||||
@@ -51,12 +50,11 @@ class GrabOperation : public GreasePencilStrokeOperationCommon {
|
||||
/* Cached point data for each affected drawing. */
|
||||
Array<PointWeights> drawing_data;
|
||||
|
||||
void foreach_grabbed_drawing(
|
||||
const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement,
|
||||
const IndexMask &mask,
|
||||
Span<float> weights)> fn) const;
|
||||
void foreach_grabbed_drawing(const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const DeltaProjectionFunc &projection_fn,
|
||||
const IndexMask &mask,
|
||||
Span<float> weights)> fn) const;
|
||||
|
||||
void on_stroke_begin(const bContext &C, const InputSample &start_sample) override;
|
||||
void on_stroke_extended(const bContext &C, const InputSample &extension_sample) override;
|
||||
@@ -66,7 +64,7 @@ class GrabOperation : public GreasePencilStrokeOperationCommon {
|
||||
void GrabOperation::foreach_grabbed_drawing(
|
||||
const bContext &C,
|
||||
FunctionRef<bool(const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement,
|
||||
const DeltaProjectionFunc &projection_fn,
|
||||
const IndexMask &mask,
|
||||
Span<float> weights)> fn) const
|
||||
{
|
||||
@@ -76,7 +74,7 @@ void GrabOperation::foreach_grabbed_drawing(
|
||||
const Scene &scene = *CTX_data_scene(&C);
|
||||
Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(&C);
|
||||
ARegion ®ion = *CTX_wm_region(&C);
|
||||
View3D &view3d = *CTX_wm_view3d(&C);
|
||||
RegionView3D &rv3d = *CTX_wm_region_view3d(&C);
|
||||
Object &object = *CTX_data_active_object(&C);
|
||||
Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
|
||||
@@ -94,25 +92,18 @@ void GrabOperation::foreach_grabbed_drawing(
|
||||
return;
|
||||
}
|
||||
|
||||
ed::greasepencil::DrawingPlacement placement(scene, region, view3d, object_eval, &layer);
|
||||
if (placement.use_project_to_surface()) {
|
||||
placement.cache_viewport_depths(&depsgraph, ®ion, &view3d);
|
||||
}
|
||||
else if (placement.use_project_to_nearest_stroke()) {
|
||||
placement.cache_viewport_depths(&depsgraph, ®ion, &view3d);
|
||||
placement.set_origin_to_nearest_stroke(this->start_mouse_position);
|
||||
}
|
||||
|
||||
GreasePencilStrokeParams params = GreasePencilStrokeParams::from_context(
|
||||
scene,
|
||||
depsgraph,
|
||||
region,
|
||||
rv3d,
|
||||
object,
|
||||
data.layer_index,
|
||||
data.frame_number,
|
||||
data.multi_frame_falloff,
|
||||
*drawing);
|
||||
if (fn(params, placement, data.point_mask, data.weights)) {
|
||||
DeltaProjectionFunc projection_fn = get_screen_projection_fn(params, object_eval, layer);
|
||||
if (fn(params, projection_fn, data.point_mask, data.weights)) {
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
@@ -154,6 +145,8 @@ void GrabOperation::on_stroke_begin(const bContext &C, const InputSample &start_
|
||||
|
||||
GreasePencilStrokeParams params = {*scene.toolsettings,
|
||||
region,
|
||||
rv3d,
|
||||
scene,
|
||||
ob_orig,
|
||||
ob_eval,
|
||||
layer,
|
||||
@@ -195,38 +188,22 @@ void GrabOperation::on_stroke_begin(const bContext &C, const InputSample &start_
|
||||
|
||||
void GrabOperation::on_stroke_extended(const bContext &C, const InputSample &extension_sample)
|
||||
{
|
||||
const ARegion ®ion = *CTX_wm_region(&C);
|
||||
const RegionView3D &rv3d = *CTX_wm_region_view3d(&C);
|
||||
|
||||
this->foreach_grabbed_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement,
|
||||
const DeltaProjectionFunc &projection_fn,
|
||||
const IndexMask &mask,
|
||||
const Span<float> weights) {
|
||||
/* Crazy-space deformation. */
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
|
||||
/* Transform mouse delta into layer space. */
|
||||
const float2 mouse_delta_win = this->mouse_delta(extension_sample);
|
||||
const float3 layer_origin = params.layer.to_world_space(params.ob_eval).location();
|
||||
const float zfac = ED_view3d_calc_zfac(&rv3d, layer_origin);
|
||||
float3 mouse_delta;
|
||||
ED_view3d_win_to_delta(®ion, mouse_delta_win, zfac, mouse_delta);
|
||||
const float4x4 &world_to_layer = math::invert(params.layer.to_world_space(params.ob_eval));
|
||||
mouse_delta = math::transform_direction(world_to_layer, mouse_delta);
|
||||
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
mask.foreach_index(GrainSize(1024), [&](const int point_i, const int index) {
|
||||
mask.foreach_index(GrainSize(4096), [&](const int point_i, const int index) {
|
||||
/* Translate the point with the influence factor. */
|
||||
const float3 new_pos_layer = deformation.positions[point_i] +
|
||||
mouse_delta * weights[index];
|
||||
const float3 new_pos_world = math::transform_point(
|
||||
params.layer.to_world_space(params.ob_eval), new_pos_layer);
|
||||
float2 new_pos_view;
|
||||
ED_view3d_project_float_global(®ion, new_pos_world, new_pos_view, V3D_PROJ_TEST_NOP);
|
||||
positions[point_i] = placement.project(new_pos_view);
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i],
|
||||
mouse_delta_win * weights[index]);
|
||||
});
|
||||
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_paint.hh"
|
||||
@@ -42,15 +43,14 @@ void PinchOperation::on_stroke_extended(const bContext &C, const InputSample &ex
|
||||
eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt));
|
||||
|
||||
this->foreach_editable_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement) {
|
||||
C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) {
|
||||
IndexMaskMemory selection_memory;
|
||||
const IndexMask selection = point_selection_mask(params, is_masking, selection_memory);
|
||||
if (selection.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
Array<float2> view_positions = calculate_view_positions(params, selection);
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
@@ -65,9 +65,11 @@ void PinchOperation::on_stroke_extended(const bContext &C, const InputSample &ex
|
||||
return;
|
||||
}
|
||||
|
||||
const float scale_offset = influence * influence / 25.0f;
|
||||
const float scale = invert ? 1.0 + scale_offset : 1.0f - scale_offset;
|
||||
positions[point_i] = placement.project(target + (co - target) * scale);
|
||||
const float influence_squared = influence * influence / 25.0f;
|
||||
const float influence_final = invert ? 1.0 + influence_squared :
|
||||
1.0f - influence_squared;
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i],
|
||||
(target - co) * (1.0f - influence_final));
|
||||
});
|
||||
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_paint.hh"
|
||||
@@ -42,15 +43,14 @@ void PushOperation::on_stroke_extended(const bContext &C, const InputSample &ext
|
||||
eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt));
|
||||
|
||||
this->foreach_editable_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement) {
|
||||
C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) {
|
||||
IndexMaskMemory selection_memory;
|
||||
const IndexMask selection = point_selection_mask(params, is_masking, selection_memory);
|
||||
if (selection.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
Array<float2> view_positions = calculate_view_positions(params, selection);
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
@@ -65,7 +65,8 @@ void PushOperation::on_stroke_extended(const bContext &C, const InputSample &ext
|
||||
return;
|
||||
}
|
||||
|
||||
positions[point_i] = placement.project(co + mouse_delta * influence);
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i],
|
||||
mouse_delta * influence);
|
||||
});
|
||||
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_paint.hh"
|
||||
@@ -62,9 +63,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample
|
||||
eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt));
|
||||
|
||||
this->foreach_editable_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement) {
|
||||
C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) {
|
||||
const uint32_t seed = this->unique_seed();
|
||||
|
||||
IndexMaskMemory selection_memory;
|
||||
@@ -73,6 +72,7 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample
|
||||
return false;
|
||||
}
|
||||
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
Array<float2> view_positions = calculate_view_positions(params, selection);
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
@@ -93,7 +93,8 @@ void RandomizeOperation::on_stroke_extended(const bContext &C, const InputSample
|
||||
return;
|
||||
}
|
||||
const float noise = 2.0f * hash_rng(seed, 5678, point_i) - 1.0f;
|
||||
positions[point_i] = placement.project(co + sideways * influence * noise);
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i],
|
||||
sideways * influence * noise);
|
||||
});
|
||||
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "BLI_math_rotation.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_paint.hh"
|
||||
@@ -52,15 +53,14 @@ void TwistOperation::on_stroke_extended(const bContext &C, const InputSample &ex
|
||||
eGP_Sculpt_SelectMaskFlag(scene.toolsettings->gpencil_selectmode_sculpt));
|
||||
|
||||
this->foreach_editable_drawing(
|
||||
C,
|
||||
[&](const GreasePencilStrokeParams ¶ms,
|
||||
const ed::greasepencil::DrawingPlacement &placement) {
|
||||
C, [&](const GreasePencilStrokeParams ¶ms, const DeltaProjectionFunc &projection_fn) {
|
||||
IndexMaskMemory selection_memory;
|
||||
const IndexMask selection = point_selection_mask(params, is_masking, selection_memory);
|
||||
if (selection.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bke::crazyspace::GeometryDeformation deformation = get_drawing_deformation(params);
|
||||
Array<float2> view_positions = calculate_view_positions(params, selection);
|
||||
bke::CurvesGeometry &curves = params.drawing.strokes_for_write();
|
||||
MutableSpan<float3> positions = curves.positions_for_write();
|
||||
@@ -76,8 +76,10 @@ void TwistOperation::on_stroke_extended(const bContext &C, const InputSample &ex
|
||||
}
|
||||
|
||||
const float angle = DEG2RADF(invert ? -1.0f : 1.0f) * influence;
|
||||
positions[point_i] = placement.project(rotate_by_angle(co - mouse_pos, angle) +
|
||||
mouse_pos);
|
||||
const float2 radial_offset = co - mouse_pos;
|
||||
positions[point_i] = projection_fn(deformation.positions[point_i],
|
||||
rotate_by_angle(radial_offset, angle) -
|
||||
radial_offset);
|
||||
});
|
||||
|
||||
params.drawing.tag_positions_changed();
|
||||
|
||||
Reference in New Issue
Block a user