2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* animation_player_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2022-01-03 20:27:34 +00:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +00:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-04 23:50:27 +00:00
2014-02-10 01:10:30 +00:00
# include "animation_player_editor_plugin.h"
2017-01-16 07:04:19 +00:00
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
2020-04-28 13:19:37 +00:00
# include "core/input/input.h"
2018-09-11 16:13:45 +00:00
# include "core/io/resource_loader.h"
# include "core/io/resource_saver.h"
# include "core/os/keyboard.h"
2022-02-12 01:46:22 +00:00
# include "editor/editor_file_dialog.h"
# include "editor/editor_node.h"
2019-12-24 07:17:23 +00:00
# include "editor/editor_scale.h"
2017-03-05 15:44:50 +00:00
# include "editor/editor_settings.h"
2020-02-23 21:52:27 +00:00
# include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning.
2020-03-27 07:44:44 +00:00
# include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning.
2022-02-12 01:46:22 +00:00
# include "editor/scene_tree_dock.h"
2020-03-04 01:51:12 +00:00
# include "scene/main/window.h"
2021-10-15 13:25:00 +00:00
# include "scene/resources/animation.h"
2021-12-06 00:46:03 +00:00
# include "scene/scene_string_names.h"
2020-03-27 18:21:27 +00:00
# include "servers/rendering_server.h"
2017-10-30 18:43:19 +00:00
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _node_removed ( Node * p_node ) {
if ( player & & player = = p_node ) {
2020-04-01 23:20:12 +00:00
player = nullptr ;
2016-01-17 23:03:57 +00:00
2014-02-10 01:10:30 +00:00
set_process ( false ) ;
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( Ref < Animation > ( ) ) ;
2020-04-01 23:20:12 +00:00
track_editor - > set_root ( nullptr ) ;
2018-06-07 15:46:14 +00:00
track_editor - > show_select_node_warning ( true ) ;
2016-01-17 23:03:57 +00:00
_update_player ( ) ;
2014-02-10 01:10:30 +00:00
}
}
void AnimationPlayerEditor : : _notification ( int p_what ) {
2017-09-09 02:19:43 +00:00
switch ( p_what ) {
case NOTIFICATION_PROCESS : {
2020-05-14 14:41:43 +00:00
if ( ! player ) {
2017-09-09 02:19:43 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2017-09-09 02:19:43 +00:00
updating = true ;
2014-02-10 01:10:30 +00:00
2017-09-09 02:19:43 +00:00
if ( player - > is_playing ( ) ) {
{
2018-01-14 10:28:57 +00:00
String animname = player - > get_assigned_animation ( ) ;
2014-02-10 01:10:30 +00:00
2017-09-09 02:19:43 +00:00
if ( player - > has_animation ( animname ) ) {
Ref < Animation > anim = player - > get_animation ( animname ) ;
if ( ! anim . is_null ( ) ) {
2021-10-15 13:25:00 +00:00
frame - > set_max ( ( double ) anim - > get_length ( ) ) ;
2017-09-09 02:19:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
2017-09-10 13:37:49 +00:00
frame - > set_value ( player - > get_current_animation_position ( ) ) ;
2018-06-07 15:46:14 +00:00
track_editor - > set_anim_pos ( player - > get_current_animation_position ( ) ) ;
2017-09-09 02:19:43 +00:00
2019-11-30 16:47:09 +00:00
} else if ( ! player - > is_valid ( ) ) {
// Reset timeline when the player has been stopped externally
frame - > set_value ( 0 ) ;
2017-09-09 02:19:43 +00:00
} else if ( last_active ) {
2019-06-19 03:51:06 +00:00
// Need the last frame after it stopped.
2017-09-10 13:37:49 +00:00
frame - > set_value ( player - > get_current_animation_position ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2015-01-03 18:39:01 +00:00
2017-09-09 02:19:43 +00:00
last_active = player - > is_playing ( ) ;
updating = false ;
} break ;
case NOTIFICATION_ENTER_TREE : {
2020-02-21 17:28:45 +00:00
tool_anim - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & AnimationPlayerEditor : : _animation_tool_menu ) ) ;
2017-09-09 02:19:43 +00:00
2020-02-21 17:28:45 +00:00
onion_skinning - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & AnimationPlayerEditor : : _onion_skinning_menu ) ) ;
2017-10-30 18:43:19 +00:00
2020-02-21 17:28:45 +00:00
blend_editor . next - > connect ( " item_selected " , callable_mp ( this , & AnimationPlayerEditor : : _blend_editor_next_changed ) ) ;
2014-02-10 01:10:30 +00:00
2020-02-21 17:28:45 +00:00
get_tree ( ) - > connect ( " node_removed " , callable_mp ( this , & AnimationPlayerEditor : : _node_removed ) ) ;
2017-09-09 02:19:43 +00:00
2022-01-27 09:36:51 +00:00
add_theme_style_override ( " panel " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_stylebox ( SNAME ( " panel " ) , SNAME ( " Panel " ) ) ) ;
2017-09-09 02:19:43 +00:00
} break ;
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
2022-01-27 09:36:51 +00:00
add_theme_style_override ( " panel " , EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_stylebox ( SNAME ( " panel " ) , SNAME ( " Panel " ) ) ) ;
2017-09-09 02:19:43 +00:00
} break ;
2020-09-03 11:22:16 +00:00
case NOTIFICATION_TRANSLATION_CHANGED :
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED :
2017-09-09 02:19:43 +00:00
case NOTIFICATION_THEME_CHANGED : {
2021-07-17 21:22:52 +00:00
autoplay - > set_icon ( get_theme_icon ( SNAME ( " AutoPlay " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-09-09 02:19:43 +00:00
2021-07-17 21:22:52 +00:00
play - > set_icon ( get_theme_icon ( SNAME ( " PlayStart " ) , SNAME ( " EditorIcons " ) ) ) ;
play_from - > set_icon ( get_theme_icon ( SNAME ( " Play " ) , SNAME ( " EditorIcons " ) ) ) ;
play_bw - > set_icon ( get_theme_icon ( SNAME ( " PlayStartBackwards " ) , SNAME ( " EditorIcons " ) ) ) ;
play_bw_from - > set_icon ( get_theme_icon ( SNAME ( " PlayBackwards " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-09-09 02:19:43 +00:00
2021-07-17 21:22:52 +00:00
autoplay_icon = get_theme_icon ( SNAME ( " AutoPlay " ) , SNAME ( " EditorIcons " ) ) ;
reset_icon = get_theme_icon ( SNAME ( " Reload " ) , SNAME ( " EditorIcons " ) ) ;
2020-12-20 10:46:44 +00:00
{
2021-03-28 11:32:17 +00:00
Ref < Image > autoplay_img = autoplay_icon - > get_image ( ) ;
Ref < Image > reset_img = reset_icon - > get_image ( ) ;
2020-12-20 10:46:44 +00:00
Ref < Image > autoplay_reset_img ;
2021-09-23 14:58:43 +00:00
Size2 icon_size = autoplay_img - > get_size ( ) ;
2021-06-17 22:03:09 +00:00
autoplay_reset_img . instantiate ( ) ;
2020-12-20 10:46:44 +00:00
autoplay_reset_img - > create ( icon_size . x * 2 , icon_size . y , false , autoplay_img - > get_format ( ) ) ;
autoplay_reset_img - > blit_rect ( autoplay_img , Rect2 ( Point2 ( ) , icon_size ) , Point2 ( ) ) ;
autoplay_reset_img - > blit_rect ( reset_img , Rect2 ( Point2 ( ) , icon_size ) , Point2 ( icon_size . x , 0 ) ) ;
2021-06-17 22:03:09 +00:00
autoplay_reset_icon . instantiate ( ) ;
2020-12-20 10:46:44 +00:00
autoplay_reset_icon - > create_from_image ( autoplay_reset_img ) ;
}
2021-07-17 21:22:52 +00:00
stop - > set_icon ( get_theme_icon ( SNAME ( " Stop " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-06-07 15:46:14 +00:00
2021-07-17 21:22:52 +00:00
onion_toggle - > set_icon ( get_theme_icon ( SNAME ( " Onion " ) , SNAME ( " EditorIcons " ) ) ) ;
onion_skinning - > set_icon ( get_theme_icon ( SNAME ( " GuiTabMenuHl " ) , SNAME ( " EditorIcons " ) ) ) ;
2019-05-14 03:42:05 +00:00
2021-07-17 21:22:52 +00:00
pin - > set_icon ( get_theme_icon ( SNAME ( " Pin " ) , SNAME ( " EditorIcons " ) ) ) ;
2017-09-09 02:19:43 +00:00
2022-02-08 09:14:58 +00:00
tool_anim - > add_theme_style_override ( " normal " , get_theme_stylebox ( SNAME ( " normal " ) , SNAME ( " Button " ) ) ) ;
track_editor - > get_edit_menu ( ) - > add_theme_style_override ( " normal " , get_theme_stylebox ( SNAME ( " normal " ) , SNAME ( " Button " ) ) ) ;
2018-06-07 15:46:14 +00:00
2021-07-17 21:22:52 +00:00
# define ITEM_ICON(m_item, m_icon) tool_anim->get_popup()->set_item_icon(tool_anim->get_popup()->get_item_index(m_item), get_theme_icon(SNAME(m_icon), SNAME("EditorIcons")))
2018-06-07 15:46:14 +00:00
ITEM_ICON ( TOOL_NEW_ANIM , " New " ) ;
ITEM_ICON ( TOOL_LOAD_ANIM , " Load " ) ;
ITEM_ICON ( TOOL_SAVE_ANIM , " Save " ) ;
ITEM_ICON ( TOOL_SAVE_AS_ANIM , " Save " ) ;
ITEM_ICON ( TOOL_DUPLICATE_ANIM , " Duplicate " ) ;
ITEM_ICON ( TOOL_RENAME_ANIM , " Rename " ) ;
ITEM_ICON ( TOOL_EDIT_TRANSITIONS , " Blend " ) ;
2018-07-01 20:44:15 +00:00
ITEM_ICON ( TOOL_EDIT_RESOURCE , " Edit " ) ;
2018-06-07 15:46:14 +00:00
ITEM_ICON ( TOOL_REMOVE_ANIM , " Remove " ) ;
2017-09-09 02:19:43 +00:00
} break ;
2014-02-10 01:10:30 +00:00
}
}
void AnimationPlayerEditor : : _autoplay_pressed ( ) {
2020-05-14 14:41:43 +00:00
if ( updating ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
}
2017-03-05 15:44:50 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
if ( player - > get_autoplay ( ) = = current ) {
2014-02-10 01:10:30 +00:00
//unset
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " Toggle Autoplay " ) ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( player , " set_autoplay " , " " ) ;
undo_redo - > add_undo_method ( player , " set_autoplay " , player - > get_autoplay ( ) ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
2014-02-10 01:10:30 +00:00
undo_redo - > commit_action ( ) ;
} else {
//set
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " Toggle Autoplay " ) ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( player , " set_autoplay " , current ) ;
undo_redo - > add_undo_method ( player , " set_autoplay " , player - > get_autoplay ( ) ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
2014-02-10 01:10:30 +00:00
undo_redo - > commit_action ( ) ;
}
}
void AnimationPlayerEditor : : _play_pressed ( ) {
String current ;
2017-03-05 15:44:50 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2020-05-14 14:41:43 +00:00
if ( current = = player - > get_assigned_animation ( ) ) {
2018-01-18 20:37:17 +00:00
player - > stop ( ) ; //so it won't blend with itself
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
player - > play ( current ) ;
2014-02-10 01:10:30 +00:00
}
//unstop
stop - > set_pressed ( false ) ;
}
2015-05-25 04:46:45 +00:00
void AnimationPlayerEditor : : _play_from_pressed ( ) {
String current ;
2017-03-05 15:44:50 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2015-05-25 04:46:45 +00:00
}
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2017-09-10 13:37:49 +00:00
float time = player - > get_current_animation_position ( ) ;
2015-05-25 04:46:45 +00:00
2018-01-14 10:28:57 +00:00
if ( current = = player - > get_assigned_animation ( ) & & player - > is_playing ( ) ) {
2018-01-18 20:37:17 +00:00
player - > stop ( ) ; //so it won't blend with itself
2015-05-25 04:46:45 +00:00
}
2017-03-05 15:44:50 +00:00
player - > play ( current ) ;
2015-05-25 04:46:45 +00:00
player - > seek ( time ) ;
}
//unstop
stop - > set_pressed ( false ) ;
}
void AnimationPlayerEditor : : _play_bw_pressed ( ) {
String current ;
2017-03-05 15:44:50 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2015-05-25 04:46:45 +00:00
}
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2020-05-14 14:41:43 +00:00
if ( current = = player - > get_assigned_animation ( ) ) {
2018-01-18 20:37:17 +00:00
player - > stop ( ) ; //so it won't blend with itself
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
player - > play ( current , - 1 , - 1 , true ) ;
2015-05-25 04:46:45 +00:00
}
//unstop
stop - > set_pressed ( false ) ;
}
void AnimationPlayerEditor : : _play_bw_from_pressed ( ) {
String current ;
2017-03-05 15:44:50 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2015-05-25 04:46:45 +00:00
}
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2017-09-10 13:37:49 +00:00
float time = player - > get_current_animation_position ( ) ;
2020-05-14 14:41:43 +00:00
if ( current = = player - > get_assigned_animation ( ) ) {
2018-01-18 20:37:17 +00:00
player - > stop ( ) ; //so it won't blend with itself
2020-05-14 14:41:43 +00:00
}
2015-05-25 04:46:45 +00:00
2017-03-05 15:44:50 +00:00
player - > play ( current , - 1 , - 1 , true ) ;
2015-05-25 04:46:45 +00:00
player - > seek ( time ) ;
}
//unstop
stop - > set_pressed ( false ) ;
}
2020-05-14 12:29:06 +00:00
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _stop_pressed ( ) {
2017-07-01 15:49:43 +00:00
if ( ! player ) {
return ;
}
2015-05-25 04:46:45 +00:00
player - > stop ( false ) ;
2014-02-10 01:10:30 +00:00
play - > set_pressed ( false ) ;
stop - > set_pressed ( true ) ;
}
2019-05-30 19:43:46 +00:00
void AnimationPlayerEditor : : _animation_selected ( int p_which ) {
2020-05-14 14:41:43 +00:00
if ( updating ) {
2019-05-30 19:43:46 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
// when selecting an animation, the idea is that the only interesting behavior
// ui-wise is that it should play/blend the next one if currently playing
2019-05-30 19:43:46 +00:00
String current ;
2017-03-05 15:44:50 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
2019-05-30 19:43:46 +00:00
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2019-05-06 19:39:24 +00:00
player - > set_assigned_animation ( current ) ;
2016-01-17 23:03:57 +00:00
2019-05-30 19:43:46 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
{
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( anim ) ;
2014-02-10 01:10:30 +00:00
Node * root = player - > get_node ( player - > get_root ( ) ) ;
if ( root ) {
2018-06-07 15:46:14 +00:00
track_editor - > set_root ( root ) ;
2014-02-10 01:10:30 +00:00
}
}
2021-10-15 13:25:00 +00:00
frame - > set_max ( ( double ) anim - > get_length ( ) ) ;
2016-01-17 23:03:57 +00:00
2014-02-10 01:10:30 +00:00
} else {
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( Ref < Animation > ( ) ) ;
2020-04-01 23:20:12 +00:00
track_editor - > set_root ( nullptr ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
autoplay - > set_pressed ( current = = player - > get_autoplay ( ) ) ;
2018-07-03 18:57:54 +00:00
2021-02-04 08:20:26 +00:00
AnimationPlayerEditor : : get_singleton ( ) - > get_track_editor ( ) - > update_keying ( ) ;
2019-10-01 16:38:03 +00:00
_animation_key_editor_seek ( timeline_position , false ) ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : _animation_new ( ) {
2022-02-14 06:28:42 +00:00
name_dialog_op = TOOL_NEW_ANIM ;
2016-05-04 01:25:37 +00:00
name_title - > set_text ( TTR ( " New Animation Name: " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
int count = 1 ;
String base = TTR ( " New Anim " ) ;
while ( true ) {
String attempt = base ;
2020-05-14 14:41:43 +00:00
if ( count > 1 ) {
2017-03-05 15:44:50 +00:00
attempt + = " ( " + itos ( count ) + " ) " ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
if ( player - > has_animation ( attempt ) ) {
count + + ;
continue ;
}
2017-03-05 15:44:50 +00:00
base = attempt ;
2014-02-10 01:10:30 +00:00
break ;
}
name - > set_text ( base ) ;
2017-03-05 15:44:50 +00:00
name_dialog - > popup_centered ( Size2 ( 300 , 90 ) ) ;
2014-02-10 01:10:30 +00:00
name - > select_all ( ) ;
name - > grab_focus ( ) ;
}
2020-05-14 12:29:06 +00:00
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_rename ( ) {
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
int selected = animation - > get_selected ( ) ;
String selected_name = animation - > get_item_text ( selected ) ;
2016-05-04 01:25:37 +00:00
name_title - > set_text ( TTR ( " Change Animation Name: " ) ) ;
2014-02-10 01:10:30 +00:00
name - > set_text ( selected_name ) ;
2022-02-14 06:28:42 +00:00
name_dialog_op = TOOL_RENAME_ANIM ;
2017-03-05 15:44:50 +00:00
name_dialog - > popup_centered ( Size2 ( 300 , 90 ) ) ;
2014-02-10 01:10:30 +00:00
name - > select_all ( ) ;
name - > grab_focus ( ) ;
}
2020-05-14 12:29:06 +00:00
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_load ( ) {
ERR_FAIL_COND ( ! player ) ;
2020-03-23 15:35:26 +00:00
file - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILES ) ;
2014-02-10 01:10:30 +00:00
file - > clear_filters ( ) ;
List < String > extensions ;
2017-03-05 15:44:50 +00:00
ResourceLoader : : get_recognized_extensions_for_type ( " Animation " , & extensions ) ;
2021-07-24 13:46:25 +00:00
for ( const String & E : extensions ) {
2021-07-16 03:45:57 +00:00
file - > add_filter ( " *. " + E + " ; " + E . to_upper ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-07-11 16:45:19 +00:00
file - > popup_file_dialog ( ) ;
2015-10-19 19:40:24 +00:00
}
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : _animation_save_in_path ( const Ref < Resource > & p_resource , const String & p_path ) {
2015-10-19 19:40:24 +00:00
int flg = 0 ;
2020-05-14 14:41:43 +00:00
if ( EditorSettings : : get_singleton ( ) - > get ( " filesystem/on_save/compress_binary_resources " ) ) {
2015-10-19 19:40:24 +00:00
flg | = ResourceSaver : : FLAG_COMPRESS ;
2020-05-14 14:41:43 +00:00
}
2015-10-19 19:40:24 +00:00
2017-07-19 20:00:46 +00:00
String path = ProjectSettings : : get_singleton ( ) - > localize_path ( p_path ) ;
2015-10-19 19:40:24 +00:00
Error err = ResourceSaver : : save ( path , p_resource , flg | ResourceSaver : : FLAG_REPLACE_SUBRESOURCE_PATHS ) ;
if ( err ! = OK ) {
2020-02-23 21:52:27 +00:00
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Error saving resource! " ) ) ;
2015-10-19 19:40:24 +00:00
return ;
}
2017-03-05 15:44:50 +00:00
( ( Resource * ) p_resource . ptr ( ) ) - > set_path ( path ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > emit_signal ( SNAME ( " resource_saved " ) , p_resource ) ;
2015-10-19 19:40:24 +00:00
}
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : _animation_save ( const Ref < Resource > & p_resource ) {
2015-10-19 19:40:24 +00:00
if ( p_resource - > get_path ( ) . is_resource_file ( ) ) {
_animation_save_in_path ( p_resource , p_resource - > get_path ( ) ) ;
2017-03-05 15:44:50 +00:00
} else {
2015-10-19 19:40:24 +00:00
_animation_save_as ( p_resource ) ;
}
}
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : _animation_save_as ( const Ref < Resource > & p_resource ) {
2020-03-06 17:00:16 +00:00
file - > set_file_mode ( EditorFileDialog : : FILE_MODE_SAVE_FILE ) ;
2015-10-19 19:40:24 +00:00
List < String > extensions ;
ResourceSaver : : get_recognized_extensions ( p_resource , & extensions ) ;
file - > clear_filters ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < extensions . size ( ) ; i + + ) {
2015-10-19 19:40:24 +00:00
file - > add_filter ( " *. " + extensions [ i ] + " ; " + extensions [ i ] . to_upper ( ) ) ;
}
2014-02-10 01:10:30 +00:00
2020-06-18 23:22:36 +00:00
String path ;
2015-10-19 19:40:24 +00:00
//file->set_current_path(current_path);
2021-12-09 09:42:46 +00:00
if ( ! p_resource - > get_path ( ) . is_empty ( ) ) {
2020-06-18 23:22:36 +00:00
path = p_resource - > get_path ( ) ;
2015-10-19 19:40:24 +00:00
if ( extensions . size ( ) ) {
2020-06-18 23:22:36 +00:00
if ( extensions . find ( p_resource - > get_path ( ) . get_extension ( ) . to_lower ( ) ) = = nullptr ) {
path = p_resource - > get_path ( ) . get_base_dir ( ) + p_resource - > get_name ( ) + " . " + extensions . front ( ) - > get ( ) ;
2015-10-19 19:40:24 +00:00
}
}
2017-03-05 15:44:50 +00:00
} else {
2015-10-19 19:40:24 +00:00
if ( extensions . size ( ) ) {
2021-12-09 09:42:46 +00:00
if ( ! p_resource - > get_name ( ) . is_empty ( ) ) {
2020-06-18 23:22:36 +00:00
path = p_resource - > get_name ( ) + " . " + extensions . front ( ) - > get ( ) . to_lower ( ) ;
2017-03-05 15:44:50 +00:00
} else {
2021-07-30 00:42:07 +00:00
String resource_name_snake_case = p_resource - > get_class ( ) . camelcase_to_underscore ( ) ;
path = " new_ " + resource_name_snake_case + " . " + extensions . front ( ) - > get ( ) . to_lower ( ) ;
2017-01-14 19:45:42 +00:00
}
2015-10-19 19:40:24 +00:00
}
}
2020-06-18 23:22:36 +00:00
file - > set_current_path ( path ) ;
2018-04-22 17:36:01 +00:00
file - > set_title ( TTR ( " Save Resource As... " ) ) ;
2020-07-11 16:45:19 +00:00
file - > popup_file_dialog ( ) ;
2014-02-10 01:10:30 +00:00
}
2017-01-25 20:22:16 +00:00
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_remove ( ) {
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-04-08 22:42:19 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2020-07-24 13:14:56 +00:00
delete_dialog - > set_text ( vformat ( TTR ( " Delete Animation '%s'? " ) , current ) ) ;
2020-03-06 17:00:16 +00:00
delete_dialog - > popup_centered ( ) ;
2017-01-25 20:22:16 +00:00
}
void AnimationPlayerEditor : : _animation_remove_confirmed ( ) {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
Ref < Animation > anim = player - > get_animation ( current ) ;
2014-02-10 01:10:30 +00:00
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " Remove Animation " ) ) ;
2018-04-26 01:09:41 +00:00
if ( player - > get_autoplay ( ) = = current ) {
undo_redo - > add_do_method ( player , " set_autoplay " , " " ) ;
undo_redo - > add_undo_method ( player , " set_autoplay " , current ) ;
2019-06-19 03:51:06 +00:00
// Avoid having the autoplay icon linger around if there is only one animation in the player.
2018-04-26 01:09:41 +00:00
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
}
2017-01-25 20:22:16 +00:00
undo_redo - > add_do_method ( player , " remove_animation " , current ) ;
undo_redo - > add_undo_method ( player , " add_animation " , current , anim ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
2019-06-19 03:51:06 +00:00
if ( animation - > get_item_count ( ) = = 1 ) {
undo_redo - > add_do_method ( this , " _stop_onion_skinning " ) ;
undo_redo - > add_undo_method ( this , " _start_onion_skinning " ) ;
}
2014-02-10 01:10:30 +00:00
undo_redo - > commit_action ( ) ;
}
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : _select_anim_by_name ( const String & p_anim ) {
int idx = - 1 ;
for ( int i = 0 ; i < animation - > get_item_count ( ) ; i + + ) {
if ( animation - > get_item_text ( i ) = = p_anim ) {
idx = i ;
2014-02-10 01:10:30 +00:00
break ;
}
}
2017-03-05 15:44:50 +00:00
ERR_FAIL_COND ( idx = = - 1 ) ;
2014-02-10 01:10:30 +00:00
animation - > select ( idx ) ;
_animation_selected ( idx ) ;
}
2019-09-02 13:49:55 +00:00
double AnimationPlayerEditor : : _get_editor_step ( ) const {
// Returns the effective snapping value depending on snapping modifiers, or 0 if snapping is disabled.
if ( track_editor - > is_snap_enabled ( ) ) {
const String current = player - > get_assigned_animation ( ) ;
const Ref < Animation > anim = player - > get_animation ( current ) ;
2019-10-03 18:42:22 +00:00
ERR_FAIL_COND_V ( ! anim . is_valid ( ) , 0.0 ) ;
2019-09-02 13:49:55 +00:00
// Use more precise snapping when holding Shift
2021-08-13 21:31:57 +00:00
return Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ? anim - > get_step ( ) * 0.25 : anim - > get_step ( ) ;
2019-09-02 13:49:55 +00:00
}
return 0.0 ;
}
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_name_edited ( ) {
player - > stop ( ) ;
String new_name = name - > get_text ( ) ;
2022-02-03 16:03:38 +00:00
if ( new_name . is_empty ( ) | | new_name . contains ( " : " ) | | new_name . contains ( " / " ) ) {
2018-04-27 01:58:30 +00:00
error_dialog - > set_text ( TTR ( " Invalid animation name! " ) ) ;
2020-03-06 17:00:16 +00:00
error_dialog - > popup_centered ( ) ;
2014-02-10 01:10:30 +00:00
return ;
}
2022-02-14 06:28:42 +00:00
if ( name_dialog_op = = TOOL_RENAME_ANIM & & animation - > get_item_count ( ) > 0 & & animation - > get_item_text ( animation - > get_selected ( ) ) = = new_name ) {
2014-02-10 01:10:30 +00:00
name_dialog - > hide ( ) ;
return ;
}
if ( player - > has_animation ( new_name ) ) {
2018-04-27 01:58:30 +00:00
error_dialog - > set_text ( TTR ( " Animation name already exists! " ) ) ;
2020-03-06 17:00:16 +00:00
error_dialog - > popup_centered ( ) ;
2014-02-10 01:10:30 +00:00
return ;
}
2022-02-14 06:28:42 +00:00
switch ( name_dialog_op ) {
case TOOL_RENAME_ANIM : {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
Ref < Animation > anim = player - > get_animation ( current ) ;
undo_redo - > create_action ( TTR ( " Rename Animation " ) ) ;
undo_redo - > add_do_method ( player , " rename_animation " , current , new_name ) ;
undo_redo - > add_do_method ( anim . ptr ( ) , " set_name " , new_name ) ;
undo_redo - > add_undo_method ( player , " rename_animation " , new_name , current ) ;
undo_redo - > add_undo_method ( anim . ptr ( ) , " set_name " , current ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > commit_action ( ) ;
_select_anim_by_name ( new_name ) ;
} break ;
2014-02-10 01:10:30 +00:00
2022-02-14 06:28:42 +00:00
case TOOL_NEW_ANIM : {
Ref < Animation > new_anim = Ref < Animation > ( memnew ( Animation ) ) ;
new_anim - > set_name ( new_name ) ;
undo_redo - > create_action ( TTR ( " Add Animation " ) ) ;
undo_redo - > add_do_method ( player , " add_animation " , new_name , new_anim ) ;
undo_redo - > add_undo_method ( player , " remove_animation " , new_name ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
if ( animation - > get_item_count ( ) = = 0 ) {
undo_redo - > add_do_method ( this , " _start_onion_skinning " ) ;
undo_redo - > add_undo_method ( this , " _stop_onion_skinning " ) ;
}
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
2022-02-14 06:28:42 +00:00
_select_anim_by_name ( new_name ) ;
} break ;
2014-02-10 01:10:30 +00:00
2022-02-14 06:28:42 +00:00
case TOOL_DUPLICATE_ANIM : {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
Ref < Animation > anim = player - > get_animation ( current ) ;
2014-02-10 01:10:30 +00:00
2022-02-14 06:28:42 +00:00
Ref < Animation > new_anim = _animation_clone ( anim ) ;
undo_redo - > create_action ( TTR ( " Duplicate Animation " ) ) ;
undo_redo - > add_do_method ( player , " add_animation " , new_name , new_anim ) ;
undo_redo - > add_undo_method ( player , " remove_animation " , new_name ) ;
undo_redo - > add_do_method ( player , " animation_set_next " , new_name , player - > animation_get_next ( current ) ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
2022-02-14 06:28:42 +00:00
_select_anim_by_name ( new_name ) ;
} break ;
2014-02-10 01:10:30 +00:00
}
name_dialog - > hide ( ) ;
}
2016-05-07 16:27:52 +00:00
void AnimationPlayerEditor : : _blend_editor_next_changed ( const int p_idx ) {
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2016-05-07 16:27:52 +00:00
undo_redo - > create_action ( TTR ( " Blend Next Changed " ) ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( player , " animation_set_next " , current , blend_editor . next - > get_item_text ( p_idx ) ) ;
undo_redo - > add_undo_method ( player , " animation_set_next " , current , player - > animation_get_next ( current ) ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
2016-05-07 16:27:52 +00:00
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : _animation_blend ( ) {
2020-05-14 14:41:43 +00:00
if ( updating_blends ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
blend_editor . tree - > clear ( ) ;
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2017-10-12 18:59:25 +00:00
blend_editor . dialog - > popup_centered ( Size2 ( 400 , 400 ) * EDSCALE ) ;
2014-02-10 01:10:30 +00:00
blend_editor . tree - > set_hide_root ( true ) ;
2021-07-04 03:13:28 +00:00
blend_editor . tree - > set_column_expand_ratio ( 0 , 10 ) ;
blend_editor . tree - > set_column_clip_content ( 0 , true ) ;
blend_editor . tree - > set_column_expand_ratio ( 1 , 3 ) ;
blend_editor . tree - > set_column_clip_content ( 1 , true ) ;
2014-02-10 01:10:30 +00:00
List < StringName > anims ;
player - > get_animation_list ( & anims ) ;
TreeItem * root = blend_editor . tree - > create_item ( ) ;
2017-03-05 15:44:50 +00:00
updating_blends = true ;
2014-02-10 01:10:30 +00:00
2016-05-07 16:27:52 +00:00
int i = 0 ;
bool anim_found = false ;
blend_editor . next - > clear ( ) ;
blend_editor . next - > add_item ( " " , i ) ;
2021-07-24 13:46:25 +00:00
for ( const StringName & to : anims ) {
2017-03-05 15:44:50 +00:00
TreeItem * blend = blend_editor . tree - > create_item ( root ) ;
blend - > set_editable ( 0 , false ) ;
blend - > set_editable ( 1 , true ) ;
blend - > set_text ( 0 , to ) ;
blend - > set_cell_mode ( 1 , TreeItem : : CELL_MODE_RANGE ) ;
blend - > set_range_config ( 1 , 0 , 3600 , 0.001 ) ;
blend - > set_range ( 1 , player - > get_blend_time ( current , to ) ) ;
2016-05-07 16:27:52 +00:00
i + + ;
blend_editor . next - > add_item ( to , i ) ;
if ( to = = player - > animation_get_next ( current ) ) {
blend_editor . next - > select ( i ) ;
anim_found = true ;
}
2014-02-10 01:10:30 +00:00
}
2016-05-07 16:27:52 +00:00
// make sure we reset it else it becomes out of sync and could contain a deleted animation
if ( ! anim_found ) {
blend_editor . next - > select ( 0 ) ;
player - > animation_set_next ( current , blend_editor . next - > get_item_text ( 0 ) ) ;
}
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
updating_blends = false ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : _blend_edited ( ) {
2020-05-14 14:41:43 +00:00
if ( updating_blends ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) = = 0 ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
TreeItem * selected = blend_editor . tree - > get_edited ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! selected ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
updating_blends = true ;
String to = selected - > get_text ( 0 ) ;
2014-02-10 01:10:30 +00:00
float blend_time = selected - > get_range ( 1 ) ;
2017-03-05 15:44:50 +00:00
float prev_blend_time = player - > get_blend_time ( current , to ) ;
2014-02-10 01:10:30 +00:00
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " Change Blend Time " ) ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( player , " set_blend_time " , current , to , blend_time ) ;
undo_redo - > add_undo_method ( player , " set_blend_time " , current , to , prev_blend_time ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
2014-02-10 01:10:30 +00:00
undo_redo - > commit_action ( ) ;
2017-03-05 15:44:50 +00:00
updating_blends = false ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : ensure_visibility ( ) {
2020-05-14 14:41:43 +00:00
if ( player & & pin - > is_pressed ( ) ) {
2016-05-01 09:37:58 +00:00
return ; // another player is pinned, don't reset
2020-05-14 14:41:43 +00:00
}
2016-05-01 09:37:58 +00:00
2014-02-10 01:10:30 +00:00
_animation_edit ( ) ;
}
2015-08-30 01:59:25 +00:00
Dictionary AnimationPlayerEditor : : get_state ( ) const {
Dictionary d ;
2017-03-05 15:44:50 +00:00
d [ " visible " ] = is_visible_in_tree ( ) ;
2017-01-13 13:45:50 +00:00
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) & & is_visible_in_tree ( ) & & player ) {
2017-03-05 15:44:50 +00:00
d [ " player " ] = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( player ) ;
2018-01-14 10:28:57 +00:00
d [ " animation " ] = player - > get_assigned_animation ( ) ;
2019-04-14 19:43:38 +00:00
d [ " track_editor_state " ] = track_editor - > get_state ( ) ;
2015-08-30 01:59:25 +00:00
}
return d ;
}
2020-05-14 12:29:06 +00:00
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : set_state ( const Dictionary & p_state ) {
2019-05-25 01:47:16 +00:00
if ( ! p_state . has ( " visible " ) | | ! p_state [ " visible " ] ) {
return ;
}
if ( ! EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
return ;
}
2015-08-30 01:59:25 +00:00
2019-05-25 01:47:16 +00:00
if ( p_state . has ( " player " ) ) {
2015-08-30 01:59:25 +00:00
Node * n = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_node ( p_state [ " player " ] ) ;
2017-08-24 20:58:51 +00:00
if ( Object : : cast_to < AnimationPlayer > ( n ) & & EditorNode : : get_singleton ( ) - > get_editor_selection ( ) - > is_selected ( n ) ) {
player = Object : : cast_to < AnimationPlayer > ( n ) ;
2015-08-30 01:59:25 +00:00
_update_player ( ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > make_bottom_panel_item_visible ( this ) ;
2015-08-30 01:59:25 +00:00
set_process ( true ) ;
ensure_visibility ( ) ;
if ( p_state . has ( " animation " ) ) {
String anim = p_state [ " animation " ] ;
2020-12-15 12:04:21 +00:00
if ( ! anim . is_empty ( ) & & player - > has_animation ( anim ) ) {
2019-09-04 16:18:25 +00:00
_select_anim_by_name ( anim ) ;
_animation_edit ( ) ;
}
2015-08-30 01:59:25 +00:00
}
}
2019-05-25 01:47:16 +00:00
}
2019-04-14 19:43:38 +00:00
2019-05-25 01:47:16 +00:00
if ( p_state . has ( " track_editor_state " ) ) {
track_editor - > set_state ( p_state [ " track_editor_state " ] ) ;
2015-08-30 01:59:25 +00:00
}
}
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_resource_edit ( ) {
if ( animation - > get_item_count ( ) ) {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2017-03-05 15:44:50 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > edit_resource ( anim ) ;
2014-02-10 01:10:30 +00:00
}
}
void AnimationPlayerEditor : : _animation_edit ( ) {
2016-01-17 23:03:57 +00:00
if ( animation - > get_item_count ( ) ) {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2017-03-05 15:44:50 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( anim ) ;
2019-05-25 01:47:16 +00:00
2016-01-17 23:03:57 +00:00
Node * root = player - > get_node ( player - > get_root ( ) ) ;
if ( root ) {
2018-06-07 15:46:14 +00:00
track_editor - > set_root ( root ) ;
2016-01-17 23:03:57 +00:00
}
} else {
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( Ref < Animation > ( ) ) ;
2020-04-01 23:20:12 +00:00
track_editor - > set_root ( nullptr ) ;
2014-02-10 01:10:30 +00:00
}
}
2019-05-25 01:47:16 +00:00
2020-03-23 15:35:26 +00:00
void AnimationPlayerEditor : : _save_animation ( String p_file ) {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2020-03-23 15:35:26 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
2014-02-10 01:10:30 +00:00
2020-03-23 15:35:26 +00:00
ERR_FAIL_COND ( ! Object : : cast_to < Resource > ( * anim ) ) ;
2014-02-10 01:10:30 +00:00
2020-03-23 15:35:26 +00:00
RES current_res = RES ( Object : : cast_to < Resource > ( * anim ) ) ;
2014-02-10 01:10:30 +00:00
2020-03-23 15:35:26 +00:00
_animation_save_in_path ( current_res , p_file ) ;
}
}
2016-03-08 23:00:52 +00:00
2020-03-23 15:35:26 +00:00
void AnimationPlayerEditor : : _load_animations ( Vector < String > p_files ) {
ERR_FAIL_COND ( ! player ) ;
2015-10-19 19:40:24 +00:00
2020-03-23 15:35:26 +00:00
for ( int i = 0 ; i < p_files . size ( ) ; i + + ) {
String file = p_files [ i ] ;
2014-02-10 01:10:30 +00:00
2020-03-23 15:35:26 +00:00
Ref < Resource > res = ResourceLoader : : load ( file , " Animation " ) ;
ERR_FAIL_COND_MSG ( res . is_null ( ) , " Cannot load Animation from file ' " + file + " '. " ) ;
ERR_FAIL_COND_MSG ( ! res - > is_class ( " Animation " ) , " Loaded resource from file ' " + file + " ' is not Animation. " ) ;
if ( file . rfind ( " / " ) ! = - 1 ) {
file = file . substr ( file . rfind ( " / " ) + 1 , file . length ( ) ) ;
}
if ( file . rfind ( " \\ " ) ! = - 1 ) {
file = file . substr ( file . rfind ( " \\ " ) + 1 , file . length ( ) ) ;
}
2022-02-03 16:03:38 +00:00
if ( file . contains ( " . " ) ) {
2020-03-23 15:35:26 +00:00
file = file . substr ( 0 , file . find ( " . " ) ) ;
2015-10-19 19:40:24 +00:00
}
2020-03-23 15:35:26 +00:00
undo_redo - > create_action ( TTR ( " Load Animation " ) ) ;
undo_redo - > add_do_method ( player , " add_animation " , file , res ) ;
undo_redo - > add_undo_method ( player , " remove_animation " , file ) ;
if ( player - > has_animation ( file ) ) {
undo_redo - > add_undo_method ( player , " add_animation " , file , player - > get_animation ( file ) ) ;
}
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > commit_action ( ) ;
2015-10-19 19:40:24 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
void AnimationPlayerEditor : : _scale_changed ( const String & p_scale ) {
2020-07-24 18:07:57 +00:00
player - > set_speed_scale ( p_scale . to_float ( ) ) ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : _update_animation ( ) {
// the purpose of _update_animation is to reflect the current state
// of the animation player in the current editor..
2017-03-05 15:44:50 +00:00
updating = true ;
2014-02-10 01:10:30 +00:00
if ( player - > is_playing ( ) ) {
play - > set_pressed ( true ) ;
stop - > set_pressed ( false ) ;
} else {
play - > set_pressed ( false ) ;
stop - > set_pressed ( true ) ;
}
2017-03-05 15:44:50 +00:00
scale - > set_text ( String : : num ( player - > get_speed_scale ( ) , 2 ) ) ;
2018-01-14 10:28:57 +00:00
String current = player - > get_assigned_animation ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < animation - > get_item_count ( ) ; i + + ) {
if ( animation - > get_item_text ( i ) = = current ) {
2014-02-10 01:10:30 +00:00
animation - > select ( i ) ;
break ;
}
}
2017-03-05 15:44:50 +00:00
updating = false ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditor : : _update_player ( ) {
2017-03-05 15:44:50 +00:00
updating = true ;
2014-02-10 01:10:30 +00:00
List < StringName > animlist ;
2020-05-14 14:41:43 +00:00
if ( player ) {
2016-01-17 23:03:57 +00:00
player - > get_animation_list ( & animlist ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
animation - > clear ( ) ;
2018-06-07 15:46:14 +00:00
# define ITEM_DISABLED(m_item, m_disabled) tool_anim->get_popup()->set_item_disabled(tool_anim->get_popup()->get_item_index(m_item), m_disabled)
ITEM_DISABLED ( TOOL_SAVE_ANIM , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_SAVE_AS_ANIM , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_DUPLICATE_ANIM , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_RENAME_ANIM , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_EDIT_TRANSITIONS , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_COPY_ANIM , animlist . size ( ) = = 0 ) ;
ITEM_DISABLED ( TOOL_REMOVE_ANIM , animlist . size ( ) = = 0 ) ;
2017-03-05 15:44:50 +00:00
stop - > set_disabled ( animlist . size ( ) = = 0 ) ;
play - > set_disabled ( animlist . size ( ) = = 0 ) ;
play_bw - > set_disabled ( animlist . size ( ) = = 0 ) ;
play_bw_from - > set_disabled ( animlist . size ( ) = = 0 ) ;
play_from - > set_disabled ( animlist . size ( ) = = 0 ) ;
2018-04-27 01:58:30 +00:00
frame - > set_editable ( animlist . size ( ) ! = 0 ) ;
animation - > set_disabled ( animlist . size ( ) = = 0 ) ;
2017-03-05 15:44:50 +00:00
autoplay - > set_disabled ( animlist . size ( ) = = 0 ) ;
2020-04-01 23:20:12 +00:00
tool_anim - > set_disabled ( player = = nullptr ) ;
2019-06-19 03:51:06 +00:00
onion_toggle - > set_disabled ( animlist . size ( ) = = 0 ) ;
onion_skinning - > set_disabled ( animlist . size ( ) = = 0 ) ;
2020-04-01 23:20:12 +00:00
pin - > set_disabled ( player = = nullptr ) ;
2015-10-19 19:40:24 +00:00
2019-04-04 20:00:16 +00:00
if ( ! player ) {
2021-02-04 08:20:26 +00:00
AnimationPlayerEditor : : get_singleton ( ) - > get_track_editor ( ) - > update_keying ( ) ;
2019-04-04 20:00:16 +00:00
return ;
}
2017-03-05 15:44:50 +00:00
int active_idx = - 1 ;
2021-07-24 13:46:25 +00:00
for ( const StringName & E : animlist ) {
2020-12-20 10:46:44 +00:00
Ref < Texture2D > icon ;
2021-07-16 03:45:57 +00:00
if ( E = = player - > get_autoplay ( ) ) {
2021-12-06 00:46:03 +00:00
if ( E = = SceneStringNames : : get_singleton ( ) - > RESET ) {
2020-12-20 10:46:44 +00:00
icon = autoplay_reset_icon ;
} else {
icon = autoplay_icon ;
}
2021-12-06 00:46:03 +00:00
} else if ( E = = SceneStringNames : : get_singleton ( ) - > RESET ) {
2020-12-20 10:46:44 +00:00
icon = reset_icon ;
2020-05-14 14:41:43 +00:00
}
2021-07-16 03:45:57 +00:00
animation - > add_icon_item ( icon , E ) ;
2014-02-10 01:10:30 +00:00
2021-07-16 03:45:57 +00:00
if ( player - > get_assigned_animation ( ) = = E ) {
2017-03-05 15:44:50 +00:00
active_idx = animation - > get_item_count ( ) - 1 ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
updating = false ;
if ( active_idx ! = - 1 ) {
2014-02-10 01:10:30 +00:00
animation - > select ( active_idx ) ;
2017-03-05 15:44:50 +00:00
autoplay - > set_pressed ( animation - > get_item_text ( active_idx ) = = player - > get_autoplay ( ) ) ;
2014-02-10 01:10:30 +00:00
_animation_selected ( active_idx ) ;
2017-03-05 15:44:50 +00:00
} else if ( animation - > get_item_count ( ) > 0 ) {
2014-02-10 01:10:30 +00:00
animation - > select ( 0 ) ;
2017-03-05 15:44:50 +00:00
autoplay - > set_pressed ( animation - > get_item_text ( 0 ) = = player - > get_autoplay ( ) ) ;
2014-02-10 01:10:30 +00:00
_animation_selected ( 0 ) ;
2018-07-03 18:57:54 +00:00
} else {
_animation_selected ( 0 ) ;
2014-02-10 01:10:30 +00:00
}
2016-01-17 23:03:57 +00:00
if ( animation - > get_item_count ( ) ) {
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2017-03-05 15:44:50 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
2018-06-07 15:46:14 +00:00
track_editor - > set_animation ( anim ) ;
2016-01-17 23:03:57 +00:00
Node * root = player - > get_node ( player - > get_root ( ) ) ;
if ( root ) {
2018-06-07 15:46:14 +00:00
track_editor - > set_root ( root ) ;
2014-02-10 01:10:30 +00:00
}
}
_update_animation ( ) ;
}
void AnimationPlayerEditor : : edit ( AnimationPlayer * p_player ) {
2020-05-14 14:41:43 +00:00
if ( player & & pin - > is_pressed ( ) ) {
2019-06-19 03:51:06 +00:00
return ; // Ignore, pinned.
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
player = p_player ;
2014-02-10 01:10:30 +00:00
2016-07-22 12:42:12 +00:00
if ( player ) {
2014-02-10 01:10:30 +00:00
_update_player ( ) ;
2019-06-19 03:51:06 +00:00
if ( onion . enabled ) {
2020-05-14 14:41:43 +00:00
if ( animation - > get_item_count ( ) > 0 ) {
2019-06-19 03:51:06 +00:00
_start_onion_skinning ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2019-06-19 03:51:06 +00:00
_stop_onion_skinning ( ) ;
2020-05-14 14:41:43 +00:00
}
2019-06-19 03:51:06 +00:00
}
2018-06-07 15:46:14 +00:00
track_editor - > show_select_node_warning ( false ) ;
2016-07-22 12:42:12 +00:00
} else {
2020-05-14 14:41:43 +00:00
if ( onion . enabled ) {
2019-06-19 03:51:06 +00:00
_stop_onion_skinning ( ) ;
2020-05-14 14:41:43 +00:00
}
2019-06-19 03:51:06 +00:00
2018-06-07 15:46:14 +00:00
track_editor - > show_select_node_warning ( true ) ;
2014-02-10 01:10:30 +00:00
}
}
2021-09-14 12:51:50 +00:00
void AnimationPlayerEditor : : forward_force_draw_over_viewport ( Control * p_overlay ) {
2020-05-14 14:41:43 +00:00
if ( ! onion . can_overlay ) {
2017-10-30 18:43:19 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
2019-06-19 03:51:06 +00:00
// Can happen on viewport resize, at least.
2020-05-14 14:41:43 +00:00
if ( ! _are_onion_layers_valid ( ) ) {
2017-10-30 18:43:19 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
RID ci = p_overlay - > get_canvas_item ( ) ;
Rect2 src_rect = p_overlay - > get_global_rect ( ) ;
2019-06-19 03:51:06 +00:00
// Re-flip since captures are already flipped.
2017-10-30 18:43:19 +00:00
src_rect . position . y = onion . capture_size . y - ( src_rect . position . y + src_rect . size . y ) ;
src_rect . size . y * = - 1 ;
Rect2 dst_rect = Rect2 ( Point2 ( ) , p_overlay - > get_size ( ) ) ;
float alpha_step = 1.0 / ( onion . steps + 1 ) ;
int cidx = 0 ;
if ( onion . past ) {
float alpha = 0 ;
do {
alpha + = alpha_step ;
if ( onion . captures_valid [ cidx ] ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_add_texture_rect_region (
ci , dst_rect , RS : : get_singleton ( ) - > viewport_get_texture ( onion . captures [ cidx ] ) , src_rect , Color ( 1 , 1 , 1 , alpha ) ) ;
2017-10-30 18:43:19 +00:00
}
cidx + + ;
} while ( cidx < onion . steps ) ;
}
if ( onion . future ) {
float alpha = 1 ;
int base_cidx = cidx ;
do {
alpha - = alpha_step ;
if ( onion . captures_valid [ cidx ] ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_add_texture_rect_region (
ci , dst_rect , RS : : get_singleton ( ) - > viewport_get_texture ( onion . captures [ cidx ] ) , src_rect , Color ( 1 , 1 , 1 , alpha ) ) ;
2017-10-30 18:43:19 +00:00
}
cidx + + ;
2019-06-19 03:51:06 +00:00
} while ( cidx < base_cidx + onion . steps ) ; // In case there's the present capture at the end, skip it.
2017-10-30 18:43:19 +00:00
}
}
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _animation_duplicate ( ) {
2020-05-14 14:41:43 +00:00
if ( ! animation - > get_item_count ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
String current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2017-03-05 15:44:50 +00:00
Ref < Animation > anim = player - > get_animation ( current ) ;
2020-05-14 14:41:43 +00:00
if ( ! anim . is_valid ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
String new_name = current ;
2017-03-05 15:44:50 +00:00
while ( player - > has_animation ( new_name ) ) {
new_name = new_name + " (copy) " ;
2014-02-10 01:10:30 +00:00
}
2022-02-14 06:28:42 +00:00
name_title - > set_text ( TTR ( " New Animation Name: " ) ) ;
name - > set_text ( new_name ) ;
name_dialog_op = TOOL_DUPLICATE_ANIM ;
name_dialog - > popup_centered ( Size2 ( 300 , 90 ) ) ;
name - > select_all ( ) ;
name - > grab_focus ( ) ;
2014-02-10 01:10:30 +00:00
}
2019-11-02 00:52:54 +00:00
Ref < Animation > AnimationPlayerEditor : : _animation_clone ( Ref < Animation > p_anim ) {
Ref < Animation > new_anim = memnew ( Animation ) ;
List < PropertyInfo > plist ;
p_anim - > get_property_list ( & plist ) ;
for ( const PropertyInfo & E : plist ) {
if ( E . usage & PROPERTY_USAGE_STORAGE ) {
new_anim - > set ( E . name , p_anim - > get ( E . name ) ) ;
}
}
new_anim - > set_path ( " " ) ;
return new_anim ;
}
void AnimationPlayerEditor : : _animation_paste ( Ref < Animation > p_anim ) {
String name = p_anim - > get_name ( ) ;
if ( name . is_empty ( ) ) {
name = TTR ( " Pasted Animation " ) ;
}
int idx = 1 ;
String base = name ;
while ( player - > has_animation ( name ) ) {
idx + + ;
name = base + " " + itos ( idx ) ;
}
undo_redo - > create_action ( TTR ( " Paste Animation " ) ) ;
undo_redo - > add_do_method ( player , " add_animation " , name , p_anim ) ;
undo_redo - > add_undo_method ( player , " remove_animation " , name ) ;
undo_redo - > add_do_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > add_undo_method ( this , " _animation_player_changed " , player ) ;
undo_redo - > commit_action ( ) ;
_select_anim_by_name ( name ) ;
}
2020-07-14 23:05:04 +00:00
void AnimationPlayerEditor : : _seek_value_changed ( float p_value , bool p_set , bool p_timeline_only ) {
2014-02-10 01:10:30 +00:00
if ( updating | | ! player | | player - > is_playing ( ) ) {
return ;
} ;
2017-03-05 15:44:50 +00:00
updating = true ;
2019-08-05 23:15:20 +00:00
String current = player - > get_assigned_animation ( ) ;
2021-12-09 09:42:46 +00:00
if ( current . is_empty ( ) | | ! player - > has_animation ( current ) ) {
2017-03-05 15:44:50 +00:00
updating = false ;
current = " " ;
2014-02-10 01:10:30 +00:00
return ;
} ;
Ref < Animation > anim ;
2017-03-05 15:44:50 +00:00
anim = player - > get_animation ( current ) ;
2014-02-10 01:10:30 +00:00
2021-10-15 13:25:00 +00:00
float pos = CLAMP ( ( double ) anim - > get_length ( ) * ( p_value / frame - > get_max ( ) ) , 0 , ( double ) anim - > get_length ( ) ) ;
2019-08-05 23:15:20 +00:00
if ( track_editor - > is_snap_enabled ( ) ) {
2020-12-21 18:02:57 +00:00
pos = Math : : snapped ( pos , _get_editor_step ( ) ) ;
2016-02-09 20:02:57 +00:00
}
2014-02-10 01:10:30 +00:00
2020-07-14 23:05:04 +00:00
if ( ! p_timeline_only ) {
if ( player - > is_valid ( ) & & ! p_set ) {
float cpos = player - > get_current_animation_position ( ) ;
2014-02-10 01:10:30 +00:00
2020-07-14 23:05:04 +00:00
player - > seek_delta ( pos , pos - cpos ) ;
} else {
player - > stop ( true ) ;
player - > seek ( pos , true ) ;
}
2014-02-10 01:10:30 +00:00
}
2018-06-07 15:46:14 +00:00
track_editor - > set_anim_pos ( pos ) ;
2014-02-10 01:10:30 +00:00
} ;
void AnimationPlayerEditor : : _animation_player_changed ( Object * p_pl ) {
2017-03-05 15:44:50 +00:00
if ( player = = p_pl & & is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
_update_player ( ) ;
2020-05-14 14:41:43 +00:00
if ( blend_editor . dialog - > is_visible ( ) ) {
2019-06-19 03:51:06 +00:00
_animation_blend ( ) ; // Update.
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
void AnimationPlayerEditor : : _list_changed ( ) {
2020-05-14 14:41:43 +00:00
if ( is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
_update_player ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2019-05-30 19:43:46 +00:00
void AnimationPlayerEditor : : _animation_key_editor_anim_len_changed ( float p_len ) {
frame - > set_max ( p_len ) ;
}
2020-07-14 23:05:04 +00:00
void AnimationPlayerEditor : : _animation_key_editor_seek ( float p_pos , bool p_drag , bool p_timeline_only ) {
2019-10-01 16:38:03 +00:00
timeline_position = p_pos ;
2020-05-14 14:41:43 +00:00
if ( ! is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-10-02 20:49:34 +00:00
2020-05-14 14:41:43 +00:00
if ( ! player ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( player - > is_playing ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( ! player - > has_animation ( player - > get_assigned_animation ( ) ) ) {
2019-10-02 20:49:34 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-10-02 20:49:34 +00:00
2017-03-05 15:44:50 +00:00
updating = true ;
2020-12-21 18:02:57 +00:00
frame - > set_value ( Math : : snapped ( p_pos , _get_editor_step ( ) ) ) ;
2017-03-05 15:44:50 +00:00
updating = false ;
2020-07-14 23:05:04 +00:00
_seek_value_changed ( p_pos , ! p_drag , p_timeline_only ) ;
2014-02-10 01:10:30 +00:00
}
2015-05-25 04:46:45 +00:00
void AnimationPlayerEditor : : _animation_tool_menu ( int p_option ) {
2018-07-01 08:26:29 +00:00
String current ;
2019-06-19 03:51:06 +00:00
if ( animation - > get_selected ( ) > = 0 & & animation - > get_selected ( ) < animation - > get_item_count ( ) ) {
2018-07-01 08:26:29 +00:00
current = animation - > get_item_text ( animation - > get_selected ( ) ) ;
2019-06-19 03:51:06 +00:00
}
2018-07-01 08:26:29 +00:00
2018-06-07 15:46:14 +00:00
Ref < Animation > anim ;
2021-12-09 09:42:46 +00:00
if ( ! current . is_empty ( ) ) {
2018-06-07 15:46:14 +00:00
anim = player - > get_animation ( current ) ;
}
2017-03-05 15:44:50 +00:00
switch ( p_option ) {
2018-06-07 15:46:14 +00:00
case TOOL_NEW_ANIM : {
_animation_new ( ) ;
} break ;
case TOOL_LOAD_ANIM : {
_animation_load ( ) ;
} break ;
case TOOL_SAVE_ANIM : {
if ( anim . is_valid ( ) ) {
_animation_save ( anim ) ;
}
} break ;
case TOOL_SAVE_AS_ANIM : {
if ( anim . is_valid ( ) ) {
_animation_save_as ( anim ) ;
}
} break ;
case TOOL_DUPLICATE_ANIM : {
_animation_duplicate ( ) ;
2022-02-14 06:28:42 +00:00
} break ;
2018-06-07 15:46:14 +00:00
case TOOL_RENAME_ANIM : {
_animation_rename ( ) ;
} break ;
case TOOL_EDIT_TRANSITIONS : {
_animation_blend ( ) ;
} break ;
case TOOL_REMOVE_ANIM : {
_animation_remove ( ) ;
} break ;
2015-05-25 04:46:45 +00:00
case TOOL_COPY_ANIM : {
if ( ! animation - > get_item_count ( ) ) {
2018-04-27 01:58:30 +00:00
error_dialog - > set_text ( TTR ( " No animation to copy! " ) ) ;
2020-03-06 17:00:16 +00:00
error_dialog - > popup_centered ( ) ;
2015-05-25 04:46:45 +00:00
return ;
}
2019-02-12 20:10:08 +00:00
String current2 = animation - > get_item_text ( animation - > get_selected ( ) ) ;
Ref < Animation > anim2 = player - > get_animation ( current2 ) ;
EditorSettings : : get_singleton ( ) - > set_resource_clipboard ( anim2 ) ;
2015-05-25 04:46:45 +00:00
} break ;
case TOOL_PASTE_ANIM : {
2019-02-12 20:10:08 +00:00
Ref < Animation > anim2 = EditorSettings : : get_singleton ( ) - > get_resource_clipboard ( ) ;
if ( ! anim2 . is_valid ( ) ) {
2019-11-02 00:52:54 +00:00
error_dialog - > set_text ( TTR ( " No animation resource in clipboard! " ) ) ;
2020-03-06 17:00:16 +00:00
error_dialog - > popup_centered ( ) ;
2015-05-25 04:46:45 +00:00
return ;
}
2019-11-02 00:52:54 +00:00
Ref < Animation > new_anim = _animation_clone ( anim2 ) ;
_animation_paste ( new_anim ) ;
} break ;
case TOOL_PASTE_ANIM_REF : {
Ref < Animation > anim2 = EditorSettings : : get_singleton ( ) - > get_resource_clipboard ( ) ;
if ( ! anim2 . is_valid ( ) ) {
error_dialog - > set_text ( TTR ( " No animation resource in clipboard! " ) ) ;
error_dialog - > popup_centered ( ) ;
return ;
2015-05-25 04:46:45 +00:00
}
2019-11-02 00:52:54 +00:00
_animation_paste ( anim2 ) ;
2015-05-25 04:46:45 +00:00
} break ;
case TOOL_EDIT_RESOURCE : {
if ( ! animation - > get_item_count ( ) ) {
2018-04-27 01:58:30 +00:00
error_dialog - > set_text ( TTR ( " No animation to edit! " ) ) ;
2020-03-06 17:00:16 +00:00
error_dialog - > popup_centered ( ) ;
2015-05-25 04:46:45 +00:00
return ;
}
2019-02-12 20:10:08 +00:00
String current2 = animation - > get_item_text ( animation - > get_selected ( ) ) ;
Ref < Animation > anim2 = player - > get_animation ( current2 ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > edit_resource ( anim2 ) ;
2015-05-25 04:46:45 +00:00
} break ;
}
}
2017-10-30 18:43:19 +00:00
void AnimationPlayerEditor : : _onion_skinning_menu ( int p_option ) {
PopupMenu * menu = onion_skinning - > get_popup ( ) ;
int idx = menu - > get_item_index ( p_option ) ;
switch ( p_option ) {
case ONION_SKINNING_ENABLE : {
onion . enabled = ! onion . enabled ;
2020-05-14 14:41:43 +00:00
if ( onion . enabled ) {
2017-10-30 18:43:19 +00:00
_start_onion_skinning ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-10-30 18:43:19 +00:00
_stop_onion_skinning ( ) ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
} break ;
case ONION_SKINNING_PAST : {
2019-06-19 03:51:06 +00:00
// Ensure at least one of past/future is checked.
2017-10-30 18:43:19 +00:00
onion . past = onion . future ? ! onion . past : true ;
menu - > set_item_checked ( idx , onion . past ) ;
} break ;
case ONION_SKINNING_FUTURE : {
2019-06-19 03:51:06 +00:00
// Ensure at least one of past/future is checked.
2017-10-30 18:43:19 +00:00
onion . future = onion . past ? ! onion . future : true ;
menu - > set_item_checked ( idx , onion . future ) ;
} break ;
2019-06-19 03:51:06 +00:00
case ONION_SKINNING_1_STEP : // Fall-through.
2017-10-30 18:43:19 +00:00
case ONION_SKINNING_2_STEPS :
case ONION_SKINNING_3_STEPS : {
onion . steps = ( p_option - ONION_SKINNING_1_STEP ) + 1 ;
int one_frame_idx = menu - > get_item_index ( ONION_SKINNING_1_STEP ) ;
for ( int i = 0 ; i < = ONION_SKINNING_LAST_STEPS_OPTION - ONION_SKINNING_1_STEP ; i + + ) {
menu - > set_item_checked ( one_frame_idx + i , onion . steps = = i + 1 ) ;
}
} break ;
case ONION_SKINNING_DIFFERENCES_ONLY : {
onion . differences_only = ! onion . differences_only ;
menu - > set_item_checked ( idx , onion . differences_only ) ;
} break ;
case ONION_SKINNING_FORCE_WHITE_MODULATE : {
onion . force_white_modulate = ! onion . force_white_modulate ;
menu - > set_item_checked ( idx , onion . force_white_modulate ) ;
} break ;
case ONION_SKINNING_INCLUDE_GIZMOS : {
onion . include_gizmos = ! onion . include_gizmos ;
menu - > set_item_checked ( idx , onion . include_gizmos ) ;
} break ;
}
}
2021-08-22 15:37:22 +00:00
void AnimationPlayerEditor : : unhandled_key_input ( const Ref < InputEvent > & p_ev ) {
2021-04-05 06:52:21 +00:00
ERR_FAIL_COND ( p_ev . is_null ( ) ) ;
2017-05-20 15:38:03 +00:00
Ref < InputEventKey > k = p_ev ;
2021-04-24 20:33:50 +00:00
if ( is_visible_in_tree ( ) & & k . is_valid ( ) & & k - > is_pressed ( ) & & ! k - > is_echo ( ) & & ! k - > is_alt_pressed ( ) & & ! k - > is_ctrl_pressed ( ) & & ! k - > is_meta_pressed ( ) ) {
2018-04-05 17:59:35 +00:00
switch ( k - > get_keycode ( ) ) {
2021-08-13 21:31:57 +00:00
case Key : : A : {
2021-04-24 20:33:50 +00:00
if ( ! k - > is_shift_pressed ( ) ) {
2015-05-25 04:46:45 +00:00
_play_bw_from_pressed ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2015-05-25 04:46:45 +00:00
_play_bw_pressed ( ) ;
2020-05-14 14:41:43 +00:00
}
2020-09-17 01:40:00 +00:00
accept_event ( ) ;
2015-05-25 04:46:45 +00:00
} break ;
2021-08-13 21:31:57 +00:00
case Key : : S : {
2015-05-25 04:46:45 +00:00
_stop_pressed ( ) ;
2020-09-17 01:40:00 +00:00
accept_event ( ) ;
2015-05-25 04:46:45 +00:00
} break ;
2021-08-13 21:31:57 +00:00
case Key : : D : {
2021-04-24 20:33:50 +00:00
if ( ! k - > is_shift_pressed ( ) ) {
2015-05-25 04:46:45 +00:00
_play_from_pressed ( ) ;
2020-05-14 14:41:43 +00:00
} else {
2015-05-25 04:46:45 +00:00
_play_pressed ( ) ;
2020-05-14 14:41:43 +00:00
}
2020-09-17 01:40:00 +00:00
accept_event ( ) ;
2015-05-25 04:46:45 +00:00
} break ;
2021-06-20 17:12:33 +00:00
default :
break ;
2015-05-25 04:46:45 +00:00
}
}
}
2017-10-30 18:43:19 +00:00
void AnimationPlayerEditor : : _editor_visibility_changed ( ) {
2019-06-19 03:51:06 +00:00
if ( is_visible ( ) & & animation - > get_item_count ( ) > 0 ) {
2017-10-30 18:43:19 +00:00
_start_onion_skinning ( ) ;
}
}
bool AnimationPlayerEditor : : _are_onion_layers_valid ( ) {
ERR_FAIL_COND_V ( ! onion . past & & ! onion . future , false ) ;
Point2 capture_size = get_tree ( ) - > get_root ( ) - > get_size ( ) ;
return onion . captures . size ( ) = = onion . get_needed_capture_count ( ) & & onion . capture_size = = capture_size ;
}
void AnimationPlayerEditor : : _allocate_onion_layers ( ) {
_free_onion_layers ( ) ;
int captures = onion . get_needed_capture_count ( ) ;
Point2 capture_size = get_tree ( ) - > get_root ( ) - > get_size ( ) ;
onion . captures . resize ( captures ) ;
onion . captures_valid . resize ( captures ) ;
for ( int i = 0 ; i < captures ; i + + ) {
bool is_present = onion . differences_only & & i = = captures - 1 ;
2019-06-19 03:51:06 +00:00
// Each capture is a viewport with a canvas item attached that renders a full-size rect with the contents of the main viewport.
2020-03-27 18:21:27 +00:00
onion . captures . write [ i ] = RS : : get_singleton ( ) - > viewport_create ( ) ;
2019-08-18 22:40:52 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_size ( onion . captures [ i ] , capture_size . width , capture_size . height ) ;
RS : : get_singleton ( ) - > viewport_set_update_mode ( onion . captures [ i ] , RS : : VIEWPORT_UPDATE_ALWAYS ) ;
RS : : get_singleton ( ) - > viewport_set_transparent_background ( onion . captures [ i ] , ! is_present ) ;
RS : : get_singleton ( ) - > viewport_attach_canvas ( onion . captures [ i ] , onion . capture . canvas ) ;
2017-10-30 18:43:19 +00:00
}
2019-06-19 03:51:06 +00:00
// Reset the capture canvas item to the current root viewport texture (defensive).
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_clear ( onion . capture . canvas_item ) ;
RS : : get_singleton ( ) - > canvas_item_add_texture_rect ( onion . capture . canvas_item , Rect2 ( Point2 ( ) , capture_size ) , get_tree ( ) - > get_root ( ) - > get_texture ( ) - > get_rid ( ) ) ;
2017-10-30 18:43:19 +00:00
onion . capture_size = capture_size ;
}
void AnimationPlayerEditor : : _free_onion_layers ( ) {
for ( int i = 0 ; i < onion . captures . size ( ) ; i + + ) {
if ( onion . captures [ i ] . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( onion . captures [ i ] ) ;
2017-10-30 18:43:19 +00:00
}
}
onion . captures . clear ( ) ;
onion . captures_valid . clear ( ) ;
}
void AnimationPlayerEditor : : _prepare_onion_layers_1 ( ) {
2019-06-19 03:51:06 +00:00
// This would be called per viewport and we want to act once only.
2017-10-30 18:43:19 +00:00
int64_t frame = get_tree ( ) - > get_frame ( ) ;
2020-05-14 14:41:43 +00:00
if ( frame = = onion . last_frame ) {
2017-10-30 18:43:19 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
if ( ! onion . enabled | | ! is_processing ( ) | | ! is_visible ( ) | | ! get_player ( ) ) {
_stop_onion_skinning ( ) ;
return ;
}
onion . last_frame = frame ;
2019-06-19 03:51:06 +00:00
// Refresh viewports with no onion layers overlaid.
2017-10-30 18:43:19 +00:00
onion . can_overlay = false ;
plugin - > update_overlays ( ) ;
2020-05-14 14:41:43 +00:00
if ( player - > is_playing ( ) ) {
2017-10-30 18:43:19 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
2019-06-19 03:51:06 +00:00
// And go to next step afterwards.
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _prepare_onion_layers_2 " ) ) ;
2017-10-30 18:43:19 +00:00
}
2020-02-25 20:41:54 +00:00
void AnimationPlayerEditor : : _prepare_onion_layers_1_deferred ( ) {
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " _prepare_onion_layers_1 " ) ) ;
2020-02-25 20:41:54 +00:00
}
2017-10-30 18:43:19 +00:00
void AnimationPlayerEditor : : _prepare_onion_layers_2 ( ) {
2018-01-14 10:28:57 +00:00
Ref < Animation > anim = player - > get_animation ( player - > get_assigned_animation ( ) ) ;
2020-05-14 14:41:43 +00:00
if ( ! anim . is_valid ( ) ) {
2017-10-30 18:43:19 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
2020-05-14 14:41:43 +00:00
if ( ! _are_onion_layers_valid ( ) ) {
2017-10-30 18:43:19 +00:00
_allocate_onion_layers ( ) ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
2019-06-19 03:51:06 +00:00
// Hide superfluous elements that would make the overlay unnecessary cluttered.
2017-10-30 18:43:19 +00:00
Dictionary canvas_edit_state ;
Dictionary spatial_edit_state ;
2020-03-26 21:49:16 +00:00
if ( Node3DEditor : : get_singleton ( ) - > is_visible ( ) ) {
2017-10-30 18:43:19 +00:00
// 3D
2020-03-26 21:49:16 +00:00
spatial_edit_state = Node3DEditor : : get_singleton ( ) - > get_state ( ) ;
2017-12-17 22:07:15 +00:00
Dictionary new_state = spatial_edit_state . duplicate ( ) ;
2017-10-30 18:43:19 +00:00
new_state [ " show_grid " ] = false ;
new_state [ " show_origin " ] = false ;
Array orig_vp = spatial_edit_state [ " viewports " ] ;
Array vp ;
vp . resize ( 4 ) ;
for ( int i = 0 ; i < vp . size ( ) ; i + + ) {
2017-12-17 22:07:15 +00:00
Dictionary d = ( ( Dictionary ) orig_vp [ i ] ) . duplicate ( ) ;
2017-10-30 18:43:19 +00:00
d [ " use_environment " ] = false ;
d [ " doppler " ] = false ;
d [ " gizmos " ] = onion . include_gizmos ? d [ " gizmos " ] : Variant ( false ) ;
d [ " information " ] = false ;
vp [ i ] = d ;
}
new_state [ " viewports " ] = vp ;
2019-06-19 03:51:06 +00:00
// TODO: Save/restore only affected entries.
2020-03-26 21:49:16 +00:00
Node3DEditor : : get_singleton ( ) - > set_state ( new_state ) ;
2017-10-30 18:43:19 +00:00
} else { // CanvasItemEditor
// 2D
canvas_edit_state = CanvasItemEditor : : get_singleton ( ) - > get_state ( ) ;
2017-12-17 22:07:15 +00:00
Dictionary new_state = canvas_edit_state . duplicate ( ) ;
2017-10-30 18:43:19 +00:00
new_state [ " show_grid " ] = false ;
new_state [ " show_rulers " ] = false ;
new_state [ " show_guides " ] = false ;
new_state [ " show_helpers " ] = false ;
2019-05-20 20:36:34 +00:00
new_state [ " show_zoom_control " ] = false ;
2019-06-19 03:51:06 +00:00
// TODO: Save/restore only affected entries.
2017-10-30 18:43:19 +00:00
CanvasItemEditor : : get_singleton ( ) - > set_state ( new_state ) ;
}
2019-06-19 03:51:06 +00:00
// Tweak the root viewport to ensure it's rendered before our target.
2017-10-30 18:43:19 +00:00
RID root_vp = get_tree ( ) - > get_root ( ) - > get_viewport_rid ( ) ;
2020-03-04 01:51:12 +00:00
Rect2 root_vp_screen_rect = Rect2 ( Vector2 ( ) , get_tree ( ) - > get_root ( ) - > get_size ( ) ) ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_attach_to_screen ( root_vp , Rect2 ( ) ) ;
RS : : get_singleton ( ) - > viewport_set_update_mode ( root_vp , RS : : VIEWPORT_UPDATE_ALWAYS ) ;
2017-10-30 18:43:19 +00:00
RID present_rid ;
if ( onion . differences_only ) {
2019-06-19 03:51:06 +00:00
// Capture present scene as it is.
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_set_material ( onion . capture . canvas_item , RID ( ) ) ;
2017-10-30 18:43:19 +00:00
present_rid = onion . captures [ onion . captures . size ( ) - 1 ] ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_active ( present_rid , true ) ;
RS : : get_singleton ( ) - > viewport_set_parent_viewport ( root_vp , present_rid ) ;
RS : : get_singleton ( ) - > draw ( false ) ;
RS : : get_singleton ( ) - > viewport_set_active ( present_rid , false ) ;
2017-10-30 18:43:19 +00:00
}
2019-06-19 03:51:06 +00:00
// Backup current animation state.
2020-12-20 10:46:44 +00:00
Ref < AnimatedValuesBackup > values_backup = player - > backup_animated_values ( ) ;
2017-10-30 18:43:19 +00:00
float cpos = player - > get_current_animation_position ( ) ;
2019-06-19 03:51:06 +00:00
// Render every past/future step with the capture shader.
2017-10-30 18:43:19 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > canvas_item_set_material ( onion . capture . canvas_item , onion . capture . material - > get_rid ( ) ) ;
2021-02-17 16:44:49 +00:00
onion . capture . material - > set_shader_param ( " bkg_color " , GLOBAL_GET ( " rendering/environment/defaults/default_clear_color " ) ) ;
2017-10-30 18:43:19 +00:00
onion . capture . material - > set_shader_param ( " differences_only " , onion . differences_only ) ;
2020-03-27 18:21:27 +00:00
onion . capture . material - > set_shader_param ( " present " , onion . differences_only ? RS : : get_singleton ( ) - > viewport_get_texture ( present_rid ) : RID ( ) ) ;
2017-10-30 18:43:19 +00:00
int step_off_a = onion . past ? - onion . steps : 0 ;
int step_off_b = onion . future ? onion . steps : 0 ;
int cidx = 0 ;
onion . capture . material - > set_shader_param ( " dir_color " , onion . force_white_modulate ? Color ( 1 , 1 , 1 ) : Color ( EDITOR_GET ( " editors/animation/onion_layers_past_color " ) ) ) ;
for ( int step_off = step_off_a ; step_off < = step_off_b ; step_off + + ) {
if ( step_off = = 0 ) {
2019-06-19 03:51:06 +00:00
// Skip present step and switch to the color of future.
2020-05-14 14:41:43 +00:00
if ( ! onion . force_white_modulate ) {
2017-10-30 18:43:19 +00:00
onion . capture . material - > set_shader_param ( " dir_color " , EDITOR_GET ( " editors/animation/onion_layers_future_color " ) ) ;
2020-05-14 14:41:43 +00:00
}
2017-10-30 18:43:19 +00:00
continue ;
}
float pos = cpos + step_off * anim - > get_step ( ) ;
2021-10-15 13:25:00 +00:00
bool valid = anim - > get_loop_mode ( ) ! = Animation : : LoopMode : : LOOP_NONE | | ( pos > = 0 & & pos < = anim - > get_length ( ) ) ;
2018-07-25 01:11:03 +00:00
onion . captures_valid . write [ cidx ] = valid ;
2017-10-30 18:43:19 +00:00
if ( valid ) {
player - > seek ( pos , true ) ;
2020-03-26 21:49:16 +00:00
get_tree ( ) - > flush_transform_notifications ( ) ; // Needed for transforms of Node3Ds.
2020-12-20 10:46:44 +00:00
values_backup - > update_skeletons ( ) ; // Needed for Skeletons (2D & 3D).
2017-10-30 18:43:19 +00:00
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_active ( onion . captures [ cidx ] , true ) ;
RS : : get_singleton ( ) - > viewport_set_parent_viewport ( root_vp , onion . captures [ cidx ] ) ;
RS : : get_singleton ( ) - > draw ( false ) ;
RS : : get_singleton ( ) - > viewport_set_active ( onion . captures [ cidx ] , false ) ;
2017-10-30 18:43:19 +00:00
}
cidx + + ;
}
2019-06-19 03:51:06 +00:00
// Restore root viewport.
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_set_parent_viewport ( root_vp , RID ( ) ) ;
RS : : get_singleton ( ) - > viewport_attach_to_screen ( root_vp , root_vp_screen_rect ) ;
RS : : get_singleton ( ) - > viewport_set_update_mode ( root_vp , RS : : VIEWPORT_UPDATE_WHEN_VISIBLE ) ;
2017-10-30 18:43:19 +00:00
// Restore animation state
// (Seeking with update=true wouldn't do the trick because the current value of the properties
2019-06-19 03:51:06 +00:00
// may not match their value for the current point in the animation).
2017-10-30 18:43:19 +00:00
player - > seek ( cpos , false ) ;
2020-12-20 10:46:44 +00:00
values_backup - > restore ( ) ;
2017-10-30 18:43:19 +00:00
2019-09-04 05:20:57 +00:00
// Restore state of main editors.
2020-03-26 21:49:16 +00:00
if ( Node3DEditor : : get_singleton ( ) - > is_visible ( ) ) {
2017-10-30 18:43:19 +00:00
// 3D
2020-03-26 21:49:16 +00:00
Node3DEditor : : get_singleton ( ) - > set_state ( spatial_edit_state ) ;
2017-10-30 18:43:19 +00:00
} else { // CanvasItemEditor
// 2D
CanvasItemEditor : : get_singleton ( ) - > set_state ( canvas_edit_state ) ;
}
2019-06-19 03:51:06 +00:00
// Update viewports with skin layers overlaid for the actual engine loop render.
2017-10-30 18:43:19 +00:00
onion . can_overlay = true ;
plugin - > update_overlays ( ) ;
}
void AnimationPlayerEditor : : _start_onion_skinning ( ) {
2021-10-04 18:57:31 +00:00
// FIXME: Using "process_frame" makes onion layers update one frame behind the current.
if ( ! get_tree ( ) - > is_connected ( " process_frame " , callable_mp ( this , & AnimationPlayerEditor : : _prepare_onion_layers_1_deferred ) ) ) {
get_tree ( ) - > connect ( " process_frame " , callable_mp ( this , & AnimationPlayerEditor : : _prepare_onion_layers_1_deferred ) ) ;
2017-10-30 18:43:19 +00:00
}
}
void AnimationPlayerEditor : : _stop_onion_skinning ( ) {
2021-10-04 18:57:31 +00:00
if ( get_tree ( ) - > is_connected ( " process_frame " , callable_mp ( this , & AnimationPlayerEditor : : _prepare_onion_layers_1_deferred ) ) ) {
get_tree ( ) - > disconnect ( " process_frame " , callable_mp ( this , & AnimationPlayerEditor : : _prepare_onion_layers_1_deferred ) ) ;
2017-10-30 18:43:19 +00:00
_free_onion_layers ( ) ;
2019-09-04 05:20:57 +00:00
// Clean up the overlay.
2017-10-30 18:43:19 +00:00
onion . can_overlay = false ;
plugin - > update_overlays ( ) ;
}
}
2018-06-07 15:46:14 +00:00
void AnimationPlayerEditor : : _pin_pressed ( ) {
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > get_tree_editor ( ) - > update_tree ( ) ;
2018-06-07 15:46:14 +00:00
}
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditor : : _bind_methods ( ) {
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _animation_new " ) , & AnimationPlayerEditor : : _animation_new ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_rename " ) , & AnimationPlayerEditor : : _animation_rename ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_load " ) , & AnimationPlayerEditor : : _animation_load ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_remove " ) , & AnimationPlayerEditor : : _animation_remove ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_blend " ) , & AnimationPlayerEditor : : _animation_blend ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_edit " ) , & AnimationPlayerEditor : : _animation_edit ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_resource_edit " ) , & AnimationPlayerEditor : : _animation_resource_edit ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_player_changed " ) , & AnimationPlayerEditor : : _animation_player_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " _list_changed " ) , & AnimationPlayerEditor : : _list_changed ) ;
ClassDB : : bind_method ( D_METHOD ( " _animation_duplicate " ) , & AnimationPlayerEditor : : _animation_duplicate ) ;
2018-06-07 15:46:14 +00:00
2017-10-30 18:43:19 +00:00
ClassDB : : bind_method ( D_METHOD ( " _prepare_onion_layers_1 " ) , & AnimationPlayerEditor : : _prepare_onion_layers_1 ) ;
ClassDB : : bind_method ( D_METHOD ( " _prepare_onion_layers_2 " ) , & AnimationPlayerEditor : : _prepare_onion_layers_2 ) ;
2019-06-19 03:51:06 +00:00
ClassDB : : bind_method ( D_METHOD ( " _start_onion_skinning " ) , & AnimationPlayerEditor : : _start_onion_skinning ) ;
ClassDB : : bind_method ( D_METHOD ( " _stop_onion_skinning " ) , & AnimationPlayerEditor : : _stop_onion_skinning ) ;
2014-02-10 01:10:30 +00:00
}
2020-04-01 23:20:12 +00:00
AnimationPlayerEditor * AnimationPlayerEditor : : singleton = nullptr ;
2015-12-05 17:18:22 +00:00
AnimationPlayer * AnimationPlayerEditor : : get_player ( ) const {
return player ;
}
2017-10-30 18:43:19 +00:00
2022-01-27 09:36:51 +00:00
AnimationPlayerEditor : : AnimationPlayerEditor ( AnimationPlayerEditorPlugin * p_plugin ) {
2017-10-30 18:43:19 +00:00
plugin = p_plugin ;
2017-03-05 15:44:50 +00:00
singleton = this ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
updating = false ;
2014-02-10 01:10:30 +00:00
set_focus_mode ( FOCUS_ALL ) ;
2020-04-01 23:20:12 +00:00
player = nullptr ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
HBoxContainer * hb = memnew ( HBoxContainer ) ;
2014-02-10 01:10:30 +00:00
add_child ( hb ) ;
2020-06-19 18:49:04 +00:00
play_bw_from = memnew ( Button ) ;
play_bw_from - > set_flat ( true ) ;
2016-05-18 22:08:12 +00:00
play_bw_from - > set_tooltip ( TTR ( " Play selected animation backwards from current pos. (A) " ) ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( play_bw_from ) ;
2020-06-19 18:49:04 +00:00
play_bw = memnew ( Button ) ;
play_bw - > set_flat ( true ) ;
2016-05-18 22:08:12 +00:00
play_bw - > set_tooltip ( TTR ( " Play selected animation backwards from end. (Shift+A) " ) ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( play_bw ) ;
2020-06-19 18:49:04 +00:00
stop = memnew ( Button ) ;
stop - > set_flat ( true ) ;
2016-01-17 23:03:57 +00:00
stop - > set_toggle_mode ( true ) ;
hb - > add_child ( stop ) ;
2016-05-04 01:25:37 +00:00
stop - > set_tooltip ( TTR ( " Stop animation playback. (S) " ) ) ;
2016-01-17 23:03:57 +00:00
2020-06-19 18:49:04 +00:00
play = memnew ( Button ) ;
play - > set_flat ( true ) ;
2016-05-04 01:25:37 +00:00
play - > set_tooltip ( TTR ( " Play selected animation from start. (Shift+D) " ) ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( play ) ;
2020-06-19 18:49:04 +00:00
play_from = memnew ( Button ) ;
play_from - > set_flat ( true ) ;
2016-05-04 01:25:37 +00:00
play_from - > set_tooltip ( TTR ( " Play selected animation from current pos. (D) " ) ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( play_from ) ;
2017-03-05 15:44:50 +00:00
frame = memnew ( SpinBox ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( frame ) ;
2017-03-05 15:44:50 +00:00
frame - > set_custom_minimum_size ( Size2 ( 60 , 0 ) ) ;
2016-01-17 23:03:57 +00:00
frame - > set_stretch_ratio ( 2 ) ;
2019-08-06 10:24:08 +00:00
frame - > set_step ( 0.0001 ) ;
2016-05-04 01:25:37 +00:00
frame - > set_tooltip ( TTR ( " Animation position (in seconds). " ) ) ;
2016-01-17 23:03:57 +00:00
2017-03-05 15:44:50 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2016-01-17 23:03:57 +00:00
2017-03-05 15:44:50 +00:00
scale = memnew ( LineEdit ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( scale ) ;
scale - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
scale - > set_stretch_ratio ( 1 ) ;
2016-05-04 01:25:37 +00:00
scale - > set_tooltip ( TTR ( " Scale animation playback globally for the node. " ) ) ;
2016-01-17 23:03:57 +00:00
scale - > hide ( ) ;
2017-01-25 20:22:16 +00:00
delete_dialog = memnew ( ConfirmationDialog ) ;
add_child ( delete_dialog ) ;
2020-02-21 17:28:45 +00:00
delete_dialog - > connect ( " confirmed " , callable_mp ( this , & AnimationPlayerEditor : : _animation_remove_confirmed ) ) ;
2017-01-25 20:22:16 +00:00
2018-06-07 15:46:14 +00:00
tool_anim = memnew ( MenuButton ) ;
2020-09-17 01:40:00 +00:00
tool_anim - > set_shortcut_context ( this ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > set_flat ( false ) ;
tool_anim - > set_tooltip ( TTR ( " Animation Tools " ) ) ;
2018-06-08 17:44:18 +00:00
tool_anim - > set_text ( TTR ( " Animation " ) ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/new_animation " , TTR ( " New " ) ) , TOOL_NEW_ANIM ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_separator ( ) ;
2018-06-08 17:44:18 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/open_animation " , TTR ( " Load " ) ) , TOOL_LOAD_ANIM ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/save_animation " , TTR ( " Save " ) ) , TOOL_SAVE_ANIM ) ;
2018-06-08 17:44:18 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/save_as_animation " , TTR ( " Save As... " ) ) , TOOL_SAVE_AS_ANIM ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_separator ( ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/copy_animation " , TTR ( " Copy " ) ) , TOOL_COPY_ANIM ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/paste_animation " , TTR ( " Paste " ) ) , TOOL_PASTE_ANIM ) ;
2019-11-02 00:52:54 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/paste_animation_as_reference " , TTR ( " Paste As Reference " ) ) , TOOL_PASTE_ANIM_REF ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_separator ( ) ;
2022-02-14 06:28:42 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/duplicate_animation " , TTR ( " Duplicate... " ) ) , TOOL_DUPLICATE_ANIM ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_separator ( ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/rename_animation " , TTR ( " Rename... " ) ) , TOOL_RENAME_ANIM ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/edit_transitions " , TTR ( " Edit Transitions... " ) ) , TOOL_EDIT_TRANSITIONS ) ;
2018-07-01 20:44:15 +00:00
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/open_animation_in_inspector " , TTR ( " Open in Inspector " ) ) , TOOL_EDIT_RESOURCE ) ;
2018-06-07 15:46:14 +00:00
tool_anim - > get_popup ( ) - > add_separator ( ) ;
tool_anim - > get_popup ( ) - > add_shortcut ( ED_SHORTCUT ( " animation_player_editor/remove_animation " , TTR ( " Remove " ) ) , TOOL_REMOVE_ANIM ) ;
hb - > add_child ( tool_anim ) ;
2015-05-25 04:46:45 +00:00
2017-03-05 15:44:50 +00:00
animation = memnew ( OptionButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( animation ) ;
animation - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2016-05-04 01:25:37 +00:00
animation - > set_tooltip ( TTR ( " Display list of animations in player. " ) ) ;
2016-06-29 23:11:14 +00:00
animation - > set_clip_text ( true ) ;
2014-02-10 01:10:30 +00:00
2020-06-19 18:49:04 +00:00
autoplay = memnew ( Button ) ;
autoplay - > set_flat ( true ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( autoplay ) ;
2016-05-18 22:08:12 +00:00
autoplay - > set_tooltip ( TTR ( " Autoplay on Load " ) ) ;
2014-02-10 01:10:30 +00:00
2018-06-09 18:49:16 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2018-06-07 15:46:14 +00:00
track_editor = memnew ( AnimationTrackEditor ) ;
hb - > add_child ( track_editor - > get_edit_menu ( ) ) ;
2014-02-10 01:10:30 +00:00
2019-05-14 03:42:05 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2020-06-19 18:49:04 +00:00
onion_toggle = memnew ( Button ) ;
onion_toggle - > set_flat ( true ) ;
2019-05-14 03:42:05 +00:00
onion_toggle - > set_toggle_mode ( true ) ;
onion_toggle - > set_tooltip ( TTR ( " Enable Onion Skinning " ) ) ;
2020-02-21 17:28:45 +00:00
onion_toggle - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _onion_skinning_menu ) , varray ( ONION_SKINNING_ENABLE ) ) ;
2019-05-14 03:42:05 +00:00
hb - > add_child ( onion_toggle ) ;
2017-10-30 18:43:19 +00:00
onion_skinning = memnew ( MenuButton ) ;
2019-05-14 03:42:05 +00:00
onion_skinning - > set_tooltip ( TTR ( " Onion Skinning Options " ) ) ;
onion_skinning - > get_popup ( ) - > add_separator ( TTR ( " Directions " ) ) ;
2017-10-30 18:43:19 +00:00
onion_skinning - > get_popup ( ) - > add_check_item ( TTR ( " Past " ) , ONION_SKINNING_PAST ) ;
onion_skinning - > get_popup ( ) - > set_item_checked ( onion_skinning - > get_popup ( ) - > get_item_count ( ) - 1 , true ) ;
onion_skinning - > get_popup ( ) - > add_check_item ( TTR ( " Future " ) , ONION_SKINNING_FUTURE ) ;
2019-05-14 03:42:05 +00:00
onion_skinning - > get_popup ( ) - > add_separator ( TTR ( " Depth " ) ) ;
2018-03-24 02:05:20 +00:00
onion_skinning - > get_popup ( ) - > add_radio_check_item ( TTR ( " 1 step " ) , ONION_SKINNING_1_STEP ) ;
2017-10-30 18:43:19 +00:00
onion_skinning - > get_popup ( ) - > set_item_checked ( onion_skinning - > get_popup ( ) - > get_item_count ( ) - 1 , true ) ;
2018-03-24 02:05:20 +00:00
onion_skinning - > get_popup ( ) - > add_radio_check_item ( TTR ( " 2 steps " ) , ONION_SKINNING_2_STEPS ) ;
onion_skinning - > get_popup ( ) - > add_radio_check_item ( TTR ( " 3 steps " ) , ONION_SKINNING_3_STEPS ) ;
2017-10-30 18:43:19 +00:00
onion_skinning - > get_popup ( ) - > add_separator ( ) ;
onion_skinning - > get_popup ( ) - > add_check_item ( TTR ( " Differences Only " ) , ONION_SKINNING_DIFFERENCES_ONLY ) ;
onion_skinning - > get_popup ( ) - > add_check_item ( TTR ( " Force White Modulate " ) , ONION_SKINNING_FORCE_WHITE_MODULATE ) ;
onion_skinning - > get_popup ( ) - > add_check_item ( TTR ( " Include Gizmos (3D) " ) , ONION_SKINNING_INCLUDE_GIZMOS ) ;
hb - > add_child ( onion_skinning ) ;
2019-05-14 03:42:05 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2020-06-19 18:49:04 +00:00
pin = memnew ( Button ) ;
pin - > set_flat ( true ) ;
2016-01-17 23:03:57 +00:00
pin - > set_toggle_mode ( true ) ;
2018-04-27 01:58:30 +00:00
pin - > set_tooltip ( TTR ( " Pin AnimationPlayer " ) ) ;
2016-01-17 23:03:57 +00:00
hb - > add_child ( pin ) ;
2020-02-21 17:28:45 +00:00
pin - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _pin_pressed ) ) ;
2014-02-10 01:10:30 +00:00
2015-06-06 12:44:38 +00:00
file = memnew ( EditorFileDialog ) ;
2014-02-10 01:10:30 +00:00
add_child ( file ) ;
2017-03-05 15:44:50 +00:00
name_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 01:25:37 +00:00
name_dialog - > set_title ( TTR ( " Create New Animation " ) ) ;
2014-02-10 01:10:30 +00:00
name_dialog - > set_hide_on_ok ( false ) ;
add_child ( name_dialog ) ;
2017-06-13 06:04:15 +00:00
VBoxContainer * vb = memnew ( VBoxContainer ) ;
name_dialog - > add_child ( vb ) ;
2014-02-10 01:10:30 +00:00
2019-05-25 01:47:16 +00:00
name_title = memnew ( Label ( TTR ( " Animation Name: " ) ) ) ;
vb - > add_child ( name_title ) ;
2014-02-10 01:10:30 +00:00
2017-06-13 06:04:15 +00:00
name = memnew ( LineEdit ) ;
vb - > add_child ( name ) ;
name_dialog - > register_text_enter ( name ) ;
2017-03-05 15:44:50 +00:00
error_dialog = memnew ( ConfirmationDialog ) ;
2020-12-14 18:37:30 +00:00
error_dialog - > get_ok_button ( ) - > set_text ( TTR ( " Close " ) ) ;
2018-04-27 01:58:30 +00:00
error_dialog - > set_title ( TTR ( " Error! " ) ) ;
2014-02-10 01:10:30 +00:00
add_child ( error_dialog ) ;
2020-02-21 17:28:45 +00:00
name_dialog - > connect ( " confirmed " , callable_mp ( this , & AnimationPlayerEditor : : _animation_name_edited ) ) ;
2016-03-08 23:00:52 +00:00
2017-03-05 15:44:50 +00:00
blend_editor . dialog = memnew ( AcceptDialog ) ;
2014-02-10 01:10:30 +00:00
add_child ( blend_editor . dialog ) ;
2020-12-14 18:37:30 +00:00
blend_editor . dialog - > get_ok_button ( ) - > set_text ( TTR ( " Close " ) ) ;
2014-02-10 01:10:30 +00:00
blend_editor . dialog - > set_hide_on_ok ( true ) ;
2017-03-05 15:44:50 +00:00
VBoxContainer * blend_vb = memnew ( VBoxContainer ) ;
2014-02-10 01:10:30 +00:00
blend_editor . dialog - > add_child ( blend_vb ) ;
2017-03-05 15:44:50 +00:00
blend_editor . tree = memnew ( Tree ) ;
2014-02-10 01:10:30 +00:00
blend_editor . tree - > set_columns ( 2 ) ;
2017-03-05 15:44:50 +00:00
blend_vb - > add_margin_child ( TTR ( " Blend Times: " ) , blend_editor . tree , true ) ;
blend_editor . next = memnew ( OptionButton ) ;
blend_vb - > add_margin_child ( TTR ( " Next (Auto Queue): " ) , blend_editor . next ) ;
2016-05-04 01:25:37 +00:00
blend_editor . dialog - > set_title ( TTR ( " Cross-Animation Blend Times " ) ) ;
2017-03-05 15:44:50 +00:00
updating_blends = false ;
2014-02-10 01:10:30 +00:00
2020-02-21 17:28:45 +00:00
blend_editor . tree - > connect ( " item_edited " , callable_mp ( this , & AnimationPlayerEditor : : _blend_edited ) ) ;
2016-03-08 23:00:52 +00:00
2020-02-21 17:28:45 +00:00
autoplay - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _autoplay_pressed ) ) ;
2014-02-10 01:10:30 +00:00
autoplay - > set_toggle_mode ( true ) ;
2020-02-21 17:28:45 +00:00
play - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _play_pressed ) ) ;
play_from - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _play_from_pressed ) ) ;
play_bw - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _play_bw_pressed ) ) ;
play_bw_from - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _play_bw_from_pressed ) ) ;
stop - > connect ( " pressed " , callable_mp ( this , & AnimationPlayerEditor : : _stop_pressed ) ) ;
2016-01-17 23:03:57 +00:00
2020-02-25 20:41:54 +00:00
animation - > connect ( " item_selected " , callable_mp ( this , & AnimationPlayerEditor : : _animation_selected ) ) ;
2018-06-07 15:46:14 +00:00
2020-03-23 15:35:26 +00:00
file - > connect ( " file_selected " , callable_mp ( this , & AnimationPlayerEditor : : _save_animation ) ) ;
file - > connect ( " files_selected " , callable_mp ( this , & AnimationPlayerEditor : : _load_animations ) ) ;
2020-07-14 23:05:04 +00:00
frame - > connect ( " value_changed " , callable_mp ( this , & AnimationPlayerEditor : : _seek_value_changed ) , make_binds ( true , false ) ) ;
2021-06-16 16:43:34 +00:00
scale - > connect ( " text_submitted " , callable_mp ( this , & AnimationPlayerEditor : : _scale_changed ) ) ;
2016-01-17 23:03:57 +00:00
2017-03-05 15:44:50 +00:00
last_active = false ;
2019-10-01 16:38:03 +00:00
timeline_position = 0 ;
2015-05-25 04:46:45 +00:00
set_process_unhandled_key_input ( true ) ;
2016-01-17 23:03:57 +00:00
2018-06-07 15:46:14 +00:00
add_child ( track_editor ) ;
track_editor - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2020-02-21 17:28:45 +00:00
track_editor - > connect ( " timeline_changed " , callable_mp ( this , & AnimationPlayerEditor : : _animation_key_editor_seek ) ) ;
track_editor - > connect ( " animation_len_changed " , callable_mp ( this , & AnimationPlayerEditor : : _animation_key_editor_anim_len_changed ) ) ;
2016-01-17 23:03:57 +00:00
_update_player ( ) ;
2017-10-30 18:43:19 +00:00
2019-09-04 05:20:57 +00:00
// Onion skinning.
2017-10-30 18:43:19 +00:00
2020-02-21 17:28:45 +00:00
track_editor - > connect ( " visibility_changed " , callable_mp ( this , & AnimationPlayerEditor : : _editor_visibility_changed ) ) ;
2017-10-30 18:43:19 +00:00
onion . enabled = false ;
onion . past = true ;
onion . future = false ;
onion . steps = 1 ;
onion . differences_only = false ;
onion . force_white_modulate = false ;
onion . include_gizmos = false ;
onion . last_frame = 0 ;
onion . can_overlay = false ;
onion . capture_size = Size2 ( ) ;
2020-03-27 18:21:27 +00:00
onion . capture . canvas = RS : : get_singleton ( ) - > canvas_create ( ) ;
onion . capture . canvas_item = RS : : get_singleton ( ) - > canvas_item_create ( ) ;
RS : : get_singleton ( ) - > canvas_item_set_parent ( onion . capture . canvas_item , onion . capture . canvas ) ;
2017-10-30 18:43:19 +00:00
onion . capture . material = Ref < ShaderMaterial > ( memnew ( ShaderMaterial ) ) ;
onion . capture . shader = Ref < Shader > ( memnew ( Shader ) ) ;
2021-07-19 06:06:51 +00:00
onion . capture . shader - > set_code ( R " (
2021-08-18 01:09:22 +00:00
// Animation editor onion skinning shader.
2021-07-19 06:06:51 +00:00
shader_type canvas_item ;
uniform vec4 bkg_color ;
uniform vec4 dir_color ;
uniform bool differences_only ;
uniform sampler2D present ;
float zero_if_equal ( vec4 a , vec4 b ) {
return smoothstep ( 0.0 , 0.005 , length ( a . rgb - b . rgb ) / sqrt ( 3.0 ) ) ;
}
void fragment ( ) {
vec4 capture_samp = texture ( TEXTURE , UV ) ;
vec4 present_samp = texture ( present , UV ) ;
float bkg_mask = zero_if_equal ( capture_samp , bkg_color ) ;
float diff_mask = 1.0 - zero_if_equal ( present_samp , bkg_color ) ;
diff_mask = min ( 1.0 , diff_mask + float ( ! differences_only ) ) ;
COLOR = vec4 ( capture_samp . rgb * dir_color . rgb , bkg_mask * diff_mask ) ;
}
) " );
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > material_set_shader ( onion . capture . material - > get_rid ( ) , onion . capture . shader - > get_rid ( ) ) ;
2017-10-30 18:43:19 +00:00
}
AnimationPlayerEditor : : ~ AnimationPlayerEditor ( ) {
_free_onion_layers ( ) ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > free ( onion . capture . canvas ) ;
RS : : get_singleton ( ) - > free ( onion . capture . canvas_item ) ;
2017-10-30 18:43:19 +00:00
}
void AnimationPlayerEditorPlugin : : _notification ( int p_what ) {
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
2021-12-02 11:01:38 +00:00
Node3DEditor : : get_singleton ( ) - > connect ( " transform_key_request " , callable_mp ( this , & AnimationPlayerEditorPlugin : : _transform_key_request ) ) ;
2022-01-21 06:31:16 +00:00
InspectorDock : : get_inspector_singleton ( ) - > connect ( " property_keyed " , callable_mp ( this , & AnimationPlayerEditorPlugin : : _property_keyed ) ) ;
2021-12-02 11:01:38 +00:00
anim_editor - > get_track_editor ( ) - > connect ( " keying_changed " , callable_mp ( this , & AnimationPlayerEditorPlugin : : _update_keying ) ) ;
2022-01-21 06:31:16 +00:00
InspectorDock : : get_inspector_singleton ( ) - > connect ( " edited_object_changed " , callable_mp ( anim_editor - > get_track_editor ( ) , & AnimationTrackEditor : : update_keying ) ) ;
2017-10-30 18:43:19 +00:00
set_force_draw_over_forwarding_enabled ( ) ;
} break ;
}
2014-02-10 01:10:30 +00:00
}
2021-12-02 11:01:38 +00:00
void AnimationPlayerEditorPlugin : : _property_keyed ( const String & p_keyed , const Variant & p_value , bool p_advance ) {
if ( ! anim_editor - > get_track_editor ( ) - > has_keying ( ) ) {
return ;
}
anim_editor - > get_track_editor ( ) - > insert_value_key ( p_keyed , p_value , p_advance ) ;
}
void AnimationPlayerEditorPlugin : : _transform_key_request ( Object * sp , const String & p_sub , const Transform3D & p_key ) {
if ( ! anim_editor - > get_track_editor ( ) - > has_keying ( ) ) {
return ;
}
Node3D * s = Object : : cast_to < Node3D > ( sp ) ;
if ( ! s ) {
return ;
}
anim_editor - > get_track_editor ( ) - > insert_transform_key ( s , p_sub , Animation : : TYPE_POSITION_3D , p_key . origin ) ;
anim_editor - > get_track_editor ( ) - > insert_transform_key ( s , p_sub , Animation : : TYPE_ROTATION_3D , p_key . basis . get_rotation_quaternion ( ) ) ;
anim_editor - > get_track_editor ( ) - > insert_transform_key ( s , p_sub , Animation : : TYPE_SCALE_3D , p_key . basis . get_scale ( ) ) ;
}
void AnimationPlayerEditorPlugin : : _update_keying ( ) {
2021-11-17 20:08:55 +00:00
InspectorDock : : get_inspector_singleton ( ) - > set_keying ( anim_editor - > get_track_editor ( ) - > has_keying ( ) ) ;
2021-12-02 11:01:38 +00:00
}
2014-02-10 01:10:30 +00:00
void AnimationPlayerEditorPlugin : : edit ( Object * p_object ) {
anim_editor - > set_undo_redo ( & get_undo_redo ( ) ) ;
2020-05-14 14:41:43 +00:00
if ( ! p_object ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-08-24 20:58:51 +00:00
anim_editor - > edit ( Object : : cast_to < AnimationPlayer > ( p_object ) ) ;
2014-02-10 01:10:30 +00:00
}
bool AnimationPlayerEditorPlugin : : handles ( Object * p_object ) const {
2017-01-03 02:03:46 +00:00
return p_object - > is_class ( " AnimationPlayer " ) ;
2014-02-10 01:10:30 +00:00
}
void AnimationPlayerEditorPlugin : : make_visible ( bool p_visible ) {
if ( p_visible ) {
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > make_bottom_panel_item_visible ( anim_editor ) ;
2014-02-10 01:10:30 +00:00
anim_editor - > set_process ( true ) ;
anim_editor - > ensure_visibility ( ) ;
}
}
2022-01-27 09:36:51 +00:00
AnimationPlayerEditorPlugin : : AnimationPlayerEditorPlugin ( ) {
anim_editor = memnew ( AnimationPlayerEditor ( this ) ) ;
2019-06-26 13:08:25 +00:00
anim_editor - > set_undo_redo ( EditorNode : : get_undo_redo ( ) ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > add_bottom_panel_item ( TTR ( " Animation " ) , anim_editor ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
AnimationPlayerEditorPlugin : : ~ AnimationPlayerEditorPlugin ( ) {
2014-02-10 01:10:30 +00:00
}