1/**************************************************************************/
2/* animation_player_editor_plugin.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef ANIMATION_PLAYER_EDITOR_PLUGIN_H
32#define ANIMATION_PLAYER_EDITOR_PLUGIN_H
33
34#include "editor/animation_track_editor.h"
35#include "editor/editor_plugin.h"
36#include "editor/plugins/animation_library_editor.h"
37#include "scene/animation/animation_player.h"
38#include "scene/gui/dialogs.h"
39#include "scene/gui/slider.h"
40#include "scene/gui/spin_box.h"
41#include "scene/gui/texture_button.h"
42#include "scene/gui/tree.h"
43
44class AnimationPlayerEditorPlugin;
45class ImageTexture;
46
47class AnimationPlayerEditor : public VBoxContainer {
48 GDCLASS(AnimationPlayerEditor, VBoxContainer);
49
50 AnimationPlayerEditorPlugin *plugin = nullptr;
51 AnimationPlayer *player = nullptr;
52
53 enum {
54 TOOL_NEW_ANIM,
55 TOOL_ANIM_LIBRARY,
56 TOOL_DUPLICATE_ANIM,
57 TOOL_RENAME_ANIM,
58 TOOL_EDIT_TRANSITIONS,
59 TOOL_REMOVE_ANIM,
60 TOOL_EDIT_RESOURCE
61 };
62
63 enum {
64 ONION_SKINNING_ENABLE,
65 ONION_SKINNING_PAST,
66 ONION_SKINNING_FUTURE,
67 ONION_SKINNING_1_STEP,
68 ONION_SKINNING_2_STEPS,
69 ONION_SKINNING_3_STEPS,
70 ONION_SKINNING_LAST_STEPS_OPTION = ONION_SKINNING_3_STEPS,
71 ONION_SKINNING_DIFFERENCES_ONLY,
72 ONION_SKINNING_FORCE_WHITE_MODULATE,
73 ONION_SKINNING_INCLUDE_GIZMOS,
74 };
75
76 enum {
77 ANIM_OPEN,
78 ANIM_SAVE,
79 ANIM_SAVE_AS
80 };
81
82 enum {
83 RESOURCE_LOAD,
84 RESOURCE_SAVE
85 };
86
87 OptionButton *animation = nullptr;
88 Button *stop = nullptr;
89 Button *play = nullptr;
90 Button *play_from = nullptr;
91 Button *play_bw = nullptr;
92 Button *play_bw_from = nullptr;
93 Button *autoplay = nullptr;
94
95 MenuButton *tool_anim = nullptr;
96 Button *onion_toggle = nullptr;
97 MenuButton *onion_skinning = nullptr;
98 Button *pin = nullptr;
99 SpinBox *frame = nullptr;
100 LineEdit *scale = nullptr;
101 LineEdit *name = nullptr;
102 OptionButton *library = nullptr;
103 Label *name_title = nullptr;
104
105 Ref<Texture2D> stop_icon;
106 Ref<Texture2D> pause_icon;
107 Ref<Texture2D> autoplay_icon;
108 Ref<Texture2D> reset_icon;
109 Ref<ImageTexture> autoplay_reset_icon;
110 bool last_active;
111 float timeline_position;
112
113 EditorFileDialog *file = nullptr;
114 ConfirmationDialog *delete_dialog = nullptr;
115
116 AnimationLibraryEditor *library_editor = nullptr;
117
118 struct BlendEditor {
119 AcceptDialog *dialog = nullptr;
120 Tree *tree = nullptr;
121 OptionButton *next = nullptr;
122
123 } blend_editor;
124
125 ConfirmationDialog *name_dialog = nullptr;
126 ConfirmationDialog *error_dialog = nullptr;
127 int name_dialog_op = TOOL_NEW_ANIM;
128
129 bool updating;
130 bool updating_blends;
131
132 AnimationTrackEditor *track_editor = nullptr;
133 static AnimationPlayerEditor *singleton;
134
135 bool hack_disable_onion_skinning = true; // Temporary hack for GH-53870.
136
137 // Onion skinning.
138 struct {
139 // Settings.
140 bool enabled = false;
141 bool past = false;
142 bool future = false;
143 int steps = 0;
144 bool differences_only = false;
145 bool force_white_modulate = false;
146 bool include_gizmos = false;
147
148 int get_needed_capture_count() const {
149 // 'Differences only' needs a capture of the present.
150 return (past && future ? 2 * steps : steps) + (differences_only ? 1 : 0);
151 }
152
153 // Rendering.
154 int64_t last_frame = 0;
155 int can_overlay = 0;
156 Size2 capture_size;
157 Vector<RID> captures;
158 Vector<bool> captures_valid;
159 struct {
160 RID canvas;
161 RID canvas_item;
162 Ref<ShaderMaterial> material;
163 Ref<Shader> shader;
164 } capture;
165 } onion;
166
167 void _select_anim_by_name(const String &p_anim);
168 float _get_editor_step() const;
169 void _play_pressed();
170 void _play_from_pressed();
171 void _play_bw_pressed();
172 void _play_bw_from_pressed();
173 void _autoplay_pressed();
174 void _stop_pressed();
175 void _animation_selected(int p_which);
176 void _animation_new();
177 void _animation_rename();
178 void _animation_name_edited();
179
180 void _animation_remove();
181 void _animation_remove_confirmed();
182 void _animation_blend();
183 void _animation_edit();
184 void _animation_duplicate();
185 Ref<Animation> _animation_clone(const Ref<Animation> p_anim);
186 void _animation_resource_edit();
187 void _scale_changed(const String &p_scale);
188 void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false);
189 void _blend_editor_next_changed(const int p_idx);
190
191 void _list_changed();
192 void _update_animation();
193 void _update_player();
194 void _update_animation_list_icons();
195 void _update_name_dialog_library_dropdown();
196 void _blend_edited();
197
198 void _animation_player_changed(Object *p_pl);
199 void _animation_libraries_updated();
200
201 void _animation_key_editor_seek(float p_pos, bool p_drag, bool p_timeline_only = false);
202 void _animation_key_editor_anim_len_changed(float p_len);
203
204 virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
205 void _animation_tool_menu(int p_option);
206 void _onion_skinning_menu(int p_option);
207
208 void _editor_visibility_changed();
209 bool _are_onion_layers_valid();
210 void _allocate_onion_layers();
211 void _free_onion_layers();
212 void _prepare_onion_layers_1();
213 void _prepare_onion_layers_1_deferred();
214 void _prepare_onion_layers_2();
215 void _start_onion_skinning();
216 void _stop_onion_skinning();
217
218 bool _validate_tracks(const Ref<Animation> p_anim);
219
220 void _pin_pressed();
221 String _get_current() const;
222
223 ~AnimationPlayerEditor();
224
225protected:
226 void _notification(int p_what);
227 void _node_removed(Node *p_node);
228 static void _bind_methods();
229
230public:
231 AnimationPlayer *get_player() const;
232
233 static AnimationPlayerEditor *get_singleton() { return singleton; }
234
235 bool is_pinned() const { return pin->is_pressed(); }
236 void unpin() { pin->set_pressed(false); }
237 AnimationTrackEditor *get_track_editor() { return track_editor; }
238 Dictionary get_state() const;
239 void set_state(const Dictionary &p_state);
240
241 void ensure_visibility();
242
243 void edit(AnimationPlayer *p_player);
244 void forward_force_draw_over_viewport(Control *p_overlay);
245
246 AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plugin);
247};
248
249class AnimationPlayerEditorPlugin : public EditorPlugin {
250 GDCLASS(AnimationPlayerEditorPlugin, EditorPlugin);
251
252 AnimationPlayerEditor *anim_editor = nullptr;
253
254protected:
255 void _notification(int p_what);
256
257 void _property_keyed(const String &p_keyed, const Variant &p_value, bool p_advance);
258 void _transform_key_request(Object *sp, const String &p_sub, const Transform3D &p_key);
259 void _update_keying();
260
261public:
262 virtual Dictionary get_state() const override { return anim_editor->get_state(); }
263 virtual void set_state(const Dictionary &p_state) override { anim_editor->set_state(p_state); }
264
265 virtual String get_name() const override { return "Anim"; }
266 bool has_main_screen() const override { return false; }
267 virtual void edit(Object *p_object) override;
268 virtual bool handles(Object *p_object) const override;
269 virtual void make_visible(bool p_visible) override;
270
271 virtual void forward_canvas_force_draw_over_viewport(Control *p_overlay) override { anim_editor->forward_force_draw_over_viewport(p_overlay); }
272 virtual void forward_3d_force_draw_over_viewport(Control *p_overlay) override { anim_editor->forward_force_draw_over_viewport(p_overlay); }
273
274 AnimationPlayerEditorPlugin();
275 ~AnimationPlayerEditorPlugin();
276};
277
278// AnimationTrackKeyEditEditorPlugin
279
280class EditorInspectorPluginAnimationTrackKeyEdit : public EditorInspectorPlugin {
281 GDCLASS(EditorInspectorPluginAnimationTrackKeyEdit, EditorInspectorPlugin);
282
283 AnimationTrackKeyEditEditor *atk_editor = nullptr;
284
285public:
286 virtual bool can_handle(Object *p_object) override;
287 virtual void parse_begin(Object *p_object) override;
288};
289
290class AnimationTrackKeyEditEditorPlugin : public EditorPlugin {
291 GDCLASS(AnimationTrackKeyEditEditorPlugin, EditorPlugin);
292
293 EditorInspectorPluginAnimationTrackKeyEdit *atk_plugin = nullptr;
294
295public:
296 bool has_main_screen() const override { return false; }
297 virtual bool handles(Object *p_object) const override;
298
299 virtual String get_name() const override { return "AnimationTrackKeyEdit"; }
300
301 AnimationTrackKeyEditEditorPlugin();
302};
303
304#endif // ANIMATION_PLAYER_EDITOR_PLUGIN_H
305