|
30 | 30 | #include "BLI_math_vector.h" |
31 | 31 | #include "BLI_string.h" |
32 | 32 | #include "BLI_utildefines.h" |
| 33 | +#include "BLI_vector.hh" |
33 | 34 |
|
34 | 35 | #include "BKE_action.hh" |
35 | 36 | #include "BKE_armature.hh" |
36 | 37 | #include "BKE_context.hh" |
37 | 38 | #include "BKE_curve.hh" |
| 39 | +#include "BKE_curves.hh" |
38 | 40 | #include "BKE_customdata.hh" |
39 | 41 | #include "BKE_deform.hh" |
40 | 42 | #include "BKE_editmesh.hh" |
|
55 | 57 | #include "RNA_access.hh" |
56 | 58 | #include "RNA_prototypes.hh" |
57 | 59 |
|
| 60 | +#include "ED_curves.hh" |
| 61 | +#include "ED_grease_pencil.hh" |
58 | 62 | #include "ED_mesh.hh" |
59 | 63 | #include "ED_object.hh" |
60 | 64 | #include "ED_object_vgroup.hh" |
@@ -92,11 +96,21 @@ struct TransformMedian_Lattice { |
92 | 96 | float location[3], weight; |
93 | 97 | }; |
94 | 98 |
|
| 99 | +struct TransformMedian_GreasePencil { |
| 100 | + float location[3]; |
| 101 | +}; |
| 102 | + |
| 103 | +struct TransformMedian_Curves { |
| 104 | + float location[3]; |
| 105 | +}; |
| 106 | + |
95 | 107 | union TransformMedian { |
96 | 108 | TransformMedian_Generic generic; |
97 | 109 | TransformMedian_Mesh mesh; |
98 | 110 | TransformMedian_Curve curve; |
99 | 111 | TransformMedian_Lattice lattice; |
| 112 | + TransformMedian_GreasePencil grease_pencil; |
| 113 | + TransformMedian_Curves curves; |
100 | 114 | }; |
101 | 115 |
|
102 | 116 | /* temporary struct for storing transform properties */ |
@@ -293,8 +307,10 @@ static TransformProperties *v3d_transform_props_ensure(View3D *v3d) |
293 | 307 | } |
294 | 308 |
|
295 | 309 | /* is used for both read and write... */ |
296 | | -static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim) |
| 310 | +static void v3d_editvertex_buts( |
| 311 | + const bContext *C, uiLayout *layout, View3D *v3d, Object *ob, float lim) |
297 | 312 | { |
| 313 | + using namespace blender; |
298 | 314 | uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : nullptr; |
299 | 315 | TransformProperties *tfp = v3d_transform_props_ensure(v3d); |
300 | 316 | TransformMedian median_basis, ve_median_basis; |
@@ -468,6 +484,61 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float |
468 | 484 | data_ptr = RNA_pointer_create_discrete(<->id, seltype, selp); |
469 | 485 | } |
470 | 486 | } |
| 487 | + else if (ob->type == OB_GREASE_PENCIL) { |
| 488 | + using namespace blender::ed::greasepencil; |
| 489 | + using namespace ed::curves; |
| 490 | + Scene &scene = *CTX_data_scene(C); |
| 491 | + GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); |
| 492 | + blender::Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, |
| 493 | + grease_pencil); |
| 494 | + |
| 495 | + threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { |
| 496 | + const bke::CurvesGeometry &curves = info.drawing.strokes(); |
| 497 | + if (curves.is_empty()) { |
| 498 | + return; |
| 499 | + } |
| 500 | + |
| 501 | + const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves); |
| 502 | + Vector<Span<float3>> positions = get_curves_positions(curves); |
| 503 | + TransformMedian_Curves &median = median_basis.curves; |
| 504 | + for (int attribute_i : selection_names.index_range()) { |
| 505 | + IndexMaskMemory memory; |
| 506 | + const IndexMask selection = retrieve_selected_points( |
| 507 | + curves, selection_names[attribute_i], memory); |
| 508 | + if (selection.is_empty()) { |
| 509 | + continue; |
| 510 | + } |
| 511 | + |
| 512 | + tot += selection.size(); |
| 513 | + selection.foreach_index( |
| 514 | + [&](const int point) { add_v3_v3(median.location, positions[attribute_i][point]); }); |
| 515 | + } |
| 516 | + }); |
| 517 | + } |
| 518 | + else if (ob->type == OB_CURVES) { |
| 519 | + using namespace ed::curves; |
| 520 | + const Curves &curves_id = *static_cast<Curves *>(ob->data); |
| 521 | + const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); |
| 522 | + if (curves.is_empty()) { |
| 523 | + return; |
| 524 | + } |
| 525 | + |
| 526 | + const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves); |
| 527 | + const Vector<Span<float3>> positions = get_curves_positions(curves); |
| 528 | + TransformMedian_Curves &median = median_basis.curves; |
| 529 | + for (int attribute_i : selection_names.index_range()) { |
| 530 | + IndexMaskMemory memory; |
| 531 | + const IndexMask selection = retrieve_selected_points( |
| 532 | + curves, selection_names[attribute_i], memory); |
| 533 | + if (selection.is_empty()) { |
| 534 | + continue; |
| 535 | + } |
| 536 | + |
| 537 | + tot += selection.size(); |
| 538 | + selection.foreach_index( |
| 539 | + [&](const int point) { add_v3_v3(median.location, positions[attribute_i][point]); }); |
| 540 | + } |
| 541 | + } |
471 | 542 |
|
472 | 543 | if (tot == 0) { |
473 | 544 | uiDefBut( |
@@ -527,6 +598,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float |
527 | 598 | /* Curve */ |
528 | 599 | c = IFACE_("Control Point:"); |
529 | 600 | } |
| 601 | + else if (ELEM(ob->type, OB_CURVES, OB_GREASE_PENCIL)) { |
| 602 | + c = IFACE_("Point:"); |
| 603 | + } |
530 | 604 | else { |
531 | 605 | /* Mesh or lattice */ |
532 | 606 | c = IFACE_("Vertex:"); |
@@ -1168,9 +1242,70 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float |
1168 | 1242 | bp++; |
1169 | 1243 | } |
1170 | 1244 | } |
| 1245 | + else if (ob->type == OB_GREASE_PENCIL && apply_vcos) { |
| 1246 | + using namespace blender::ed::greasepencil; |
| 1247 | + using namespace ed::curves; |
| 1248 | + Scene &scene = *CTX_data_scene(C); |
| 1249 | + GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data); |
| 1250 | + blender::Vector<MutableDrawingInfo> drawings = retrieve_editable_drawings(scene, |
| 1251 | + grease_pencil); |
| 1252 | + |
| 1253 | + threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) { |
| 1254 | + bke::CurvesGeometry &curves = info.drawing.strokes_for_write(); |
| 1255 | + if (curves.is_empty()) { |
| 1256 | + return; |
| 1257 | + } |
1171 | 1258 |
|
1172 | | - // ED_undo_push(C, "Transform properties"); |
| 1259 | + TransformMedian_GreasePencil &median = median_basis.grease_pencil; |
| 1260 | + TransformMedian_GreasePencil &ve_median = ve_median_basis.grease_pencil; |
| 1261 | + IndexMaskMemory memory; |
| 1262 | + const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves); |
| 1263 | + const Vector<MutableSpan<float3>> positions = get_curves_positions_for_write(curves); |
| 1264 | + for (int attribute_i : selection_names.index_range()) { |
| 1265 | + const IndexMask selection = retrieve_selected_points( |
| 1266 | + curves, selection_names[attribute_i], memory); |
| 1267 | + if (selection.is_empty()) { |
| 1268 | + continue; |
| 1269 | + } |
| 1270 | + |
| 1271 | + selection.foreach_index([&](const int point) { |
| 1272 | + apply_raw_diff_v3( |
| 1273 | + positions[attribute_i][point], tot, ve_median.location, median.location); |
| 1274 | + }); |
| 1275 | + info.drawing.tag_positions_changed(); |
| 1276 | + } |
| 1277 | + }); |
| 1278 | + } |
| 1279 | + else if (ob->type == OB_CURVES && apply_vcos) { |
| 1280 | + using namespace ed::curves; |
| 1281 | + Curves &curves_id = *static_cast<Curves *>(ob->data); |
| 1282 | + bke::CurvesGeometry &curves = curves_id.geometry.wrap(); |
| 1283 | + if (curves.is_empty()) { |
| 1284 | + return; |
| 1285 | + } |
| 1286 | + |
| 1287 | + TransformMedian_Curves &median = median_basis.curves; |
| 1288 | + TransformMedian_Curves &ve_median = ve_median_basis.curves; |
| 1289 | + IndexMaskMemory memory; |
| 1290 | + const Span<StringRef> selection_names = get_curves_selection_attribute_names(curves); |
| 1291 | + Vector<MutableSpan<float3>> positions = get_curves_positions_for_write(curves); |
| 1292 | + for (int attribute_i : selection_names.index_range()) { |
| 1293 | + const IndexMask selection = retrieve_selected_points( |
| 1294 | + curves, selection_names[attribute_i], memory); |
| 1295 | + if (selection.is_empty()) { |
| 1296 | + continue; |
| 1297 | + } |
| 1298 | + |
| 1299 | + selection.foreach_index([&](const int point) { |
| 1300 | + apply_raw_diff_v3( |
| 1301 | + positions[attribute_i][point], tot, ve_median.location, median.location); |
| 1302 | + }); |
| 1303 | + } |
| 1304 | + curves.tag_positions_changed(); |
| 1305 | + } |
1173 | 1306 | } |
| 1307 | + |
| 1308 | + // ED_undo_push(C, "Transform properties"); |
1174 | 1309 | } |
1175 | 1310 |
|
1176 | 1311 | #undef TRANSFORM_MEDIAN_ARRAY_LEN |
@@ -1691,7 +1826,7 @@ static void do_view3d_region_buttons(bContext *C, void * /*index*/, int event) |
1691 | 1826 |
|
1692 | 1827 | case B_TRANSFORM_PANEL_MEDIAN: |
1693 | 1828 | if (ob) { |
1694 | | - v3d_editvertex_buts(nullptr, v3d, ob, 1.0); |
| 1829 | + v3d_editvertex_buts(C, nullptr, v3d, ob, 1.0); |
1695 | 1830 | DEG_id_tag_update(static_cast<ID *>(ob->data), ID_RECALC_GEOMETRY); |
1696 | 1831 | } |
1697 | 1832 | break; |
@@ -1738,7 +1873,7 @@ static void view3d_panel_transform(const bContext *C, Panel *panel) |
1738 | 1873 | } |
1739 | 1874 | else { |
1740 | 1875 | View3D *v3d = CTX_wm_view3d(C); |
1741 | | - v3d_editvertex_buts(col, v3d, ob, FLT_MAX); |
| 1876 | + v3d_editvertex_buts(C, col, v3d, ob, FLT_MAX); |
1742 | 1877 | } |
1743 | 1878 | } |
1744 | 1879 | else if (ob->mode & OB_MODE_POSE) { |
|
0 commit comments