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 | |
44 | class AnimationPlayerEditorPlugin; |
45 | class ImageTexture; |
46 | |
47 | class 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 (int p_option); |
206 | void (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 | |
225 | protected: |
226 | void _notification(int p_what); |
227 | void _node_removed(Node *p_node); |
228 | static void _bind_methods(); |
229 | |
230 | public: |
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 | |
249 | class AnimationPlayerEditorPlugin : public EditorPlugin { |
250 | GDCLASS(AnimationPlayerEditorPlugin, EditorPlugin); |
251 | |
252 | AnimationPlayerEditor *anim_editor = nullptr; |
253 | |
254 | protected: |
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 | |
261 | public: |
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 | |
280 | class EditorInspectorPluginAnimationTrackKeyEdit : public EditorInspectorPlugin { |
281 | GDCLASS(EditorInspectorPluginAnimationTrackKeyEdit, EditorInspectorPlugin); |
282 | |
283 | AnimationTrackKeyEditEditor *atk_editor = nullptr; |
284 | |
285 | public: |
286 | virtual bool can_handle(Object *p_object) override; |
287 | virtual void parse_begin(Object *p_object) override; |
288 | }; |
289 | |
290 | class AnimationTrackKeyEditEditorPlugin : public EditorPlugin { |
291 | GDCLASS(AnimationTrackKeyEditEditorPlugin, EditorPlugin); |
292 | |
293 | EditorInspectorPluginAnimationTrackKeyEdit *atk_plugin = nullptr; |
294 | |
295 | public: |
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 | |