sprite_frames_editor_plugin.cpp 37 KB

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