From 1410bca5ce48eb3d43089c141abd4f7906d7c8b8 Mon Sep 17 00:00:00 2001 From: Lazy-Rabbit-2001 <2733679597@qq.com> Date: Mon, 28 Apr 2025 22:43:41 +0800 Subject: [PATCH] Allow Sprite2D being dragged to change their region_rect --- editor/plugins/sprite_2d_editor_plugin.cpp | 40 ++++++++++++++++- editor/plugins/sprite_2d_editor_plugin.h | 5 +++ scene/2d/sprite_2d.cpp | 52 ++++++++++++++++++---- scene/2d/sprite_2d.h | 5 +++ 4 files changed, 92 insertions(+), 10 deletions(-) diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index 0bd666dbeb6..edfc74f00d3 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -665,8 +665,38 @@ Sprite2DEditor::Sprite2DEditor() { add_child(debug_uv_dialog); } +void Sprite2DEditorPlugin::_editor_theme_changed() { + dragging_mode_hint->add_theme_color_override(SceneStringName(font_color), Color(0.6f, 0.6f, 0.6f, 1)); + dragging_mode_hint->add_theme_color_override("font_shadow_color", Color(0.2f, 0.2f, 0.2f, 1)); + dragging_mode_hint->add_theme_constant_override("shadow_outline_size", 1 * EDSCALE); + dragging_mode_hint->add_theme_constant_override("line_spacing", 0); +} + +void Sprite2DEditorPlugin::_update_dragging_mode_hint(bool p_region_enabled) { + if (p_region_enabled) { + dragging_mode_hint->show(); + } else { + dragging_mode_hint->hide(); + } +} + void Sprite2DEditorPlugin::edit(Object *p_object) { - sprite_editor->edit(Object::cast_to(p_object)); + Callable update_text = callable_mp(this, &Sprite2DEditorPlugin::_update_dragging_mode_hint); + StringName update_signal = SNAME("_editor_region_rect_enabled"); + + Sprite2D *spr = sprite_editor->node; + if (spr != nullptr && spr->is_connected(update_signal, update_text)) { + spr->disconnect(update_signal, update_text); + } + + spr = Object::cast_to(p_object); + sprite_editor->edit(spr); + if (spr != nullptr) { + _update_dragging_mode_hint(spr->is_editor_region_rect_draggable()); + if (!spr->is_connected(update_signal, update_text)) { + spr->connect(update_signal, update_text); + } + } } bool Sprite2DEditorPlugin::handles(Object *p_object) const { @@ -678,14 +708,20 @@ void Sprite2DEditorPlugin::make_visible(bool p_visible) { sprite_editor->options->show(); } else { sprite_editor->options->hide(); + dragging_mode_hint->hide(); sprite_editor->edit(nullptr); } } Sprite2DEditorPlugin::Sprite2DEditorPlugin() { sprite_editor = memnew(Sprite2DEditor); + sprite_editor->connect(SceneStringName(theme_changed), callable_mp(this, &Sprite2DEditorPlugin::_editor_theme_changed)); EditorNode::get_singleton()->get_gui_base()->add_child(sprite_editor); - make_visible(false); + dragging_mode_hint = memnew(Label); + dragging_mode_hint->set_text(TTRC("When dragging:\nHold Ctrl + left mouse button to change the region_rect and position.\nHold left mouse button to modify the scale of the sprite.")); + CanvasItemEditor::get_singleton()->get_controls_container()->add_child(dragging_mode_hint); + + make_visible(false); //sprite_editor->options->hide(); } diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h index 609b5d9bc34..b863c676bfb 100644 --- a/editor/plugins/sprite_2d_editor_plugin.h +++ b/editor/plugins/sprite_2d_editor_plugin.h @@ -119,6 +119,11 @@ class Sprite2DEditorPlugin : public EditorPlugin { Sprite2DEditor *sprite_editor = nullptr; + Label *dragging_mode_hint = nullptr; + + void _editor_theme_changed(); + void _update_dragging_mode_hint(bool p_region_enabled); + public: virtual String get_plugin_name() const override { return "Sprite2D"; } bool has_main_screen() const override { return false; } diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index 904eaf8ff72..efe3cfae1b7 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -30,18 +30,21 @@ #include "sprite_2d.h" +#include "core/input/input.h" #include "scene/main/viewport.h" #ifdef TOOLS_ENABLED Dictionary Sprite2D::_edit_get_state() const { Dictionary state = Node2D::_edit_get_state(); state["offset"] = offset; + state["region_rect"] = region_rect; return state; } void Sprite2D::_edit_set_state(const Dictionary &p_state) { Node2D::_edit_set_state(p_state); set_offset(p_state["offset"]); + set_region_rect(p_state["region_rect"]); } void Sprite2D::_edit_set_pivot(const Point2 &p_pivot) { @@ -56,6 +59,19 @@ Point2 Sprite2D::_edit_get_pivot() const { bool Sprite2D::_edit_use_pivot() const { return true; } + +void Sprite2D::_edit_set_rect(const Rect2 &p_rect) { + if (texture.is_null()) { + return; + } + if (!(region_enabled && hframes <= 1 && vframes <= 1 && Input::get_singleton()->is_key_label_pressed(Key::CTRL))) { + Node2D::_edit_set_rect(p_rect); + return; + } + Point2 delta = p_rect.position - (centered ? _get_rect_offset(p_rect.size) : Vector2()); + set_region_rect(Rect2(region_rect.position, p_rect.size)); + set_position(get_position() + get_transform().basis_xform(delta)); +} #endif // TOOLS_ENABLED #ifdef DEBUG_ENABLED @@ -113,6 +129,19 @@ void Sprite2D::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_c } } +Point2 Sprite2D::_get_rect_offset(const Size2i &p_size) const { + Point2 ofs = offset; + if (centered) { + ofs -= Size2(p_size) / 2; + } + + if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) { + ofs = (ofs + Point2(0.5, 0.5)).floor(); + } + + return ofs; +} + void Sprite2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ACCESSIBILITY_UPDATE: { @@ -226,6 +255,7 @@ void Sprite2D::set_region_enabled(bool p_region_enabled) { } region_enabled = p_region_enabled; + _emit_region_rect_enabled(); queue_redraw(); notify_property_list_changed(); } @@ -301,6 +331,7 @@ void Sprite2D::set_vframes(int p_amount) { if (frame >= vframes * hframes) { frame = 0; } + _emit_region_rect_enabled(); queue_redraw(); item_rect_changed(); notify_property_list_changed(); @@ -332,6 +363,7 @@ void Sprite2D::set_hframes(int p_amount) { if (frame >= vframes * hframes) { frame = 0; } + _emit_region_rect_enabled(); queue_redraw(); item_rect_changed(); notify_property_list_changed(); @@ -392,6 +424,10 @@ bool Sprite2D::is_pixel_opaque(const Point2 &p_point) const { return texture->is_pixel_opaque((int)q.x, (int)q.y); } +bool Sprite2D::is_editor_region_rect_draggable() const { + return hframes <= 1 && vframes <= 1 && region_enabled; +} + Rect2 Sprite2D::get_rect() const { if (texture.is_null()) { return Rect2(0, 0, 1, 1); @@ -407,14 +443,7 @@ Rect2 Sprite2D::get_rect() const { s = s / Point2(hframes, vframes); - Point2 ofs = offset; - if (centered) { - ofs -= Size2(s) / 2; - } - - if (get_viewport() && get_viewport()->is_snap_2d_transforms_to_pixel_enabled()) { - ofs = (ofs + Point2(0.5, 0.5)).floor(); - } + Point2 ofs = _get_rect_offset(s); if (s == Size2(0, 0)) { s = Size2(1, 1); @@ -447,6 +476,10 @@ void Sprite2D::_texture_changed() { } } +void Sprite2D::_emit_region_rect_enabled() { + emit_signal("_editor_region_rect_enabled", is_editor_region_rect_draggable()); +} + void Sprite2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Sprite2D::set_texture); ClassDB::bind_method(D_METHOD("get_texture"), &Sprite2D::get_texture); @@ -510,6 +543,9 @@ void Sprite2D::_bind_methods() { } Sprite2D::Sprite2D() { +#ifdef TOOLS_ENABLED + add_user_signal(MethodInfo("_editor_region_rect_enabled", PropertyInfo(Variant::BOOL, "enabled"))); // Sprite2DEditorPlugin listens to this. +#endif } Sprite2D::~Sprite2D() { diff --git a/scene/2d/sprite_2d.h b/scene/2d/sprite_2d.h index d5bfd24aa1d..260104ca21f 100644 --- a/scene/2d/sprite_2d.h +++ b/scene/2d/sprite_2d.h @@ -55,8 +55,10 @@ class Sprite2D : public Node2D { int hframes = 1; void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip_enabled) const; + Point2 _get_rect_offset(const Size2i &p_size) const; void _texture_changed(); + void _emit_region_rect_enabled(); protected: void _notification(int p_what); @@ -73,6 +75,8 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot) override; virtual Point2 _edit_get_pivot() const override; virtual bool _edit_use_pivot() const override; + + virtual void _edit_set_rect(const Rect2 &p_rect) override; #endif // TOOLS_ENABLED #ifdef DEBUG_ENABLED @@ -83,6 +87,7 @@ public: #endif // DEBUG_ENABLED bool is_pixel_opaque(const Point2 &p_point) const; + bool is_editor_region_rect_draggable() const; void set_texture(const Ref &p_texture); Ref get_texture() const;