Skip to content

Commit e64fe63

Browse files
committed
Improve Path2D debug performance
Improves Path2D node debug performance by changing the debug to use mesh and multimesh instead of slower canvas draw functions.
1 parent 8f87e60 commit e64fe63

File tree

4 files changed

+372
-73
lines changed

4 files changed

+372
-73
lines changed

editor/plugins/path_2d_editor_plugin.cpp

Lines changed: 200 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
443443
int len = curve->get_point_count();
444444
Control *vpc = canvas_item_editor->get_viewport_control();
445445

446+
debug_handle_lines.clear();
447+
debug_handle_curve_transforms.clear();
448+
debug_handle_sharp_transforms.clear();
449+
debug_handle_smooth_transforms.clear();
450+
451+
Transform2D handle_curve_transform = Transform2D().scaled(curve_handle_size * 0.5);
452+
Transform2D handle_point_transform = Transform2D().scaled(handle_size * 0.5);
453+
446454
for (int i = 0; i < len; i++) {
447455
Vector2 point = xform.xform(curve->get_point_position(i));
448456
// Determines the point icon to be used
@@ -452,34 +460,154 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
452460
Vector2 point_out = xform.xform(curve->get_point_position(i) + curve->get_point_out(i));
453461
if (point != point_out) {
454462
smooth = true;
455-
// Draw the line with a dark and light color to be visible on all backgrounds
456-
vpc->draw_line(point, point_out, Color(0, 0, 0, 0.5), Math::round(EDSCALE));
457-
vpc->draw_line(point, point_out, Color(1, 1, 1, 0.5), Math::round(EDSCALE));
458-
vpc->draw_texture_rect(curve_handle, Rect2(point_out - curve_handle_size * 0.5, curve_handle_size), false, Color(1, 1, 1, 0.75));
463+
debug_handle_lines.push_back(point);
464+
debug_handle_lines.push_back(point_out);
465+
handle_curve_transform.set_origin(point_out);
466+
debug_handle_curve_transforms.push_back(handle_curve_transform);
459467
}
460468
}
461469

462470
if (i > 0) {
463471
Vector2 point_in = xform.xform(curve->get_point_position(i) + curve->get_point_in(i));
464472
if (point != point_in) {
465473
smooth = true;
466-
// Draw the line with a dark and light color to be visible on all backgrounds
467-
vpc->draw_line(point, point_in, Color(0, 0, 0, 0.5), Math::round(EDSCALE));
468-
vpc->draw_line(point, point_in, Color(1, 1, 1, 0.5), Math::round(EDSCALE));
469-
vpc->draw_texture_rect(curve_handle, Rect2(point_in - curve_handle_size * 0.5, curve_handle_size), false, Color(1, 1, 1, 0.75));
474+
debug_handle_lines.push_back(point);
475+
debug_handle_lines.push_back(point_in);
476+
handle_curve_transform.set_origin(point_in);
477+
debug_handle_curve_transforms.push_back(handle_curve_transform);
470478
}
471479
}
472480

473-
vpc->draw_texture_rect(
474-
smooth ? path_smooth_handle : path_sharp_handle,
475-
Rect2(point - handle_size * 0.5, handle_size),
476-
false);
481+
handle_point_transform.set_origin(point);
482+
if (smooth) {
483+
debug_handle_smooth_transforms.push_back(handle_point_transform);
484+
} else {
485+
debug_handle_sharp_transforms.push_back(handle_point_transform);
486+
}
477487
}
478488

