2
0
Эх сурвалжийг харах

Merge pull request #41223 from javidcf/sprite_frames_editor_zoom

Added zoom functionality to sprite frames editor plugin
Rémi Verschelde 5 жил өмнө
parent
commit
ac5619f521

+ 174 - 12
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -36,6 +36,8 @@
 #include "editor/editor_settings.h"
 #include "editor/editor_settings.h"
 #include "scene/3d/sprite_3d.h"
 #include "scene/3d/sprite_3d.h"
 #include "scene/gui/center_container.h"
 #include "scene/gui/center_container.h"
+#include "scene/gui/margin_container.h"
+#include "scene/gui/panel_container.h"
 
 
 void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) {
 void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) {
 }
 }
@@ -140,8 +142,27 @@ void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
 	}
 	}
 }
 }
 
 
+void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
+	const Ref<InputEventMouseButton> mb = p_event;
+
+	if (mb.is_valid()) {
+		// Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer
+		// to allow performing this action anywhere, even if the cursor isn't
+		// hovering the texture in the workspace.
+		if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+			_sheet_zoom_in();
+			// Don't scroll up after zooming in.
+			accept_event();
+		} else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+			_sheet_zoom_out();
+			// Don't scroll down after zooming out.
+			accept_event();
+		}
+	}
+}
+
 void SpriteFramesEditor::_sheet_add_frames() {
 void SpriteFramesEditor::_sheet_add_frames() {
-	Size2i size = split_sheet_preview->get_size();
+	Size2i size = split_sheet_preview->get_texture()->get_size();
 	int h = split_sheet_h->get_value();
 	int h = split_sheet_h->get_value();
 	int v = split_sheet_v->get_value();
 	int v = split_sheet_v->get_value();
 
 
@@ -180,6 +201,28 @@ void SpriteFramesEditor::_sheet_add_frames() {
 	undo_redo->commit_action();
 	undo_redo->commit_action();
 }
 }
 
 
+void SpriteFramesEditor::_sheet_zoom_in() {
+	if (sheet_zoom < max_sheet_zoom) {
+		sheet_zoom *= scale_ratio;
+		Size2 texture_size = split_sheet_preview->get_texture()->get_size();
+		split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
+	}
+}
+
+void SpriteFramesEditor::_sheet_zoom_out() {
+	if (sheet_zoom > min_sheet_zoom) {
+		sheet_zoom /= scale_ratio;
+		Size2 texture_size = split_sheet_preview->get_texture()->get_size();
+		split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
+	}
+}
+
+void SpriteFramesEditor::_sheet_zoom_reset() {
+	sheet_zoom = 1.f;
+	Size2 texture_size = split_sheet_preview->get_texture()->get_size();
+	split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
+}
+
 void SpriteFramesEditor::_sheet_select_clear_all_frames() {
 void SpriteFramesEditor::_sheet_select_clear_all_frames() {
 	bool should_clear = true;
 	bool should_clear = true;
 	for (int i = 0; i < split_sheet_h->get_value() * split_sheet_v->get_value(); i++) {
 	for (int i = 0; i < split_sheet_h->get_value() * split_sheet_v->get_value(); i++) {
@@ -207,15 +250,18 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
 		EditorNode::get_singleton()->show_warning(TTR("Unable to load images"));
 		EditorNode::get_singleton()->show_warning(TTR("Unable to load images"));
 		ERR_FAIL_COND(!texture.is_valid());
 		ERR_FAIL_COND(!texture.is_valid());
 	}
 	}
-	if (texture != split_sheet_preview->get_texture()) {
-		//different texture, reset to 4x4
-		split_sheet_h->set_value(4);
-		split_sheet_v->set_value(4);
-	}
+	bool new_texture = texture != split_sheet_preview->get_texture();
 	frames_selected.clear();
 	frames_selected.clear();
 	last_frame_selected = -1;
 	last_frame_selected = -1;
 
 
 	split_sheet_preview->set_texture(texture);
 	split_sheet_preview->set_texture(texture);
+	if (new_texture) {
+		//different texture, reset to 4x4
+		split_sheet_h->set_value(4);
+		split_sheet_v->set_value(4);
+		//reset zoom
+		_sheet_zoom_reset();
+	}
 	split_sheet_dialog->popup_centered_ratio(0.65);
 	split_sheet_dialog->popup_centered_ratio(0.65);
 }
 }
 
 
@@ -231,8 +277,14 @@ void SpriteFramesEditor::_notification(int p_what) {
 			move_up->set_icon(get_theme_icon("MoveLeft", "EditorIcons"));
 			move_up->set_icon(get_theme_icon("MoveLeft", "EditorIcons"));
 			move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons"));
 			move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons"));
 			_delete->set_icon(get_theme_icon("Remove", "EditorIcons"));
 			_delete->set_icon(get_theme_icon("Remove", "EditorIcons"));
+			zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
+			zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
+			zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
 			new_anim->set_icon(get_theme_icon("New", "EditorIcons"));
 			new_anim->set_icon(get_theme_icon("New", "EditorIcons"));
 			remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons"));
 			remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons"));
+			split_sheet_zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
+			split_sheet_zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
+			split_sheet_zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
 			[[fallthrough]];
 			[[fallthrough]];
 		}
 		}
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
@@ -636,6 +688,54 @@ void SpriteFramesEditor::_animation_fps_changed(double p_value) {
 	undo_redo->commit_action();
 	undo_redo->commit_action();
 }
 }
 
 
