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