1/**************************************************************************/
2/* sprite_frames_editor_plugin.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef SPRITE_FRAMES_EDITOR_PLUGIN_H
32#define SPRITE_FRAMES_EDITOR_PLUGIN_H
33
34#include "editor/editor_plugin.h"
35#include "scene/2d/animated_sprite_2d.h"
36#include "scene/3d/sprite_3d.h"
37#include "scene/gui/button.h"
38#include "scene/gui/check_button.h"
39#include "scene/gui/dialogs.h"
40#include "scene/gui/item_list.h"
41#include "scene/gui/line_edit.h"
42#include "scene/gui/scroll_container.h"
43#include "scene/gui/spin_box.h"
44#include "scene/gui/split_container.h"
45#include "scene/gui/texture_rect.h"
46#include "scene/gui/tree.h"
47#include "scene/resources/image_texture.h"
48
49class OptionButton;
50class EditorFileDialog;
51
52class EditorSpriteFramesFrame : public Resource {
53 GDCLASS(EditorSpriteFramesFrame, Resource);
54
55public:
56 Ref<Texture2D> texture;
57 float duration;
58};
59
60class SpriteFramesEditor : public HSplitContainer {
61 GDCLASS(SpriteFramesEditor, HSplitContainer);
62
63 Ref<SpriteFrames> frames;
64 Node *animated_sprite = nullptr;
65
66 enum {
67 PARAM_USE_CURRENT, // Used in callbacks to indicate `dominant_param` should be not updated.
68 PARAM_FRAME_COUNT, // Keep "Horizontal" & "Vertical" values.
69 PARAM_SIZE, // Keep "Size" values.
70 };
71 int dominant_param = PARAM_FRAME_COUNT;
72
73 enum {
74 FRAME_ORDER_SELECTION, // Order frames were selected in.
75
76 // By Row.
77 FRAME_ORDER_LEFT_RIGHT_TOP_BOTTOM,
78 FRAME_ORDER_LEFT_RIGHT_BOTTOM_TOP,
79 FRAME_ORDER_RIGHT_LEFT_TOP_BOTTOM,
80 FRAME_ORDER_RIGHT_LEFT_BOTTOM_TOP,
81
82 // By Column.
83 FRAME_ORDER_TOP_BOTTOM_LEFT_RIGHT,
84 FRAME_ORDER_TOP_BOTTOM_RIGHT_LEFT,
85 FRAME_ORDER_BOTTOM_TOP_LEFT_RIGHT,
86 FRAME_ORDER_BOTTOM_TOP_RIGHT_LEFT,
87 };
88
89 bool read_only = false;
90
91 Ref<Texture2D> autoplay_icon;
92 Ref<Texture2D> stop_icon;
93 Ref<Texture2D> pause_icon;
94 Ref<Texture2D> empty_icon = memnew(ImageTexture);
95
96 HBoxContainer *playback_container = nullptr;
97 Button *stop = nullptr;
98 Button *play = nullptr;
99 Button *play_from = nullptr;
100 Button *play_bw = nullptr;
101 Button *play_bw_from = nullptr;
102
103 Button *load = nullptr;
104 Button *load_sheet = nullptr;
105 Button *delete_frame = nullptr;
106 Button *copy = nullptr;
107 Button *paste = nullptr;
108 Button *empty_before = nullptr;
109 Button *empty_after = nullptr;
110 Button *move_up = nullptr;
111 Button *move_down = nullptr;
112 Button *zoom_out = nullptr;
113 Button *zoom_reset = nullptr;
114 Button *zoom_in = nullptr;
115 SpinBox *frame_duration = nullptr;
116 ItemList *frame_list = nullptr;
117 bool loading_scene;
118 int sel;
119
120 Button *add_anim = nullptr;
121 Button *delete_anim = nullptr;
122 SpinBox *anim_speed = nullptr;
123 Button *anim_loop = nullptr;
124
125 HBoxContainer *autoplay_container = nullptr;
126 Button *autoplay = nullptr;
127
128 LineEdit *anim_search_box = nullptr;
129 Tree *animations = nullptr;
130
131 Label *missing_anim_label = nullptr;
132 VBoxContainer *anim_frames_vb = nullptr;
133
134 EditorFileDialog *file = nullptr;
135
136 AcceptDialog *dialog = nullptr;
137
138 StringName edited_anim;
139
140 ConfirmationDialog *delete_dialog = nullptr;
141
142 ConfirmationDialog *split_sheet_dialog = nullptr;
143 ScrollContainer *split_sheet_scroll = nullptr;
144 TextureRect *split_sheet_preview = nullptr;
145 VBoxContainer *split_sheet_settings_vb = nullptr;
146 SpinBox *split_sheet_h = nullptr;
147 SpinBox *split_sheet_v = nullptr;
148 SpinBox *split_sheet_size_x = nullptr;
149 SpinBox *split_sheet_size_y = nullptr;
150 SpinBox *split_sheet_sep_x = nullptr;
151 SpinBox *split_sheet_sep_y = nullptr;
152 SpinBox *split_sheet_offset_x = nullptr;
153 SpinBox *split_sheet_offset_y = nullptr;
154 Button *split_sheet_zoom_out = nullptr;
155 Button *split_sheet_zoom_reset = nullptr;
156 Button *split_sheet_zoom_in = nullptr;
157 Button *toggle_settings_button = nullptr;
158 OptionButton *split_sheet_order = nullptr;
159 EditorFileDialog *file_split_sheet = nullptr;
160 HashMap<int, int> frames_selected; // Key is frame index. Value is selection order.
161 HashSet<int> frames_toggled_by_mouse_hover;
162 Vector<Pair<int, int>> frames_ordered; // First is the index to be ordered by. Second is the actual frame index.
163 int selected_count = 0;
164 bool frames_need_sort = false;
165 int last_frame_selected = 0;
166
167 float scale_ratio;
168 int thumbnail_default_size;
169 float thumbnail_zoom;
170 float max_thumbnail_zoom;
171 float min_thumbnail_zoom;
172 float sheet_zoom;
173 float max_sheet_zoom;
174 float min_sheet_zoom;
175
176 Size2i _get_frame_count() const;
177 Size2i _get_frame_size() const;
178 Size2i _get_offset() const;
179 Size2i _get_separation() const;
180
181 void _load_pressed();
182 void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
183 void _copy_pressed();
184 void _paste_pressed();
185 void _empty_pressed();
186 void _empty2_pressed();
187 void _delete_pressed();
188 void _up_pressed();
189 void _down_pressed();
190 void _frame_duration_changed(double p_value);
191 void _update_library(bool p_skip_selector = false);
192
193 void _update_stop_icon();
194 void _play_pressed();
195 void _play_from_pressed();
196 void _play_bw_pressed();
197 void _play_bw_from_pressed();
198 void _autoplay_pressed();
199 void _stop_pressed();
200
201 void _animation_selected();
202 void _animation_name_edited();
203 void _animation_add();
204 void _animation_remove();
205 void _animation_remove_confirmed();
206 void _animation_search_text_changed(const String &p_text);
207 void _animation_loop_changed();
208 void _animation_speed_changed(double p_value);
209
210 void _frame_list_gui_input(const Ref<InputEvent> &p_event);
211 void _frame_list_item_selected(int p_index);
212
213 void _zoom_in();
214 void _zoom_out();
215 void _zoom_reset();
216
217 bool updating;
218 bool updating_split_settings = false; // Skip SpinBox/Range callback when setting value by code.
219
220 Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
221 bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
222 void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
223
224 void _open_sprite_sheet();
225 void _prepare_sprite_sheet(const String &p_file);
226 int _sheet_preview_position_to_frame_index(const Vector2 &p_position);
227 void _sheet_preview_draw();
228 void _sheet_spin_changed(double p_value, int p_dominant_param);
229 void _sheet_preview_input(const Ref<InputEvent> &p_event);
230 void _sheet_scroll_input(const Ref<InputEvent> &p_event);
231 void _sheet_add_frames();
232 void _sheet_zoom_on_position(float p_zoom, const Vector2 &p_position);
233 void _sheet_zoom_in();
234 void _sheet_zoom_out();
235 void _sheet_zoom_reset();
236 void _sheet_order_selected(int p_option);
237 void _sheet_select_all_frames();
238 void _sheet_clear_all_frames();
239 void _sheet_sort_frames();
240 void _toggle_show_settings();
241 void _update_show_settings();
242
243 void _edit();
244 void _regist_scene_undo(EditorUndoRedoManager *undo_redo);
245 void _fetch_sprite_node();
246 void _remove_sprite_node();
247
248 bool sprite_node_updating = false;
249 void _sync_animation();
250
251 void _select_animation(const String &p_name, bool p_update_node = true);
252 void _rename_node_animation(EditorUndoRedoManager *undo_redo, bool is_undo, const String &p_filter, const String &p_new_animation, const String &p_new_autoplay);
253
254protected:
255 void _notification(int p_what);
256 void _node_removed(Node *p_node);
257 static void _bind_methods();
258
259public:
260 void edit(Ref<SpriteFrames> p_frames);
261 SpriteFramesEditor();
262};
263
264class SpriteFramesEditorPlugin : public EditorPlugin {
265 GDCLASS(SpriteFramesEditorPlugin, EditorPlugin);
266
267 SpriteFramesEditor *frames_editor = nullptr;
268 Button *button = nullptr;
269
270public:
271 virtual String get_name() const override { return "SpriteFrames"; }
272 bool has_main_screen() const override { return false; }
273 virtual void edit(Object *p_object) override;
274 virtual bool handles(Object *p_object) const override;
275 virtual void make_visible(bool p_visible) override;
276
277 SpriteFramesEditorPlugin();
278 ~SpriteFramesEditorPlugin();
279};
280
281#endif // SPRITE_FRAMES_EDITOR_PLUGIN_H
282