479489
if (on_edge) {
480490
Ref<Texture2D> add_handle = get_editor_theme_icon(SNAME("EditorHandleAdd"));
481491
p_overlay->draw_texture(add_handle, edge_point - add_handle->get_size() * 0.5);
482492
}
493+
494+
RenderingServer *rs = RS::get_singleton();
495+
rs->mesh_clear(debug_mesh_rid);
496+
497+
if (!debug_handle_lines.is_empty()) {
498+
Array handles_array;
499+
handles_array.resize(Mesh::ARRAY_MAX);
500+
501+
handles_array[Mesh::ARRAY_VERTEX] = Vector<Vector2>(debug_handle_lines);
502+
503+
rs->mesh_add_surface_from_arrays(debug_mesh_rid, RS::PRIMITIVE_LINES, handles_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
504+
rs->canvas_item_add_mesh(vpc->get_canvas_item(), debug_mesh_rid, Transform2D(), Color(0.5, 0.5, 0.5, 1.0));
505+
}
506+
507+
// Add texture rects multimeshes for handle vertices.
508+
509+
uint32_t handle_curve_count = debug_handle_curve_transforms.size();
510+
uint32_t handle_sharp_count = debug_handle_sharp_transforms.size();
511+
uint32_t handle_smooth_count = debug_handle_smooth_transforms.size();
512+
513+
// Add texture rects for curve handle vertices.
514+
515+
rs->multimesh_set_visible_instances(debug_handle_curve_multimesh_rid, 0);
516+
if (handle_curve_count > 0) {
517+
if (rs->multimesh_get_instance_count(debug_handle_curve_multimesh_rid) != int(handle_curve_count)) {
518+
rs->multimesh_allocate_data(debug_handle_curve_multimesh_rid, handle_curve_count, RS::MULTIMESH_TRANSFORM_2D);
519+
}
520+
521+
Vector<float> multimesh_buffer;
522+
multimesh_buffer.resize(8 * handle_curve_count);
523+
float *multimesh_buffer_ptrw = multimesh_buffer.ptrw();
524+
525+
const Transform2D *debug_handle_transforms_ptr = debug_handle_curve_transforms.ptr();
526+
527+
for (uint32_t i = 0; i < handle_curve_count; i++) {
528+
const Transform2D &handle_transform = debug_handle_transforms_ptr[i];
529+
530+
multimesh_buffer_ptrw[i * 8 + 0] = handle_transform[0][0];
531+
multimesh_buffer_ptrw[i * 8 + 1] = handle_transform[1][0];
532+
multimesh_buffer_ptrw[i * 8 + 2] = 0;
533+
multimesh_buffer_ptrw[i * 8 + 3] = handle_transform[2][0];
534+
multimesh_buffer_ptrw[i * 8 + 4] = handle_transform[0][1];
535+
multimesh_buffer_ptrw[i * 8 + 5] = handle_transform[1][1];
536+
multimesh_buffer_ptrw[i * 8 + 6] = 0;
537+
multimesh_buffer_ptrw[i * 8 + 7] = handle_transform[2][1];
538+
}
539+
540+
rs->multimesh_set_buffer(debug_handle_curve_multimesh_rid, multimesh_buffer);
541+
rs->multimesh_set_visible_instances(debug_handle_curve_multimesh_rid, handle_curve_count);
542+
543+
rs->canvas_item_add_multimesh(vpc->get_canvas_item(), debug_handle_curve_multimesh_rid, curve_handle->get_rid());
544+
}
545+
546+
// Add texture rects for sharp handle vertices.
547+
548+
rs->multimesh_set_visible_instances(debug_handle_sharp_multimesh_rid, 0);
549+
if (handle_sharp_count > 0) {
550+
if (rs->multimesh_get_instance_count(debug_handle_sharp_multimesh_rid) != int(handle_sharp_count)) {
551+
rs->multimesh_allocate_data(debug_handle_sharp_multimesh_rid, handle_sharp_count, RS::MULTIMESH_TRANSFORM_2D);
552+
}
553+
554+
Vector<float> multimesh_buffer;
555+
multimesh_buffer.resize(8 * handle_sharp_count);
556+
float *multimesh_buffer_ptrw = multimesh_buffer.ptrw();
557+
558+
const Transform2D *debug_handle_transforms_ptr = debug_handle_sharp_transforms.ptr();
559+
560+
for (uint32_t i = 0; i < handle_sharp_count; i++) {
561+
const Transform2D &handle_transform = debug_handle_transforms_ptr[i];
562+
563+
multimesh_buffer_ptrw[i * 8 + 0] = handle_transform[0][0];
564+
multimesh_buffer_ptrw[i * 8 + 1] = handle_transform[1][0];
565+
multimesh_buffer_ptrw[i * 8 + 2] = 0;
566+
multimesh_buffer_ptrw[i * 8 + 3] = handle_transform[2][0];
567+
multimesh_buffer_ptrw[i * 8 + 4] = handle_transform[0][1];
568+
multimesh_buffer_ptrw[i * 8 + 5] = handle_transform[1][1];
569+
multimesh_buffer_ptrw[i * 8 + 6] = 0;
570+
multimesh_buffer_ptrw[i * 8 + 7] = handle_transform[2][1];
571+
}
572+
573+
rs->multimesh_set_buffer(debug_handle_sharp_multimesh_rid, multimesh_buffer);
574+
rs->multimesh_set_visible_instances(debug_handle_sharp_multimesh_rid, handle_sharp_count);
575+
576+
rs->canvas_item_add_multimesh(vpc->get_canvas_item(), debug_handle_sharp_multimesh_rid, curve_handle->get_rid());
577+
}
578+
579+
// Add texture rects for smooth handle vertices.
580+
581+
rs->multimesh_set_visible_instances(debug_handle_smooth_multimesh_rid, 0);
582+
if (handle_smooth_count > 0) {
583+
if (rs->multimesh_get_instance_count(debug_handle_smooth_multimesh_rid) != int(handle_smooth_count)) {
584+
rs->multimesh_allocate_data(debug_handle_smooth_multimesh_rid, handle_smooth_count, RS::MULTIMESH_TRANSFORM_2D);
585+
}
586+
587+
Vector<float> multimesh_buffer;
588+
multimesh_buffer.resize(8 * handle_smooth_count);
589+
float *multimesh_buffer_ptrw = multimesh_buffer.ptrw();
590+
591+
const Transform2D *debug_handle_transforms_ptr = debug_handle_smooth_transforms.ptr();
592+
593+
for (uint32_t i = 0; i < handle_smooth_count; i++) {
594+
const Transform2D &handle_transform = debug_handle_transforms_ptr[i];
595+
596+
multimesh_buffer_ptrw[i * 8 + 0] = handle_transform[0][0];
597+
multimesh_buffer_ptrw[i * 8 + 1] = handle_transform[1][0];
598+
multimesh_buffer_ptrw[i * 8 + 2] = 0;
599+
multimesh_buffer_ptrw[i * 8 + 3] = handle_transform[2][0];
600+
multimesh_buffer_ptrw[i * 8 + 4] = handle_transform[0][1];
601+
multimesh_buffer_ptrw[i * 8 + 5] = handle_transform[1][1];
602+
multimesh_buffer_ptrw[i * 8 + 6] = 0;
603+
multimesh_buffer_ptrw[i * 8 + 7] = handle_transform[2][1];
604+
}
605+
606+
rs->multimesh_set_buffer(debug_handle_smooth_multimesh_rid, multimesh_buffer);
607+
rs->multimesh_set_visible_instances(debug_handle_smooth_multimesh_rid, handle_smooth_count);
608+
609+
rs->canvas_item_add_multimesh(vpc->get_canvas_item(), debug_handle_smooth_multimesh_rid, curve_handle->get_rid());
610+
}
483611
}
484612

