From 2f0b293da3766516993b242f5c87f68d15064adc Mon Sep 17 00:00:00 2001 From: Sietse Brouwer Date: Tue, 13 Feb 2024 12:04:45 +0100 Subject: [PATCH] GPv3: Add function to retrieve falloff factor for multi frame editing This PR prepares GPv3 for calculating falloff factors when working in multi frame editing mode. The falloff popover is added to the UI. A `float multi_frame_falloff` is added to `MutableDrawingInfo`. This is a factor from 0.0 to 1.0f. A `retrieve_editable_drawings_with_falloff()` is added to the utility functions, which retrieves the falloff factor for each drawing when multi frame falloff is enabled. To avoid a copy, the return type of `retrieve_editable_drawings()` and friends is changed from `Array` to `Vector`. Pull Request: https://projects.blender.org/blender/blender/pulls/118108 --- scripts/startup/bl_ui/space_view3d.py | 36 +++++- .../intern/draw_cache_impl_grease_pencil.cc | 4 +- .../intern/grease_pencil_edit.cc | 49 ++++---- .../intern/grease_pencil_material.cc | 2 +- .../intern/grease_pencil_select.cc | 14 +-- .../intern/grease_pencil_utils.cc | 113 ++++++++++++++++-- .../editors/include/ED_grease_pencil.hh | 13 +- .../sculpt_paint/grease_pencil_erase.cc | 2 +- .../editors/space_view3d/view3d_select.cc | 8 +- .../transform_convert_grease_pencil.cc | 10 +- .../editors/transform/transform_gizmo_3d.cc | 2 +- 11 files changed, 190 insertions(+), 63 deletions(-) diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index 503c7146520..4f0cabba966 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -827,13 +827,21 @@ class VIEW3D_HT_header(Header): depress=(tool_settings.gpencil_selectmode_edit == 'STROKE'), ).mode = 'STROKE' + if object_mode == 'PAINT_GREASE_PENCIL': + row = layout.row(align=True) + row.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE') + + if object_mode in {'PAINT_GREASE_PENCIL', 'EDIT', 'WEIGHT_PAINT'}: row = layout.row(align=True) row.prop(tool_settings, "use_grease_pencil_multi_frame_editing", text="") - if object_mode == 'PAINT_GREASE_PENCIL': - row = layout.row() - sub = row.row(align=True) - sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE') + if object_mode in {'EDIT', 'WEIGHT_PAINT'}: + sub = row.row(align=True) + sub.enabled = tool_settings.use_grease_pencil_multi_frame_editing + sub.popover( + panel="VIEW3D_PT_grease_pencil_multi_frame", + text="Multiframe", + ) # Grease Pencil (legacy) if obj and obj.type == 'GPENCIL' and context.gpencil_data: @@ -8004,6 +8012,25 @@ class VIEW3D_PT_gpencil_multi_frame(Panel): layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True) +class VIEW3D_PT_grease_pencil_multi_frame(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'HEADER' + bl_label = "Multi Frame" + + def draw(self, context): + layout = self.layout + tool_settings = context.tool_settings + + settings = tool_settings.gpencil_sculpt + + col = layout.column(align=True) + col.prop(settings, "use_multiframe_falloff") + + # Falloff curve + if settings.use_multiframe_falloff: + layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True) + + # Grease Pencil Object - Curve Editing tools class VIEW3D_PT_gpencil_curve_edit(Panel): bl_space_type = 'VIEW_3D' @@ -9024,6 +9051,7 @@ classes = ( VIEW3D_PT_grease_pencil, VIEW3D_PT_annotation_onion, VIEW3D_PT_gpencil_multi_frame, + VIEW3D_PT_grease_pencil_multi_frame, VIEW3D_PT_gpencil_curve_edit, VIEW3D_PT_gpencil_sculpt_automasking, VIEW3D_PT_quad_view, diff --git a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc index e49d894be71..cfe42561d38 100644 --- a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc @@ -228,7 +228,7 @@ static void grease_pencil_edit_batch_ensure(Object &object, BLI_assert(cache->edit_points == nullptr && cache->edit_lines == nullptr); /* Get the visible drawings. */ - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_visible_drawings(scene, grease_pencil); const Span layers = grease_pencil.layers(); @@ -422,7 +422,7 @@ static void grease_pencil_geom_batch_ensure(Object &object, BLI_assert(cache->geom_batch == nullptr); /* Get the visible drawings. */ - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_visible_drawings(scene, grease_pencil); /* First, count how many vertices and triangles are needed for the whole object. Also record the diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc index 60b9536d55c..7b358c83c3c 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_edit.cc @@ -69,7 +69,7 @@ static int grease_pencil_stroke_smooth_exec(bContext *C, wmOperator *op) } bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); if (curves.points_num() == 0) { @@ -231,7 +231,7 @@ static int grease_pencil_stroke_simplify_exec(bContext *C, wmOperator *op) const float epsilon = RNA_float_get(op->ptr, "factor"); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); if (curves.points_num() == 0) { @@ -444,7 +444,7 @@ static int grease_pencil_delete_exec(bContext *C, wmOperator * /*op*/) scene->toolsettings); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask elements = ed::greasepencil::retrieve_editable_and_selected_elements( @@ -587,7 +587,7 @@ static int grease_pencil_dissolve_exec(bContext *C, wmOperator *op) const DissolveMode mode = DissolveMode(RNA_enum_get(op->ptr, "type")); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); if (curves.points_num() == 0) { @@ -760,7 +760,7 @@ static int grease_pencil_stroke_material_set_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -829,7 +829,7 @@ static int grease_pencil_cyclical_set_exec(bContext *C, wmOperator *op) const CyclicalMode mode = CyclicalMode(RNA_enum_get(op->ptr, "type")); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); if (mode == CyclicalMode::OPEN && !curves.attributes().contains("cyclic")) { @@ -910,7 +910,7 @@ static int grease_pencil_set_active_material_exec(bContext *C, wmOperator * /*op return OPERATOR_CANCELLED; } - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); for (const MutableDrawingInfo &info : drawings) { IndexMaskMemory memory; const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -958,7 +958,7 @@ static int grease_pencil_set_uniform_thickness_exec(bContext *C, wmOperator *op) const float radius = RNA_float_get(op->ptr, "thickness") * 0.5f; bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -1015,7 +1015,7 @@ static int grease_pencil_set_uniform_opacity_exec(bContext *C, wmOperator *op) const float opacity = RNA_float_get(op->ptr, "opacity"); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -1070,7 +1070,7 @@ static int grease_pencil_stroke_switch_direction_exec(bContext *C, wmOperator * GreasePencil &grease_pencil = *static_cast(object->data); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -1146,7 +1146,7 @@ static int grease_pencil_caps_set_exec(bContext *C, wmOperator *op) const CapsMode mode = CapsMode(RNA_enum_get(op->ptr, "type")); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); IndexMaskMemory memory; @@ -1322,7 +1322,7 @@ static int grease_pencil_duplicate_exec(bContext *C, wmOperator * /*op*/) scene->toolsettings); std::atomic changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask elements = retrieve_editable_and_selected_elements( @@ -1370,9 +1370,9 @@ static int grease_pencil_clean_loose_exec(bContext *C, wmOperator *op) const int limit = RNA_int_get(op->ptr, "limit"); GreasePencil &grease_pencil = *static_cast(object->data); - Array drawings = retrieve_editable_drawings(scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(scene, grease_pencil); - threading::parallel_for_each(drawings, [&](MutableDrawingInfo &info) { + threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); const OffsetIndices points_by_curve = curves.points_by_curve(); @@ -1436,7 +1436,7 @@ static int gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op) const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get( scene->toolsettings); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; @@ -1633,7 +1633,7 @@ static int grease_pencil_stroke_reorder_exec(bContext *C, wmOperator *op) const ReorderDirection direction = ReorderDirection(RNA_enum_get(op->ptr, "direction")); std::atomic changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes( @@ -1736,7 +1736,8 @@ static int grease_pencil_move_to_layer_exec(bContext *C, wmOperator *op) } /* Iterate through all the drawings at current scene frame. */ - const Array drawings_src = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings_src = retrieve_editable_drawings(*scene, + grease_pencil); for (const MutableDrawingInfo &info : drawings_src) { bke::CurvesGeometry &curves_src = info.drawing.strokes_for_write(); IndexMaskMemory memory; @@ -1903,8 +1904,8 @@ static bool grease_pencil_separate_selected(bContext &C, GreasePencil &grease_pencil_dst = *static_cast(object_dst->data); /* Iterate through all the drawings at current scene frame. */ - const Array drawings_src = retrieve_editable_drawings(scene, - grease_pencil_src); + const Vector drawings_src = retrieve_editable_drawings(scene, + grease_pencil_src); for (const MutableDrawingInfo &info : drawings_src) { bke::CurvesGeometry &curves_src = info.drawing.strokes_for_write(); IndexMaskMemory memory; @@ -1973,7 +1974,7 @@ static bool grease_pencil_separate_layer(bContext &C, grease_pencil_src.layers().first_index(layer_src), grease_pencil_src, grease_pencil_dst); /* Iterate through all the drawings at current frame. */ - const Array drawings_src = retrieve_editable_drawings_from_layer( + const Vector drawings_src = retrieve_editable_drawings_from_layer( scene, grease_pencil_src, *layer_src); for (const MutableDrawingInfo &info : drawings_src) { bke::CurvesGeometry &curves_src = info.drawing.strokes_for_write(); @@ -2041,8 +2042,8 @@ static bool grease_pencil_separate_material(bContext &C, false); /* Iterate through all the drawings at current scene frame. */ - const Array drawings_src = retrieve_editable_drawings(scene, - grease_pencil_src); + const Vector drawings_src = retrieve_editable_drawings(scene, + grease_pencil_src); for (const MutableDrawingInfo &info : drawings_src) { bke::CurvesGeometry &curves_src = info.drawing.strokes_for_write(); IndexMaskMemory memory; @@ -2101,8 +2102,8 @@ static int grease_pencil_separate_exec(bContext *C, wmOperator *op) switch (mode) { case SeparateMode::SELECTED: { /* Cancel if nothing selected. */ - const Array drawings = retrieve_editable_drawings(*scene, - grease_pencil_src); + const Vector drawings = retrieve_editable_drawings(*scene, + grease_pencil_src); const bool has_selection = std::any_of( drawings.begin(), drawings.end(), [&](const MutableDrawingInfo &info) { return ed::curves::has_anything_selected(info.drawing.strokes()); diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc index a14a5a147a9..6924c748d5e 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_material.cc @@ -271,7 +271,7 @@ static int grease_pencil_material_lock_unselected_exec(bContext *C, wmOperator * GreasePencil &grease_pencil = *static_cast(object->data); bool changed = false; - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); Set materials_used; diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc index dd65bde3853..f997e4db3d0 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc @@ -36,7 +36,7 @@ static int select_all_exec(bContext *C, wmOperator *op) GreasePencil &grease_pencil = *static_cast(object->data); bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask selectable_elements = retrieve_editable_elements( @@ -76,7 +76,7 @@ static int select_more_exec(bContext *C, wmOperator * /*op*/) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask selectable_strokes = ed::greasepencil::retrieve_editable_strokes( @@ -114,7 +114,7 @@ static int select_less_exec(bContext *C, wmOperator * /*op*/) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask selectable_strokes = ed::greasepencil::retrieve_editable_strokes( @@ -152,7 +152,7 @@ static int select_linked_exec(bContext *C, wmOperator * /*op*/) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { IndexMaskMemory memory; const IndexMask selectable_strokes = ed::greasepencil::retrieve_editable_strokes( @@ -193,7 +193,7 @@ static int select_random_exec(bContext *C, wmOperator *op) GreasePencil &grease_pencil = *static_cast(object->data); bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); @@ -253,7 +253,7 @@ static int select_alternate_exec(bContext *C, wmOperator *op) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { blender::ed::curves::select_alternate(info.drawing.strokes_for_write(), deselect_ends); }); @@ -292,7 +292,7 @@ static int select_ends_exec(bContext *C, wmOperator *op) Object *object = CTX_data_active_object(C); GreasePencil &grease_pencil = *static_cast(object->data); - const Array drawings = retrieve_editable_drawings(*scene, grease_pencil); + const Vector drawings = retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc index f443c43ae2c..42210b2f21e 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_utils.cc @@ -7,6 +7,7 @@ */ #include "BKE_attribute.hh" +#include "BKE_colortools.hh" #include "BKE_grease_pencil.hh" #include "BKE_material.h" #include "BKE_scene.hh" @@ -182,6 +183,53 @@ void DrawingPlacement::project(const Span src, MutableSpan dst) }); } +static float get_multi_frame_falloff(const int frame_number, + const int center_frame, + const int min_frame, + const int max_frame, + const CurveMapping *falloff_curve) +{ + if (falloff_curve == nullptr) { + return 1.0f; + } + + /* Frame right of the center frame. */ + if (frame_number > center_frame) { + const float frame_factor = 0.5f * float(center_frame - min_frame) / (frame_number - min_frame); + return BKE_curvemapping_evaluateF(falloff_curve, 0, frame_factor); + } + /* Frame left of the center frame. */ + if (frame_number < center_frame) { + const float frame_factor = 0.5f * float(center_frame - frame_number) / + (max_frame - frame_number); + return BKE_curvemapping_evaluateF(falloff_curve, 0, frame_factor + 0.5f); + } + /* Frame at center. */ + return BKE_curvemapping_evaluateF(falloff_curve, 0, 0.5f); +} + +static std::pair get_minmax_selected_frame_numbers(const GreasePencil &grease_pencil, + const int current_frame) +{ + using namespace blender::bke::greasepencil; + int frame_min = current_frame; + int frame_max = current_frame; + Span layers = grease_pencil.layers(); + for (const int layer_i : layers.index_range()) { + const Layer &layer = *layers[layer_i]; + if (!layer.is_editable()) { + continue; + } + for (const auto [frame_number, frame] : layer.frames().items()) { + if (frame_number != current_frame && frame.is_selected()) { + frame_min = math::min(frame_min, frame_number); + frame_max = math::min(frame_max, frame_number); + } + } + } + return std::pair(frame_min, frame_max); +} + static Array get_frame_numbers_for_layer(const bke::greasepencil::Layer &layer, const int current_frame, const bool use_multi_frame_editing) @@ -197,8 +245,8 @@ static Array get_frame_numbers_for_layer(const bke::greasepencil::Layer &la return frame_numbers.as_span(); } -Array retrieve_editable_drawings(const Scene &scene, - GreasePencil &grease_pencil) +Vector retrieve_editable_drawings(const Scene &scene, + GreasePencil &grease_pencil) { using namespace blender::bke::greasepencil; const int current_frame = scene.r.cfra; @@ -217,15 +265,60 @@ Array retrieve_editable_drawings(const Scene &scene, layer, current_frame, use_multi_frame_editing); for (const int frame_number : frame_numbers) { if (Drawing *drawing = grease_pencil.get_editable_drawing_at(layer, frame_number)) { - editable_drawings.append({*drawing, layer_i, frame_number}); + editable_drawings.append({*drawing, layer_i, frame_number, 1.0f}); } } } - return editable_drawings.as_span(); + return editable_drawings; } -Array retrieve_editable_drawings_from_layer( +Vector retrieve_editable_drawings_with_falloff(const Scene &scene, + GreasePencil &grease_pencil) +{ + using namespace blender::bke::greasepencil; + const int current_frame = scene.r.cfra; + const ToolSettings *toolsettings = scene.toolsettings; + const bool use_multi_frame_editing = (toolsettings->gpencil_flags & + GP_USE_MULTI_FRAME_EDITING) != 0; + const bool use_multi_frame_falloff = use_multi_frame_editing && + (toolsettings->gp_sculpt.flag & + GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0; + int center_frame; + std::pair minmax_frame; + if (use_multi_frame_falloff) { + BKE_curvemapping_init(toolsettings->gp_sculpt.cur_falloff); + minmax_frame = get_minmax_selected_frame_numbers(grease_pencil, current_frame); + center_frame = math::clamp(current_frame, minmax_frame.first, minmax_frame.second); + } + + Vector editable_drawings; + Span layers = grease_pencil.layers(); + for (const int layer_i : layers.index_range()) { + const Layer &layer = *layers[layer_i]; + if (!layer.is_editable()) { + continue; + } + const Array frame_numbers = get_frame_numbers_for_layer( + layer, current_frame, use_multi_frame_editing); + for (const int frame_number : frame_numbers) { + if (Drawing *drawing = grease_pencil.get_editable_drawing_at(layer, frame_number)) { + const float falloff = use_multi_frame_falloff ? + get_multi_frame_falloff(frame_number, + center_frame, + minmax_frame.first, + minmax_frame.second, + toolsettings->gp_sculpt.cur_falloff) : + 1.0f; + editable_drawings.append({*drawing, layer_i, frame_number, falloff}); + } + } + } + + return editable_drawings; +} + +Vector retrieve_editable_drawings_from_layer( const Scene &scene, GreasePencil &grease_pencil, const blender::bke::greasepencil::Layer &layer) @@ -241,14 +334,16 @@ Array retrieve_editable_drawings_from_layer( layer, current_frame, use_multi_frame_editing); for (const int frame_number : frame_numbers) { if (Drawing *drawing = grease_pencil.get_editable_drawing_at(layer, frame_number)) { - editable_drawings.append({*drawing, layer.drawing_index_at(frame_number), frame_number}); + editable_drawings.append( + {*drawing, layer.drawing_index_at(frame_number), frame_number, 1.0f}); } } - return editable_drawings.as_span(); + return editable_drawings; } -Array retrieve_visible_drawings(const Scene &scene, const GreasePencil &grease_pencil) +Vector retrieve_visible_drawings(const Scene &scene, + const GreasePencil &grease_pencil) { using namespace blender::bke::greasepencil; const int current_frame = scene.r.cfra; @@ -272,7 +367,7 @@ Array retrieve_visible_drawings(const Scene &scene, const GreasePen } } - return visible_drawings.as_span(); + return visible_drawings; } static VectorSet get_editable_material_indices(Object &object) diff --git a/source/blender/editors/include/ED_grease_pencil.hh b/source/blender/editors/include/ED_grease_pencil.hh index fc5183144ec..88627183e9f 100644 --- a/source/blender/editors/include/ED_grease_pencil.hh +++ b/source/blender/editors/include/ED_grease_pencil.hh @@ -171,13 +171,16 @@ struct MutableDrawingInfo { bke::greasepencil::Drawing &drawing; const int layer_index; const int frame_number; + const float multi_frame_falloff; }; -Array retrieve_editable_drawings(const Scene &scene, - GreasePencil &grease_pencil); -Array retrieve_editable_drawings_from_layer( +Vector retrieve_editable_drawings(const Scene &scene, + GreasePencil &grease_pencil); +Vector retrieve_editable_drawings_with_falloff(const Scene &scene, + GreasePencil &grease_pencil); +Vector retrieve_editable_drawings_from_layer( const Scene &scene, GreasePencil &grease_pencil, const bke::greasepencil::Layer &layer); -Array retrieve_visible_drawings(const Scene &scene, - const GreasePencil &grease_pencil); +Vector retrieve_visible_drawings(const Scene &scene, + const GreasePencil &grease_pencil); IndexMask retrieve_editable_strokes(Object &grease_pencil_object, const bke::greasepencil::Drawing &drawing, diff --git a/source/blender/editors/sculpt_paint/grease_pencil_erase.cc b/source/blender/editors/sculpt_paint/grease_pencil_erase.cc index cb19d5d8e36..65f6d9dcffe 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_erase.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_erase.cc @@ -810,7 +810,7 @@ struct EraseOperationExecutor { } else { /* Erase on all editable drawings. */ - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each( drawings, [&](const ed::greasepencil::MutableDrawingInfo &info) { diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 4c88b30f4d6..d76202c4eb2 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -1194,7 +1194,7 @@ static bool do_lasso_select_grease_pencil(ViewContext *vc, vc->scene->toolsettings); bool changed = false; - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*vc->scene, grease_pencil); for (const ed::greasepencil::MutableDrawingInfo info : drawings) { const bke::greasepencil::Layer &layer = *grease_pencil.layers()[info.layer_index]; @@ -3200,7 +3200,7 @@ static bool ed_grease_pencil_select_pick(bContext *C, /* Collect editable drawings. */ const Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, const_cast(vc.obedit)); GreasePencil &grease_pencil = *static_cast(vc.obedit->data); - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*vc.scene, grease_pencil); /* Get selection domain from tool settings. */ @@ -4224,7 +4224,7 @@ static bool do_grease_pencil_box_select(ViewContext *vc, const rcti *rect, const scene->toolsettings); bool changed = false; - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*scene, grease_pencil); for (const ed::greasepencil::MutableDrawingInfo info : drawings) { const bke::greasepencil::Layer &layer = *grease_pencil.layers()[info.layer_index]; @@ -5089,7 +5089,7 @@ static bool grease_pencil_circle_select(ViewContext *vc, vc->scene->toolsettings); bool changed = false; - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*vc->scene, grease_pencil); for (const ed::greasepencil::MutableDrawingInfo info : drawings) { const bke::greasepencil::Layer &layer = *grease_pencil.layers()[info.layer_index]; diff --git a/source/blender/editors/transform/transform_convert_grease_pencil.cc b/source/blender/editors/transform/transform_convert_grease_pencil.cc index 3f10b1f7e30..ade9177c2b1 100644 --- a/source/blender/editors/transform/transform_convert_grease_pencil.cc +++ b/source/blender/editors/transform/transform_convert_grease_pencil.cc @@ -31,13 +31,13 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t) const bool use_connected_only = (t->flag & T_PROP_CONNECTED) != 0; int total_number_of_drawings = 0; - Vector> all_drawings; + Vector> all_drawings; /* Count the number layers in all objects. */ for (const int i : trans_data_contrainers.index_range()) { TransDataContainer &tc = trans_data_contrainers[i]; GreasePencil &grease_pencil = *static_cast(tc.obedit->data); - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*scene, grease_pencil); all_drawings.append(drawings); total_number_of_drawings += drawings.size(); @@ -51,7 +51,7 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t) for (const int i : trans_data_contrainers.index_range()) { TransDataContainer &tc = trans_data_contrainers[i]; - const Array drawings = all_drawings[i]; + const Vector drawings = all_drawings[i]; for (ed::greasepencil::MutableDrawingInfo info : drawings) { if (use_proportional_edit) { points_per_layer_per_object[layer_offset] = ed::greasepencil::retrieve_editable_points( @@ -86,7 +86,7 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t) Span layers = grease_pencil.layers(); int layer_points_offset = 0; - const Array drawings = all_drawings[i]; + const Vector drawings = all_drawings[i]; for (ed::greasepencil::MutableDrawingInfo info : drawings) { const bke::greasepencil::Layer &layer = *layers[info.layer_index]; const float4x4 layer_space_to_world_space = layer.to_world_space(*object_eval); @@ -143,7 +143,7 @@ static void recalcData_grease_pencil(TransInfo *t) for (const TransDataContainer &tc : trans_data_contrainers) { GreasePencil &grease_pencil = *static_cast(tc.obedit->data); - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*scene, grease_pencil); for (ed::greasepencil::MutableDrawingInfo info : drawings) { bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); diff --git a/source/blender/editors/transform/transform_gizmo_3d.cc b/source/blender/editors/transform/transform_gizmo_3d.cc index 5f8cc962342..01a997e299f 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.cc +++ b/source/blender/editors/transform/transform_gizmo_3d.cc @@ -815,7 +815,7 @@ static int gizmo_3d_foreach_selected(const bContext *C, mat_local = float4x4(obedit->world_to_object) * float4x4(ob_iter->object_to_world); } - const Array drawings = + const Vector drawings = ed::greasepencil::retrieve_editable_drawings(*scene, grease_pencil); threading::parallel_for_each( drawings, [&](const ed::greasepencil::MutableDrawingInfo &info) {