Browse Source

Allow Sprite2D being dragged to change their region_rect

Lazy-Rabbit-2001 4 months ago
parent
commit
1410bca5ce

+ 38 - 2
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<Sprite2D>(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<Sprite2D>(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();
 }

+ 5 - 0
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; }

+ 44 - 8
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() {

+ 5 - 0
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<Texture2D> &p_texture);
 	Ref<Texture2D> get_texture() const;