sprite_frames_editor_plugin.cpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. /*************************************************************************/
  2. /* sprite_frames_editor_plugin.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  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. #include "sprite_frames_editor_plugin.h"
  31. #include "core/io/resource_loader.h"
  32. #include "core/project_settings.h"
  33. #include "editor/editor_scale.h"
  34. #include "editor/editor_settings.h"
  35. #include "scene/3d/sprite_3d.h"
  36. #include "scene/gui/center_container.h"
  37. #include "scene/gui/margin_container.h"
  38. #include "scene/gui/panel_container.h"
  39. void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) {
  40. }
  41. void SpriteFramesEditor::_open_sprite_sheet() {
  42. file_split_sheet->clear_filters();
  43. List<String> extensions;
  44. ResourceLoader::get_recognized_extensions_for_type("Texture2D", &extensions);
  45. for (int i = 0; i < extensions.size(); i++) {
  46. file_split_sheet->add_filter("*." + extensions[i]);
  47. }
  48. file_split_sheet->popup_file_dialog();
  49. }
  50. void SpriteFramesEditor::_sheet_preview_draw() {
  51. Size2i size = split_sheet_preview->get_size();
  52. int h = split_sheet_h->get_value();
  53. int v = split_sheet_v->get_value();
  54. int width = size.width / h;
  55. int height = size.height / v;
  56. const float a = 0.3;
  57. for (int i = 1; i < h; i++) {
  58. int x = i * width;
  59. split_sheet_preview->draw_line(Point2(x, 0), Point2(x, size.height), Color(1, 1, 1, a));
  60. split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, size.height), Color(0, 0, 0, a));
  61. for (int j = 1; j < v; j++) {
  62. int y = j * height;
  63. split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a));
  64. split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a));
  65. }
  66. }
  67. if (frames_selected.size() == 0) {
  68. split_sheet_dialog->get_ok()->set_disabled(true);
  69. split_sheet_dialog->get_ok()->set_text(TTR("No Frames Selected"));
  70. return;
  71. }
  72. Color accent = get_theme_color("accent_color", "Editor");
  73. for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
  74. int idx = E->get();
  75. int xp = idx % h;
  76. int yp = (idx - xp) / h;
  77. int x = xp * width;
  78. int y = yp * height;
  79. split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 0.35), true);
  80. split_sheet_preview->draw_rect(Rect2(x + 0, y + 0, width - 0, height - 0), Color(0, 0, 0, 1), false);
  81. split_sheet_preview->draw_rect(Rect2(x + 1, y + 1, width - 2, height - 2), Color(0, 0, 0, 1), false);
  82. split_sheet_preview->draw_rect(Rect2(x + 2, y + 2, width - 4, height - 4), accent, false);
  83. split_sheet_preview->draw_rect(Rect2(x + 3, y + 3, width - 6, height - 6), accent, false);
  84. split_sheet_preview->draw_rect(Rect2(x + 4, y + 4, width - 8, height - 8), Color(0, 0, 0, 1), false);
  85. split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 1), false);
  86. }
  87. split_sheet_dialog->get_ok()->set_disabled(false);
  88. split_sheet_dialog->get_ok()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size()));
  89. }
  90. void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) {
  91. Ref<InputEventMouseButton> mb = p_event;
  92. if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
  93. Size2i size = split_sheet_preview->get_size();
  94. int h = split_sheet_h->get_value();
  95. int v = split_sheet_v->get_value();
  96. int x = CLAMP(int(mb->get_position().x) * h / size.width, 0, h - 1);
  97. int y = CLAMP(int(mb->get_position().y) * v / size.height, 0, v - 1);
  98. int idx = h * y + x;
  99. if (mb->get_shift() && last_frame_selected >= 0) {
  100. //select multiple
  101. int from = idx;
  102. int to = last_frame_selected;
  103. if (from > to) {
  104. SWAP(from, to);
  105. }
  106. for (int i = from; i <= to; i++) {
  107. if (mb->get_control()) {
  108. frames_selected.erase(i);
  109. } else {
  110. frames_selected.insert(i);
  111. }
  112. }
  113. } else {
  114. if (frames_selected.has(idx)) {
  115. frames_selected.erase(idx);
  116. } else {
  117. frames_selected.insert(idx);
  118. }
  119. }
  120. last_frame_selected = idx;
  121. split_sheet_preview->update();
  122. }
  123. }
  124. void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
  125. const Ref<InputEventMouseButton> mb = p_event;
  126. if (mb.is_valid()) {
  127. // Zoom in/out using Ctrl + mouse wheel. This is done on the ScrollContainer
  128. // to allow performing this action anywhere, even if the cursor isn't
  129. // hovering the texture in the workspace.
  130. if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
  131. _sheet_zoom_in();
  132. // Don't scroll up after zooming in.
  133. accept_event();
  134. } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
  135. _sheet_zoom_out();
  136. // Don't scroll down after zooming out.
  137. accept_event();
  138. }
  139. }
  140. }
  141. void SpriteFramesEditor::_sheet_add_frames() {
  142. Size2i size = split_sheet_preview->get_texture()->get_size();
  143. int h = split_sheet_h->get_value();
  144. int v = split_sheet_v->get_value();
  145. undo_redo->create_action(TTR("Add Frame"));
  146. int fc = frames->get_frame_count(edited_anim);
  147. AtlasTexture *atlas_source = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture());
  148. Rect2 region_rect = Rect2();
  149. if (atlas_source && atlas_source->get_atlas().is_valid()) {
  150. region_rect = atlas_source->get_region();
  151. }
  152. for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
  153. int idx = E->get();
  154. int width = size.width / h;
  155. int height = size.height / v;
  156. int xp = idx % h;
  157. int yp = (idx - xp) / h;
  158. int x = (xp * width) + region_rect.position.x;
  159. int y = (yp * height) + region_rect.position.y;
  160. Ref<AtlasTexture> at;
  161. at.instance();
  162. at->set_atlas(split_sheet_preview->get_texture());
  163. at->set_region(Rect2(x, y, width, height));
  164. undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1);
  165. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);
  166. }
  167. undo_redo->add_do_method(this, "_update_library");
  168. undo_redo->add_undo_method(this, "_update_library");
  169. undo_redo->commit_action();
  170. }
  171. void SpriteFramesEditor::_sheet_zoom_in() {
  172. if (sheet_zoom < max_sheet_zoom) {
  173. sheet_zoom *= scale_ratio;
  174. Size2 texture_size = split_sheet_preview->get_texture()->get_size();
  175. split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
  176. }
  177. }
  178. void SpriteFramesEditor::_sheet_zoom_out() {
  179. if (sheet_zoom > min_sheet_zoom) {
  180. sheet_zoom /= scale_ratio;
  181. Size2 texture_size = split_sheet_preview->get_texture()->get_size();
  182. split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
  183. }
  184. }
  185. void SpriteFramesEditor::_sheet_zoom_reset() {
  186. sheet_zoom = 1.f;
  187. Size2 texture_size = split_sheet_preview->get_texture()->get_size();
  188. split_sheet_preview->set_custom_minimum_size(texture_size * sheet_zoom);
  189. }
  190. void SpriteFramesEditor::_sheet_select_clear_all_frames() {
  191. bool should_clear = true;
  192. for (int i = 0; i < split_sheet_h->get_value() * split_sheet_v->get_value(); i++) {
  193. if (!frames_selected.has(i)) {
  194. frames_selected.insert(i);
  195. should_clear = false;
  196. }
  197. }
  198. if (should_clear) {
  199. frames_selected.clear();
  200. }
  201. split_sheet_preview->update();
  202. }
  203. void SpriteFramesEditor::_sheet_spin_changed(double) {
  204. frames_selected.clear();
  205. last_frame_selected = -1;
  206. split_sheet_preview->update();
  207. }
  208. void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
  209. Ref<Resource> texture = ResourceLoader::load(p_file);
  210. if (!texture.is_valid()) {
  211. EditorNode::get_singleton()->show_warning(TTR("Unable to load images"));
  212. ERR_FAIL_COND(!texture.is_valid());
  213. }
  214. bool new_texture = texture != split_sheet_preview->get_texture();
  215. frames_selected.clear();
  216. last_frame_selected = -1;
  217. split_sheet_preview->set_texture(texture);
  218. if (new_texture) {
  219. //different texture, reset to 4x4
  220. split_sheet_h->set_value(4);
  221. split_sheet_v->set_value(4);
  222. //reset zoom
  223. _sheet_zoom_reset();
  224. }
  225. split_sheet_dialog->popup_centered_ratio(0.65);
  226. }
  227. void SpriteFramesEditor::_notification(int p_what) {
  228. switch (p_what) {
  229. case NOTIFICATION_ENTER_TREE: {
  230. load->set_icon(get_theme_icon("Load", "EditorIcons"));
  231. load_sheet->set_icon(get_theme_icon("SpriteSheet", "EditorIcons"));
  232. copy->set_icon(get_theme_icon("ActionCopy", "EditorIcons"));
  233. paste->set_icon(get_theme_icon("ActionPaste", "EditorIcons"));
  234. empty->set_icon(get_theme_icon("InsertBefore", "EditorIcons"));
  235. empty2->set_icon(get_theme_icon("InsertAfter", "EditorIcons"));
  236. move_up->set_icon(get_theme_icon("MoveLeft", "EditorIcons"));
  237. move_down->set_icon(get_theme_icon("MoveRight", "EditorIcons"));
  238. _delete->set_icon(get_theme_icon("Remove", "EditorIcons"));
  239. zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
  240. zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
  241. zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
  242. new_anim->set_icon(get_theme_icon("New", "EditorIcons"));
  243. remove_anim->set_icon(get_theme_icon("Remove", "EditorIcons"));
  244. split_sheet_zoom_out->set_icon(get_theme_icon("ZoomLess", "EditorIcons"));
  245. split_sheet_zoom_1->set_icon(get_theme_icon("ZoomReset", "EditorIcons"));
  246. split_sheet_zoom_in->set_icon(get_theme_icon("ZoomMore", "EditorIcons"));
  247. [[fallthrough]];
  248. }
  249. case NOTIFICATION_THEME_CHANGED: {
  250. splite_sheet_scroll->add_theme_style_override("bg", get_theme_stylebox("bg", "Tree"));
  251. } break;
  252. case NOTIFICATION_READY: {
  253. add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
  254. } break;
  255. }
  256. }
  257. void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_at_pos) {
  258. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  259. List<Ref<Texture2D>> resources;
  260. for (int i = 0; i < p_path.size(); i++) {
  261. Ref<Texture2D> resource;
  262. resource = ResourceLoader::load(p_path[i]);
  263. if (resource.is_null()) {
  264. dialog->set_text(TTR("ERROR: Couldn't load frame resource!"));
  265. dialog->set_title(TTR("Error!"));
  266. //dialog->get_cancel()->set_text("Close");
  267. dialog->get_ok()->set_text(TTR("Close"));
  268. dialog->popup_centered();
  269. return; ///beh should show an error i guess
  270. }
  271. resources.push_back(resource);
  272. }
  273. if (resources.empty()) {
  274. return;
  275. }
  276. undo_redo->create_action(TTR("Add Frame"));
  277. int fc = frames->get_frame_count(edited_anim);
  278. int count = 0;
  279. for (List<Ref<Texture2D>>::Element *E = resources.front(); E; E = E->next()) {
  280. undo_redo->add_do_method(frames, "add_frame", edited_anim, E->get(), p_at_pos == -1 ? -1 : p_at_pos + count);
  281. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
  282. count++;
  283. }
  284. undo_redo->add_do_method(this, "_update_library");
  285. undo_redo->add_undo_method(this, "_update_library");
  286. undo_redo->commit_action();
  287. }
  288. void SpriteFramesEditor::_load_pressed() {
  289. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  290. loading_scene = false;
  291. file->clear_filters();
  292. List<String> extensions;
  293. ResourceLoader::get_recognized_extensions_for_type("Texture2D", &extensions);
  294. for (int i = 0; i < extensions.size(); i++) {
  295. file->add_filter("*." + extensions[i]);
  296. }
  297. file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
  298. file->popup_file_dialog();
  299. }
  300. void SpriteFramesEditor::_paste_pressed() {
  301. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  302. Ref<Texture2D> r = EditorSettings::get_singleton()->get_resource_clipboard();
  303. if (!r.is_valid()) {
  304. dialog->set_text(TTR("Resource clipboard is empty or not a texture!"));
  305. dialog->set_title(TTR("Error!"));
  306. //dialog->get_cancel()->set_text("Close");
  307. dialog->get_ok()->set_text(TTR("Close"));
  308. dialog->popup_centered();
  309. return; ///beh should show an error i guess
  310. }
  311. undo_redo->create_action(TTR("Paste Frame"));
  312. undo_redo->add_do_method(frames, "add_frame", edited_anim, r);
  313. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, frames->get_frame_count(edited_anim));
  314. undo_redo->add_do_method(this, "_update_library");
  315. undo_redo->add_undo_method(this, "_update_library");
  316. undo_redo->commit_action();
  317. }
  318. void SpriteFramesEditor::_copy_pressed() {
  319. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  320. if (tree->get_current() < 0) {
  321. return;
  322. }
  323. Ref<Texture2D> r = frames->get_frame(edited_anim, tree->get_current());
  324. if (!r.is_valid()) {
  325. return;
  326. }
  327. EditorSettings::get_singleton()->set_resource_clipboard(r);
  328. }
  329. void SpriteFramesEditor::_empty_pressed() {
  330. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  331. int from = -1;
  332. if (tree->get_current() >= 0) {
  333. from = tree->get_current();
  334. sel = from;
  335. } else {
  336. from = frames->get_frame_count(edited_anim);
  337. }
  338. Ref<Texture2D> r;
  339. undo_redo->create_action(TTR("Add Empty"));
  340. undo_redo->add_do_method(frames, "add_frame", edited_anim, r, from);
  341. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from);
  342. undo_redo->add_do_method(this, "_update_library");
  343. undo_redo->add_undo_method(this, "_update_library");
  344. undo_redo->commit_action();
  345. }
  346. void SpriteFramesEditor::_empty2_pressed() {
  347. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  348. int from = -1;
  349. if (tree->get_current() >= 0) {
  350. from = tree->get_current();
  351. sel = from;
  352. } else {
  353. from = frames->get_frame_count(edited_anim);
  354. }
  355. Ref<Texture2D> r;
  356. undo_redo->create_action(TTR("Add Empty"));
  357. undo_redo->add_do_method(frames, "add_frame", edited_anim, r, from + 1);
  358. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, from + 1);
  359. undo_redo->add_do_method(this, "_update_library");
  360. undo_redo->add_undo_method(this, "_update_library");
  361. undo_redo->commit_action();
  362. }
  363. void SpriteFramesEditor::_up_pressed() {
  364. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  365. if (tree->get_current() < 0) {
  366. return;
  367. }
  368. int to_move = tree->get_current();
  369. if (to_move < 1) {
  370. return;
  371. }
  372. sel = to_move;
  373. sel -= 1;
  374. undo_redo->create_action(TTR("Delete Resource"));
  375. undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move - 1));
  376. undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame(edited_anim, to_move));
  377. undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move));
  378. undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move - 1, frames->get_frame(edited_anim, to_move - 1));
  379. undo_redo->add_do_method(this, "_update_library");
  380. undo_redo->add_undo_method(this, "_update_library");
  381. undo_redo->commit_action();
  382. }
  383. void SpriteFramesEditor::_down_pressed() {
  384. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  385. if (tree->get_current() < 0) {
  386. return;
  387. }
  388. int to_move = tree->get_current();
  389. if (to_move < 0 || to_move >= frames->get_frame_count(edited_anim) - 1) {
  390. return;
  391. }
  392. sel = to_move;
  393. sel += 1;
  394. undo_redo->create_action(TTR("Delete Resource"));
  395. undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move + 1));
  396. undo_redo->add_do_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame(edited_anim, to_move));
  397. undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move, frames->get_frame(edited_anim, to_move));
  398. undo_redo->add_undo_method(frames, "set_frame", edited_anim, to_move + 1, frames->get_frame(edited_anim, to_move + 1));
  399. undo_redo->add_do_method(this, "_update_library");
  400. undo_redo->add_undo_method(this, "_update_library");
  401. undo_redo->commit_action();
  402. }
  403. void SpriteFramesEditor::_delete_pressed() {
  404. ERR_FAIL_COND(!frames->has_animation(edited_anim));
  405. if (tree->get_current() < 0) {
  406. return;
  407. }
  408. int to_delete = tree->get_current();
  409. if (to_delete < 0 || to_delete >= frames->get_frame_count(edited_anim)) {
  410. return;
  411. }
  412. undo_redo->create_action(TTR("Delete Resource"));
  413. undo_redo->add_do_method(frames, "remove_frame", edited_anim, to_delete);
  414. undo_redo->add_undo_method(frames, "add_frame", edited_anim, frames->get_frame(edited_anim, to_delete), to_delete);
  415. undo_redo->add_do_method(this, "_update_library");
  416. undo_redo->add_undo_method(this, "_update_library");
  417. undo_redo->commit_action();
  418. }
  419. void SpriteFramesEditor::_animation_select() {
  420. if (updating) {
  421. return;
  422. }
  423. if (frames->has_animation(edited_anim)) {
  424. double value = anim_speed->get_line_edit()->get_text().to_float();
  425. if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) {
  426. _animation_fps_changed(value);
  427. }
  428. }
  429. TreeItem *selected = animations->get_selected();
  430. ERR_FAIL_COND(!selected);
  431. edited_anim = selected->get_text(0);
  432. _update_library(true);
  433. }
  434. static void _find_anim_sprites(Node *p_node, List<Node *> *r_nodes, Ref<SpriteFrames> p_sfames) {
  435. Node *edited = EditorNode::get_singleton()->get_edited_scene();
  436. if (!edited) {
  437. return;
  438. }
  439. if (p_node != edited && p_node->get_owner() != edited) {
  440. return;
  441. }
  442. {
  443. AnimatedSprite2D *as = Object::cast_to<AnimatedSprite2D>(p_node);
  444. if (as && as->get_sprite_frames() == p_sfames) {
  445. r_nodes->push_back(p_node);
  446. }
  447. }
  448. {
  449. AnimatedSprite3D *as = Object::cast_to<AnimatedSprite3D>(p_node);
  450. if (as && as->get_sprite_frames() == p_sfames) {
  451. r_nodes->push_back(p_node);
  452. }
  453. }
  454. for (int i = 0; i < p_node->get_child_count(); i++) {
  455. _find_anim_sprites(p_node->get_child(i), r_nodes, p_sfames);
  456. }
  457. }
  458. void SpriteFramesEditor::_animation_name_edited() {
  459. if (updating) {
  460. return;
  461. }
  462. if (!frames->has_animation(edited_anim)) {
  463. return;
  464. }
  465. TreeItem *edited = animations->get_edited();
  466. if (!edited) {
  467. return;
  468. }
  469. String new_name = edited->get_text(0);
  470. if (new_name == String(edited_anim)) {
  471. return;
  472. }
  473. new_name = new_name.replace("/", "_").replace(",", " ");
  474. String name = new_name;
  475. int counter = 0;
  476. while (frames->has_animation(name)) {
  477. counter++;
  478. name = new_name + " " + itos(counter);
  479. }
  480. List<Node *> nodes;
  481. _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
  482. undo_redo->create_action(TTR("Rename Animation"));
  483. undo_redo->add_do_method(frames, "rename_animation", edited_anim, name);
  484. undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim);
  485. for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
  486. String current = E->get()->call("get_animation");
  487. undo_redo->add_do_method(E->get(), "set_animation", name);
  488. undo_redo->add_undo_method(E->get(), "set_animation", edited_anim);
  489. }
  490. undo_redo->add_do_method(this, "_update_library");
  491. undo_redo->add_undo_method(this, "_update_library");
  492. edited_anim = new_name;
  493. undo_redo->commit_action();
  494. }
  495. void SpriteFramesEditor::_animation_add() {
  496. String name = "New Anim";
  497. int counter = 0;
  498. while (frames->has_animation(name)) {
  499. counter++;
  500. name = "New Anim " + itos(counter);
  501. }
  502. List<Node *> nodes;
  503. _find_anim_sprites(EditorNode::get_singleton()->get_edited_scene(), &nodes, Ref<SpriteFrames>(frames));
  504. undo_redo->create_action(TTR("Add Animation"));
  505. undo_redo->add_do_method(frames, "add_animation", name);
  506. undo_redo->add_undo_method(frames, "remove_animation", name);
  507. undo_redo->add_do_method(this, "_update_library");
  508. undo_redo->add_undo_method(this, "_update_library");
  509. for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
  510. String current = E->get()->call("get_animation");
  511. undo_redo->add_do_method(E->get(), "set_animation", name);
  512. undo_redo->add_undo_method(E->get(), "set_animation", current);
  513. }
  514. edited_anim = name;
  515. undo_redo->commit_action();
  516. animations->grab_focus();
  517. }
  518. void SpriteFramesEditor::_animation_remove() {
  519. if (updating) {
  520. return;
  521. }
  522. if (!frames->has_animation(edited_anim)) {
  523. return;
  524. }
  525. delete_dialog->set_text(TTR("Delete Animation?"));
  526. delete_dialog->popup_centered();
  527. }
  528. void SpriteFramesEditor::_animation_remove_confirmed() {
  529. undo_redo->create_action(TTR("Remove Animation"));
  530. undo_redo->add_do_method(frames, "remove_animation", edited_anim);
  531. undo_redo->add_undo_method(frames, "add_animation", edited_anim);
  532. undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
  533. undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
  534. int fc = frames->get_frame_count(edited_anim);
  535. for (int i = 0; i < fc; i++) {
  536. Ref<Texture2D> frame = frames->get_frame(edited_anim, i);
  537. undo_redo->add_undo_method(frames, "add_frame", edited_anim, frame);
  538. }
  539. undo_redo->add_do_method(this, "_update_library");
  540. undo_redo->add_undo_method(this, "_update_library");
  541. edited_anim = StringName();
  542. undo_redo->commit_action();
  543. }
  544. void SpriteFramesEditor::_animation_loop_changed() {
  545. if (updating) {
  546. return;
  547. }
  548. undo_redo->create_action(TTR("Change Animation Loop"));
  549. undo_redo->add_do_method(frames, "set_animation_loop", edited_anim, anim_loop->is_pressed());
  550. undo_redo->add_undo_method(frames, "set_animation_loop", edited_anim, frames->get_animation_loop(edited_anim));
  551. undo_redo->add_do_method(this, "_update_library", true);
  552. undo_redo->add_undo_method(this, "_update_library", true);
  553. undo_redo->commit_action();
  554. }
  555. void SpriteFramesEditor::_animation_fps_changed(double p_value) {
  556. if (updating) {
  557. return;
  558. }
  559. undo_redo->create_action(TTR("Change Animation FPS"), UndoRedo::MERGE_ENDS);
  560. undo_redo->add_do_method(frames, "set_animation_speed", edited_anim, p_value);
  561. undo_redo->add_undo_method(frames, "set_animation_speed", edited_anim, frames->get_animation_speed(edited_anim));
  562. undo_redo->add_do_method(this, "_update_library", true);
  563. undo_redo->add_undo_method(this, "_update_library", true);
  564. undo_redo->commit_action();
  565. }
  566. void SpriteFramesEditor::_tree_input(const Ref<InputEvent> &p_event) {
  567. const Ref<InputEventMouseButton> mb = p_event;
  568. if (mb.is_valid()) {
  569. if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) {
  570. _zoom_in();
  571. // Don't scroll up after zooming in.
  572. accept_event();
  573. } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) {
  574. _zoom_out();
  575. // Don't scroll down after zooming out.
  576. accept_event();
  577. }
  578. }
  579. }
  580. void SpriteFramesEditor::_zoom_in() {
  581. // Do not zoom in or out with no visible frames
  582. if (frames->get_frame_count(edited_anim) <= 0) {
  583. return;
  584. }
  585. if (thumbnail_zoom < max_thumbnail_zoom) {
  586. thumbnail_zoom *= scale_ratio;
  587. int thumbnail_size = (int)(thumbnail_default_size * thumbnail_zoom);
  588. tree->set_fixed_column_width(thumbnail_size * 3 / 2);
  589. tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
  590. }
  591. }
  592. void SpriteFramesEditor::_zoom_out() {
  593. // Do not zoom in or out with no visible frames
  594. if (frames->get_frame_count(edited_anim) <= 0) {
  595. return;
  596. }
  597. if (thumbnail_zoom > min_thumbnail_zoom) {
  598. thumbnail_zoom /= scale_ratio;
  599. int thumbnail_size = (int)(thumbnail_default_size * thumbnail_zoom);
  600. tree->set_fixed_column_width(thumbnail_size * 3 / 2);
  601. tree->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
  602. }
  603. }
  604. void SpriteFramesEditor::_zoom_reset() {
  605. thumbnail_zoom = 1.0f;
  606. tree->set_fixed_column_width(thumbnail_default_size * 3 / 2);
  607. tree->set_fixed_icon_size(Size2(thumbnail_default_size, thumbnail_default_size));
  608. }
  609. void SpriteFramesEditor::_update_library(bool p_skip_selector) {
  610. updating = true;
  611. if (!p_skip_selector) {
  612. animations->clear();
  613. TreeItem *anim_root = animations->create_item();
  614. List<StringName> anim_names;
  615. frames->get_animation_list(&anim_names);
  616. anim_names.sort_custom<StringName::AlphCompare>();
  617. for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) {
  618. String name = E->get();
  619. TreeItem *it = animations->create_item(anim_root);
  620. it->set_metadata(0, name);
  621. it->set_text(0, name);
  622. it->set_editable(0, true);
  623. if (E->get() == edited_anim) {
  624. it->select(0);
  625. }
  626. }
  627. }
  628. tree->clear();
  629. if (!frames->has_animation(edited_anim)) {
  630. updating = false;
  631. return;
  632. }
  633. if (sel >= frames->get_frame_count(edited_anim)) {
  634. sel = frames->get_frame_count(edited_anim) - 1;
  635. } else if (sel < 0 && frames->get_frame_count(edited_anim)) {
  636. sel = 0;
  637. }
  638. for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
  639. String name;
  640. Ref<Texture2D> icon;
  641. if (frames->get_frame(edited_anim, i).is_null()) {
  642. name = itos(i) + ": " + TTR("(empty)");
  643. } else {
  644. name = itos(i) + ": " + frames->get_frame(edited_anim, i)->get_name();
  645. icon = frames->get_frame(edited_anim, i);
  646. }
  647. tree->add_item(name, icon);
  648. if (frames->get_frame(edited_anim, i).is_valid()) {
  649. tree->set_item_tooltip(tree->get_item_count() - 1, frames->get_frame(edited_anim, i)->get_path());
  650. }
  651. if (sel == i) {
  652. tree->select(tree->get_item_count() - 1);
  653. }
  654. }
  655. anim_speed->set_value(frames->get_animation_speed(edited_anim));
  656. anim_loop->set_pressed(frames->get_animation_loop(edited_anim));
  657. updating = false;
  658. //player->add_resource("default",resource);
  659. }
  660. void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
  661. if (frames == p_frames) {
  662. return;
  663. }
  664. frames = p_frames;
  665. if (p_frames) {
  666. if (!p_frames->has_animation(edited_anim)) {
  667. List<StringName> anim_names;
  668. frames->get_animation_list(&anim_names);
  669. anim_names.sort_custom<StringName::AlphCompare>();
  670. if (anim_names.size()) {
  671. edited_anim = anim_names.front()->get();
  672. } else {
  673. edited_anim = StringName();
  674. }
  675. }
  676. _update_library();
  677. // Clear zoom and split sheet texture
  678. split_sheet_preview->set_texture(Ref<Texture2D>());
  679. _zoom_reset();
  680. } else {
  681. hide();
  682. }
  683. }
  684. Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
  685. if (!frames->has_animation(edited_anim)) {
  686. return false;
  687. }
  688. int idx = tree->get_item_at_position(p_point, true);
  689. if (idx < 0 || idx >= frames->get_frame_count(edited_anim)) {
  690. return Variant();
  691. }
  692. RES frame = frames->get_frame(edited_anim, idx);
  693. if (frame.is_null()) {
  694. return Variant();
  695. }
  696. Dictionary drag_data = EditorNode::get_singleton()->drag_resource(frame, p_from);
  697. drag_data["frame"] = idx; // store the frame, in case we want to reorder frames inside 'drop_data_fw'
  698. return drag_data;
  699. }
  700. bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
  701. Dictionary d = p_data;
  702. if (!d.has("type")) {
  703. return false;
  704. }
  705. // reordering frames
  706. if (d.has("from") && (Object *)(d["from"]) == tree) {
  707. return true;
  708. }
  709. if (String(d["type"]) == "resource" && d.has("resource")) {
  710. RES r = d["resource"];
  711. Ref<Texture2D> texture = r;
  712. if (texture.is_valid()) {
  713. return true;
  714. }
  715. }
  716. if (String(d["type"]) == "files") {
  717. Vector<String> files = d["files"];
  718. if (files.size() == 0) {
  719. return false;
  720. }
  721. for (int i = 0; i < files.size(); i++) {
  722. String file = files[i];
  723. String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
  724. if (!ClassDB::is_parent_class(ftype, "Texture2D")) {
  725. return false;
  726. }
  727. }
  728. return true;
  729. }
  730. return false;
  731. }
  732. void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
  733. if (!can_drop_data_fw(p_point, p_data, p_from)) {
  734. return;
  735. }
  736. Dictionary d = p_data;
  737. if (!d.has("type")) {
  738. return;
  739. }
  740. int at_pos = tree->get_item_at_position(p_point, true);
  741. if (String(d["type"]) == "resource" && d.has("resource")) {
  742. RES r = d["resource"];
  743. Ref<Texture2D> texture = r;
  744. if (texture.is_valid()) {
  745. bool reorder = false;
  746. if (d.has("from") && (Object *)(d["from"]) == tree) {
  747. reorder = true;
  748. }
  749. if (reorder) { //drop is from reordering frames
  750. int from_frame = -1;
  751. if (d.has("frame")) {
  752. from_frame = d["frame"];
  753. }
  754. undo_redo->create_action(TTR("Move Frame"));
  755. undo_redo->add_do_method(frames, "remove_frame", edited_anim, from_frame == -1 ? frames->get_frame_count(edited_anim) : from_frame);
  756. undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos);
  757. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) - 1 : at_pos);
  758. undo_redo->add_undo_method(frames, "add_frame", edited_anim, texture, from_frame);
  759. undo_redo->add_do_method(this, "_update_library");
  760. undo_redo->add_undo_method(this, "_update_library");
  761. undo_redo->commit_action();
  762. } else {
  763. undo_redo->create_action(TTR("Add Frame"));
  764. undo_redo->add_do_method(frames, "add_frame", edited_anim, texture, at_pos == -1 ? -1 : at_pos);
  765. undo_redo->add_undo_method(frames, "remove_frame", edited_anim, at_pos == -1 ? frames->get_frame_count(edited_anim) : at_pos);
  766. undo_redo->add_do_method(this, "_update_library");
  767. undo_redo->add_undo_method(this, "_update_library");
  768. undo_redo->commit_action();
  769. }
  770. }
  771. }
  772. if (String(d["type"]) == "files") {
  773. Vector<String> files = d["files"];
  774. _file_load_request(files, at_pos);
  775. }
  776. }
  777. void SpriteFramesEditor::_bind_methods() {
  778. ClassDB::bind_method(D_METHOD("_update_library", "skipsel"), &SpriteFramesEditor::_update_library, DEFVAL(false));
  779. ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw);
  780. ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw);
  781. ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw);
  782. }
  783. SpriteFramesEditor::SpriteFramesEditor() {
  784. VBoxContainer *vbc_animlist = memnew(VBoxContainer);
  785. add_child(vbc_animlist);
  786. vbc_animlist->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
  787. VBoxContainer *sub_vb = memnew(VBoxContainer);
  788. vbc_animlist->add_margin_child(TTR("Animations:"), sub_vb, true);
  789. sub_vb->set_v_size_flags(SIZE_EXPAND_FILL);
  790. HBoxContainer *hbc_animlist = memnew(HBoxContainer);
  791. sub_vb->add_child(hbc_animlist);
  792. new_anim = memnew(Button);
  793. new_anim->set_flat(true);
  794. new_anim->set_tooltip(TTR("New Animation"));
  795. hbc_animlist->add_child(new_anim);
  796. new_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_add));
  797. remove_anim = memnew(Button);
  798. remove_anim->set_flat(true);
  799. remove_anim->set_tooltip(TTR("Remove Animation"));
  800. hbc_animlist->add_child(remove_anim);
  801. remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove));
  802. animations = memnew(Tree);
  803. sub_vb->add_child(animations);
  804. animations->set_v_size_flags(SIZE_EXPAND_FILL);
  805. animations->set_hide_root(true);
  806. animations->connect("cell_selected", callable_mp(this, &SpriteFramesEditor::_animation_select));
  807. animations->connect("item_edited", callable_mp(this, &SpriteFramesEditor::_animation_name_edited));
  808. animations->set_allow_reselect(true);
  809. anim_speed = memnew(SpinBox);
  810. vbc_animlist->add_margin_child(TTR("Speed (FPS):"), anim_speed);
  811. anim_speed->set_min(0);
  812. anim_speed->set_max(100);
  813. anim_speed->set_step(0.01);
  814. anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_fps_changed));
  815. anim_loop = memnew(CheckButton);
  816. anim_loop->set_text(TTR("Loop"));
  817. vbc_animlist->add_child(anim_loop);
  818. anim_loop->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_loop_changed));
  819. VBoxContainer *vbc = memnew(VBoxContainer);
  820. add_child(vbc);
  821. vbc->set_h_size_flags(SIZE_EXPAND_FILL);
  822. sub_vb = memnew(VBoxContainer);
  823. vbc->add_margin_child(TTR("Animation Frames:"), sub_vb, true);
  824. HBoxContainer *hbc = memnew(HBoxContainer);
  825. sub_vb->add_child(hbc);
  826. load = memnew(Button);
  827. load->set_flat(true);
  828. load->set_tooltip(TTR("Add a Texture from File"));
  829. hbc->add_child(load);
  830. load_sheet = memnew(Button);
  831. load_sheet->set_flat(true);
  832. load_sheet->set_tooltip(TTR("Add Frames from a Sprite Sheet"));
  833. hbc->add_child(load_sheet);
  834. hbc->add_child(memnew(VSeparator));
  835. copy = memnew(Button);
  836. copy->set_flat(true);
  837. copy->set_tooltip(TTR("Copy"));
  838. hbc->add_child(copy);
  839. paste = memnew(Button);
  840. paste->set_flat(true);
  841. paste->set_tooltip(TTR("Paste"));
  842. hbc->add_child(paste);
  843. hbc->add_child(memnew(VSeparator));
  844. empty = memnew(Button);
  845. empty->set_flat(true);
  846. empty->set_tooltip(TTR("Insert Empty (Before)"));
  847. hbc->add_child(empty);
  848. empty2 = memnew(Button);
  849. empty2->set_flat(true);
  850. empty2->set_tooltip(TTR("Insert Empty (After)"));
  851. hbc->add_child(empty2);
  852. hbc->add_child(memnew(VSeparator));
  853. move_up = memnew(Button);
  854. move_up->set_flat(true);
  855. move_up->set_tooltip(TTR("Move (Before)"));
  856. hbc->add_child(move_up);
  857. move_down = memnew(Button);
  858. move_down->set_flat(true);
  859. move_down->set_tooltip(TTR("Move (After)"));
  860. hbc->add_child(move_down);
  861. _delete = memnew(Button);
  862. _delete->set_flat(true);
  863. _delete->set_tooltip(TTR("Delete"));
  864. hbc->add_child(_delete);
  865. hbc->add_spacer();
  866. zoom_out = memnew(Button);
  867. zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_out));
  868. zoom_out->set_flat(true);
  869. zoom_out->set_tooltip(TTR("Zoom Out"));
  870. hbc->add_child(zoom_out);
  871. zoom_1 = memnew(Button);
  872. zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_reset));
  873. zoom_1->set_flat(true);
  874. zoom_1->set_tooltip(TTR("Zoom Reset"));
  875. hbc->add_child(zoom_1);
  876. zoom_in = memnew(Button);
  877. zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_in));
  878. zoom_in->set_flat(true);
  879. zoom_in->set_tooltip(TTR("Zoom In"));
  880. hbc->add_child(zoom_in);
  881. file = memnew(EditorFileDialog);
  882. add_child(file);
  883. tree = memnew(ItemList);
  884. tree->set_v_size_flags(SIZE_EXPAND_FILL);
  885. tree->set_icon_mode(ItemList::ICON_MODE_TOP);
  886. tree->set_max_columns(0);
  887. tree->set_icon_mode(ItemList::ICON_MODE_TOP);
  888. tree->set_max_text_lines(2);
  889. tree->set_drag_forwarding(this);
  890. tree->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_tree_input));
  891. sub_vb->add_child(tree);
  892. dialog = memnew(AcceptDialog);
  893. add_child(dialog);
  894. load->connect("pressed", callable_mp(this, &SpriteFramesEditor::_load_pressed));
  895. load_sheet->connect("pressed", callable_mp(this, &SpriteFramesEditor::_open_sprite_sheet));
  896. _delete->connect("pressed", callable_mp(this, &SpriteFramesEditor::_delete_pressed));
  897. copy->connect("pressed", callable_mp(this, &SpriteFramesEditor::_copy_pressed));
  898. paste->connect("pressed", callable_mp(this, &SpriteFramesEditor::_paste_pressed));
  899. empty->connect("pressed", callable_mp(this, &SpriteFramesEditor::_empty_pressed));
  900. empty2->connect("pressed", callable_mp(this, &SpriteFramesEditor::_empty2_pressed));
  901. move_up->connect("pressed", callable_mp(this, &SpriteFramesEditor::_up_pressed));
  902. move_down->connect("pressed", callable_mp(this, &SpriteFramesEditor::_down_pressed));
  903. file->connect("files_selected", callable_mp(this, &SpriteFramesEditor::_file_load_request), make_binds(-1));
  904. loading_scene = false;
  905. sel = -1;
  906. updating = false;
  907. edited_anim = "default";
  908. delete_dialog = memnew(ConfirmationDialog);
  909. add_child(delete_dialog);
  910. delete_dialog->connect("confirmed", callable_mp(this, &SpriteFramesEditor::_animation_remove_confirmed));
  911. split_sheet_dialog = memnew(ConfirmationDialog);
  912. add_child(split_sheet_dialog);
  913. VBoxContainer *split_sheet_vb = memnew(VBoxContainer);
  914. split_sheet_dialog->add_child(split_sheet_vb);
  915. split_sheet_dialog->set_title(TTR("Select Frames"));
  916. split_sheet_dialog->connect("confirmed", callable_mp(this, &SpriteFramesEditor::_sheet_add_frames));
  917. HBoxContainer *split_sheet_hb = memnew(HBoxContainer);
  918. Label *ss_label = memnew(Label(TTR("Horizontal:")));
  919. split_sheet_hb->add_child(ss_label);
  920. split_sheet_h = memnew(SpinBox);
  921. split_sheet_h->set_min(1);
  922. split_sheet_h->set_max(128);
  923. split_sheet_h->set_step(1);
  924. split_sheet_hb->add_child(split_sheet_h);
  925. split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
  926. ss_label = memnew(Label(TTR("Vertical:")));
  927. split_sheet_hb->add_child(ss_label);
  928. split_sheet_v = memnew(SpinBox);
  929. split_sheet_v->set_min(1);
  930. split_sheet_v->set_max(128);
  931. split_sheet_v->set_step(1);
  932. split_sheet_hb->add_child(split_sheet_v);
  933. split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
  934. split_sheet_hb->add_spacer();
  935. Button *select_clear_all = memnew(Button);
  936. select_clear_all->set_text(TTR("Select/Clear All Frames"));
  937. select_clear_all->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_select_clear_all_frames));
  938. split_sheet_hb->add_child(select_clear_all);
  939. split_sheet_vb->add_child(split_sheet_hb);
  940. PanelContainer *split_sheet_panel = memnew(PanelContainer);
  941. split_sheet_panel->set_h_size_flags(SIZE_EXPAND_FILL);
  942. split_sheet_panel->set_v_size_flags(SIZE_EXPAND_FILL);
  943. split_sheet_vb->add_child(split_sheet_panel);
  944. split_sheet_preview = memnew(TextureRect);
  945. split_sheet_preview->set_expand(true);
  946. split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS);
  947. split_sheet_preview->connect("draw", callable_mp(this, &SpriteFramesEditor::_sheet_preview_draw));
  948. split_sheet_preview->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_preview_input));
  949. splite_sheet_scroll = memnew(ScrollContainer);
  950. splite_sheet_scroll->set_enable_h_scroll(true);
  951. splite_sheet_scroll->set_enable_v_scroll(true);
  952. splite_sheet_scroll->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_sheet_scroll_input));
  953. split_sheet_panel->add_child(splite_sheet_scroll);
  954. CenterContainer *cc = memnew(CenterContainer);
  955. cc->add_child(split_sheet_preview);
  956. cc->set_h_size_flags(SIZE_EXPAND_FILL);
  957. cc->set_v_size_flags(SIZE_EXPAND_FILL);
  958. splite_sheet_scroll->add_child(cc);
  959. MarginContainer *split_sheet_zoom_margin = memnew(MarginContainer);
  960. split_sheet_panel->add_child(split_sheet_zoom_margin);
  961. split_sheet_zoom_margin->set_h_size_flags(0);
  962. split_sheet_zoom_margin->set_v_size_flags(0);
  963. split_sheet_zoom_margin->add_theme_constant_override("margin_top", 5);
  964. split_sheet_zoom_margin->add_theme_constant_override("margin_left", 5);
  965. HBoxContainer *split_sheet_zoom_hb = memnew(HBoxContainer);
  966. split_sheet_zoom_margin->add_child(split_sheet_zoom_hb);
  967. split_sheet_zoom_out = memnew(Button);
  968. split_sheet_zoom_out->set_flat(true);
  969. split_sheet_zoom_out->set_focus_mode(FOCUS_NONE);
  970. split_sheet_zoom_out->set_tooltip(TTR("Zoom Out"));
  971. split_sheet_zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_out));
  972. split_sheet_zoom_hb->add_child(split_sheet_zoom_out);
  973. split_sheet_zoom_1 = memnew(Button);
  974. split_sheet_zoom_1->set_flat(true);
  975. split_sheet_zoom_1->set_focus_mode(FOCUS_NONE);
  976. split_sheet_zoom_1->set_tooltip(TTR("Zoom Reset"));
  977. split_sheet_zoom_1->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_reset));
  978. split_sheet_zoom_hb->add_child(split_sheet_zoom_1);
  979. split_sheet_zoom_in = memnew(Button);
  980. split_sheet_zoom_in->set_flat(true);
  981. split_sheet_zoom_in->set_focus_mode(FOCUS_NONE);
  982. split_sheet_zoom_in->set_tooltip(TTR("Zoom In"));
  983. split_sheet_zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_in));
  984. split_sheet_zoom_hb->add_child(split_sheet_zoom_in);
  985. file_split_sheet = memnew(EditorFileDialog);
  986. file_split_sheet->set_title(TTR("Create Frames from Sprite Sheet"));
  987. file_split_sheet->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
  988. add_child(file_split_sheet);
  989. file_split_sheet->connect("file_selected", callable_mp(this, &SpriteFramesEditor::_prepare_sprite_sheet));
  990. // Config scale.
  991. scale_ratio = 1.2f;
  992. thumbnail_default_size = 96;
  993. thumbnail_zoom = 1.0f;
  994. max_thumbnail_zoom = 8.0f;
  995. min_thumbnail_zoom = 0.1f;
  996. sheet_zoom = 1.0f;
  997. max_sheet_zoom = 16.0f;
  998. min_sheet_zoom = 0.01f;
  999. _zoom_reset();
  1000. }
  1001. void SpriteFramesEditorPlugin::edit(Object *p_object) {
  1002. frames_editor->set_undo_redo(&get_undo_redo());
  1003. SpriteFrames *s;
  1004. AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
  1005. if (animated_sprite) {
  1006. s = *animated_sprite->get_sprite_frames();
  1007. } else {
  1008. AnimatedSprite3D *animated_sprite_3d = Object::cast_to<AnimatedSprite3D>(p_object);
  1009. if (animated_sprite_3d) {
  1010. s = *animated_sprite_3d->get_sprite_frames();
  1011. } else {
  1012. s = Object::cast_to<SpriteFrames>(p_object);
  1013. }
  1014. }
  1015. frames_editor->edit(s);
  1016. }
  1017. bool SpriteFramesEditorPlugin::handles(Object *p_object) const {
  1018. AnimatedSprite2D *animated_sprite = Object::cast_to<AnimatedSprite2D>(p_object);
  1019. AnimatedSprite3D *animated_sprite_3d = Object::cast_to<AnimatedSprite3D>(p_object);
  1020. if (animated_sprite && *animated_sprite->get_sprite_frames()) {
  1021. return true;
  1022. } else if (animated_sprite_3d && *animated_sprite_3d->get_sprite_frames()) {
  1023. return true;
  1024. } else {
  1025. return p_object->is_class("SpriteFrames");
  1026. }
  1027. }
  1028. void SpriteFramesEditorPlugin::make_visible(bool p_visible) {
  1029. if (p_visible) {
  1030. button->show();
  1031. editor->make_bottom_panel_item_visible(frames_editor);
  1032. } else {
  1033. button->hide();
  1034. if (frames_editor->is_visible_in_tree()) {
  1035. editor->hide_bottom_panel();
  1036. }
  1037. }
  1038. }
  1039. SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
  1040. editor = p_node;
  1041. frames_editor = memnew(SpriteFramesEditor);
  1042. frames_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
  1043. button = editor->add_bottom_panel_item(TTR("SpriteFrames"), frames_editor);
  1044. button->hide();
  1045. }
  1046. SpriteFramesEditorPlugin::~SpriteFramesEditorPlugin() {
  1047. }