+void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) {
+	const Ref<InputEventMouseButton> mb = p_event;
+
+	if (mb.is_valid()) {
+		if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
+			_zoom_in();
+			// Don't scroll up after zooming in.
+			accept_event();
+		} else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
+			_zoom_out();
+			// Don't scroll down after zooming out.
+			accept_event();
+		}
+	}
+}
+
+void SpriteFramesEditor::_zoom_in() {
+	// Do not zoom in or out with no visible frames
+	if (frames->get_frame_count(edited_anim) <= 0) {
+		return;
+	}
+	if (thumbnail_zoom < max_thumbnail_zoom) {
+		thumbnail_zoom *= scale_ratio;
+		int thumbnail_size = (int)(thumbnail_default_size * thumbnail_zoom);
+		tree->set_fixed_column_width(thumbnail_size * 3 / 2);
+		tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
+	}
+}
+
+void SpriteFramesEditor::_zoom_out() {
+	// Do not zoom in or out with no visible frames
+	if (frames->get_frame_count(edited_anim) <= 0) {
+		return;
+	}
+	if (thumbnail_zoom > min_thumbnail_zoom) {
+		thumbnail_zoom /= scale_ratio;
+		int thumbnail_size = (int)(thumbnail_default_size * thumbnail_zoom);
+		tree->set_fixed_column_width(thumbnail_size * 3 / 2);
+		tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
+	}
+}
+
+void SpriteFramesEditor::_zoom_reset() {
+	thumbnail_zoom = 1.0f;
+	tree->set_fixed_column_width(thumbnail_default_size * 3 / 2);
+	tree->set_fixed_icon_size(Size2(thumbnail_default_size, thumbnail_default_size));
+}
+
 void SpriteFramesEditor::_update_library(bool p_skip_selector) {
 void SpriteFramesEditor::_update_library(bool p_skip_selector) {
 	updating = true;
 	updating = true;
 
 
@@ -727,6 +827,9 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
 		}
 		}
 
 
 		_update_library();
 		_update_library();
+		// Clear zoom and split sheet texture
+		split_sheet_preview->set_texture(Ref<Texture2D>());
+		_zoom_reset();
 	} else {
 	} else {
 		hide();
 		hide();
 	}
 	}
@@ -965,6 +1068,24 @@ SpriteFramesEditor::SpriteFramesEditor() {
 	_delete->set_tooltip(TTR("Delete"));
 	_delete->set_tooltip(TTR("Delete"));
 	hbc->add_child(_delete);
 	hbc->add_child(_delete);
 
 
+	hbc->add_spacer();
+
+	zoom_out = memnew(Button);
+	zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_out));
+	zoom_out->set_flat(true);
+	zoom_out->set_tooltip(TTR("Zoom Out"));
+	hbc->add_child(zoom_out);
+	zoom_1 = memnew(Button);
+	zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_reset));
+	zoom_1->set_flat(true);
+	zoom_1->set_tooltip(TTR("Zoom Reset"));
+	hbc->add_child(zoom_1);
+	zoom_in = memnew(Button);
+	zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_in));
+	zoom_in->set_flat(true);
+	zoom_in->set_tooltip(TTR("Zoom In"));
+	hbc->add_child(zoom_in);
+
 	file = memnew(EditorFileDialog);
 	file = memnew(EditorFileDialog);
 	add_child(file);
 	add_child(file);
 
 
@@ -972,13 +1093,11 @@ SpriteFramesEditor::SpriteFramesEditor() {
 	tree->set_v_size_flags(SIZE_EXPAND_FILL);
 	tree->set_v_size_flags(SIZE_EXPAND_FILL);
 	tree->set_icon_mode(ItemList::ICON_MODE_TOP);
 	tree->set_icon_mode(ItemList::ICON_MODE_TOP);
 
 
-	int thumbnail_size = 96;
 	tree->set_max_columns(0);
 	tree->set_max_columns(0);
 	tree->set_icon_mode(ItemList::ICON_MODE_TOP);
 	tree->set_icon_mode(ItemList::ICON_MODE_TOP);
-	tree->set_fixed_column_width(thumbnail_size * 3 / 2);
 	tree->set_max_text_lines(2);
 	tree->set_max_text_lines(2);
-	tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
 	tree->set_drag_forwarding(this);
 	tree->set_drag_forwarding(this);
+	tree->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_tree_input));
 
 
 	sub_vb->add_child(tree);
 	sub_vb->add_child(tree);
 
 
