Merge pull request #76492 from KoBeWi/shaped_up_nicely

Improve reliability of 2D shape editor redrawing
This commit is contained in:
Rémi Verschelde 2023-04-27 08:21:06 +02:00
commit fc27bc0306
No known key found for this signature in database
GPG Key ID: C3336907360768E1
2 changed files with 34 additions and 72 deletions

View File

@ -42,6 +42,7 @@
#include "scene/resources/segment_shape_2d.h" #include "scene/resources/segment_shape_2d.h"
#include "scene/resources/separation_ray_shape_2d.h" #include "scene/resources/separation_ray_shape_2d.h"
#include "scene/resources/world_boundary_shape_2d.h" #include "scene/resources/world_boundary_shape_2d.h"
#include "scene/scene_string_names.h"
void CollisionShape2DEditor::_node_removed(Node *p_node) { void CollisionShape2DEditor::_node_removed(Node *p_node) {
if (p_node == node) { if (p_node == node) {
@ -129,8 +130,6 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} else if (idx == 1) { } else if (idx == 1) {
capsule->set_height(parameter * 2); capsule->set_height(parameter * 2);
} }
canvas_item_editor->update_viewport();
} }
} break; } break;
@ -138,9 +137,6 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
case CIRCLE_SHAPE: { case CIRCLE_SHAPE: {
Ref<CircleShape2D> circle = node->get_shape(); Ref<CircleShape2D> circle = node->get_shape();
circle->set_radius(p_point.length()); circle->set_radius(p_point.length());
canvas_item_editor->update_viewport();
} break; } break;
case CONCAVE_POLYGON_SHAPE: { case CONCAVE_POLYGON_SHAPE: {
@ -158,19 +154,13 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} else { } else {
world_boundary->set_normal(p_point.normalized()); world_boundary->set_normal(p_point.normalized());
} }
canvas_item_editor->update_viewport();
} }
} break; } break;
case SEPARATION_RAY_SHAPE: { case SEPARATION_RAY_SHAPE: {
Ref<SeparationRayShape2D> ray = node->get_shape(); Ref<SeparationRayShape2D> ray = node->get_shape();
ray->set_length(Math::abs(p_point.y)); ray->set_length(Math::abs(p_point.y));
canvas_item_editor->update_viewport();
} break; } break;
case RECTANGLE_SHAPE: { case RECTANGLE_SHAPE: {
@ -194,8 +184,6 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
pos += (size - (Point2)original) * 0.5 * RECT_HANDLES[idx] * 0.5; pos += (size - (Point2)original) * 0.5 * RECT_HANDLES[idx] * 0.5;
node->set_global_position(original_transform.xform(pos)); node->set_global_position(original_transform.xform(pos));
} }
canvas_item_editor->update_viewport();
} }
} break; } break;
@ -209,13 +197,9 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} else if (idx == 1) { } else if (idx == 1) {
seg->set_b(p_point); seg->set_b(p_point);
} }
canvas_item_editor->update_viewport();
} }
} break; } break;
} }
node->get_shape()->notify_property_list_changed();
} }
void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
@ -233,10 +217,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
} else if (idx == 1) { } else if (idx == 1) {
undo_redo->add_do_method(capsule.ptr(), "set_height", capsule->get_height()); undo_redo->add_do_method(capsule.ptr(), "set_height", capsule->get_height());
} }
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(capsule.ptr(), "set_radius", values[0]); undo_redo->add_undo_method(capsule.ptr(), "set_radius", values[0]);
undo_redo->add_undo_method(capsule.ptr(), "set_height", values[1]); undo_redo->add_undo_method(capsule.ptr(), "set_height", values[1]);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break; } break;
@ -244,9 +226,7 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
Ref<CircleShape2D> circle = node->get_shape(); Ref<CircleShape2D> circle = node->get_shape();
undo_redo->add_do_method(circle.ptr(), "set_radius", circle->get_radius()); undo_redo->add_do_method(circle.ptr(), "set_radius", circle->get_radius());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(circle.ptr(), "set_radius", p_org); undo_redo->add_undo_method(circle.ptr(), "set_radius", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break; } break;
@ -263,14 +243,10 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
if (idx == 0) { if (idx == 0) {
undo_redo->add_do_method(world_boundary.ptr(), "set_distance", world_boundary->get_distance()); undo_redo->add_do_method(world_boundary.ptr(), "set_distance", world_boundary->get_distance());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(world_boundary.ptr(), "set_distance", p_org); undo_redo->add_undo_method(world_boundary.ptr(), "set_distance", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} else { } else {
undo_redo->add_do_method(world_boundary.ptr(), "set_normal", world_boundary->get_normal()); undo_redo->add_do_method(world_boundary.ptr(), "set_normal", world_boundary->get_normal());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(world_boundary.ptr(), "set_normal", p_org); undo_redo->add_undo_method(world_boundary.ptr(), "set_normal", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} }
} break; } break;
@ -279,9 +255,7 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
Ref<SeparationRayShape2D> ray = node->get_shape(); Ref<SeparationRayShape2D> ray = node->get_shape();
undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length()); undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(ray.ptr(), "set_length", p_org); undo_redo->add_undo_method(ray.ptr(), "set_length", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break; } break;
@ -290,10 +264,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
undo_redo->add_do_method(rect.ptr(), "set_size", rect->get_size()); undo_redo->add_do_method(rect.ptr(), "set_size", rect->get_size());
undo_redo->add_do_method(node, "set_global_transform", node->get_global_transform()); undo_redo->add_do_method(node, "set_global_transform", node->get_global_transform());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(rect.ptr(), "set_size", p_org); undo_redo->add_undo_method(rect.ptr(), "set_size", p_org);
undo_redo->add_undo_method(node, "set_global_transform", original_transform); undo_redo->add_undo_method(node, "set_global_transform", original_transform);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break; } break;
@ -301,14 +273,10 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
Ref<SegmentShape2D> seg = node->get_shape(); Ref<SegmentShape2D> seg = node->get_shape();
if (idx == 0) { if (idx == 0) {
undo_redo->add_do_method(seg.ptr(), "set_a", seg->get_a()); undo_redo->add_do_method(seg.ptr(), "set_a", seg->get_a());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(seg.ptr(), "set_a", p_org); undo_redo->add_undo_method(seg.ptr(), "set_a", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} else if (idx == 1) { } else if (idx == 1) {
undo_redo->add_do_method(seg.ptr(), "set_b", seg->get_b()); undo_redo->add_do_method(seg.ptr(), "set_b", seg->get_b());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(seg.ptr(), "set_b", p_org); undo_redo->add_undo_method(seg.ptr(), "set_b", p_org);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} }
} break; } break;
@ -322,10 +290,6 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
return false; return false;
} }
if (!node->get_shape().is_valid()) {
return false;
}
if (!node->is_visible_in_tree()) { if (!node->is_visible_in_tree()) {
return false; return false;
} }
@ -410,38 +374,44 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
return false; return false;
} }
void CollisionShape2DEditor::_get_current_shape_type() { void CollisionShape2DEditor::_shape_changed() {
canvas_item_editor->update_viewport();
if (current_shape.is_valid()) {
current_shape->disconnect(SceneStringNames::get_singleton()->changed, callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
current_shape = Ref<Shape2D>();
shape_type = -1;
}
if (!node) { if (!node) {
return; return;
} }
Ref<Shape2D> s = node->get_shape(); current_shape = node->get_shape();
if (!s.is_valid()) { if (current_shape.is_valid()) {
current_shape->connect(SceneStringNames::get_singleton()->changed, callable_mp(canvas_item_editor, &CanvasItemEditor::update_viewport));
} else {
return; return;
} }
if (Object::cast_to<CapsuleShape2D>(*s)) { if (Object::cast_to<CapsuleShape2D>(*current_shape)) {
shape_type = CAPSULE_SHAPE; shape_type = CAPSULE_SHAPE;
} else if (Object::cast_to<CircleShape2D>(*s)) { } else if (Object::cast_to<CircleShape2D>(*current_shape)) {
shape_type = CIRCLE_SHAPE; shape_type = CIRCLE_SHAPE;
} else if (Object::cast_to<ConcavePolygonShape2D>(*s)) { } else if (Object::cast_to<ConcavePolygonShape2D>(*current_shape)) {
shape_type = CONCAVE_POLYGON_SHAPE; shape_type = CONCAVE_POLYGON_SHAPE;
} else if (Object::cast_to<ConvexPolygonShape2D>(*s)) { } else if (Object::cast_to<ConvexPolygonShape2D>(*current_shape)) {
shape_type = CONVEX_POLYGON_SHAPE; shape_type = CONVEX_POLYGON_SHAPE;
} else if (Object::cast_to<WorldBoundaryShape2D>(*s)) { } else if (Object::cast_to<WorldBoundaryShape2D>(*current_shape)) {
shape_type = WORLD_BOUNDARY_SHAPE; shape_type = WORLD_BOUNDARY_SHAPE;
} else if (Object::cast_to<SeparationRayShape2D>(*s)) { } else if (Object::cast_to<SeparationRayShape2D>(*current_shape)) {
shape_type = SEPARATION_RAY_SHAPE; shape_type = SEPARATION_RAY_SHAPE;
} else if (Object::cast_to<RectangleShape2D>(*s)) { } else if (Object::cast_to<RectangleShape2D>(*current_shape)) {
shape_type = RECTANGLE_SHAPE; shape_type = RECTANGLE_SHAPE;
} else if (Object::cast_to<SegmentShape2D>(*s)) { } else if (Object::cast_to<SegmentShape2D>(*current_shape)) {
shape_type = SEGMENT_SHAPE; shape_type = SEGMENT_SHAPE;
} else {
shape_type = -1;
} }
canvas_item_editor->update_viewport();
} }
void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
@ -449,16 +419,10 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
return; return;
} }
if (!node->get_shape().is_valid()) {
return;
}
if (!node->is_visible_in_tree()) { if (!node->is_visible_in_tree()) {
return; return;
} }
_get_current_shape_type();
if (shape_type == -1) { if (shape_type == -1) {
return; return;
} }
@ -559,6 +523,12 @@ void CollisionShape2DEditor::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
get_tree()->disconnect("node_removed", callable_mp(this, &CollisionShape2DEditor::_node_removed)); get_tree()->disconnect("node_removed", callable_mp(this, &CollisionShape2DEditor::_node_removed));
} break; } break;
case NOTIFICATION_PROCESS: {
if (node && node->get_shape() != current_shape) {
_shape_changed();
}
} break;
} }
} }
@ -569,26 +539,17 @@ void CollisionShape2DEditor::edit(Node *p_node) {
if (p_node) { if (p_node) {
node = Object::cast_to<CollisionShape2D>(p_node); node = Object::cast_to<CollisionShape2D>(p_node);
set_process(true);
_get_current_shape_type();
} else { } else {
if (pressed) { if (pressed) {
set_handle(edit_handle, original_point); set_handle(edit_handle, original_point);
pressed = false; pressed = false;
} }
edit_handle = -1; edit_handle = -1;
shape_type = -1;
node = nullptr; node = nullptr;
set_process(false);
} }
_shape_changed();
canvas_item_editor->update_viewport();
}
void CollisionShape2DEditor::_bind_methods() {
ClassDB::bind_method("_get_current_shape_type", &CollisionShape2DEditor::_get_current_shape_type);
} }
CollisionShape2DEditor::CollisionShape2DEditor() { CollisionShape2DEditor::CollisionShape2DEditor() {

View File

@ -74,16 +74,17 @@ class CollisionShape2DEditor : public Control {
Vector2 original_point; Vector2 original_point;
Point2 last_point; Point2 last_point;
Ref<Shape2D> current_shape;
Variant get_handle_value(int idx) const; Variant get_handle_value(int idx) const;
void set_handle(int idx, Point2 &p_point); void set_handle(int idx, Point2 &p_point);
void commit_handle(int idx, Variant &p_org); void commit_handle(int idx, Variant &p_org);
void _get_current_shape_type(); void _shape_changed();
protected: protected:
void _notification(int p_what); void _notification(int p_what);
void _node_removed(Node *p_node); void _node_removed(Node *p_node);
static void _bind_methods();
public: public:
bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);