485613
void Path2DEditor::_node_visibility_changed() {
@@ -795,6 +923,66 @@ Path2DEditor::Path2DEditor() {
795923
create_curve_button->hide();
796924
add_child(create_curve_button);
797925
create_curve_button->connect(SceneStringName(pressed), callable_mp(this, &Path2DEditor::_create_curve));
926+
927+
ERR_FAIL_NULL(RS::get_singleton());
928+
RenderingServer *rs = RS::get_singleton();
929+
930+
debug_mesh_rid = rs->mesh_create();
931+
932+
{
933+
debug_handle_mesh_rid = rs->mesh_create();
934+
935+
Vector<Vector2> vertex_array;
936+
vertex_array.resize(4);
937+
Vector2 *vertex_array_ptrw = vertex_array.ptrw();
938+
vertex_array_ptrw[0] = Vector2(-1.0, -1.0);
939+
vertex_array_ptrw[1] = Vector2(1.0, -1.0);
940+
vertex_array_ptrw[2] = Vector2(1.0, 1.0);
941+
vertex_array_ptrw[3] = Vector2(-1.0, 1.0);
942+
943+
Vector<Vector2> uv_array;
944+
uv_array.resize(4);
945+
Vector2 *uv_array_ptrw = uv_array.ptrw();
946+
uv_array_ptrw[0] = Vector2(0.0, 0.0);
947+
uv_array_ptrw[1] = Vector2(1.0, 0.0);
948+
uv_array_ptrw[2] = Vector2(1.0, 1.0);
949+
uv_array_ptrw[3] = Vector2(0.0, 1.0);
950+
951+
Vector<int> index_array;
952+
index_array.resize(6);
953+
int *index_array_ptrw = index_array.ptrw();
954+
index_array_ptrw[0] = 0;
955+
index_array_ptrw[1] = 1;
956+
index_array_ptrw[2] = 3;
957+
index_array_ptrw[3] = 1;
958+
index_array_ptrw[4] = 2;
959+
index_array_ptrw[5] = 3;
960+
961+
Array mesh_arrays;
962+
mesh_arrays.resize(RS::ARRAY_MAX);
963+
mesh_arrays[RS::ARRAY_VERTEX] = vertex_array;
964+
mesh_arrays[RS::ARRAY_TEX_UV] = uv_array;
965+
mesh_arrays[RS::ARRAY_INDEX] = index_array;
966+
967+
rs->mesh_add_surface_from_arrays(debug_handle_mesh_rid, RS::PRIMITIVE_TRIANGLES, mesh_arrays, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
968+
969+
debug_handle_curve_multimesh_rid = rs->multimesh_create();
970+
debug_handle_sharp_multimesh_rid = rs->multimesh_create();
971+
debug_handle_smooth_multimesh_rid = rs->multimesh_create();
972+
973+
rs->multimesh_set_mesh(debug_handle_curve_multimesh_rid, debug_handle_mesh_rid);
974+
rs->multimesh_set_mesh(debug_handle_sharp_multimesh_rid, debug_handle_mesh_rid);
975+
rs->multimesh_set_mesh(debug_handle_smooth_multimesh_rid, debug_handle_mesh_rid);
976+
}
977+
}
978+
979+
Path2DEditor::~Path2DEditor() {
980+
ERR_FAIL_NULL(RS::get_singleton());
981+
RS::get_singleton()->free(debug_mesh_rid);
982+
RS::get_singleton()->free(debug_handle_curve_multimesh_rid);
983+
RS::get_singleton()->free(debug_handle_sharp_multimesh_rid);
984+
RS::get_singleton()->free(debug_handle_smooth_multimesh_rid);
985+
RS::get_singleton()->free(debug_handle_mesh_rid);
798986
}
799987

800988
void Path2DEditorPlugin::edit(Object *p_object) {

editor/plugins/path_2d_editor_plugin.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,19 @@ class Path2DEditor : public HBoxContainer {
112112
void _clear_curve_points(Path2D *p_path2d);
113113
void _restore_curve_points(Path2D *p_path2d, const PackedVector2Array &p_points);
114114

115+
RID debug_mesh_rid;
116+
RID debug_handle_mesh_rid;
117+
RID debug_handle_multimesh_rid;
118+
119+
RID debug_handle_curve_multimesh_rid;
120+
RID debug_handle_sharp_multimesh_rid;
121+
RID debug_handle_smooth_multimesh_rid;
122+
123+
LocalVector<Vector2> debug_handle_lines;
124+
LocalVector<Transform2D> debug_handle_curve_transforms;
125+
LocalVector<Transform2D> debug_handle_sharp_transforms;
126+
LocalVector<Transform2D> debug_handle_smooth_transforms;
127+
115128
protected:
116129
void _notification(int p_what);
117130
void _node_removed(Node *p_node);
@@ -122,6 +135,7 @@ class Path2DEditor : public HBoxContainer {
122135
void forward_canvas_draw_over_viewport(Control *p_overlay);
123136
void edit(Node *p_path2d);
124137
Path2DEditor();
138+
~Path2DEditor();
125139
};
126140

127141
class Path2DEditorPlugin : public EditorPlugin {

0 commit comments

Comments
 (0)