1 /*************************************************************************/
2 /*  animation_player_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 "animation_player_editor_plugin.h"
31 #include "editor/animation_editor.h"
32 #include "editor/editor_settings.h"
33 #include "globals.h"
34 #include "io/resource_loader.h"
35 #include "io/resource_saver.h"
36 #include "os/keyboard.h"
37 
_node_removed(Node * p_node)38 void AnimationPlayerEditor::_node_removed(Node *p_node) {
39 
40 	if (player && player == p_node) {
41 		player = NULL;
42 
43 		set_process(false);
44 
45 		key_editor->set_animation(Ref<Animation>());
46 		key_editor->set_root(NULL);
47 		key_editor->show_select_node_warning(true);
48 		_update_player();
49 		//editor->animation_editor_make_visible(false);
50 	}
51 }
52 
_input_event(InputEvent p_event)53 void AnimationPlayerEditor::_input_event(InputEvent p_event) {
54 }
55 
_notification(int p_what)56 void AnimationPlayerEditor::_notification(int p_what) {
57 
58 	if (p_what == NOTIFICATION_PROCESS) {
59 
60 		if (!player)
61 			return;
62 
63 		updating = true;
64 
65 		if (player->is_playing()) {
66 
67 			{
68 				String animname = player->get_current_animation();
69 
70 				if (player->has_animation(animname)) {
71 					Ref<Animation> anim = player->get_animation(animname);
72 					if (!anim.is_null()) {
73 
74 						frame->set_max(anim->get_length());
75 					}
76 				}
77 			}
78 			frame->set_val(player->get_current_animation_pos());
79 			key_editor->set_anim_pos(player->get_current_animation_pos());
80 			EditorNode::get_singleton()->get_property_editor()->refresh();
81 
82 		} else if (last_active) {
83 			//need the last frame after it stopped
84 
85 			frame->set_val(player->get_current_animation_pos());
86 		}
87 
88 		last_active = player->is_playing();
89 		//seek->set_val(player->get_pos());
90 		updating = false;
91 	}
92 
93 	if (p_what == NOTIFICATION_ENTER_TREE) {
94 
95 		//		editor->connect("hide_animation_player_editors",this,"_hide_anim_editors");
96 		add_anim->set_icon(get_icon("New", "EditorIcons"));
97 		rename_anim->set_icon(get_icon("Rename", "EditorIcons"));
98 		duplicate_anim->set_icon(get_icon("Duplicate", "EditorIcons"));
99 		autoplay->set_icon(get_icon("AutoPlay", "EditorIcons"));
100 		load_anim->set_icon(get_icon("Folder", "EditorIcons"));
101 		save_anim->set_icon(get_icon("Save", "EditorIcons"));
102 		save_anim->get_popup()->connect("item_pressed", this, "_animation_save_menu");
103 		remove_anim->set_icon(get_icon("Remove", "EditorIcons"));
104 
105 		blend_anim->set_icon(get_icon("Blend", "EditorIcons"));
106 		play->set_icon(get_icon("PlayStart", "EditorIcons"));
107 		play_from->set_icon(get_icon("Play", "EditorIcons"));
108 		play_bw->set_icon(get_icon("PlayStartBackwards", "EditorIcons"));
109 		play_bw_from->set_icon(get_icon("PlayBackwards", "EditorIcons"));
110 
111 		autoplay_icon = get_icon("AutoPlay", "EditorIcons");
112 		stop->set_icon(get_icon("Stop", "EditorIcons"));
113 		resource_edit_anim->set_icon(get_icon("EditResource", "EditorIcons"));
114 		pin->set_icon(get_icon("Pin", "EditorIcons"));
115 		tool_anim->set_icon(get_icon("Tools", "EditorIcons"));
116 		tool_anim->get_popup()->connect("item_pressed", this, "_animation_tool_menu");
117 
118 		blend_editor.next->connect("item_selected", this, "_blend_editor_next_changed");
119 
120 		nodename->set_icon(get_icon("AnimationPlayer", "EditorIcons"));
121 
122 		/*
123 		anim_editor_load->set_normal_texture( get_icon("AnimGet","EditorIcons"));
124 		anim_editor_store->set_normal_texture( get_icon("AnimSet","EditorIcons"));
125 		anim_editor_load->set_pressed_texture( get_icon("AnimGet","EditorIcons"));
126 		anim_editor_store->set_pressed_texture( get_icon("AnimSet","EditorIcons"));
127 		anim_editor_load->set_hover_texture( get_icon("AnimGetHl","EditorIcons"));
128 		anim_editor_store->set_hover_texture( get_icon("AnimSetHl","EditorIcons"));
129 */
130 
131 		get_tree()->connect("node_removed", this, "_node_removed");
132 	}
133 }
134 
_autoplay_pressed()135 void AnimationPlayerEditor::_autoplay_pressed() {
136 
137 	if (updating)
138 		return;
139 	if (animation->get_item_count() == 0) {
140 		return;
141 	}
142 
143 	String current = animation->get_item_text(animation->get_selected());
144 	if (player->get_autoplay() == current) {
145 		//unset
146 		undo_redo->create_action(TTR("Toggle Autoplay"));
147 		undo_redo->add_do_method(player, "set_autoplay", "");
148 		undo_redo->add_undo_method(player, "set_autoplay", player->get_autoplay());
149 		undo_redo->add_do_method(this, "_animation_player_changed", player);
150 		undo_redo->add_undo_method(this, "_animation_player_changed", player);
151 		undo_redo->commit_action();
152 
153 	} else {
154 		//set
155 		undo_redo->create_action(TTR("Toggle Autoplay"));
156 		undo_redo->add_do_method(player, "set_autoplay", current);
157 		undo_redo->add_undo_method(player, "set_autoplay", player->get_autoplay());
158 		undo_redo->add_do_method(this, "_animation_player_changed", player);
159 		undo_redo->add_undo_method(this, "_animation_player_changed", player);
160 		undo_redo->commit_action();
161 	}
162 }
163 
_play_pressed()164 void AnimationPlayerEditor::_play_pressed() {
165 
166 	String current;
167 	if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
168 
169 		current = animation->get_item_text(animation->get_selected());
170 	}
171 
172 	if (current != "") {
173 
174 		if (current == player->get_current_animation())
175 			player->stop(); //so it wont blend with itself
176 		player->play(current);
177 	}
178 
179 	//unstop
180 	stop->set_pressed(false);
181 	//unpause
182 	//pause->set_pressed(false);
183 }
184 
_play_from_pressed()185 void AnimationPlayerEditor::_play_from_pressed() {
186 
187 	String current;
188 	if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
189 
190 		current = animation->get_item_text(animation->get_selected());
191 	}
192 
193 	if (current != "") {
194 
195 		float time = player->get_current_animation_pos();
196 
197 		if (current == player->get_current_animation() && player->is_playing()) {
198 
199 			player->stop(); //so it wont blend with itself
200 		}
201 
202 		player->play(current);
203 		player->seek(time);
204 	}
205 
206 	//unstop
207 	stop->set_pressed(false);
208 	//unpause
209 	//pause->set_pressed(false);
210 }
211 
_play_bw_pressed()212 void AnimationPlayerEditor::_play_bw_pressed() {
213 
214 	String current;
215 	if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
216 
217 		current = animation->get_item_text(animation->get_selected());
218 	}
219 
220 	if (current != "") {
221 
222 		if (current == player->get_current_animation())
223 			player->stop(); //so it wont blend with itself
224 		player->play(current, -1, -1, true);
225 	}
226 
227 	//unstop
228 	stop->set_pressed(false);
229 	//unpause
230 	//pause->set_pressed(false);
231 }
232 
_play_bw_from_pressed()233 void AnimationPlayerEditor::_play_bw_from_pressed() {
234 
235 	String current;
236 	if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
237 
238 		current = animation->get_item_text(animation->get_selected());
239 	}
240 
241 	if (current != "") {
242 
243 		float time = player->get_current_animation_pos();
244 		if (current == player->get_current_animation())
245 			player->stop(); //so it wont blend with itself
246 
247 		player->play(current, -1, -1, true);
248 		player->seek(time);
249 	}
250 
251 	//unstop
252 	stop->set_pressed(false);
253 	//unpause
254 	//pause->set_pressed(false);
255 }
_stop_pressed()256 void AnimationPlayerEditor::_stop_pressed() {
257 
258 	if (!player) {
259 		return;
260 	}
261 
262 	player->stop(false);
263 	play->set_pressed(false);
264 	stop->set_pressed(true);
265 	//pause->set_pressed(false);
266 	//player->set_pause(false);
267 }
268 
_pause_pressed()269 void AnimationPlayerEditor::_pause_pressed() {
270 
271 	//player->set_pause( pause->is_pressed() );
272 }
_animation_selected(int p_which)273 void AnimationPlayerEditor::_animation_selected(int p_which) {
274 
275 	if (updating)
276 		return;
277 	// when selecting an animation, the idea is that the only interesting behavior
278 	// ui-wise is that it should play/blend the next one if currently playing
279 	String current;
280 	if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
281 
282 		current = animation->get_item_text(animation->get_selected());
283 	}
284 
285 	if (current != "") {
286 
287 		player->set_current_animation(current);
288 
289 		Ref<Animation> anim = player->get_animation(current);
290 		{
291 
292 			key_editor->set_animation(anim);
293 			Node *root = player->get_node(player->get_root());
294 			if (root) {
295 				key_editor->set_root(root);
296 			}
297 		}
298 		frame->set_max(anim->get_length());
299 		if (anim->get_step())
300 			frame->set_step(anim->get_step());
301 		else
302 			frame->set_step(0.00001);
303 
304 	} else {
305 		key_editor->set_animation(Ref<Animation>());
306 		key_editor->set_root(NULL);
307 	}
308 
309 	autoplay->set_pressed(current == player->get_autoplay());
310 }
311 
_animation_new()312 void AnimationPlayerEditor::_animation_new() {
313 
314 	renaming = false;
315 	name_title->set_text(TTR("New Animation Name:"));
316 
317 	int count = 1;
318 	String base = TTR("New Anim");
319 	while (true) {
320 		String attempt = base;
321 		if (count > 1)
322 			attempt += " (" + itos(count) + ")";
323 		if (player->has_animation(attempt)) {
324 			count++;
325 			continue;
326 		}
327 		base = attempt;
328 		break;
329 	}
330 
331 	name->set_text(base);
332 	name_dialog->popup_centered(Size2(300, 90));
333 	name->select_all();
334 	name->grab_focus();
335 }
_animation_rename()336 void AnimationPlayerEditor::_animation_rename() {
337 
338 	if (animation->get_item_count() == 0)
339 		return;
340 	int selected = animation->get_selected();
341 	String selected_name = animation->get_item_text(selected);
342 
343 	name_title->set_text(TTR("Change Animation Name:"));
344 	name->set_text(selected_name);
345 	renaming = true;
346 	name_dialog->popup_centered(Size2(300, 90));
347 	name->select_all();
348 	name->grab_focus();
349 }
_animation_load()350 void AnimationPlayerEditor::_animation_load() {
351 	ERR_FAIL_COND(!player);
352 	file->set_mode(EditorFileDialog::MODE_OPEN_FILE);
353 	file->clear_filters();
354 	List<String> extensions;
355 
356 	ResourceLoader::get_recognized_extensions_for_type("Animation", &extensions);
357 	for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
358 
359 		file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
360 	}
361 
362 	file->popup_centered_ratio();
363 	current_option = RESOURCE_LOAD;
364 }
365 
_animation_save_in_path(const Ref<Resource> & p_resource,const String & p_path)366 void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource> &p_resource, const String &p_path) {
367 
368 	int flg = 0;
369 	if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
370 		flg |= ResourceSaver::FLAG_COMPRESS;
371 	//if (EditorSettings::get_singleton()->get("on_save/save_paths_as_relative"))
372 	//	flg |= ResourceSaver::FLAG_RELATIVE_PATHS;
373 
374 	String path = Globals::get_singleton()->localize_path(p_path);
375 	Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
376 
377 	if (err != OK) {
378 		accept->set_text(TTR("Error saving resource!"));
379 		accept->popup_centered_minsize();
380 		return;
381 	}
382 	//	EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
383 
384 	((Resource *)p_resource.ptr())->set_path(path);
385 	editor->emit_signal("resource_saved", p_resource);
386 }
387 
_animation_save(const Ref<Resource> & p_resource)388 void AnimationPlayerEditor::_animation_save(const Ref<Resource> &p_resource) {
389 
390 	if (p_resource->get_path().is_resource_file()) {
391 		_animation_save_in_path(p_resource, p_resource->get_path());
392 	} else {
393 		_animation_save_as(p_resource);
394 	}
395 }
396 
_animation_save_as(const Ref<Resource> & p_resource)397 void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) {
398 
399 	file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
400 
401 	List<String> extensions;
402 	ResourceSaver::get_recognized_extensions(p_resource, &extensions);
403 	file->clear_filters();
404 	for (int i = 0; i < extensions.size(); i++) {
405 
406 		file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
407 	}
408 
409 	//file->set_current_path(current_path);
410 	if (p_resource->get_path() != "") {
411 		file->set_current_path(p_resource->get_path());
412 		if (extensions.size()) {
413 			String ext = p_resource->get_path().extension().to_lower();
414 			if (extensions.find(ext) == NULL) {
415 				file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get()));
416 			}
417 		}
418 	} else {
419 
420 		String existing;
421 		if (extensions.size()) {
422 			existing = "new_" + p_resource->get_type().to_lower() + "." + extensions.front()->get().to_lower();
423 		}
424 		file->set_current_path(existing);
425 	}
426 	file->popup_centered_ratio();
427 	file->set_title(TTR("Save Resource As.."));
428 	current_option = RESOURCE_SAVE;
429 }
430 
_animation_remove()431 void AnimationPlayerEditor::_animation_remove() {
432 
433 	if (animation->get_item_count() == 0)
434 		return;
435 
436 	delete_dialog->set_text(TTR("Delete Animation?"));
437 	delete_dialog->popup_centered_minsize();
438 }
439 
_animation_remove_confirmed()440 void AnimationPlayerEditor::_animation_remove_confirmed() {
441 
442 	String current = animation->get_item_text(animation->get_selected());
443 	Ref<Animation> anim = player->get_animation(current);
444 
445 	undo_redo->create_action(TTR("Remove Animation"));
446 	undo_redo->add_do_method(player, "remove_animation", current);
447 	undo_redo->add_undo_method(player, "add_animation", current, anim);
448 	undo_redo->add_do_method(this, "_animation_player_changed", player);
449 	undo_redo->add_undo_method(this, "_animation_player_changed", player);
450 	undo_redo->commit_action();
451 }
452 
_select_anim_by_name(const String & p_anim)453 void AnimationPlayerEditor::_select_anim_by_name(const String &p_anim) {
454 
455 	int idx = -1;
456 	for (int i = 0; i < animation->get_item_count(); i++) {
457 
458 		if (animation->get_item_text(i) == p_anim) {
459 
460 			idx = i;
461 			break;
462 		}
463 	}
464 
465 	ERR_FAIL_COND(idx == -1);
466 
467 	animation->select(idx);
468 
469 	_animation_selected(idx);
470 }
471 
_animation_name_edited()472 void AnimationPlayerEditor::_animation_name_edited() {
473 
474 	player->stop();
475 
476 	String new_name = name->get_text();
477 	if (new_name == "" || new_name.find(":") != -1 || new_name.find("/") != -1) {
478 		error_dialog->set_text(TTR("ERROR: Invalid animation name!"));
479 		error_dialog->popup_centered_minsize();
480 		return;
481 	}
482 
483 	if (renaming && animation->get_item_count() > 0 && animation->get_item_text(animation->get_selected()) == new_name) {
484 		name_dialog->hide();
485 		return;
486 	}
487 
488 	if (player->has_animation(new_name)) {
489 		error_dialog->set_text(TTR("ERROR: Animation name already exists!"));
490 		error_dialog->popup_centered_minsize();
491 		return;
492 	}
493 
494 	if (renaming) {
495 		String current = animation->get_item_text(animation->get_selected());
496 		Ref<Animation> anim = player->get_animation(current);
497 
498 		undo_redo->create_action(TTR("Rename Animation"));
499 		undo_redo->add_do_method(player, "rename_animation", current, new_name);
500 		undo_redo->add_do_method(anim.ptr(), "set_name", new_name);
501 		undo_redo->add_undo_method(player, "rename_animation", new_name, current);
502 		undo_redo->add_undo_method(anim.ptr(), "set_name", current);
503 		undo_redo->add_do_method(this, "_animation_player_changed", player);
504 		undo_redo->add_undo_method(this, "_animation_player_changed", player);
505 		undo_redo->commit_action();
506 
507 		_select_anim_by_name(new_name);
508 
509 	} else {
510 
511 		Ref<Animation> new_anim = Ref<Animation>(memnew(Animation));
512 		new_anim->set_name(new_name);
513 
514 		undo_redo->create_action(TTR("Add Animation"));
515 		undo_redo->add_do_method(player, "add_animation", new_name, new_anim);
516 		undo_redo->add_undo_method(player, "remove_animation", new_name);
517 		undo_redo->add_do_method(this, "_animation_player_changed", player);
518 		undo_redo->add_undo_method(this, "_animation_player_changed", player);
519 		undo_redo->commit_action();
520 
521 		_select_anim_by_name(new_name);
522 	}
523 
524 	name_dialog->hide();
525 }
526 
_blend_editor_next_changed(const int p_idx)527 void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) {
528 
529 	if (animation->get_item_count() == 0)
530 		return;
531 
532 	String current = animation->get_item_text(animation->get_selected());
533 
534 	undo_redo->create_action(TTR("Blend Next Changed"));
535 	undo_redo->add_do_method(player, "animation_set_next", current, blend_editor.next->get_item_text(p_idx));
536 	undo_redo->add_undo_method(player, "animation_set_next", current, player->animation_get_next(current));
537 	undo_redo->add_do_method(this, "_animation_player_changed", player);
538 	undo_redo->add_undo_method(this, "_animation_player_changed", player);
539 	undo_redo->commit_action();
540 }
541 
_animation_blend()542 void AnimationPlayerEditor::_animation_blend() {
543 
544 	if (updating_blends)
545 		return;
546 
547 	blend_editor.tree->clear();
548 
549 	if (animation->get_item_count() == 0)
550 		return;
551 
552 	String current = animation->get_item_text(animation->get_selected());
553 
554 	blend_editor.dialog->popup_centered(Size2(400, 400));
555 
556 	blend_editor.tree->set_hide_root(true);
557 	blend_editor.tree->set_column_min_width(0, 10);
558 	blend_editor.tree->set_column_min_width(1, 3);
559 
560 	List<StringName> anims;
561 	player->get_animation_list(&anims);
562 	TreeItem *root = blend_editor.tree->create_item();
563 	updating_blends = true;
564 
565 	int i = 0;
566 	bool anim_found = false;
567 	blend_editor.next->clear();
568 	blend_editor.next->add_item("", i);
569 
570 	for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
571 
572 		String to = E->get();
573 		TreeItem *blend = blend_editor.tree->create_item(root);
574 		blend->set_editable(0, false);
575 		blend->set_editable(1, true);
576 		blend->set_text(0, to);
577 		blend->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
578 		blend->set_range_config(1, 0, 3600, 0.001);
579 		blend->set_range(1, player->get_blend_time(current, to));
580 
581 		i++;
582 		blend_editor.next->add_item(to, i);
583 		if (to == player->animation_get_next(current)) {
584 			blend_editor.next->select(i);
585 			anim_found = true;
586 		}
587 	}
588 
589 	// make sure we reset it else it becomes out of sync and could contain a deleted animation
590 	if (!anim_found) {
591 		blend_editor.next->select(0);
592 		player->animation_set_next(current, blend_editor.next->get_item_text(0));
593 	}
594 
595 	updating_blends = false;
596 }
597 
_blend_edited()598 void AnimationPlayerEditor::_blend_edited() {
599 
600 	if (updating_blends)
601 		return;
602 
603 	if (animation->get_item_count() == 0)
604 		return;
605 
606 	String current = animation->get_item_text(animation->get_selected());
607 
608 	TreeItem *selected = blend_editor.tree->get_edited();
609 	if (!selected)
610 		return;
611 
612 	updating_blends = true;
613 	String to = selected->get_text(0);
614 	float blend_time = selected->get_range(1);
615 	float prev_blend_time = player->get_blend_time(current, to);
616 
617 	undo_redo->create_action(TTR("Change Blend Time"));
618 	undo_redo->add_do_method(player, "set_blend_time", current, to, blend_time);
619 	undo_redo->add_undo_method(player, "set_blend_time", current, to, prev_blend_time);
620 	undo_redo->add_do_method(this, "_animation_player_changed", player);
621 	undo_redo->add_undo_method(this, "_animation_player_changed", player);
622 	undo_redo->commit_action();
623 	updating_blends = false;
624 }
625 
ensure_visibility()626 void AnimationPlayerEditor::ensure_visibility() {
627 
628 	if (player && pin->is_pressed())
629 		return; // another player is pinned, don't reset
630 
631 	_animation_edit();
632 }
633 
get_state() const634 Dictionary AnimationPlayerEditor::get_state() const {
635 
636 	Dictionary d;
637 
638 	d["visible"] = is_visible();
639 	if (EditorNode::get_singleton()->get_edited_scene() && is_visible() && player) {
640 		d["player"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
641 		d["animation"] = player->get_current_animation();
642 	}
643 
644 	return d;
645 }
set_state(const Dictionary & p_state)646 void AnimationPlayerEditor::set_state(const Dictionary &p_state) {
647 
648 	if (p_state.has("visible") && p_state["visible"]) {
649 
650 		if (!EditorNode::get_singleton()->get_edited_scene())
651 			return;
652 
653 		Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
654 		if (n && n->cast_to<AnimationPlayer>() && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
655 			player = n->cast_to<AnimationPlayer>();
656 			_update_player();
657 			show();
658 			set_process(true);
659 			ensure_visibility();
660 			//			EditorNode::get_singleton()->animation_panel_make_visible(true);
661 
662 			if (p_state.has("animation")) {
663 				String anim = p_state["animation"];
664 				_select_anim_by_name(anim);
665 				_animation_edit();
666 			}
667 		}
668 	}
669 }
670 
_animation_resource_edit()671 void AnimationPlayerEditor::_animation_resource_edit() {
672 
673 	if (animation->get_item_count()) {
674 		String current = animation->get_item_text(animation->get_selected());
675 		Ref<Animation> anim = player->get_animation(current);
676 		editor->edit_resource(anim);
677 	}
678 }
679 
_animation_edit()680 void AnimationPlayerEditor::_animation_edit() {
681 
682 	if (animation->get_item_count()) {
683 		String current = animation->get_item_text(animation->get_selected());
684 		Ref<Animation> anim = player->get_animation(current);
685 		key_editor->set_animation(anim);
686 		Node *root = player->get_node(player->get_root());
687 		if (root) {
688 			key_editor->set_root(root);
689 		}
690 
691 	} else {
692 
693 		key_editor->set_animation(Ref<Animation>());
694 		key_editor->set_root(NULL);
695 	}
696 }
_dialog_action(String p_file)697 void AnimationPlayerEditor::_dialog_action(String p_file) {
698 
699 	switch (current_option) {
700 		case RESOURCE_LOAD: {
701 			ERR_FAIL_COND(!player);
702 
703 			Ref<Resource> res = ResourceLoader::load(p_file, "Animation");
704 			ERR_FAIL_COND(res.is_null());
705 			ERR_FAIL_COND(!res->is_type("Animation"));
706 			if (p_file.find_last("/") != -1) {
707 
708 				p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length());
709 			}
710 			if (p_file.find_last("\\") != -1) {
711 
712 				p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length());
713 			}
714 
715 			if (p_file.find(".") != -1)
716 				p_file = p_file.substr(0, p_file.find("."));
717 
718 			undo_redo->create_action(TTR("Load Animation"));
719 			undo_redo->add_do_method(player, "add_animation", p_file, res);
720 			undo_redo->add_undo_method(player, "remove_animation", p_file);
721 			if (player->has_animation(p_file)) {
722 				undo_redo->add_undo_method(player, "add_animation", p_file, player->get_animation(p_file));
723 			}
724 			undo_redo->add_do_method(this, "_animation_player_changed", player);
725 			undo_redo->add_undo_method(this, "_animation_player_changed", player);
726 			undo_redo->commit_action();
727 			break;
728 		}
729 		case RESOURCE_SAVE: {
730 
731 			String current = animation->get_item_text(animation->get_selected());
732 			if (current != "") {
733 				Ref<Animation> anim = player->get_animation(current);
734 
735 				ERR_FAIL_COND(!anim->cast_to<Resource>())
736 
737 				RES current_res = RES(anim->cast_to<Resource>());
738 
739 				_animation_save_in_path(current_res, p_file);
740 			}
741 		}
742 	}
743 }
744 
_scale_changed(const String & p_scale)745 void AnimationPlayerEditor::_scale_changed(const String &p_scale) {
746 
747 	player->set_speed(p_scale.to_double());
748 }
749 
_update_animation()750 void AnimationPlayerEditor::_update_animation() {
751 
752 	// the purpose of _update_animation is to reflect the current state
753 	// of the animation player in the current editor..
754 
755 	updating = true;
756 
757 	if (player->is_playing()) {
758 
759 		play->set_pressed(true);
760 		stop->set_pressed(false);
761 
762 	} else {
763 
764 		play->set_pressed(false);
765 		stop->set_pressed(true);
766 	}
767 
768 	scale->set_text(String::num(player->get_speed(), 2));
769 	String current = player->get_current_animation();
770 
771 	for (int i = 0; i < animation->get_item_count(); i++) {
772 
773 		if (animation->get_item_text(i) == current) {
774 			animation->select(i);
775 			break;
776 		}
777 	}
778 
779 	updating = false;
780 }
781 
_update_player()782 void AnimationPlayerEditor::_update_player() {
783 
784 	updating = true;
785 	List<StringName> animlist;
786 	if (player)
787 		player->get_animation_list(&animlist);
788 
789 	animation->clear();
790 	if (player)
791 		nodename->set_text(player->get_name());
792 	else
793 		nodename->set_text("<empty>");
794 
795 	add_anim->set_disabled(player == NULL);
796 	load_anim->set_disabled(player == NULL);
797 	stop->set_disabled(animlist.size() == 0);
798 	play->set_disabled(animlist.size() == 0);
799 	play_bw->set_disabled(animlist.size() == 0);
800 	play_bw_from->set_disabled(animlist.size() == 0);
801 	play_from->set_disabled(animlist.size() == 0);
802 	autoplay->set_disabled(animlist.size() == 0);
803 	duplicate_anim->set_disabled(animlist.size() == 0);
804 	rename_anim->set_disabled(animlist.size() == 0);
805 	blend_anim->set_disabled(animlist.size() == 0);
806 	remove_anim->set_disabled(animlist.size() == 0);
807 	resource_edit_anim->set_disabled(animlist.size() == 0);
808 	save_anim->set_disabled(animlist.size() == 0);
809 	tool_anim->set_disabled(player == NULL);
810 
811 	int active_idx = -1;
812 	for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
813 
814 		if (player->get_autoplay() == E->get())
815 			animation->add_icon_item(autoplay_icon, E->get());
816 		else
817 			animation->add_item(E->get());
818 
819 		if (player->get_current_animation() == E->get())
820 			active_idx = animation->get_item_count() - 1;
821 	}
822 
823 	if (!player)
824 		return;
825 
826 	updating = false;
827 	if (active_idx != -1) {
828 		animation->select(active_idx);
829 		autoplay->set_pressed(animation->get_item_text(active_idx) == player->get_autoplay());
830 		_animation_selected(active_idx);
831 
832 	} else if (animation->get_item_count() > 0) {
833 
834 		animation->select(0);
835 		autoplay->set_pressed(animation->get_item_text(0) == player->get_autoplay());
836 		_animation_selected(0);
837 	}
838 
839 	//pause->set_pressed(player->is_paused());
840 
841 	if (animation->get_item_count()) {
842 		String current = animation->get_item_text(animation->get_selected());
843 		Ref<Animation> anim = player->get_animation(current);
844 		key_editor->set_animation(anim);
845 		Node *root = player->get_node(player->get_root());
846 		if (root) {
847 			key_editor->set_root(root);
848 		}
849 	}
850 
851 	_update_animation();
852 }
853 
edit(AnimationPlayer * p_player)854 void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
855 
856 	if (player && pin->is_pressed())
857 		return; //ignore, pinned
858 	player = p_player;
859 
860 	if (player) {
861 		_update_player();
862 		key_editor->show_select_node_warning(false);
863 	} else {
864 		key_editor->show_select_node_warning(true);
865 
866 		//		hide();
867 	}
868 }
869 
_animation_duplicate()870 void AnimationPlayerEditor::_animation_duplicate() {
871 
872 	if (!animation->get_item_count())
873 		return;
874 
875 	String current = animation->get_item_text(animation->get_selected());
876 	Ref<Animation> anim = player->get_animation(current);
877 	if (!anim.is_valid())
878 		return;
879 
880 	Ref<Animation> new_anim = memnew(Animation);
881 	List<PropertyInfo> plist;
882 	anim->get_property_list(&plist);
883 	for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
884 
885 		if (E->get().usage & PROPERTY_USAGE_STORAGE) {
886 
887 			new_anim->set(E->get().name, anim->get(E->get().name));
888 		}
889 	}
890 	new_anim->set_path("");
891 
892 	String new_name = current;
893 	while (player->has_animation(new_name)) {
894 
895 		new_name = new_name + " (copy)";
896 	}
897 
898 	undo_redo->create_action(TTR("Duplicate Animation"));
899 	undo_redo->add_do_method(player, "add_animation", new_name, new_anim);
900 	undo_redo->add_undo_method(player, "remove_animation", new_name);
901 	undo_redo->add_do_method(player, "animation_set_next", new_name, player->animation_get_next(current));
902 	undo_redo->add_do_method(this, "_animation_player_changed", player);
903 	undo_redo->add_undo_method(this, "_animation_player_changed", player);
904 	undo_redo->commit_action();
905 
906 	for (int i = 0; i < animation->get_item_count(); i++) {
907 
908 		if (animation->get_item_text(i) == new_name) {
909 
910 			animation->select(i);
911 			_animation_selected(i);
912 			return;
913 		}
914 	}
915 }
916 
_seek_value_changed(float p_value,bool p_set)917 void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) {
918 
919 	if (updating || !player || player->is_playing()) {
920 		return;
921 	};
922 
923 	updating = true;
924 	String current = player->get_current_animation(); //animation->get_item_text( animation->get_selected() );
925 	if (current == "" || !player->has_animation(current)) {
926 		updating = false;
927 		current = "";
928 		return;
929 	};
930 
931 	Ref<Animation> anim;
932 	anim = player->get_animation(current);
933 
934 	float pos = anim->get_length() * (p_value / frame->get_max());
935 	float step = anim->get_step();
936 	if (step) {
937 		pos = Math::stepify(pos, step);
938 		if (pos < 0)
939 			pos = 0;
940 		if (pos >= anim->get_length())
941 			pos = anim->get_length();
942 	}
943 
944 	if (player->is_valid() && !p_set) {
945 		float cpos = player->get_current_animation_pos();
946 
947 		player->seek_delta(pos, pos - cpos);
948 	} else {
949 		player->seek(pos, true);
950 	}
951 
952 	key_editor->set_anim_pos(pos);
953 
954 	updating = true;
955 };
956 
_animation_player_changed(Object * p_pl)957 void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
958 
959 	if (player == p_pl && is_visible()) {
960 
961 		_update_player();
962 		if (blend_editor.dialog->is_visible())
963 			_animation_blend(); //update
964 	}
965 }
966 
_list_changed()967 void AnimationPlayerEditor::_list_changed() {
968 
969 	if (is_visible())
970 		_update_player();
971 }
972 #if 0
973 void AnimationPlayerEditor::_editor_store() {
974 
975 	if (animation->get_item_count()==0)
976 		return;
977 	String current = animation->get_item_text(animation->get_selected());
978 	Ref<Animation> anim =  player->get_animation(current);
979 
980 	if (key_editor->get_current_animation()==anim)
981 		return; //already there
982 
983 
984 	undo_redo->create_action("Store anim in editor");
985 	undo_redo->add_do_method(key_editor,"set_animation",anim);
986 	undo_redo->add_undo_method(key_editor,"remove_animation",anim);
987 	undo_redo->commit_action();
988 }
989 
990 void AnimationPlayerEditor::_editor_load(){
991 
992 	Ref<Animation> anim = key_editor->get_current_animation();
993 	if (anim.is_null())
994 		return;
995 
996 	String existing = player->find_animation(anim);
997 	if (existing!="") {
998 		_select_anim_by_name(existing);
999 		return; //already has
1000 	}
1001 
1002 	int count=1;
1003 	String base=anim->get_name();
1004 	bool noname=false;
1005 	if (base=="") {
1006 		base="New Anim";
1007 		noname=true;
1008 	}
1009 
1010 	while(true) {
1011 		String attempt  = base;
1012 		if (count>1)
1013 			attempt+=" ("+itos(count)+")";
1014 		if (player->has_animation(attempt)) {
1015 			count++;
1016 			continue;
1017 		}
1018 		base=attempt;
1019 		break;
1020 	}
1021 
1022 	if (noname)
1023 		anim->set_name(base);
1024 
1025 	undo_redo->create_action("Add Animation From Editor");
1026 	undo_redo->add_do_method(player,"add_animation",base,anim);
1027 	undo_redo->add_undo_method(player,"remove_animation",base);
1028 	undo_redo->add_do_method(this,"_animation_player_changed",player);
1029 	undo_redo->add_undo_method(this,"_animation_player_changed",player);
1030 	undo_redo->commit_action();
1031 
1032 	_select_anim_by_name(base);
1033 
1034 
1035 }
1036 #endif
1037 
_animation_key_editor_anim_len_changed(float p_len)1038 void AnimationPlayerEditor::_animation_key_editor_anim_len_changed(float p_len) {
1039 
1040 	frame->set_max(p_len);
1041 }
1042 
_animation_key_editor_anim_step_changed(float p_len)1043 void AnimationPlayerEditor::_animation_key_editor_anim_step_changed(float p_len) {
1044 
1045 	if (p_len)
1046 		frame->set_step(p_len);
1047 	else
1048 		frame->set_step(0.00001);
1049 }
1050 
_animation_key_editor_seek(float p_pos,bool p_drag)1051 void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag) {
1052 
1053 	if (!is_visible())
1054 		return;
1055 	if (!player)
1056 		return;
1057 
1058 	if (player->is_playing())
1059 		return;
1060 
1061 	updating = true;
1062 	frame->set_val(p_pos);
1063 	updating = false;
1064 	_seek_value_changed(p_pos, !p_drag);
1065 
1066 	EditorNode::get_singleton()->get_property_editor()->refresh();
1067 
1068 	//seekit
1069 }
1070 
_hide_anim_editors()1071 void AnimationPlayerEditor::_hide_anim_editors() {
1072 
1073 	player = NULL;
1074 	hide();
1075 	set_process(false);
1076 
1077 	key_editor->set_animation(Ref<Animation>());
1078 	key_editor->set_root(NULL);
1079 	key_editor->show_select_node_warning(true);
1080 	//		editor->animation_editor_make_visible(false);
1081 }
1082 
_animation_tool_menu(int p_option)1083 void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
1084 
1085 	switch (p_option) {
1086 
1087 		case TOOL_COPY_ANIM: {
1088 
1089 			if (!animation->get_item_count()) {
1090 				error_dialog->set_text(TTR("ERROR: No animation to copy!"));
1091 				error_dialog->popup_centered_minsize();
1092 				return;
1093 			}
1094 
1095 			String current = animation->get_item_text(animation->get_selected());
1096 			Ref<Animation> anim = player->get_animation(current);
1097 			//editor->edit_resource(anim);
1098 			EditorSettings::get_singleton()->set_resource_clipboard(anim);
1099 
1100 		} break;
1101 		case TOOL_PASTE_ANIM: {
1102 
1103 			Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard();
1104 			if (!anim.is_valid()) {
1105 				error_dialog->set_text(TTR("ERROR: No animation resource on clipboard!"));
1106 				error_dialog->popup_centered_minsize();
1107 				return;
1108 			}
1109 
1110 			String name = anim->get_name();
1111 			if (name == "") {
1112 				name = TTR("Pasted Animation");
1113 			}
1114 
1115 			int idx = 1;
1116 			String base = name;
1117 			while (player->has_animation(name)) {
1118 
1119 				idx++;
1120 				name = base + " " + itos(idx);
1121 			}
1122 
1123 			undo_redo->create_action(TTR("Paste Animation"));
1124 			undo_redo->add_do_method(player, "add_animation", name, anim);
1125 			undo_redo->add_undo_method(player, "remove_animation", name);
1126 			undo_redo->add_do_method(this, "_animation_player_changed", player);
1127 			undo_redo->add_undo_method(this, "_animation_player_changed", player);
1128 			undo_redo->commit_action();
1129 
1130 			_select_anim_by_name(name);
1131 
1132 		} break;
1133 		case TOOL_EDIT_RESOURCE: {
1134 
1135 			if (!animation->get_item_count()) {
1136 				error_dialog->set_text(TTR("ERROR: No animation to edit!"));
1137 				error_dialog->popup_centered_minsize();
1138 				return;
1139 			}
1140 
1141 			String current = animation->get_item_text(animation->get_selected());
1142 			Ref<Animation> anim = player->get_animation(current);
1143 			editor->edit_resource(anim);
1144 
1145 		} break;
1146 	}
1147 }
1148 
_animation_save_menu(int p_option)1149 void AnimationPlayerEditor::_animation_save_menu(int p_option) {
1150 
1151 	String current = animation->get_item_text(animation->get_selected());
1152 	if (current != "") {
1153 		Ref<Animation> anim = player->get_animation(current);
1154 
1155 		switch (p_option) {
1156 			case ANIM_SAVE:
1157 				_animation_save(anim);
1158 				break;
1159 			case ANIM_SAVE_AS:
1160 				_animation_save_as(anim);
1161 				break;
1162 		}
1163 	}
1164 }
1165 
_unhandled_key_input(const InputEvent & p_ev)1166 void AnimationPlayerEditor::_unhandled_key_input(const InputEvent &p_ev) {
1167 
1168 	if (is_visible() && p_ev.type == InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) {
1169 
1170 		switch (p_ev.key.scancode) {
1171 
1172 			case KEY_A: {
1173 				if (!p_ev.key.mod.shift)
1174 					_play_bw_from_pressed();
1175 				else
1176 					_play_bw_pressed();
1177 			} break;
1178 			case KEY_S: {
1179 				_stop_pressed();
1180 			} break;
1181 			case KEY_D: {
1182 				if (!p_ev.key.mod.shift)
1183 					_play_from_pressed();
1184 				else
1185 					_play_pressed();
1186 			} break;
1187 		}
1188 	}
1189 }
1190 
_bind_methods()1191 void AnimationPlayerEditor::_bind_methods() {
1192 
1193 	ObjectTypeDB::bind_method(_MD("_input_event"), &AnimationPlayerEditor::_input_event);
1194 	ObjectTypeDB::bind_method(_MD("_node_removed"), &AnimationPlayerEditor::_node_removed);
1195 	ObjectTypeDB::bind_method(_MD("_play_pressed"), &AnimationPlayerEditor::_play_pressed);
1196 	ObjectTypeDB::bind_method(_MD("_play_from_pressed"), &AnimationPlayerEditor::_play_from_pressed);
1197 	ObjectTypeDB::bind_method(_MD("_play_bw_pressed"), &AnimationPlayerEditor::_play_bw_pressed);
1198 	ObjectTypeDB::bind_method(_MD("_play_bw_from_pressed"), &AnimationPlayerEditor::_play_bw_from_pressed);
1199 	ObjectTypeDB::bind_method(_MD("_stop_pressed"), &AnimationPlayerEditor::_stop_pressed);
1200 	ObjectTypeDB::bind_method(_MD("_autoplay_pressed"), &AnimationPlayerEditor::_autoplay_pressed);
1201 	ObjectTypeDB::bind_method(_MD("_pause_pressed"), &AnimationPlayerEditor::_pause_pressed);
1202 	ObjectTypeDB::bind_method(_MD("_animation_selected"), &AnimationPlayerEditor::_animation_selected);
1203 	ObjectTypeDB::bind_method(_MD("_animation_name_edited"), &AnimationPlayerEditor::_animation_name_edited);
1204 	ObjectTypeDB::bind_method(_MD("_animation_new"), &AnimationPlayerEditor::_animation_new);
1205 	ObjectTypeDB::bind_method(_MD("_animation_rename"), &AnimationPlayerEditor::_animation_rename);
1206 	ObjectTypeDB::bind_method(_MD("_animation_load"), &AnimationPlayerEditor::_animation_load);
1207 	ObjectTypeDB::bind_method(_MD("_animation_remove"), &AnimationPlayerEditor::_animation_remove);
1208 	ObjectTypeDB::bind_method(_MD("_animation_remove_confirmed"), &AnimationPlayerEditor::_animation_remove_confirmed);
1209 	ObjectTypeDB::bind_method(_MD("_animation_blend"), &AnimationPlayerEditor::_animation_blend);
1210 	ObjectTypeDB::bind_method(_MD("_animation_edit"), &AnimationPlayerEditor::_animation_edit);
1211 	ObjectTypeDB::bind_method(_MD("_animation_resource_edit"), &AnimationPlayerEditor::_animation_resource_edit);
1212 	ObjectTypeDB::bind_method(_MD("_dialog_action"), &AnimationPlayerEditor::_dialog_action);
1213 	ObjectTypeDB::bind_method(_MD("_seek_value_changed"), &AnimationPlayerEditor::_seek_value_changed, DEFVAL(true));
1214 	ObjectTypeDB::bind_method(_MD("_animation_player_changed"), &AnimationPlayerEditor::_animation_player_changed);
1215 	ObjectTypeDB::bind_method(_MD("_blend_edited"), &AnimationPlayerEditor::_blend_edited);
1216 	//	ObjectTypeDB::bind_method(_MD("_seek_frame_changed"),&AnimationPlayerEditor::_seek_frame_changed);
1217 	ObjectTypeDB::bind_method(_MD("_scale_changed"), &AnimationPlayerEditor::_scale_changed);
1218 	//ObjectTypeDB::bind_method(_MD("_editor_store_all"),&AnimationPlayerEditor::_editor_store_all);
1219 	///jectTypeDB::bind_method(_MD("_editor_load_all"),&AnimationPlayerEditor::_editor_load_all);
1220 	ObjectTypeDB::bind_method(_MD("_list_changed"), &AnimationPlayerEditor::_list_changed);
1221 	ObjectTypeDB::bind_method(_MD("_animation_key_editor_seek"), &AnimationPlayerEditor::_animation_key_editor_seek);
1222 	ObjectTypeDB::bind_method(_MD("_animation_key_editor_anim_len_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_len_changed);
1223 	ObjectTypeDB::bind_method(_MD("_animation_key_editor_anim_step_changed"), &AnimationPlayerEditor::_animation_key_editor_anim_step_changed);
1224 	ObjectTypeDB::bind_method(_MD("_hide_anim_editors"), &AnimationPlayerEditor::_hide_anim_editors);
1225 	ObjectTypeDB::bind_method(_MD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate);
1226 	ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"), &AnimationPlayerEditor::_blend_editor_next_changed);
1227 	ObjectTypeDB::bind_method(_MD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input);
1228 	ObjectTypeDB::bind_method(_MD("_animation_tool_menu"), &AnimationPlayerEditor::_animation_tool_menu);
1229 	ObjectTypeDB::bind_method(_MD("_animation_save_menu"), &AnimationPlayerEditor::_animation_save_menu);
1230 }
1231 
1232 AnimationPlayerEditor *AnimationPlayerEditor::singleton = NULL;
1233 
get_player() const1234 AnimationPlayer *AnimationPlayerEditor::get_player() const {
1235 
1236 	return player;
1237 }
AnimationPlayerEditor(EditorNode * p_editor)1238 AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
1239 	editor = p_editor;
1240 	singleton = this;
1241 
1242 	updating = false;
1243 
1244 	set_focus_mode(FOCUS_ALL);
1245 
1246 	player = NULL;
1247 	add_style_override("panel", get_stylebox("panel", "Panel"));
1248 
1249 	Label *l;
1250 
1251 	/*l= memnew( Label );
1252 	l->set_text("Animation Player:");
1253 	add_child(l);*/
1254 
1255 	HBoxContainer *hb = memnew(HBoxContainer);
1256 	add_child(hb);
1257 
1258 	play_bw_from = memnew(ToolButton);
1259 	play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)"));
1260 	hb->add_child(play_bw_from);
1261 
1262 	play_bw = memnew(ToolButton);
1263 	play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)"));
1264 	hb->add_child(play_bw);
1265 
1266 	stop = memnew(ToolButton);
1267 	stop->set_toggle_mode(true);
1268 	hb->add_child(stop);
1269 	stop->set_tooltip(TTR("Stop animation playback. (S)"));
1270 
1271 	play = memnew(ToolButton);
1272 	play->set_tooltip(TTR("Play selected animation from start. (Shift+D)"));
1273 	hb->add_child(play);
1274 
1275 	play_from = memnew(ToolButton);
1276 	play_from->set_tooltip(TTR("Play selected animation from current pos. (D)"));
1277 	hb->add_child(play_from);
1278 
1279 	//pause = memnew( Button );
1280 	//pause->set_toggle_mode(true);
1281 	//hb->add_child(pause);
1282 
1283 	frame = memnew(SpinBox);
1284 	hb->add_child(frame);
1285 	frame->set_custom_minimum_size(Size2(60, 0));
1286 	frame->set_stretch_ratio(2);
1287 	frame->set_tooltip(TTR("Animation position (in seconds)."));
1288 
1289 	hb->add_child(memnew(VSeparator));
1290 
1291 	scale = memnew(LineEdit);
1292 	hb->add_child(scale);
1293 	scale->set_h_size_flags(SIZE_EXPAND_FILL);
1294 	scale->set_stretch_ratio(1);
1295 	scale->set_tooltip(TTR("Scale animation playback globally for the node."));
1296 	scale->hide();
1297 
1298 	add_anim = memnew(ToolButton);
1299 	ED_SHORTCUT("animation_player_editor/add_animation", TTR("Create new animation in player."));
1300 	add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/add_animation"));
1301 	add_anim->set_tooltip(TTR("Create new animation in player."));
1302 
1303 	hb->add_child(add_anim);
1304 
1305 	load_anim = memnew(ToolButton);
1306 	ED_SHORTCUT("animation_player_editor/load_from_disk", TTR("Load animation from disk."));
1307 	add_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/load_from_disk"));
1308 	load_anim->set_tooltip(TTR("Load an animation from disk."));
1309 	hb->add_child(load_anim);
1310 
1311 	save_anim = memnew(MenuButton);
1312 	save_anim->set_tooltip(TTR("Save the current animation"));
1313 	save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save", TTR("Save")), ANIM_SAVE);
1314 	save_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as", TTR("Save As")), ANIM_SAVE_AS);
1315 	save_anim->set_focus_mode(Control::FOCUS_NONE);
1316 	hb->add_child(save_anim);
1317 
1318 	accept = memnew(AcceptDialog);
1319 	add_child(accept);
1320 	accept->connect("confirmed", this, "_menu_confirm_current");
1321 
1322 	delete_dialog = memnew(ConfirmationDialog);
1323 	add_child(delete_dialog);
1324 	delete_dialog->connect("confirmed", this, "_animation_remove_confirmed");
1325 
1326 	duplicate_anim = memnew(ToolButton);
1327 	hb->add_child(duplicate_anim);
1328 	ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate Animation"));
1329 	duplicate_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/duplicate_animation"));
1330 	duplicate_anim->set_tooltip(TTR("Duplicate Animation"));
1331 
1332 	rename_anim = memnew(ToolButton);
1333 	hb->add_child(rename_anim);
1334 	ED_SHORTCUT("animation_player_editor/rename_animation", TTR("Rename Animation"));
1335 	rename_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/rename_animation"));
1336 	rename_anim->set_tooltip(TTR("Rename Animation"));
1337 
1338 	remove_anim = memnew(ToolButton);
1339 	hb->add_child(remove_anim);
1340 	ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove Animation"));
1341 	remove_anim->set_shortcut(ED_GET_SHORTCUT("animation_player_editor/remove_animation"));
1342 	remove_anim->set_tooltip(TTR("Remove Animation"));
1343 
1344 	animation = memnew(OptionButton);
1345 	hb->add_child(animation);
1346 	animation->set_h_size_flags(SIZE_EXPAND_FILL);
1347 	animation->set_tooltip(TTR("Display list of animations in player."));
1348 	animation->set_clip_text(true);
1349 
1350 	autoplay = memnew(ToolButton);
1351 	hb->add_child(autoplay);
1352 	autoplay->set_tooltip(TTR("Autoplay on Load"));
1353 
1354 	blend_anim = memnew(ToolButton);
1355 	hb->add_child(blend_anim);
1356 	blend_anim->set_tooltip(TTR("Edit Target Blend Times"));
1357 
1358 	tool_anim = memnew(MenuButton);
1359 	//tool_anim->set_flat(false);
1360 	tool_anim->set_tooltip(TTR("Animation Tools"));
1361 	tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy Animation")), TOOL_COPY_ANIM);
1362 	tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste Animation")), TOOL_PASTE_ANIM);
1363 	//tool_anim->get_popup()->add_separator();
1364 	//tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
1365 	hb->add_child(tool_anim);
1366 
1367 	nodename = memnew(Button);
1368 	hb->add_child(nodename);
1369 	pin = memnew(ToolButton);
1370 	pin->set_toggle_mode(true);
1371 	hb->add_child(pin);
1372 
1373 	resource_edit_anim = memnew(Button);
1374 	hb->add_child(resource_edit_anim);
1375 	resource_edit_anim->hide();
1376 
1377 	file = memnew(EditorFileDialog);
1378 	add_child(file);
1379 
1380 	name_dialog = memnew(ConfirmationDialog);
1381 	name_dialog->set_title(TTR("Create New Animation"));
1382 	name_dialog->set_hide_on_ok(false);
1383 	add_child(name_dialog);
1384 	name = memnew(LineEdit);
1385 	name_dialog->add_child(name);
1386 	name->set_pos(Point2(18, 30));
1387 	name->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 10);
1388 	name_dialog->register_text_enter(name);
1389 
1390 	l = memnew(Label);
1391 	l->set_text(TTR("Animation Name:"));
1392 	l->set_pos(Point2(10, 10));
1393 
1394 	name_dialog->add_child(l);
1395 	name_title = l;
1396 
1397 	error_dialog = memnew(ConfirmationDialog);
1398 	error_dialog->get_ok()->set_text(TTR("Close"));
1399 	//error_dialog->get_cancel()->set_text("Close");
1400 	error_dialog->set_text(TTR("Error!"));
1401 	add_child(error_dialog);
1402 
1403 	name_dialog->connect("confirmed", this, "_animation_name_edited");
1404 
1405 	blend_editor.dialog = memnew(AcceptDialog);
1406 	add_child(blend_editor.dialog);
1407 	blend_editor.dialog->get_ok()->set_text(TTR("Close"));
1408 	blend_editor.dialog->set_hide_on_ok(true);
1409 	VBoxContainer *blend_vb = memnew(VBoxContainer);
1410 	blend_editor.dialog->add_child(blend_vb);
1411 	blend_editor.dialog->set_child_rect(blend_vb);
1412 	blend_editor.tree = memnew(Tree);
1413 	blend_editor.tree->set_columns(2);
1414 	blend_vb->add_margin_child(TTR("Blend Times:"), blend_editor.tree, true);
1415 	blend_editor.next = memnew(OptionButton);
1416 	blend_vb->add_margin_child(TTR("Next (Auto Queue):"), blend_editor.next);
1417 	blend_editor.dialog->set_title(TTR("Cross-Animation Blend Times"));
1418 	updating_blends = false;
1419 
1420 	blend_editor.tree->connect("item_edited", this, "_blend_edited");
1421 
1422 	autoplay->connect("pressed", this, "_autoplay_pressed");
1423 	autoplay->set_toggle_mode(true);
1424 	play->connect("pressed", this, "_play_pressed");
1425 	play_from->connect("pressed", this, "_play_from_pressed");
1426 	play_bw->connect("pressed", this, "_play_bw_pressed");
1427 	play_bw_from->connect("pressed", this, "_play_bw_from_pressed");
1428 	stop->connect("pressed", this, "_stop_pressed");
1429 	//pause->connect("pressed", this,"_pause_pressed");
1430 	add_anim->connect("pressed", this, "_animation_new");
1431 	rename_anim->connect("pressed", this, "_animation_rename");
1432 	load_anim->connect("pressed", this, "_animation_load");
1433 	duplicate_anim->connect("pressed", this, "_animation_duplicate");
1434 	//frame->connect("text_entered", this,"_seek_frame_changed");
1435 
1436 	blend_anim->connect("pressed", this, "_animation_blend");
1437 	remove_anim->connect("pressed", this, "_animation_remove");
1438 	animation->connect("item_selected", this, "_animation_selected", Vector<Variant>(), true);
1439 	resource_edit_anim->connect("pressed", this, "_animation_resource_edit");
1440 	file->connect("file_selected", this, "_dialog_action");
1441 	frame->connect("value_changed", this, "_seek_value_changed", Vector<Variant>(), true);
1442 	scale->connect("text_entered", this, "_scale_changed", Vector<Variant>(), true);
1443 
1444 	renaming = false;
1445 	last_active = false;
1446 
1447 	set_process_unhandled_key_input(true);
1448 
1449 	key_editor = memnew(AnimationKeyEditor);
1450 	add_child(key_editor);
1451 	add_constant_override("separation", get_constant("separation", "VBoxContainer"));
1452 	key_editor->set_v_size_flags(SIZE_EXPAND_FILL);
1453 	key_editor->connect("timeline_changed", this, "_animation_key_editor_seek");
1454 	key_editor->connect("animation_len_changed", this, "_animation_key_editor_anim_len_changed");
1455 	key_editor->connect("animation_step_changed", this, "_animation_key_editor_anim_step_changed");
1456 
1457 	_update_player();
1458 }
1459 
edit(Object * p_object)1460 void AnimationPlayerEditorPlugin::edit(Object *p_object) {
1461 
1462 	anim_editor->set_undo_redo(&get_undo_redo());
1463 	if (!p_object)
1464 		return;
1465 	anim_editor->edit(p_object->cast_to<AnimationPlayer>());
1466 }
1467 
handles(Object * p_object) const1468 bool AnimationPlayerEditorPlugin::handles(Object *p_object) const {
1469 
1470 	return p_object->is_type("AnimationPlayer");
1471 }
1472 
make_visible(bool p_visible)1473 void AnimationPlayerEditorPlugin::make_visible(bool p_visible) {
1474 
1475 	if (p_visible) {
1476 
1477 		editor->make_bottom_panel_item_visible(anim_editor);
1478 		anim_editor->set_process(true);
1479 		anim_editor->ensure_visibility();
1480 		//		editor->animation_panel_make_visible(true);
1481 	} else {
1482 
1483 		//		anim_editor->hide();
1484 		//		anim_editor->set_idle_process(false);
1485 	}
1486 }
1487 
AnimationPlayerEditorPlugin(EditorNode * p_node)1488 AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
1489 
1490 	editor = p_node;
1491 	anim_editor = memnew(AnimationPlayerEditor(editor));
1492 	anim_editor->set_undo_redo(editor->get_undo_redo());
1493 
1494 	editor->add_bottom_panel_item(TTR("Animation"), anim_editor);
1495 	/*
1496 	editor->get_viewport()->add_child(anim_editor);
1497 	anim_editor->set_area_as_parent_rect();
1498 	anim_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
1499 	anim_editor->set_margin( MARGIN_TOP, 75 );
1500 	anim_editor->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END);
1501 	anim_editor->set_margin( MARGIN_RIGHT, 0 );*/
1502 	anim_editor->hide();
1503 }
1504 
~AnimationPlayerEditorPlugin()1505 AnimationPlayerEditorPlugin::~AnimationPlayerEditorPlugin() {
1506 }
1507