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