@@ -1042,8 +1161,13 @@ SpriteFramesEditor::SpriteFramesEditor() {
 
 
 	split_sheet_vb->add_child(split_sheet_hb);
 	split_sheet_vb->add_child(split_sheet_hb);
 
 
+	PanelContainer *split_sheet_panel = memnew(PanelContainer);
+	split_sheet_panel->set_h_size_flags(SIZE_EXPAND_FILL);
+	split_sheet_panel->set_v_size_flags(SIZE_EXPAND_FILL);
+	split_sheet_vb->add_child(split_sheet_panel);
+
 	split_sheet_preview = memnew(TextureRect);
 	split_sheet_preview = memnew(TextureRect);
-	split_sheet_preview->set_expand(false);
+	split_sheet_preview->set_expand(true);
 	split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS);
 	split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS);
 	split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
 	split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
 	split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));
 	split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));
@@ -1051,20 +1175,58 @@ SpriteFramesEditor::SpriteFramesEditor() {
 	splite_sheet_scroll = memnew(ScrollContainer);
 	splite_sheet_scroll = memnew(ScrollContainer);
 	splite_sheet_scroll->set_enable_h_scroll(true);
 	splite_sheet_scroll->set_enable_h_scroll(true);
 	splite_sheet_scroll->set_enable_v_scroll(true);
 	splite_sheet_scroll->set_enable_v_scroll(true);
-	splite_sheet_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+	splite_sheet_scroll->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_scroll_input));
+	split_sheet_panel->add_child(splite_sheet_scroll);
 	CenterContainer *cc = memnew(CenterContainer);
 	CenterContainer *cc = memnew(CenterContainer);
 	cc->add_child(split_sheet_preview);
 	cc->add_child(split_sheet_preview);
 	cc->set_h_size_flags(SIZE_EXPAND_FILL);
 	cc->set_h_size_flags(SIZE_EXPAND_FILL);
 	cc->set_v_size_flags(SIZE_EXPAND_FILL);
 	cc->set_v_size_flags(SIZE_EXPAND_FILL);
 	splite_sheet_scroll->add_child(cc);
 	splite_sheet_scroll->add_child(cc);
 
 
-	split_sheet_vb->add_child(splite_sheet_scroll);
+	MarginContainer *split_sheet_zoom_margin = memnew(MarginContainer);
+	split_sheet_panel->add_child(split_sheet_zoom_margin);
+	split_sheet_zoom_margin->set_h_size_flags(0);
+	split_sheet_zoom_margin->set_v_size_flags(0);
+	split_sheet_zoom_margin->add_theme_constant_override("margin_top", 5);
+	split_sheet_zoom_margin->add_theme_constant_override("margin_left", 5);
+	HBoxContainer *split_sheet_zoom_hb = memnew(HBoxContainer);
+	split_sheet_zoom_margin->add_child(split_sheet_zoom_hb);
+
+	split_sheet_zoom_out = memnew(Button);
+	split_sheet_zoom_out->set_flat(true);
+	split_sheet_zoom_out->set_focus_mode(FOCUS_NONE);
+	split_sheet_zoom_out->set_tooltip(TTR("Zoom Out"));
+	split_sheet_zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_out));
+	split_sheet_zoom_hb->add_child(split_sheet_zoom_out);
+	split_sheet_zoom_1 = memnew(Button);
+	split_sheet_zoom_1->set_flat(true);
+	split_sheet_zoom_1->set_focus_mode(FOCUS_NONE);
+	split_sheet_zoom_1->set_tooltip(TTR("Zoom Reset"));
+	split_sheet_zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_reset));
+	split_sheet_zoom_hb->add_child(split_sheet_zoom_1);
+	split_sheet_zoom_in = memnew(Button);
+	split_sheet_zoom_in->set_flat(true);
+	split_sheet_zoom_in->set_focus_mode(FOCUS_NONE);
+	split_sheet_zoom_in->set_tooltip(TTR("Zoom In"));
+	split_sheet_zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_in));
+	split_sheet_zoom_hb->add_child(split_sheet_zoom_in);
 
 
 	file_split_sheet = memnew(EditorFileDialog);
 	file_split_sheet = memnew(EditorFileDialog);
 	file_split_sheet->set_title(TTR("Create Frames from Sprite Sheet"));
 	file_split_sheet->set_title(TTR("Create Frames from Sprite Sheet"));
 	file_split_sheet->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
 	file_split_sheet->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
 	add_child(file_split_sheet);
 	add_child(file_split_sheet);
 	file_split_sheet->connect("file_selected", callable_mp(this, &SpriteFramesEditor::_prepare_sprite_sheet));
 	file_split_sheet->connect("file_selected", callable_mp(this, &SpriteFramesEditor::_prepare_sprite_sheet));
