104 if (!(smooth_position || smooth_radius || smooth_opacity)) {
109 bool changed =
false;
119 *
object,
info.drawing,
info.layer_index, memory);
130 if (smooth_position) {
144 if (smooth_opacity &&
info.drawing.opacities().is_span()) {
158 if (smooth_radius &&
info.drawing.radii().is_span()) {
186 ot->
name =
"Smooth Stroke";
187 ot->
idname =
"GREASE_PENCIL_OT_stroke_smooth";
224 "Delete alternating vertices in the stroke, except extremes"},
229 "Use a Ramer-Douglas-Peucker algorithm to simplify the stroke preserving main shape"},
234 "Re-sample the stroke with segments of the specified length"},
239 "Simplify the stroke by merging vertices closer than a given distance"},
240 {0,
nullptr, 0,
nullptr,
nullptr},
252 points_by_curve, stroke_selection, memory);
257 const int curve_i = point_to_curve_map[i];
258 const IndexRange points = points_by_curve[curve_i];
259 if (points.
size() <= 2) {
262 const int local_i = i - points.
start();
279 bool changed =
false;
289 *
object,
info.drawing,
info.layer_index, memory);
299 info.drawing.strokes_for_write() = {};
306 curves, points_to_keep, {});
321 info.drawing.strokes_for_write().remove_points(points_to_delete, {});
322 info.drawing.tag_topology_changed();
330 info.drawing.tag_topology_changed();
341 const int curve_i = point_to_curve_map[i];
342 const IndexRange points = points_by_curve[curve_i];
349 curves, merge_distance, filtered_points, {});
402 ot->
name =
"Simplify Stroke";
403 ot->
idname =
"GREASE_PENCIL_OT_stroke_simplify";
417 prop =
RNA_def_float(
ot->
srna,
"distance", 0.01f, 0.0f, 100.0f,
"Distance",
"", 0.0f, 1.0f);
426 "Method used for simplifying stroke points");
445 bool changed =
false;
450 *
object,
info.drawing,
info.layer_index, selection_domain, memory);
462 info.drawing.tag_topology_changed();
476 ot->
idname =
"GREASE_PENCIL_OT_delete";
506 "Dissolve points between selected points"},
511 "Dissolve all unselected points"},
512 {0,
nullptr, 0,
nullptr,
nullptr},
526 return points_to_dissolve;
538 for (const int64_t curve_i : range) {
539 const IndexRange points = points_by_curve[curve_i];
540 const Span<bool> curve_selection = points_to_dissolve.as_span().slice(points);
542 if (!curve_selection.contains(true)) {
543 points_to_keep.slice(points).fill(true);
549 if (mode != DissolveMode::BETWEEN) {
553 const Vector<IndexRange> deselection_ranges = array_utils::find_all_ranges(curve_selection,
556 if (deselection_ranges.size() != 0) {
557 const IndexRange first_range = deselection_ranges.first().shift(points.first());
558 const IndexRange last_range = deselection_ranges.last().shift(points.first());
562 if (first_range.first() == points.first()) {
563 points_to_keep.slice(first_range).fill(true);
565 if (last_range.last() == points.last()) {
566 points_to_keep.slice(last_range).fill(true);
574 return points_to_dissolve;
585 bool changed =
false;
594 const IndexMask points = ed::greasepencil::retrieve_editable_and_selected_points(
595 *
object,
info.drawing,
info.layer_index, memory);
601 if (points_to_dissolve.
as_span().contains(
true)) {
602 curves.
remove_points(IndexMask::from_bools(points_to_dissolve, memory), {});
603 info.drawing.tag_topology_changed();
620 ot->
idname =
"GREASE_PENCIL_OT_dissolve";
621 ot->
description =
"Delete selected points without splitting strokes";
634 "Method used for dissolving stroke points");
653 {int(DeleteFrameMode::ACTIVE_FRAME),
657 "Deletes current frame in the active layer"},
658 {int(DeleteFrameMode::ALL_FRAMES),
662 "Delete active frames for all layers"},
663 {0,
nullptr, 0,
nullptr,
nullptr},
675 bool changed =
false;
676 if (mode == DeleteFrameMode::ACTIVE_FRAME && grease_pencil.has_active_layer()) {
679 changed |= grease_pencil.remove_frames(layer, {*layer.
start_frame_at(current_frame)});
682 else if (mode == DeleteFrameMode::ALL_FRAMES) {
684 if (layer->is_editable() && layer->start_frame_at(current_frame)) {
685 changed |= grease_pencil.remove_frames(*layer, {*layer->start_frame_at(current_frame)});
703 ot->
name =
"Delete Frame";
704 ot->
idname =
"GREASE_PENCIL_OT_delete_frame";
718 "Method used for deleting Grease Pencil frames");
738 int material_index =
object->actcol - 1;
740 if (
name[0] !=
'\0') {
751 if (material_index == -1) {
758 IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
759 *
object,
info.drawing,
info.layer_index, memory);
767 bke::AttrDomain::Curve);
768 index_mask::masked_fill(materials.
span, material_index, strokes);
780 ot->
name =
"Assign Material";
781 ot->
idname =
"GREASE_PENCIL_OT_stroke_material_set";
782 ot->
description =
"Assign the active material slot to the selected strokes";
790 ot->
srna,
"material",
nullptr,
MAX_ID_NAME - 2,
"Material",
"Name of the material");
809 {int(CyclicalMode::CLOSE),
"CLOSE", 0,
"Close All",
""},
810 {int(CyclicalMode::OPEN),
"OPEN", 0,
"Open All",
""},
811 {int(CyclicalMode::TOGGLE),
"TOGGLE", 0,
"Toggle",
""},
812 {0,
nullptr, 0,
nullptr,
nullptr},
826 if (cyclic[curve_i]) {
827 const IndexRange points = points_by_curve[curve_i];
829 positions[points.
last()]);
836 const float point_density = float(points.
size()) / curve_length;
837 use_cuts[points.
last()] = int(point_density * end_distance);
843 return geometry::subdivide_curves(curves, strokes, cuts);
853 const bool subdivide_cyclic_segment =
RNA_boolean_get(op->
ptr,
"subdivide_cyclic_segment");
855 bool changed =
false;
865 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
866 *
object,
info.drawing,
info.layer_index, memory);
873 case CyclicalMode::CLOSE:
874 index_mask::masked_fill(cyclic,
true, strokes);
876 case CyclicalMode::OPEN:
877 index_mask::masked_fill(cyclic,
false, strokes);
879 case CyclicalMode::TOGGLE:
880 array_utils::invert_booleans(cyclic, strokes);
885 if (mode != CyclicalMode::CLOSE) {
886 if (array_utils::booleans_mix_calc(curves.
cyclic()) == array_utils::BooleanMix::AllFalse) {
891 if (subdivide_cyclic_segment) {
898 info.drawing.tag_topology_changed();
912 ot->
name =
"Set Cyclical State";
913 ot->
idname =
"GREASE_PENCIL_OT_cyclical_set";
914 ot->
description =
"Close or open the selected stroke adding a segment from last to first point";
926 "subdivide_cyclic_segment",
928 "Match Point Density",
929 "Add point in the new segment to keep the same density");
944 if (object->
totcol == 0) {
951 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
952 *
object,
info.drawing,
info.layer_index, memory);
959 "material_index", bke::AttrDomain::Curve, 0);
960 object->actcol = materials[strokes.
first()] + 1;
971 ot->
name =
"Set Active Material";
972 ot->
idname =
"GREASE_PENCIL_OT_set_active_material";
973 ot->
description =
"Set the selected stroke material as the active material";
995 bool changed =
false;
999 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1000 *
object,
info.drawing,
info.layer_index, memory);
1008 bke::curves::fill_points<float>(points_by_curve, strokes, radius, radii);
1022 ot->
name =
"Set Uniform Thickness";
1023 ot->
idname =
"GREASE_PENCIL_OT_set_uniform_thickness";
1024 ot->
description =
"Set all stroke points to same thickness";
1032 ot->
srna,
"thickness", 0.1f, 0.0f, 1000.0f,
"Thickness",
"Thickness", 0.0f, 1000.0f);
1051 bool changed =
false;
1055 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1056 *
object,
info.drawing,
info.layer_index, memory);
1065 bke::curves::fill_points<float>(points_by_curve, strokes, opacity_stroke, opacities);
1068 "fill_opacity", AttrDomain::Curve))
1071 fill_opacities.span[
curve] = opacity_fill;
1088 ot->
name =
"Set Uniform Opacity";
1089 ot->
idname =
"GREASE_PENCIL_OT_set_uniform_opacity";
1099 RNA_def_float(
ot->
srna,
"opacity_stroke", 1.0f, 0.0f, 1.0f,
"Stroke Opacity",
"", 0.0f, 1.0f);
1100 RNA_def_float(
ot->
srna,
"opacity_fill", 0.5f, 0.0f, 1.0f,
"Fill Opacity",
"", 0.0f, 1.0f);
1116 bool changed =
false;
1120 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1121 *
object,
info.drawing,
info.layer_index, memory);
1144 ot->
name =
"Switch Direction";
1145 ot->
idname =
"GREASE_PENCIL_OT_stroke_switch_direction";
1146 ot->
description =
"Change direction of the points of the selected strokes";
1167 if (array_utils::booleans_mix_calc(src_cyclic) == array_utils::BooleanMix::AllFalse) {
1177 for (const int curve_i : range) {
1178 const IndexRange points = points_by_curve[curve_i];
1179 const Span<bool> curve_i_selected_points = start_set_points.as_span().slice(points);
1180 const int first_selected = curve_i_selected_points.first_index_try(true);
1182 MutableSpan<int> dst_to_src_slice = dst_to_src_point.as_mutable_span().slice(points);
1184 array_utils::fill_index_range<int>(dst_to_src_slice, points.start());
1186 if (first_selected == -1 || src_cyclic[curve_i] == false) {
1190 std::rotate(dst_to_src_slice.begin(),
1191 dst_to_src_slice.begin() + first_selected,
1192 dst_to_src_slice.end());
1201 array_utils::copy(curves.offsets(), dst_curves.offsets_for_write());
1208 bke::copy_attributes(
1209 src_attributes, bke::AttrDomain::Curve, bke::AttrDomain::Curve, {}, dst_attributes);
1210 array_utils::copy(src_cyclic, dst_curves.cyclic_for_write());
1213 gather_attributes(src_attributes,
1214 bke::AttrDomain::Point,
1215 bke::AttrDomain::Point,
1220 dst_curves.update_curve_types();
1222 if (curves.nurbs_has_custom_knots()) {
1223 bke::curves::nurbs::update_custom_knot_modes(
1231 using namespace bke::greasepencil;
1236 std::atomic<bool> changed =
false;
1241 *
object,
info.drawing,
info.layer_index, memory);
1248 info.drawing.tag_topology_changed();
1261 ot->
name =
"Set Start Point";
1262 ot->
idname =
"GREASE_PENCIL_OT_set_start_point";
1263 ot->
description =
"Select which point is the beginning of the curve";
1308 bool changed =
false;
1313 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1314 *
object,
info.drawing,
info.layer_index, memory);
1321 if (
ELEM(mode, CapsMode::ROUND, CapsMode::FLAT)) {
1327 index_mask::masked_fill(start_caps.span, flag_set, strokes);
1328 start_caps.finish();
1333 index_mask::masked_fill(end_caps.span, flag_set, strokes);
1339 case CapsMode::START: {
1342 bke::AttrDomain::Curve))
1349 case CapsMode::END: {
1352 bke::AttrDomain::Curve))
1359 case CapsMode::ROUND:
1360 case CapsMode::FLAT:
1379 {int(CapsMode::ROUND),
"ROUND", 0,
"Rounded",
"Set as default rounded"},
1380 {int(CapsMode::FLAT),
"FLAT", 0,
"Flat",
""},
1382 {int(CapsMode::START),
"START", 0,
"Toggle Start",
""},
1383 {int(CapsMode::END),
"END", 0,
"Toggle End",
""},
1384 {0,
nullptr, 0,
nullptr,
nullptr},
1387 ot->
name =
"Set Curve Caps";
1388 ot->
idname =
"GREASE_PENCIL_OT_caps_set";
1389 ot->
description =
"Change curve caps mode (rounded or flat)";
1416 if (ob ==
nullptr) {
1424 item_tmp.name = ma->id.name + 2;
1425 item_tmp.value = i + 1;
1426 item_tmp.icon = ma->preview ? ma->preview->runtime->icon_id : ICON_NONE;
1444 if ((slot < 1) || (slot > object->
totcol)) {
1449 object->actcol = slot;
1458 ot->
name =
"Set Active Material";
1459 ot->
idname =
"GREASE_PENCIL_OT_set_material";
1486 std::atomic<bool> changed =
false;
1491 *
object,
info.drawing,
info.layer_index, selection_domain, memory);
1497 if (selection_domain == bke::AttrDomain::Curve) {
1498 curves::duplicate_curves(curves, elements);
1500 else if (selection_domain == bke::AttrDomain::Point) {
1501 curves::duplicate_points(curves, elements);
1503 info.drawing.tag_topology_changed();
1504 changed.store(
true, std::memory_order_relaxed);
1517 ot->
idname =
"GREASE_PENCIL_OT_duplicate";
1540 const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_strokes(
1541 *
object,
info.drawing,
info.layer_index, memory);
1543 const IndexMask curves_to_delete = IndexMask::from_predicate(
1544 editable_strokes,
GrainSize(4096), memory, [&](
const int i) {
1545 return points_by_curve[i].
size() <= limit;
1562 C, op, event,
IFACE_(
"Remove Loose Points"),
IFACE_(
"Delete"));
1567 ot->
name =
"Clean Loose Points";
1568 ot->
idname =
"GREASE_PENCIL_OT_clean_loose";
1583 "Number of points to consider stroke as loose",
1599 std::atomic<bool> changed =
false;
1611 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1612 *
object,
info.drawing,
info.layer_index, memory);
1620 if (selection_domain == bke::AttrDomain::Curve || !only_selected) {
1624 else if (selection_domain == bke::AttrDomain::Point) {
1629 ".selection", bke::AttrDomain::Point,
true);
1640 for (
const int point : points_by_curve[
curve].drop_back(1)) {
1642 if (!selection[point]) {
1646 if (selection[point + 1]) {
1647 use_cuts[point] = cuts;
1651 if (cyclic[
curve]) {
1652 const int first_point = points_by_curve[
curve].
first();
1653 const int last_point = points_by_curve[
curve].last();
1654 if (selection[first_point] && selection[last_point]) {
1655 use_cuts[last_point] = cuts;
1662 curves = geometry::subdivide_curves(curves, strokes, vcuts);
1663 info.drawing.tag_topology_changed();
1664 changed.store(
true, std::memory_order_relaxed);
1679 ot->
name =
"Subdivide Stroke";
1680 ot->
idname =
"GREASE_PENCIL_OT_stroke_subdivide";
1682 "Subdivide between continuous selected points of the stroke adding a point half way "
1687 ot->
poll = ed::greasepencil::editable_grease_pencil_poll;
1691 prop =
RNA_def_int(
ot->
srna,
"number_cuts", 1, 1, 32,
"Number of Cuts",
"", 1, 5);
1699 "Smooth only selected points in the stroke");
1725 if (
ELEM(direction, ReorderDirection::UP, ReorderDirection::DOWN)) {
1727 array_utils::fill_index_range<int>(
indices);
1730 if (
ELEM(direction, ReorderDirection::TOP, ReorderDirection::BOTTOM)) {
1755 const IndexMask &
A = (direction == ReorderDirection::BOTTOM) ? selected : unselected;
1756 const IndexMask &
B = (direction == ReorderDirection::BOTTOM) ? unselected : selected;
1759 B.to_indices(
indices.as_mutable_span().take_back(
B.size()));
1761 else if (direction == ReorderDirection::DOWN) {
1764 if (curve_i !=
pos) {
1770 else if (direction == ReorderDirection::UP) {
1776 for (
const int i : selected_indices.
index_range()) {
1778 const int curve_i = selected_indices[
pos];
1781 if (curve_i != universe.
last(i)) {
1799 std::atomic<bool> changed =
false;
1803 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
1804 *
object,
info.drawing,
info.layer_index, memory);
1817 curves = geometry::reorder_curves_geometry(curves,
indices, {});
1819 changed.store(
true, std::memory_order_relaxed);
1833 {int(ReorderDirection::TOP),
"TOP", 0,
"Bring to Front",
""},
1834 {int(ReorderDirection::UP),
"UP", 0,
"Bring Forward",
""},
1836 {int(ReorderDirection::DOWN),
"DOWN", 0,
"Send Backward",
""},
1837 {int(ReorderDirection::BOTTOM),
"BOTTOM", 0,
"Send to Back",
""},
1838 {0,
nullptr, 0,
nullptr,
nullptr},
1842 ot->
idname =
"GREASE_PENCIL_OT_reorder";
1843 ot->
description =
"Change the display order of the selected strokes";
1851 ot->
srna,
"direction", prop_reorder_direction,
int(ReorderDirection::TOP),
"Direction",
"");
1862 using namespace bke::greasepencil;
1864 bool changed =
false;
1869 int target_layer_name_length;
1871 op->
ptr,
"target_layer_name",
nullptr, 0, &target_layer_name_length);
1876 if (add_new_layer) {
1877 target_node = &grease_pencil.add_layer(target_layer_name).as_node();
1880 target_node = grease_pencil.find_node_by_name(target_layer_name);
1883 if (target_node ==
nullptr || !target_node->
is_layer()) {
1889 if (layer_dst.is_locked()) {
1900 const IndexMask selected_strokes = ed::curves::retrieve_selected_curves(curves_src, memory);
1907 Drawing &drawing_dst = *grease_pencil.insert_frame(layer_dst,
info.frame_number);
1909 curves_src, selected_strokes, {});
1914 else if (
Drawing *drawing_dst = grease_pencil.get_drawing_at(layer_dst,
info.frame_number)) {
1917 curves_src, selected_strokes, {});
1918 Curves *selected_curves = bke::curves_new_nomain(std::move(selected_elems));
1919 Curves *layer_curves = bke::curves_new_nomain(std::move(drawing_dst->strokes_for_write()));
1920 std::array<bke::GeometrySet, 2> geometry_sets{
1921 bke::GeometrySet::from_curves(layer_curves),
1922 bke::GeometrySet::from_curves(selected_curves)};
1928 drawing_dst->tag_topology_changed();
1931 info.drawing.tag_topology_changed();
1949 if (add_new_layer) {
1953 const std::string
unique_name = grease_pencil.unique_layer_name(
"Layer");
1957 C, op, event,
IFACE_(
"Move to New Layer"),
IFACE_(
"Create"));
1975 ot->
name =
"Move to Layer";
1976 ot->
idname =
"GREASE_PENCIL_OT_move_to_layer";
1986 ot->
srna,
"target_layer_name",
nullptr,
INT16_MAX,
"Name",
"Target Grease Pencil Layer");
1989 ot->
srna,
"add_new_layer",
false,
"New Layer",
"Move selection to a new layer");
2009 {int(SeparateMode::SELECTED),
"SELECTED", 0,
"Selection",
"Separate selected geometry"},
2010 {int(SeparateMode::MATERIAL),
"MATERIAL", 0,
"By Material",
"Separate by material"},
2011 {int(SeparateMode::LAYER),
"LAYER", 0,
"By Layer",
"Separate by layer"},
2012 {0,
nullptr, 0,
nullptr,
nullptr},
2017 int actcol =
object->actcol;
2018 for (
int slot = 1; slot <=
object->totcol; slot++) {
2020 object->actcol = slot;
2025 if (actcol >= slot) {
2030 object->actcol = actcol;
2040 Base *base_new = object::add_duplicate(bmain,
scene, view_layer, base_prev, dupflag);
2045 object_dst->
data = grease_pencil_dst;
2051 const int layer_index,
2056 using namespace bke::greasepencil;
2059 const Layer &layer_src = grease_pencil_src.layer(layer_index);
2060 if (
TreeNode *
node = grease_pencil_dst.find_node_by_name(layer_src.name())) {
2061 return node->as_layer();
2065 Layer &new_layer = grease_pencil_dst.add_layer(layer_src.name());
2067 src_to_dst_layer_indices.
append(layer_index);
2079 using namespace bke::greasepencil;
2080 bool changed =
false;
2084 &bmain, &
scene, &view_layer, &base_prev, grease_pencil_src);
2094 const IndexMask selected_points = ed::curves::retrieve_selected_points(curves_src, memory);
2101 info.layer_index, grease_pencil_src, grease_pencil_dst, src_to_dst_layer_indices);
2103 Drawing *drawing_dst = grease_pencil_dst.insert_frame(layer_dst,
info.frame_number);
2108 curves_src, selected_points, {});
2109 curves_src = geometry::remove_points_and_split(curves_src, selected_points);
2111 info.drawing.tag_topology_changed();
2119 bke::gather_attributes(grease_pencil_src.attributes(),
2120 bke::AttrDomain::Layer,
2121 bke::AttrDomain::Layer,
2123 src_to_dst_layer_indices.
as_span(),
2124 grease_pencil_dst.attributes_for_write());
2127 if (grease_pencil_src.has_active_layer()) {
2128 const Layer &active_layer_src = *grease_pencil_src.get_active_layer();
2129 TreeNode *active_layer_dst = grease_pencil_dst.find_node_by_name(active_layer_src.name());
2130 if (active_layer_dst && active_layer_dst->
is_layer()) {
2131 grease_pencil_dst.set_active_layer(&active_layer_dst->
as_layer());
2156 using namespace bke::greasepencil;
2157 bool changed =
false;
2162 for (
const int layer_i : grease_pencil_src.layers().index_range()) {
2163 Layer &layer_src = grease_pencil_src.layer(layer_i);
2164 if (layer_src.is_locked()) {
2169 &bmain, &
scene, &view_layer, &base_prev, grease_pencil_src);
2173 layer_i, grease_pencil_src, grease_pencil_dst, src_to_dst_layer_indices);
2177 scene, grease_pencil_src, layer_src);
2182 object_src,
info.drawing,
info.layer_index, memory);
2195 Drawing *drawing_dst = grease_pencil_dst.insert_frame(layer_dst,
info.frame_number);
2201 info.drawing.strokes(), strokes, {});
2204 info.drawing.tag_topology_changed();
2211 bke::gather_attributes(grease_pencil_src.attributes(),
2212 bke::AttrDomain::Layer,
2213 bke::AttrDomain::Layer,
2215 src_to_dst_layer_indices.
as_span(),
2216 grease_pencil_dst.attributes_for_write());
2235 using namespace bke::greasepencil;
2236 bool changed =
false;
2247 &bmain, &
scene, &view_layer, &base_prev, grease_pencil_src);
2265 object_src,
info.drawing, mat_i, memory);
2272 info.layer_index, grease_pencil_src, grease_pencil_dst, src_to_dst_layer_indices);
2274 Drawing *drawing_dst = grease_pencil_dst.insert_frame(layer_dst,
info.frame_number);
2279 drawing_dst->
strokes_for_write() = bke::curves_copy_curve_selection(curves_src, strokes, {});
2282 info.drawing.tag_topology_changed();
2289 bke::gather_attributes(grease_pencil_src.attributes(),
2290 bke::AttrDomain::Layer,
2291 bke::AttrDomain::Layer,
2293 src_to_dst_layer_indices.
as_span(),
2294 grease_pencil_dst.attributes_for_write());
2311 using namespace bke::greasepencil;
2320 bool changed =
false;
2325 case SeparateMode::SELECTED: {
2329 const bool has_selection = std::any_of(
2331 return ed::curves::has_anything_selected(info.drawing.strokes());
2333 if (!has_selection) {
2340 *C, *bmain, *
scene, *view_layer, *base_prev, *object_src);
2343 case SeparateMode::MATERIAL: {
2345 if (object_src->
totcol == 1) {
2352 *C, *bmain, *
scene, *view_layer, *base_prev, *object_src);
2355 case SeparateMode::LAYER: {
2357 if (grease_pencil_src.layers().size() == 1) {
2363 *C, *bmain, *
scene, *view_layer, *base_prev, *object_src);
2381 ot->
idname =
"GREASE_PENCIL_OT_separate";
2382 ot->
description =
"Separate the selected geometry into a new Grease Pencil object";
2415} *grease_pencil_clipboard =
nullptr;
2460 clipboard_material_remap[clipboard.
materials[i].second] = target_index;
2466 clipboard_material_remap[clipboard.
materials[i].second] = target_index;
2469 return clipboard_material_remap;
2477 std::unique_ptr<bke::Instances> instances = std::make_unique<bke::Instances>();
2478 instances->resize(geometries.
size());
2479 transforms.
materialize(instances->transforms_for_write());
2486 options.keep_original_ids =
true;
2487 options.realize_instance_attributes =
false;
2488 return realize_instances(bke::GeometrySet::from_instances(instances.release()),
options);
2509 int num_elements_copied = 0;
2516 const Layer &layer = grease_pencil.layer(drawing_info.layer_index);
2521 if (!ed::curves::has_anything_selected(curves)) {
2529 if (selection_domain == bke::AttrDomain::Curve) {
2530 const IndexMask selected_curves = ed::curves::retrieve_selected_curves(curves, memory);
2531 copied_curves = curves_copy_curve_selection(curves, selected_curves, {});
2532 num_elements_copied += copied_curves.
curves_num();
2534 else if (selection_domain == bke::AttrDomain::Point) {
2535 const IndexMask selected_points = ed::curves::retrieve_selected_points(curves, memory);
2536 copied_curves = geometry::remove_points_and_split(
2538 num_elements_copied += copied_curves.
points_num();
2543 bke::GeometrySet::from_curves(curves_new_nomain(std::move(copied_curves))));
2546 if (copied_curves_per_layer.
is_empty()) {
2547 clipboard.
layers.reinitialize(0);
2551 clipboard.
layers.reinitialize(copied_curves_per_layer.
size());
2554 for (
auto const &[layer, geometries] : copied_curves_per_layer.
items()) {
2555 const float4x4 layer_to_object = layer->to_object_space(*
object);
2561 cliplayer.
name = layer->name();
2571 const auto is_material_index_used = [&](
const int material_index) ->
bool {
2575 "material_index", bke::AttrDomain::Curve, 0);
2576 if (material_indices.
contains(material_index)) {
2584 if (!is_material_index_used(material_index)) {
2592 if (selection_domain == bke::AttrDomain::Curve) {
2595 else if (selection_domain == bke::AttrDomain::Point) {
2604 ot->
name =
"Copy Strokes";
2605 ot->
idname =
"GREASE_PENCIL_OT_copy";
2606 ot->
description =
"Copy the selected Grease Pencil points or strokes to the internal clipboard";
2617 const float4x4 &object_to_paste_layer,
2618 const float4x4 &clipboard_to_world,
2619 const bool keep_world_transform,
2620 const bool paste_back,
2624 const Array<int> clipboard_material_remap = ed::greasepencil::clipboard_materials_remap(bmain,
2633 Curves *clipboard_id = bke::curves_new_nomain(curves_to_paste);
2637 bke::GeometrySet::from_curves(paste_back ? clipboard_id : target_id),
2638 bke::GeometrySet::from_curves(paste_back ? target_id : clipboard_id)};
2641 (keep_world_transform ?
2642 object.world_to_object() * clipboard_to_world :
2651 if (!clipboard_material_remap.
is_empty()) {
2655 "material_index", bke::AttrDomain::Curve);
2656 if (material_indices) {
2657 for (
const int i : pasted_curves_range) {
2658 material_indices.
span[i] = clipboard_material_remap[material_indices.
span[i]];
2660 material_indices.
finish();
2666 return pasted_curves_range;
2676 using namespace bke::greasepencil;
2690 if (clipboard.
layers.is_empty()) {
2696 bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
2697 layer.curves, selection_domain, CD_PROP_BOOL);
2701 if (type == PasteType::Active) {
2702 Layer *active_layer = grease_pencil.get_active_layer();
2703 if (!active_layer) {
2707 if (!active_layer->is_editable()) {
2718 ed::curves::fill_selection_false(selection_in_target.
span);
2719 selection_in_target.
finish();
2725 bool inserted_keyframe =
false;
2732 ed::greasepencil::retrieve_editable_drawings_from_layer(
2733 scene, grease_pencil, *active_layer);
2736 *bmain, *
object, object_to_layer, keep_world_transform, paste_on_back,
info.drawing);
2739 if (inserted_keyframe) {
2743 else if (type == PasteType::ByLayer) {
2744 Layer *active_layer = grease_pencil.get_active_layer();
2747 for (
const int clip_layer_i : clipboard.
layers.index_range()) {
2750 const bool found_layer =
node &&
node->is_layer() &&
node->as_layer().is_editable();
2752 layers_to_paste_into[clip_layer_i] = &
node->as_layer();
2755 if (active_layer && active_layer->is_editable()) {
2758 op->
reports,
RPT_WARNING,
"Couldn't find matching layer, pasting into active layer");
2759 layers_to_paste_into[clip_layer_i] = active_layer;
2763 if (!active_layer) {
2766 if (!active_layer->is_editable()) {
2778 ed::curves::fill_selection_false(selection_in_target.
span);
2779 selection_in_target.
finish();
2782 for (
const int clip_layer_i : clipboard.
layers.index_range()) {
2786 BLI_assert(layers_to_paste_into[clip_layer_i] !=
nullptr);
2787 Layer &paste_layer = *layers_to_paste_into[clip_layer_i];
2791 bool inserted_keyframe =
false;
2798 ed::greasepencil::retrieve_editable_drawings_from_layer(
2799 scene, grease_pencil, paste_layer);
2804 object_to_paste_layer,
2806 keep_world_transform,
2811 if (inserted_keyframe) {
2842 {int(PasteType::Active),
"ACTIVE", 0,
"Paste to Active",
""},
2843 {int(PasteType::ByLayer),
"LAYER", 0,
"Paste by Layer",
""},
2844 {0,
nullptr, 0,
nullptr,
nullptr},
2847 ot->
name =
"Paste Strokes";
2848 ot->
idname =
"GREASE_PENCIL_OT_paste";
2850 "Paste Grease Pencil points or strokes from the internal clipboard to the active layer";
2860 ot->
srna,
"paste_back",
false,
"Paste on Back",
"Add pasted strokes behind all strokes");
2864 "keep_world_transform",
2866 "Keep World Transform",
2867 "Keep the world transform of strokes from the clipboard unchanged");
2875 const float4x4 &object_to_paste_layer,
2876 const bool keep_world_transform,
2877 const bool paste_back,
2881 if (clipboard.
layers.is_empty()) {
2887 geometries_to_join.
append(bke::GeometrySet::from_curves(curves_new_nomain(layer.curves)));
2897 joined_clipboard_curves,
2898 object_to_paste_layer,
2900 keep_world_transform,
2917 std::atomic<bool> changed =
false;
2923 const IndexMask points = use_unselected ?
2924 ed::greasepencil::retrieve_editable_points(
2925 *
object, drawing,
info.layer_index, memory) :
2926 ed::greasepencil::retrieve_editable_and_selected_points(
2927 *
object,
info.drawing,
info.layer_index, memory);
2932 drawing.
strokes(), threshold, points, {});
2934 changed.store(
true, std::memory_order_relaxed);
2947 ot->
name =
"Merge by Distance";
2948 ot->
idname =
"GREASE_PENCIL_OT_stroke_merge_by_distance";
2956 prop =
RNA_def_float(
ot->
srna,
"threshold", 0.001f, 0.0f, 100.0f,
"Threshold",
"", 0.0f, 100.0f);
2964 "Use whole stroke, not only selected points");
2991 offset_indices::copy_group_sizes(
2997 int point_offset = 0;
2999 const IndexRange curve_points = points_by_curve[curve_index];
3001 const bool curve_cyclic = src_cyclic[curve_index];
3003 curve_points_to_extrude.
foreach_index([&](
const int src_point_index) {
3004 if (!curve_cyclic && (src_point_index == curve_points.
first())) {
3007 dst_to_src_points.
insert(src_point_index + point_offset, src_point_index);
3008 dst_selected.
insert(src_point_index + point_offset,
true);
3009 ++dst_curve_counts[curve_index];
3013 if (!curve_cyclic && (src_point_index == curve_points.
last())) {
3016 dst_to_src_points.
insert(src_point_index + point_offset + 1, src_point_index);
3017 dst_selected.
insert(src_point_index + point_offset + 1,
true);
3018 ++dst_curve_counts[curve_index];
3026 dst_to_src_points.
append(src_point_index);
3027 dst_selected.
append(
false);
3028 dst_to_src_points.
append(src_point_index);
3029 dst_selected.
append(
true);
3030 dst_to_src_curves.
append(curve_index);
3031 dst_curve_counts.
append(2);
3035 const int new_points_num = dst_to_src_points.
size();
3036 const int new_curves_num = dst_to_src_curves.
size();
3043 array_utils::copy(dst_curve_counts.
as_span(), new_curve_offsets.
drop_back(1));
3044 offset_indices::accumulate_counts_to_offsets(new_curve_offsets);
3056 for (
const StringRef selection_attribute_name :
3057 ed::curves::get_curves_selection_attribute_names(src))
3060 dst, bke::AttrDomain::Point,
CD_PROP_BOOL, selection_attribute_name);
3065 bke::gather_attributes(src_attributes,
3066 bke::AttrDomain::Curve,
3067 bke::AttrDomain::Curve,
3075 bke::gather_attributes(src_attributes,
3076 bke::AttrDomain::Point,
3077 bke::AttrDomain::Point,
3078 bke::attribute_filter_from_skip_ref(
3079 {
".selection",
".selection_handle_left",
".selection_handle_right"}),
3089 const IndexMask include_curves = IndexMask::from_predicate(
3093 points_by_curve[curve_index].
size() == dst_points_by_curve[curve_index].
size();
3095 bke::curves::nurbs::update_custom_knot_modes(
3100 bke::curves::nurbs::gather_custom_knots(src, include_curves, 0, dst);
3111 std::atomic<bool> changed =
false;
3116 *
object,
info.drawing,
info.layer_index, memory);
3117 if (points_to_extrude.
is_empty()) {
3124 info.drawing.tag_topology_changed();
3125 changed.store(
true, std::memory_order_relaxed);
3138 ot->
name =
"Extrude Stroke Points";
3139 ot->
idname =
"GREASE_PENCIL_OT_extrude";
3188 if (mode == ReprojectMode::Surface) {
3189 return transform::snap_object_context_create(&
scene, 0);
3198 if (keep_original) {
3203 *
object,
info.drawing,
info.layer_index, selection_domain, memory);
3209 if (selection_domain == bke::AttrDomain::Curve) {
3210 curves::duplicate_curves(curves, elements);
3212 else if (selection_domain == bke::AttrDomain::Point) {
3213 curves::duplicate_points(curves, elements);
3215 info.drawing.tag_topology_changed();
3222 std::atomic<bool> changed =
false;
3226 if (drawings.is_empty()) {
3229 const int current_frame_number = drawings.first().frame_number;
3231 if (mode == ReprojectMode::Surface) {
3242 *
object,
info.drawing,
info.layer_index, memory);
3245 ed::curves::get_curves_selection_attribute_names(curves))
3247 const IndexMask selected_points = ed::curves::retrieve_selected_points(
3248 curves, selection_name, memory);
3249 const IndexMask points_to_reproject = IndexMask::from_intersection(
3250 editable_points, selected_points, memory);
3252 if (points_to_reproject.
is_empty()) {
3257 if (selection_name ==
".selection_handle_left") {
3260 else if (selection_name ==
".selection_handle_right") {
3265 if (mode == ReprojectMode::Surface) {
3269 float3 &position = positions[point_i];
3278 float3 ray_start, ray_direction;
3280 depsgraph, region, v3d, screen_co, ray_start, ray_direction,
true))
3285 float hit_depth = std::numeric_limits<float>::max();
3286 float3 hit_position(0.0f);
3292 if (transform::snap_object_project_ray(snap_context,
3304 world_space_to_layer_space,
3307 if (selection_name ==
".selection") {
3316 scene, *region, *v3d, *
object, &layer, mode, offset,
nullptr);
3318 const float3 new_pos = drawing_placement.
reproject(positions[point_i]);
3319 if (selection_name ==
".selection") {
3321 rv3d, positions[point_i], new_pos);
3323 positions[point_i] = new_pos;
3327 info.drawing.tag_positions_changed();
3328 changed.store(
true, std::memory_order_relaxed);
3334 if (snap_context !=
nullptr) {
3335 transform::snap_object_context_destroy(snap_context);
3339 if (mode == ReprojectMode::Surface) {
3361 row = &layout->
row(
true);
3364 if (type == ReprojectMode::Surface) {
3365 row = &layout->
row(
true);
3368 row = &layout->
row(
true);
3375 {int(ReprojectMode::Front),
3379 "Reproject the strokes using the X-Z plane"},
3380 {int(ReprojectMode::Side),
"SIDE", 0,
"Side",
"Reproject the strokes using the Y-Z plane"},
3381 {int(ReprojectMode::Top),
"TOP", 0,
"Top",
"Reproject the strokes using the X-Y plane"},
3382 {int(ReprojectMode::View),
3386 "Reproject the strokes to end up on the same plane, as if drawn from the current "
3388 "using 'Cursor' Stroke Placement"},
3389 {int(ReprojectMode::Surface),
3393 "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
3394 {int(ReprojectMode::Cursor),
3398 "Reproject the strokes using the orientation of 3D cursor"},
3399 {0,
nullptr, 0,
nullptr,
nullptr},
3403 ot->
name =
"Reproject Strokes";
3404 ot->
idname =
"GREASE_PENCIL_OT_reproject";
3406 "Reproject the selected strokes from the current viewpoint as if they had been newly "
3408 "(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
3409 "or for matching deforming geometry)";
3422 ot->
srna,
"type", reproject_type,
int(ReprojectMode::View),
"Projection Type",
"");
3429 "Keep original strokes and create a copy before reprojecting");
3479 if (!ed::curves::has_anything_selected(curves)) {
3483 for (
const StringRef selection_name : ed::curves::get_curves_selection_attribute_names(curves))
3486 const IndexMask selected_points = ed::curves::retrieve_selected_points(
3487 curves, selection_name, memory);
3489 const Layer &layer = grease_pencil.layer(drawing_info.layer_index);
3494 if (selection_name ==
".selection_handle_left") {
3497 else if (selection_name ==
".selection_handle_right") {
3502 const float3 pos_snapped = grid_size *
math::floor(pos_world / grid_size + 0.5f);
3507 drawing_info.drawing.tag_positions_changed();
3519 ot->
name =
"Snap Selection to Grid";
3520 ot->
idname =
"GREASE_PENCIL_OT_snap_to_grid";
3521 ot->
description =
"Snap selected points to the nearest grid points";
3551 if (!ed::curves::has_anything_selected(curves)) {
3556 const IndexMask selected_points = ed::curves::retrieve_selected_points(curves,
3557 selected_points_memory);
3559 const Layer &layer = grease_pencil.layer(drawing_info.layer_index);
3568 const IndexMask selected_curves = ed::curves::retrieve_selected_curves(
3569 curves, selected_curves_memory);
3572 const IndexRange points = points_by_curve[curve_i];
3575 const float3 offset = cursor_layer - positions[points.
first()];
3577 GrainSize(4096), [&](
const int point_i) { positions[point_i] += offset; });
3582 index_mask::masked_fill(positions, cursor_layer, selected_points);
3586 drawing_info.drawing.tag_positions_changed();
3599 ot->
name =
"Snap Selection to Cursor";
3600 ot->
idname =
"GREASE_PENCIL_OT_snap_to_cursor";
3601 ot->
description =
"Snap selected points/strokes to the cursor";
3615 "Offset the entire stroke instead of selected points only");
3633 int num_selected = 0;
3634 r_centroid =
float3(0.0f);
3635 r_min =
float3(std::numeric_limits<float>::max());
3636 r_max =
float3(std::numeric_limits<float>::lowest());
3639 for (
const DrawingInfo &drawing_info : drawings) {
3640 const Layer &layer = grease_pencil.layer(drawing_info.layer_index);
3641 if (layer.is_locked()) {
3648 if (!ed::curves::has_anything_selected(curves)) {
3653 const IndexMask selected_points = ed::curves::retrieve_selected_points(curves,
3654 selected_points_memory);
3660 r_centroid += pos_world;
3663 num_selected += selected_points.
size();
3665 if (num_selected == 0) {
3666 r_min = r_max =
float3(0.0f);
3670 r_centroid /= num_selected;
3681 float3 centroid, points_min, points_max;
3683 scene,
object, grease_pencil, centroid, points_min, points_max))
3711 ot->
name =
"Snap Cursor to Selected Points";
3712 ot->
idname =
"GREASE_PENCIL_OT_snap_cursor_to_selected";
3713 ot->
description =
"Snap cursor to center of selected points";
3737 strokemat4x3[2][2] = 0.0f;
3738 strokemat4x3[3][2] = 1.0f;
3740 return strokemat4x3;
3750 std::atomic<bool> changed =
false;
3754 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
3755 *
object,
info.drawing,
info.layer_index, memory);
3766 const float2 screen_direction = screen_end - screen_start;
3767 const float2 screen_tangent = screen_start +
float2(-screen_direction[1], screen_direction[0]);
3774 "material_index", bke::AttrDomain::Curve, 0);
3779 const int material_index = materials[curve_i];
3782 material_index + 1);
3793 positions[points_by_curve[curve_i].first()]);
3806 const float3 origin = start;
3812 if (
math::dot(tangent - start, v_dir) < 0.0f) {
3820 float3x2 offset_matrix = float3x2::identity();
3824 offset_matrix *= 0.5f;
3825 offset_matrix[2] +=
float2(0.5f, 0.5f);
3829 offset_matrix[2] -=
float2(0.5f, 0.5f);
3832 offset_matrix = texture_rotation * offset_matrix;
3833 offset_matrix[2] -= texture_offset;
3836 layer_space_to_world_space;
3839 info.drawing.set_texture_matrices(texture_matrices, strokes);
3841 changed.store(
true, std::memory_order_relaxed);
3862 ret &= ~OPERATOR_RUNNING_MODAL;
3892 ot->
name =
"Texture Gradient";
3893 ot->
idname =
"GREASE_PENCIL_OT_texture_gradient";
3894 ot->
description =
"Draw a line to set the fill material gradient for the selected strokes";
3924 bool changed =
false;
3929 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
3930 *
object,
info.drawing,
info.layer_index, memory);
3936 options.convert_bezier_handles_to_poly_points = use_handles;
3937 options.convert_bezier_handles_to_catmull_rom_points = use_handles;
3938 options.keep_bezier_shape_as_nurbs = use_handles;
3939 options.keep_catmull_rom_shape_as_nurbs = use_handles;
3941 curves = geometry::convert_curves(curves, strokes, dst_type, {},
options);
3957 ot->
name =
"Set Curve Type";
3958 ot->
idname =
"GREASE_PENCIL_OT_set_curve_type";
3974 "Take handle information into account in the conversion");
3991 bool changed =
false;
3999 const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_strokes(
4000 *
object,
info.drawing,
info.layer_index, memory);
4006 ".selection", bke::AttrDomain::Point,
true);
4008 ".selection_handle_left", bke::AttrDomain::Point,
true);
4010 ".selection_handle_right", bke::AttrDomain::Point,
true);
4016 const IndexRange points = points_by_curve[curve_i];
4017 for (
const int point_i : points) {
4018 if (selection_left[point_i] || selection[point_i]) {
4019 handle_types_left[point_i] =
int8_t(dst_handle_type);
4021 if (selection_right[point_i] || selection[point_i]) {
4022 handle_types_right[point_i] =
int8_t(dst_handle_type);
4029 info.drawing.tag_topology_changed();
4044 ot->
name =
"Set Handle Type";
4045 ot->
idname =
"GREASE_PENCIL_OT_set_handle_type";
4072 bool changed =
false;
4077 const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
4078 *
object,
info.drawing,
info.layer_index, memory);
4088 info.drawing.tag_topology_changed();
4102 ot->
name =
"Set Curve Resolution";
4103 ot->
idname =
"GREASE_PENCIL_OT_set_curve_resolution";
4117 "The resolution to use for each curve segment",
4134 bool changed =
false;
4140 const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
4141 *
object,
info.drawing,
info.layer_index, memory);
4146 if (attributes.
contains(
"uv_rotation")) {
4148 attributes.
remove(
"uv_rotation");
4153 index_mask::masked_fill(uv_rotations.
span, 0.0f, editable_strokes);
4158 if (attributes.
contains(
"uv_translation")) {
4160 attributes.
remove(
"uv_translation");
4165 index_mask::masked_fill(uv_translations.
span,
float2(0.0f, 0.0f), editable_strokes);
4166 uv_translations.
finish();
4170 if (attributes.
contains(
"uv_scale")) {
4172 attributes.
remove(
"uv_scale");
4177 index_mask::masked_fill(uv_scales.
span,
float2(1.0f, 1.0f), editable_strokes);
4182 if (attributes.
contains(
"uv_shear")) {
4184 attributes.
remove(
"uv_shear");
4189 index_mask::masked_fill(uv_shears.
span, 0.0f, editable_strokes);
4194 info.drawing.tag_positions_changed();
4210 ot->
idname =
"GREASE_PENCIL_OT_reset_uvs";
4211 ot->
description =
"Reset UV transformation to default values";
4225 std::atomic<bool> changed =
false;
4232 object,
info.drawing,
info.layer_index, memory);
4238 info.drawing.strokes_for_write() = ed::curves::split_points(
info.drawing.strokes(),
4240 info.drawing.tag_topology_changed();
4241 changed.store(
true, std::memory_order_relaxed);
4256 ot->
name =
"Split stroke";
4257 ot->
idname =
"GREASE_PENCIL_OT_stroke_split";
4284 std::atomic<bool> changed =
false;
4286 if (mode == RemoveFillGuidesMode::ActiveFrame) {
4287 for (
const int layer_i : grease_pencil.layers().index_range()) {
4288 const Layer &layer = grease_pencil.layer(layer_i);
4289 if (!layer.is_editable()) {
4292 if (
Drawing *drawing = grease_pencil.get_editable_drawing_at(layer,
scene.
r.
cfra)) {
4297 else if (mode == RemoveFillGuidesMode::AllFrames) {
4298 for (
const int layer_i : grease_pencil.layers().index_range()) {
4299 const Layer &layer = grease_pencil.layer(layer_i);
4300 if (!layer.is_editable()) {
4304 if (
Drawing *drawing = grease_pencil.get_editable_drawing_at(layer, frame_number)) {
4305 drawings.
append({*drawing, layer_i, frame_number, 1.0f});
4311 if (ed::greasepencil::remove_fill_guides(
info.drawing.strokes_for_write())) {
4312 info.drawing.tag_topology_changed();
4313 changed.store(true, std::memory_order_relaxed);
4329 {int(RemoveFillGuidesMode::ActiveFrame),
"ACTIVE_FRAME", 0,
"Active Frame",
""},
4330 {int(RemoveFillGuidesMode::AllFrames),
"ALL_FRAMES", 0,
"All Frames",
""},
4331 {0,
nullptr, 0,
nullptr,
nullptr},
4335 ot->
name =
"Remove Fill Guides";
4336 ot->
idname =
"GREASE_PENCIL_OT_remove_fill_guides";
4337 ot->
description =
"Remove all the strokes that were created from the fill tool as guides";
4346 ot->
srna,
"mode", rna_mode_items,
int(RemoveFillGuidesMode::AllFrames),
"Mode",
"");
4363 {int(OutlineMode::View),
"VIEW", 0,
"View",
""},
4364 {int(OutlineMode::Front),
"FRONT", 0,
"Front",
""},
4365 {int(OutlineMode::Side),
"SIDE", 0,
"Side",
""},
4366 {int(OutlineMode::Top),
"TOP", 0,
"Top",
""},
4367 {int(OutlineMode::Cursor),
"CURSOR", 0,
"Cursor",
""},
4368 {int(OutlineMode::Camera),
"CAMERA", 0,
"Camera",
""},
4369 {0,
nullptr, 0,
nullptr,
nullptr},
4382 const int corner_subdivisions =
RNA_int_get(op->
ptr,
"corner_subdivisions");
4383 const float outline_offset = radius * offset_factor;
4384 const int mat_nr = -1;
4390 case OutlineMode::View: {
4395 case OutlineMode::Front:
4396 viewinv =
float4x4({1.0f, 0.0f, 0.0f, 0.0f},
4397 {0.0f, 0.0f, 1.0f, 0.0f},
4398 {0.0f, 1.0f, 0.0f, 0.0f},
4399 {0.0f, 0.0f, 0.0f, 1.0f});
4401 case OutlineMode::Side:
4402 viewinv =
float4x4({0.0f, 0.0f, 1.0f, 0.0f},
4403 {0.0f, 1.0f, 0.0f, 0.0f},
4404 {1.0f, 0.0f, 0.0f, 0.0f},
4405 {0.0f, 0.0f, 0.0f, 1.0f});
4407 case OutlineMode::Top:
4410 case OutlineMode::Cursor: {
4414 case OutlineMode::Camera:
4422 bool changed =
false;
4426 const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
4427 *
object,
info.drawing,
info.layer_index, memory);
4432 const Layer &layer = grease_pencil.layer(
info.layer_index);
4438 corner_subdivisions,
4443 info.drawing.strokes_for_write().remove_curves(editable_strokes, {});
4446 Curves *strokes = bke::curves_new_nomain(std::move(outline));
4448 Curves *other_curves = bke::curves_new_nomain(std::move(
info.drawing.strokes_for_write()));
4449 const std::array<bke::GeometrySet, 2> geometry_sets = {
4450 bke::GeometrySet::from_curves(other_curves), bke::GeometrySet::from_curves(strokes)};
4452 info.drawing.strokes_for_write() = std::move(
4453 geometry::join_geometries(geometry_sets, {}).get_curves_for_write()->geometry.wrap());
4455 info.drawing.tag_topology_changed();
4471 ot->
idname =
"GREASE_PENCIL_OT_outline";
4485 ot->
srna,
"offset_factor", -1.0f, -1.0f, 1.0f,
"Offset Factor",
"", -1.0f, 1.0f);
4486 RNA_def_int(
ot->
srna,
"corner_subdivisions", 2, 0, 10,
"Corner Subdivisions",
"", 0, 5);
4497 const float threshold)
4502 return geometry::fit_poly_to_bezier_curves(
4503 curves, selection, thresholds, corners, geometry::FitMethod::Refit, {});
4508 const float threshold)
4514 const IndexMask non_catmull_rom_curves_selection =
4518 curves = geometry::resample_to_evaluated(curves, non_catmull_rom_curves_selection);
4523 const IndexMask points_to_remove = geometry::simplify_curve_attribute(
4525 non_catmull_rom_curves_selection,
4534 options.convert_bezier_handles_to_poly_points =
false;
4535 options.convert_bezier_handles_to_catmull_rom_points =
false;
4536 options.keep_bezier_shape_as_nurbs =
true;
4537 options.keep_catmull_rom_shape_as_nurbs =
true;
4538 curves = geometry::convert_curves(
4548 const IndexMask non_poly_curves_selection = curves
4553 curves = geometry::resample_to_evaluated(curves, non_poly_curves_selection);
4558 const float threshold)
4566 if (!poly_curves_selection.
is_empty()) {
4571 options.convert_bezier_handles_to_poly_points =
false;
4572 options.convert_bezier_handles_to_catmull_rom_points =
false;
4573 options.keep_bezier_shape_as_nurbs =
true;
4574 options.keep_catmull_rom_shape_as_nurbs =
true;
4580 const float threshold)
4589 if (!poly_curves_selection.
is_empty()) {
4594 options.convert_bezier_handles_to_poly_points =
false;
4595 options.convert_bezier_handles_to_catmull_rom_points =
false;
4596 options.keep_bezier_shape_as_nurbs =
true;
4597 options.keep_catmull_rom_shape_as_nurbs =
true;
4610 std::atomic<bool> changed =
false;
4615 const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
4616 *
object,
info.drawing,
info.layer_index, memory);
4636 info.drawing.tag_topology_changed();
4637 changed.store(
true, std::memory_order_relaxed);
4671 ot->
name =
"Convert Curve Type";
4672 ot->
idname =
"GREASE_PENCIL_OT_convert_curve_type";
4693 "The distance that the resulting points are allowed to be within",
4760 Layer &layer_dst = grease_pencil_dst.add_layer(group_dst, layer_src.name());
4783 switch (child->type) {
4786 Layer &layer_dst =
copy_layer(grease_pencil_dst, group_dst, layer_src);
4787 layer_name_map.
add_new(layer_src.name(), layer_dst.name());
4817 for (
const int i : material_index_map.
index_range()) {
4823 material_index_map[i] = 0;
4826 return material_index_map;
4838 for (const int curve_i : range) {
4839 material_writer.span[curve_i] = material_index_map[material_writer.span[curve_i]];
4842 material_writer.
finish();
4847 const ListBase &vertex_group_names)
4856 return vertex_group_map;
4863 STRNCPY(dg->name, vertex_group_map.
lookup(dg->name).c_str());
4887 const int orig_layers_num = grease_pencil_dst.layers().size();
4900 const IndexRange new_drawings_dst = IndexRange::from_begin_size(
4902 const IndexRange new_drawings_src = IndexRange::from_begin_size(
4905 copy_drawing_array(grease_pencil_dst.drawings(), new_drawings.
slice(new_drawings_dst));
4906 copy_drawing_array(grease_pencil_src.drawings(), new_drawings.
slice(new_drawings_src));
4909 grease_pencil_dst.resize_drawings(0);
4917 grease_pencil_dst.root_group(),
4918 grease_pencil_src.root_group(),
4926 grease_pencil_dst.layers().size());
4931 grease_pencil_src.layers().size());
4934 for (
const int layer_index : grease_pencil_dst.layers().index_range()) {
4935 Layer &layer = *grease_pencil_dst.layers_for_write()[layer_index];
4936 const bool is_orig_layer = (layer_index < orig_layers_num);
4941 if (!is_orig_layer) {
4945 if (new_mask_name) {
4953 drawing_index = new_drawings_src[drawing_index];
4978 if (!is_orig_layer) {
4987 if (
id == &grease_pencil_src.
id && fcu->
rna_path && strstr(fcu->
rna_path,
"layers[")) {
4989 for (auto [name_src, name_dst] : layer_name_map.items()) {
4990 if (name_dst != name_src) {
4991 const char *old_path = fcu->rna_path;
4992 fcu->rna_path = BKE_animsys_fix_rna_path_rename(
4993 id, fcu->rna_path,
"layers", name_src.c_str(), name_dst.c_str(), 0, 0, false);
4994 if (old_path != fcu->rna_path) {
5003 LISTBASE_FOREACH (DriverVar *, dvar, &fcu->driver->variables) {
5005 DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
5006 if (dtar->id != &grease_pencil_src.id) {
5009 dtar->id = &grease_pencil_dst.id;
5011 if (dtar->rna_path && strstr(dtar->rna_path,
"layers[")) {
5012 for (auto [name_src, name_dst] : layer_name_map.items()) {
5013 if (name_dst != name_src) {
5014 const char *old_path = fcu->rna_path;
5015 dtar->rna_path = BKE_animsys_fix_rna_path_rename(
5016 id, dtar->rna_path,
"layers", name_src.c_str(), name_dst.c_str(), 0, 0, false);
5017 if (old_path != dtar->rna_path) {
5024 DRIVER_TARGETS_LOOPER_END;
5031 if (ob_dst.adt ==
nullptr) {
5038 if (ob_dst.adt->action) {
5042 if (grease_pencil_src.adt) {
5043 if (grease_pencil_dst.adt ==
nullptr) {
5051 if (grease_pencil_dst.adt->action) {
5072 if (ob_iter == ob_active) {
5084 Object *ob_dst = ob_active;
5089 *ob_dst, materials);
void BKE_animdata_merge_copy(Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
AnimData * BKE_animdata_copy(Main *bmain, AnimData *adt, int flag)
void BKE_fcurves_main_cb(struct Main *bmain, blender::FunctionRef< void(ID *, FCurve *)> func)
#define CTX_DATA_BEGIN(C, Type, instance, member)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
bool CustomData_merge_layout(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
Low-level operations for grease pencil.
void BKE_grease_pencil_copy_parameters(const GreasePencil &src, GreasePencil &dst)
Material * BKE_grease_pencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
GreasePencil * BKE_grease_pencil_add(Main *bmain, const char *name)
void BKE_grease_pencil_copy_layer_parameters(const blender::bke::greasepencil::Layer &src, blender::bke::greasepencil::Layer &dst)
void BKE_grease_pencil_copy_layer_group_parameters(const blender::bke::greasepencil::LayerGroup &src, blender::bke::greasepencil::LayerGroup &dst)
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
General operations, lookup, etc. for materials.
short * BKE_object_material_len_p(Object *ob)
MaterialGPencilStyle * BKE_gpencil_material_settings(Object *ob, short act)
void BKE_object_material_array_assign(Main *bmain, Object *ob, Material ***matar, int totcol, bool to_object_only)
bool BKE_object_material_slot_used(Object *object, short actcol)
int BKE_object_material_ensure(Main *bmain, Object *ob, Material *material)
Material * BKE_object_material_get(Object *ob, short act)
int BKE_object_material_index_get(Object *ob, const Material *ma)
Material *** BKE_object_material_array_p(Object *ob)
bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
#define BLI_SCOPED_DEFER(function_to_defer)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * STRNCPY(char(&dst)[N], const char *src)
#define BLT_I18NCONTEXT_ID_GPENCIL
#define BLT_I18NCONTEXT_ID_MOVIECLIP
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
float DEG_get_ctime(const Depsgraph *graph)
T * DEG_get_original(T *id)
@ ID_RECALC_ANIMATION_NO_FLUSH
@ NURBS_KNOT_MODE_ENDPOINT
@ GP_STROKE_CAP_TYPE_FLAT
@ GP_STROKE_CAP_TYPE_ROUND
@ GP_MATERIAL_GRADIENT_RADIAL
Object is a sort of wrapper for general info.
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CENTER_MEDIAN
@ V3D_AROUND_LOCAL_ORIGINS
bool ED_view3d_win_to_ray_clipped(Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_normal[3], bool do_clip_planes)
float ED_view3d_grid_view_scale(const Scene *scene, const View3D *v3d, const ARegion *region, const char **r_grid_unit)
bool ED_view3d_win_to_3d_on_plane(const ARegion *region, const float plane[4], const float mval[2], bool do_clip, float r_out[3])
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
static void View(GHOST_IWindow *window, bool stereo, int eye=0)
#define RNA_ENUM_ITEM_SEPR
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
IndexRange index_range() const
void copy_from(GSpan values)
constexpr int64_t first() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr bool contains(int64_t value) const
constexpr IndexRange drop_front(int64_t n) const
const Value * lookup_ptr(const Key &key) const
Value & lookup_or_add_default(const Key &key)
bool add(const Key &key, const Value &value)
const Value & lookup(const Key &key) const
Value lookup_default(const Key &key, const Value &default_value) const
void add_new(const Key &key, const Value &value)
KeyIterator keys() const &
ItemIterator items() const &
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan drop_back(const int64_t n) const
constexpr void fill(const T &value) const
constexpr MutableSpan drop_front(const int64_t n) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool contains(const T &value) const
constexpr const char * c_str() const
void materialize(MutableSpan< T > r_span) const
int64_t index_of_or_add(const Key &key)
void append(const T &value)
void insert(const int64_t insert_index, const T &value)
IndexRange index_range() const
MutableSpan< T > as_mutable_span()
Span< T > as_span() const
bool contains(StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
void reverse_curves(const IndexMask &curves_to_reverse)
MutableSpan< float3 > positions_for_write()
Array< int > point_to_curve_map() const
OffsetIndices< int > points_by_curve() const
MutableSpan< int8_t > handle_types_right_for_write()
IndexRange curves_range() const
void update_curve_types()
MutableSpan< int > resolution_for_write()
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
IndexRange points_range() const
VArray< int8_t > nurbs_knots_modes() const
Span< float3 > positions() const
MutableSpan< float > radius_for_write()
bool has_curve_with_type(CurveType type) const
void tag_topology_changed()
void remove_curves(const IndexMask &curves_to_delete, const AttributeFilter &attribute_filter)
AttributeAccessor attributes() const
float evaluated_length_total_for_curve(int curve_index, bool cyclic) const
IndexMask indices_for_curve_type(CurveType type, IndexMaskMemory &memory) const
bool is_single_type(CurveType type) const
MutableSpan< int > offsets_for_write()
void remove_points(const IndexMask &points_to_delete, const AttributeFilter &attribute_filter)
bool nurbs_has_custom_knots() const
void transform(const float4x4 &matrix)
void ensure_evaluated_lengths() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
void calculate_bezier_auto_handles()
MutableSpan< bool > cyclic_for_write()
MutableSpan< int8_t > handle_types_left_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_topology_changed()
float4x4 to_world_space(const Object &object) const
const Map< FramesMapKeyT, GreasePencilFrame > & frames() const
void tag_frames_map_changed()
std::optional< int > start_frame_at(int frame_number) const
float4x4 to_object_space(const Object &object) const
Map< FramesMapKeyT, GreasePencilFrame > & frames_for_write()
const Layer & as_layer() const
float3 reproject(float3 pos) const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
void to_indices(MutableSpan< T > r_indices) const
IndexMask slice_content(IndexRange range) const
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
void foreach_index_optimized(Fn &&fn) const
static IndexMask from_ranges(OffsetIndices< T > offsets, const IndexMask &mask, IndexMaskMemory &memory)
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
CCL_NAMESPACE_BEGIN struct Options options
const Depsgraph * depsgraph
static float normals[][3]
VecBase< float, 2 > float2
VecBase< float, 4 > float4
VecBase< float, 3 > float3
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
void ED_operatortypes_grease_pencil_edit()
wmOperatorStatus ED_grease_pencil_join_objects_exec(bContext *C, wmOperator *op)
blender::bke::AttrDomain ED_grease_pencil_edit_selection_domain_get(const ToolSettings *tool_settings)
void GREASE_PENCIL_OT_stroke_trim(wmOperatorType *ot)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void invert_booleans(MutableSpan< bool > span)
CurvesGeometry curves_copy_point_selection(const CurvesGeometry &curves, const IndexMask &points_to_copy, const AttributeFilter &attribute_filter)
static void convert_to_nurbs(bke::CurvesGeometry &curves, const IndexMask &selection, const float threshold)
IndexMask retrieve_editable_and_selected_elements(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, const bke::AttrDomain selection_domain, IndexMaskMemory &memory)
static void GREASE_PENCIL_OT_extrude(wmOperatorType *ot)
static bke::GeometrySet join_geometries_with_transforms(Span< bke::GeometrySet > geometries, const VArray< float4x4 > &transforms)
static void GREASE_PENCIL_OT_texture_gradient(wmOperatorType *ot)
bool active_grease_pencil_poll(bContext *C)
IndexMask retrieve_editable_and_selected_strokes(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static wmOperatorStatus grease_pencil_convert_curve_type_exec(bContext *C, wmOperator *op)
static wmOperatorStatus grease_pencil_set_active_material_exec(bContext *C, wmOperator *)
static void GREASE_PENCIL_OT_caps_set(wmOperatorType *ot)
blender::bke::CurvesGeometry curves_merge_by_distance(const bke::CurvesGeometry &src_curves, const float merge_distance, const IndexMask &selection, const bke::AttributeFilter &attribute_filter)
static bke::greasepencil::Layer & copy_layer(GreasePencil &grease_pencil_dst, bke::greasepencil::LayerGroup &group_dst, const bke::greasepencil::Layer &layer_src)
static void grease_pencil_reproject_ui(bContext *, wmOperator *op)
static bke::greasepencil::Layer & find_or_create_layer_in_dst_by_name(const int layer_index, const GreasePencil &grease_pencil_src, GreasePencil &grease_pencil_dst, Vector< int > &src_to_dst_layer_indices)
static wmOperatorStatus grease_pencil_delete_exec(bContext *C, wmOperator *)
static wmOperatorStatus grease_pencil_stroke_material_set_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_stroke_simplify(wmOperatorType *ot)
static void convert_to_catmull_rom(bke::CurvesGeometry &curves, const IndexMask &selection, const float threshold)
static wmOperatorStatus grease_pencil_set_curve_type_exec(bContext *C, wmOperator *op)
blender::Mutex grease_pencil_clipboard_lock
static wmOperatorStatus grease_pencil_extrude_exec(bContext *C, wmOperator *)
static wmOperatorStatus grease_pencil_outline_exec(bContext *C, wmOperator *op)
static void join_object_with_active(Main &bmain, Object &ob_src, Object &ob_dst, VectorSet< Material * > &materials)
IndexMask retrieve_editable_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static wmOperatorStatus grease_pencil_stroke_smooth_exec(bContext *C, wmOperator *op)
static wmOperatorStatus grease_pencil_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool ensure_active_keyframe(const Scene &scene, GreasePencil &grease_pencil, bke::greasepencil::Layer &layer, const bool duplicate_previous_key, bool &r_inserted_keyframe)
static void convert_to_bezier(bke::CurvesGeometry &curves, const IndexMask &selection, const float threshold)
static wmOperatorStatus grease_pencil_duplicate_exec(bContext *C, wmOperator *)
static wmOperatorStatus grease_pencil_dissolve_exec(bContext *C, wmOperator *op)
static void convert_to_poly(bke::CurvesGeometry &curves, const IndexMask &selection)
static bke::CurvesGeometry set_start_point(const bke::CurvesGeometry &curves, const IndexMask &mask)
static float calculate_radius_projection_factor(const RegionView3D *rv3d, const float3 &old_pos, const float3 &new_pos)
static wmOperatorStatus grease_pencil_texture_gradient_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void GREASE_PENCIL_OT_set_curve_type(wmOperatorType *ot)
static void toggle_caps(MutableSpan< int8_t > caps, const IndexMask &strokes)
static void GREASE_PENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_copy_strokes_exec(bContext *C, wmOperator *op)
static void grease_pencil_convert_curve_type_ui(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_outline_modes[]
static Array< int > clipboard_materials_remap(Main &bmain, Object &object)
static wmOperatorStatus grease_pencil_stroke_merge_by_distance_exec(bContext *C, wmOperator *op)
static bool grease_pencil_paste_strokes_poll(bContext *C)
bool editable_grease_pencil_point_selection_poll(bContext *C)
static bke::CurvesGeometry extrude_grease_pencil_curves(const bke::CurvesGeometry &src, const IndexMask &points_to_extrude)
static void GREASE_PENCIL_OT_set_start_point(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_reproject_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_delete(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_stroke_switch_direction_exec(bContext *C, wmOperator *)
static IndexMask simplify_fixed(const bke::CurvesGeometry &curves, const int step, const IndexMask &stroke_selection, IndexMaskMemory &memory)
bool editable_grease_pencil_with_region_view3d_poll(bContext *C)
static wmOperatorStatus grease_pencil_snap_to_cursor_exec(bContext *C, wmOperator *op)
static bool grease_pencil_separate_material(bContext &C, Main &bmain, Scene &scene, ViewLayer &view_layer, Base &base_prev, Object &object_src)
static IndexRange clipboard_paste_strokes_ex(Main &bmain, Object &object, const bke::CurvesGeometry &curves_to_paste, const float4x4 &object_to_paste_layer, const float4x4 &clipboard_to_world, const bool keep_world_transform, const bool paste_back, bke::greasepencil::Drawing &drawing)
static wmOperatorStatus grease_pencil_set_handle_type_exec(bContext *C, wmOperator *op)
static void remove_unused_materials(Main *bmain, Object *object)
static void GREASE_PENCIL_OT_stroke_switch_direction(wmOperatorType *ot)
Vector< DrawingInfo > retrieve_visible_drawings(const Scene &scene, const GreasePencil &grease_pencil, const bool do_onion_skinning)
static void GREASE_PENCIL_OT_set_active_material(wmOperatorType *ot)
static Clipboard & ensure_grease_pencil_clipboard()
static void GREASE_PENCIL_OT_outline(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_set_material_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_simplify_modes[]
static void remap_material_indices(bke::greasepencil::Drawing &drawing, const Span< int > material_index_map)
IndexMask retrieve_editable_strokes_by_material(Object &object, const bke::greasepencil::Drawing &drawing, const int mat_i, IndexMaskMemory &memory)
static wmOperatorStatus grease_pencil_reset_uvs_exec(bContext *C, wmOperator *)
static wmOperatorStatus grease_pencil_clean_loose_exec(bContext *C, wmOperator *op)
static wmOperatorStatus grease_pencil_set_curve_resolution_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_separate_modes[]
static void GREASE_PENCIL_OT_copy(wmOperatorType *ot)
static void GREASE_PENCIL_OT_separate(wmOperatorType *ot)
static bool grease_pencil_separate_layer(bContext &C, Main &bmain, Scene &scene, ViewLayer &view_layer, Base &base_prev, Object &object_src)
static void GREASE_PENCIL_OT_delete_frame(wmOperatorType *ot)
static bke::greasepencil::LayerGroup & copy_layer_group_recursive(GreasePencil &grease_pencil_dst, bke::greasepencil::LayerGroup &parent_dst, const bke::greasepencil::LayerGroup &group_src, Map< StringRefNull, StringRefNull > &layer_name_map)
static void GREASE_PENCIL_OT_set_curve_resolution(wmOperatorType *ot)
static float4x3 expand_4x2_mat(float4x2 strokemat)
static wmOperatorStatus grease_pencil_cyclical_set_exec(bContext *C, wmOperator *op)
bool editable_grease_pencil_poll(bContext *C)
static void remap_vertex_groups(bke::greasepencil::Drawing &drawing, const Map< StringRefNull, StringRefNull > &vertex_group_map)
static wmOperatorStatus grease_pencil_set_start_point_exec(bContext *C, wmOperator *)
static void GREASE_PENCIL_OT_set_uniform_opacity(wmOperatorType *ot)
static Array< int > add_materials_to_map(Object &object, VectorSet< Material * > &materials)
static void GREASE_PENCIL_OT_move_to_layer(wmOperatorType *ot)
static void GREASE_PENCIL_OT_snap_to_grid(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_remove_fill_guides_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_clean_loose(wmOperatorType *ot)
static void GREASE_PENCIL_OT_stroke_smooth(wmOperatorType *ot)
IndexMask retrieve_editable_and_selected_points(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static wmOperatorStatus grease_pencil_move_to_layer_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_remove_fill_guides(wmOperatorType *ot)
static void GREASE_PENCIL_OT_stroke_split(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_snap_cursor_to_sel_exec(bContext *C, wmOperator *)
static void GREASE_PENCIL_OT_set_handle_type(wmOperatorType *ot)
static void GREASE_PENCIL_OT_stroke_reorder(wmOperatorType *ot)
static void GREASE_PENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot)
static bool grease_pencil_snap_compute_centroid(const Scene &scene, const Object &object, const GreasePencil &grease_pencil, float3 &r_centroid, float3 &r_min, float3 &r_max)
static const EnumPropertyItem prop_dissolve_types[]
static wmOperatorStatus grease_pencil_set_uniform_opacity_exec(bContext *C, wmOperator *op)
Vector< MutableDrawingInfo > retrieve_editable_drawings_from_layer(const Scene &scene, GreasePencil &grease_pencil, const blender::bke::greasepencil::Layer &layer)
static wmOperatorStatus grease_pencil_clean_loose_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void GREASE_PENCIL_OT_stroke_subdivide(wmOperatorType *ot)
static bool grease_pencil_snap_poll(bContext *C)
static wmOperatorStatus grease_pencil_caps_set_exec(bContext *C, wmOperator *op)
static wmOperatorStatus gpencil_stroke_subdivide_exec(bContext *C, wmOperator *op)
IndexRange paste_all_strokes_from_clipboard(Main &bmain, Object &object, const float4x4 &object_to_paste_layer, const bool keep_world_transform, const bool paste_back, bke::greasepencil::Drawing &drawing)
static wmOperatorStatus grease_pencil_paste_strokes_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_reproject(wmOperatorType *ot)
static Map< StringRefNull, StringRefNull > add_vertex_groups(Object &object, GreasePencil &grease_pencil, const ListBase &vertex_group_names)
static bke::CurvesGeometry subdivide_last_segement(const bke::CurvesGeometry &curves, const IndexMask &strokes)
static void copy_layer_group_content(GreasePencil &grease_pencil_dst, bke::greasepencil::LayerGroup &group_dst, const bke::greasepencil::LayerGroup &group_src, Map< StringRefNull, StringRefNull > &layer_name_map)
static wmOperatorStatus grease_pencil_texture_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void GREASE_PENCIL_OT_convert_curve_type(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_snap_to_grid_exec(bContext *C, wmOperator *)
static void GREASE_PENCIL_OT_snap_to_cursor(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_set_uniform_thickness_exec(bContext *C, wmOperator *op)
IndexMask retrieve_editable_strokes(Object &object, const bke::greasepencil::Drawing &drawing, int layer_index, IndexMaskMemory &memory)
static wmOperatorStatus grease_pencil_stroke_split_exec(bContext *C, wmOperator *)
Vector< MutableDrawingInfo > retrieve_editable_drawings(const Scene &scene, GreasePencil &grease_pencil)
static struct blender::ed::greasepencil::Clipboard * grease_pencil_clipboard
static void GREASE_PENCIL_OT_stroke_material_set(wmOperatorType *ot)
static void GREASE_PENCIL_OT_set_uniform_thickness(wmOperatorType *ot)
static void GREASE_PENCIL_OT_reset_uvs(wmOperatorType *ot)
static wmOperatorStatus grease_pencil_texture_gradient_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_duplicate(wmOperatorType *ot)
static const EnumPropertyItem * material_enum_itemf(bContext *C, PointerRNA *, PropertyRNA *, bool *r_free)
static Object * duplicate_grease_pencil_object(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_prev, const GreasePencil &grease_pencil_src)
static void GREASE_PENCIL_OT_paste(wmOperatorType *ot)
static bke::GeometrySet join_geometries_with_transform(Span< bke::GeometrySet > geometries, const float4x4 &transform)
static const bke::CurvesGeometry fit_poly_curves(bke::CurvesGeometry &curves, const IndexMask &selection, const float threshold)
static void GREASE_PENCIL_OT_cyclical_set(wmOperatorType *ot)
Array< Vector< MutableDrawingInfo > > retrieve_editable_drawings_grouped_per_frame(const Scene &scene, GreasePencil &grease_pencil)
static wmOperatorStatus grease_pencil_stroke_simplify_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_cyclical_types[]
static wmOperatorStatus grease_pencil_delete_frame_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_dissolve(wmOperatorType *ot)
bool active_grease_pencil_layer_poll(bContext *C)
static wmOperatorStatus grease_pencil_separate_exec(bContext *C, wmOperator *op)
static bool grease_pencil_separate_selected(bContext &C, Main &bmain, Scene &scene, ViewLayer &view_layer, Base &base_prev, Object &object_src)
bke::CurvesGeometry create_curves_outline(const bke::greasepencil::Drawing &drawing, const IndexMask &strokes, const float4x4 &transform, const int corner_subdivisions, const float outline_radius, const float outline_offset, const int material_index)
static wmOperatorStatus grease_pencil_stroke_reorder_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_greasepencil_deleteframe_types[]
static void grease_pencil_simplify_ui(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_set_material(wmOperatorType *ot)
static Array< bool > get_points_to_dissolve(bke::CurvesGeometry &curves, const IndexMask &mask, const DissolveMode mode)
static Array< int > get_reordered_indices(const IndexRange universe, const IndexMask &selected, const ReorderDirection direction)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
bke::CurvesGeometry remove_points_and_split(const bke::CurvesGeometry &curves, const IndexMask &mask)
void smooth_curve_attribute(const IndexMask &curves_to_smooth, const OffsetIndices< int > points_by_curve, const VArray< bool > &point_selection, const VArray< bool > &cyclic, int iterations, float influence, bool smooth_ends, bool keep_shape, GMutableSpan attribute_data)
IndexMask simplify_curve_attribute(const Span< float3 > positions, const IndexMask &curves_selection, const OffsetIndices< int > points_by_curve, const VArray< bool > &cyclic, float epsilon, GSpan attribute_data, IndexMaskMemory &memory)
CurvesGeometry resample_to_length(const CurvesGeometry &src_curves, const IndexMask &selection, const VArray< float > &sample_lengths, const ResampleCurvesOutputAttributeIDs &output_ids={}, bool keep_last_segment=false)
T length_squared(const VecBase< T, Size > &a)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
T pow(const T &x, const T &power)
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
T midpoint(const T &a, const T &b)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
void min_max(const T &value, T &min, T &max)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
MatT from_rotation(const RotationT &rotation)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for_each(Range &&range, const Function &function)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
float wrap(float value, float max, float min)
static void unique_name(bNode *node)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const EnumPropertyItem rna_enum_curves_handle_type_items[]
const EnumPropertyItem rna_enum_curves_type_items[]
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
const EnumPropertyItem rna_enum_dummy_DEFAULT_items[]
ListBase vertex_group_names
GreasePencilLayerTreeNode base
ListBase vertex_group_names
GreasePencilDrawingBase ** drawing_array
struct ToolSettings * toolsettings
static MatBase identity()
Curves * get_curves_for_write()
const Curves * get_curves() const
MutableVArraySpan< T > span
bke::CurvesGeometry curves
Vector< std::pair< uint, int > > materials
Array< ClipboardLayer > layers
int materials_in_source_num
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void(* ui)(bContext *C, wmOperator *op)
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void(* cancel)(bContext *C, wmOperator *op)
struct ReportList * reports
struct wmOperatorType * type
void WM_cursor_wait(bool val)
void WM_menu_name_call(bContext *C, const char *menu_name, short context)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_gesture_straightline_cancel(bContext *C, wmOperator *op)
wmOperatorStatus WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
wmOperatorStatus WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)