+
+	// Config scale.
+	scale_ratio = 1.2f;
+	thumbnail_default_size = 96;
+	thumbnail_zoom = 1.0f;
+	max_thumbnail_zoom = 8.0f;
+	min_thumbnail_zoom = 0.1f;
+	sheet_zoom = 1.0f;
+	max_sheet_zoom = 16.0f;
+	min_sheet_zoom = 0.01f;
+	_zoom_reset();
 }
 }
 
 
 void SpriteFramesEditorPlugin::edit(Object *p_object) {
 void SpriteFramesEditorPlugin::edit(Object *p_object) {

+ 25 - 0
editor/plugins/sprite_frames_editor_plugin.h

@@ -36,6 +36,7 @@
 #include "scene/2d/animated_sprite_2d.h"
 #include "scene/2d/animated_sprite_2d.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/dialogs.h"
 #include "scene/gui/file_dialog.h"
 #include "scene/gui/file_dialog.h"
+#include "scene/gui/scroll_container.h"
 #include "scene/gui/split_container.h"
 #include "scene/gui/split_container.h"
 #include "scene/gui/texture_rect.h"
 #include "scene/gui/texture_rect.h"
 #include "scene/gui/tree.h"
 #include "scene/gui/tree.h"
@@ -52,6 +53,9 @@ class SpriteFramesEditor : public HSplitContainer {
 	Button *empty2;
 	Button *empty2;
 	Button *move_up;
 	Button *move_up;
 	Button *move_down;
 	Button *move_down;
+	Button *zoom_out;
+	Button *zoom_1;
+	Button *zoom_in;
 	ItemList *tree;
 	ItemList *tree;
 	bool loading_scene;
 	bool loading_scene;
 	int sel;
 	int sel;
@@ -79,10 +83,22 @@ class SpriteFramesEditor : public HSplitContainer {
 	TextureRect *split_sheet_preview;
 	TextureRect *split_sheet_preview;
 	SpinBox *split_sheet_h;
 	SpinBox *split_sheet_h;
 	SpinBox *split_sheet_v;
 	SpinBox *split_sheet_v;
+	Button *split_sheet_zoom_out;
+	Button *split_sheet_zoom_1;
+	Button *split_sheet_zoom_in;
 	EditorFileDialog *file_split_sheet;
 	EditorFileDialog *file_split_sheet;
 	Set<int> frames_selected;
 	Set<int> frames_selected;
 	int last_frame_selected;
 	int last_frame_selected;
 
 
+	float scale_ratio;
+	int thumbnail_default_size;
+	float thumbnail_zoom;
+	float max_thumbnail_zoom;
+	float min_thumbnail_zoom;
+	float sheet_zoom;
+	float max_sheet_zoom;
+	float min_sheet_zoom;
+
 	void _load_pressed();
 	void _load_pressed();
 	void _load_scene_pressed();
 	void _load_scene_pressed();
 	void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
 	void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
@@ -103,6 +119,11 @@ class SpriteFramesEditor : public HSplitContainer {
 	void _animation_loop_changed();
 	void _animation_loop_changed();
 	void _animation_fps_changed(double p_value);
 	void _animation_fps_changed(double p_value);
 
 
+	void _tree_input(const Ref<InputEvent> &p_event);
+	void _zoom_in();
+	void _zoom_out();
+	void _zoom_reset();
+
 	bool updating;
 	bool updating;
 
 
 	UndoRedo *undo_redo;
 	UndoRedo *undo_redo;
@@ -117,7 +138,11 @@ class SpriteFramesEditor : public HSplitContainer {
 	void _sheet_preview_draw();
 	void _sheet_preview_draw();
 	void _sheet_spin_changed(double);
 	void _sheet_spin_changed(double);
 	void _sheet_preview_input(const Ref<InputEvent> &p_event);
 	void _sheet_preview_input(const Ref<InputEvent> &p_event);
+	void _sheet_scroll_input(const Ref<InputEvent> &p_event);
 	void _sheet_add_frames();
 	void _sheet_add_frames();
+	void _sheet_zoom_in();
+	void _sheet_zoom_out();
+	void _sheet_zoom_reset();
 	void _sheet_select_clear_all_frames();
 	void _sheet_select_clear_all_frames();
 
 
 protected:
 protected: