1 | /**************************************************************************/ |
2 | /* animation_blend_tree.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_BLEND_TREE_H |
32 | #define ANIMATION_BLEND_TREE_H |
33 | |
34 | #include "scene/animation/animation_tree.h" |
35 | |
36 | class AnimationNodeAnimation : public AnimationRootNode { |
37 | GDCLASS(AnimationNodeAnimation, AnimationRootNode); |
38 | |
39 | StringName animation; |
40 | StringName time = "time" ; |
41 | |
42 | uint64_t last_version = 0; |
43 | bool skip = false; |
44 | |
45 | public: |
46 | enum PlayMode { |
47 | PLAY_MODE_FORWARD, |
48 | PLAY_MODE_BACKWARD |
49 | }; |
50 | |
51 | void get_parameter_list(List<PropertyInfo> *r_list) const override; |
52 | |
53 | static Vector<String> (*get_editable_animation_list)(); |
54 | |
55 | virtual String get_caption() const override; |
56 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
57 | |
58 | void set_animation(const StringName &p_name); |
59 | StringName get_animation() const; |
60 | |
61 | void set_play_mode(PlayMode p_play_mode); |
62 | PlayMode get_play_mode() const; |
63 | |
64 | void set_backward(bool p_backward); |
65 | bool is_backward() const; |
66 | |
67 | AnimationNodeAnimation(); |
68 | |
69 | protected: |
70 | void _validate_property(PropertyInfo &p_property) const; |
71 | static void _bind_methods(); |
72 | |
73 | private: |
74 | PlayMode play_mode = PLAY_MODE_FORWARD; |
75 | bool backward = false; // Only used by pingpong animation. |
76 | }; |
77 | |
78 | VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode) |
79 | |
80 | class AnimationNodeSync : public AnimationNode { |
81 | GDCLASS(AnimationNodeSync, AnimationNode); |
82 | |
83 | protected: |
84 | bool sync = false; |
85 | |
86 | static void _bind_methods(); |
87 | |
88 | public: |
89 | void set_use_sync(bool p_sync); |
90 | bool is_using_sync() const; |
91 | |
92 | AnimationNodeSync(); |
93 | }; |
94 | |
95 | class AnimationNodeOneShot : public AnimationNodeSync { |
96 | GDCLASS(AnimationNodeOneShot, AnimationNodeSync); |
97 | |
98 | public: |
99 | enum OneShotRequest { |
100 | ONE_SHOT_REQUEST_NONE, |
101 | ONE_SHOT_REQUEST_FIRE, |
102 | ONE_SHOT_REQUEST_ABORT, |
103 | ONE_SHOT_REQUEST_FADE_OUT, |
104 | }; |
105 | |
106 | enum MixMode { |
107 | MIX_MODE_BLEND, |
108 | MIX_MODE_ADD |
109 | }; |
110 | |
111 | private: |
112 | double fade_in = 0.0; |
113 | Ref<Curve> fade_in_curve; |
114 | double fade_out = 0.0; |
115 | Ref<Curve> fade_out_curve; |
116 | |
117 | bool auto_restart = false; |
118 | double auto_restart_delay = 1.0; |
119 | double auto_restart_random_delay = 0.0; |
120 | MixMode mix = MIX_MODE_BLEND; |
121 | |
122 | StringName request = PNAME("request" ); |
123 | StringName active = PNAME("active" ); |
124 | StringName internal_active = PNAME("internal_active" ); |
125 | StringName time = "time" ; |
126 | StringName remaining = "remaining" ; |
127 | StringName fade_out_remaining = "fade_out_remaining" ; |
128 | StringName time_to_restart = "time_to_restart" ; |
129 | |
130 | protected: |
131 | static void _bind_methods(); |
132 | |
133 | public: |
134 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
135 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
136 | virtual bool is_parameter_read_only(const StringName &p_parameter) const override; |
137 | |
138 | virtual String get_caption() const override; |
139 | |
140 | void set_fade_in_time(double p_time); |
141 | double get_fade_in_time() const; |
142 | |
143 | void set_fade_in_curve(const Ref<Curve> &p_curve); |
144 | Ref<Curve> get_fade_in_curve() const; |
145 | |
146 | void set_fade_out_time(double p_time); |
147 | double get_fade_out_time() const; |
148 | |
149 | void set_fade_out_curve(const Ref<Curve> &p_curve); |
150 | Ref<Curve> get_fade_out_curve() const; |
151 | |
152 | void set_auto_restart_enabled(bool p_enabled); |
153 | void set_auto_restart_delay(double p_time); |
154 | void set_auto_restart_random_delay(double p_time); |
155 | |
156 | bool is_auto_restart_enabled() const; |
157 | double get_auto_restart_delay() const; |
158 | double get_auto_restart_random_delay() const; |
159 | |
160 | void set_mix_mode(MixMode p_mix); |
161 | MixMode get_mix_mode() const; |
162 | |
163 | virtual bool has_filter() const override; |
164 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
165 | |
166 | AnimationNodeOneShot(); |
167 | }; |
168 | |
169 | VARIANT_ENUM_CAST(AnimationNodeOneShot::OneShotRequest) |
170 | VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode) |
171 | |
172 | class AnimationNodeAdd2 : public AnimationNodeSync { |
173 | GDCLASS(AnimationNodeAdd2, AnimationNodeSync); |
174 | |
175 | StringName add_amount = PNAME("add_amount" ); |
176 | |
177 | protected: |
178 | static void _bind_methods(); |
179 | |
180 | public: |
181 | void get_parameter_list(List<PropertyInfo> *r_list) const override; |
182 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
183 | |
184 | virtual String get_caption() const override; |
185 | |
186 | virtual bool has_filter() const override; |
187 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
188 | |
189 | AnimationNodeAdd2(); |
190 | }; |
191 | |
192 | class AnimationNodeAdd3 : public AnimationNodeSync { |
193 | GDCLASS(AnimationNodeAdd3, AnimationNodeSync); |
194 | |
195 | StringName add_amount = PNAME("add_amount" ); |
196 | |
197 | protected: |
198 | static void _bind_methods(); |
199 | |
200 | public: |
201 | void get_parameter_list(List<PropertyInfo> *r_list) const override; |
202 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
203 | |
204 | virtual String get_caption() const override; |
205 | |
206 | virtual bool has_filter() const override; |
207 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
208 | |
209 | AnimationNodeAdd3(); |
210 | }; |
211 | |
212 | class AnimationNodeBlend2 : public AnimationNodeSync { |
213 | GDCLASS(AnimationNodeBlend2, AnimationNodeSync); |
214 | |
215 | StringName blend_amount = PNAME("blend_amount" ); |
216 | |
217 | protected: |
218 | static void _bind_methods(); |
219 | |
220 | public: |
221 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
222 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
223 | |
224 | virtual String get_caption() const override; |
225 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
226 | |
227 | virtual bool has_filter() const override; |
228 | AnimationNodeBlend2(); |
229 | }; |
230 | |
231 | class AnimationNodeBlend3 : public AnimationNodeSync { |
232 | GDCLASS(AnimationNodeBlend3, AnimationNodeSync); |
233 | |
234 | StringName blend_amount = PNAME("blend_amount" ); |
235 | |
236 | protected: |
237 | static void _bind_methods(); |
238 | |
239 | public: |
240 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
241 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
242 | |
243 | virtual String get_caption() const override; |
244 | |
245 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
246 | AnimationNodeBlend3(); |
247 | }; |
248 | |
249 | class AnimationNodeSub2 : public AnimationNodeSync { |
250 | GDCLASS(AnimationNodeSub2, AnimationNodeSync); |
251 | |
252 | StringName sub_amount = PNAME("sub_amount" ); |
253 | |
254 | protected: |
255 | static void _bind_methods(); |
256 | |
257 | public: |
258 | void get_parameter_list(List<PropertyInfo> *r_list) const override; |
259 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
260 | |
261 | virtual String get_caption() const override; |
262 | |
263 | virtual bool has_filter() const override; |
264 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
265 | |
266 | AnimationNodeSub2(); |
267 | }; |
268 | |
269 | class AnimationNodeTimeScale : public AnimationNode { |
270 | GDCLASS(AnimationNodeTimeScale, AnimationNode); |
271 | |
272 | StringName scale = PNAME("scale" ); |
273 | |
274 | protected: |
275 | static void _bind_methods(); |
276 | |
277 | public: |
278 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
279 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
280 | |
281 | virtual String get_caption() const override; |
282 | |
283 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
284 | |
285 | AnimationNodeTimeScale(); |
286 | }; |
287 | |
288 | class AnimationNodeTimeSeek : public AnimationNode { |
289 | GDCLASS(AnimationNodeTimeSeek, AnimationNode); |
290 | |
291 | StringName seek_pos_request = PNAME("seek_request" ); |
292 | |
293 | protected: |
294 | static void _bind_methods(); |
295 | |
296 | public: |
297 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
298 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
299 | |
300 | virtual String get_caption() const override; |
301 | |
302 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
303 | |
304 | AnimationNodeTimeSeek(); |
305 | }; |
306 | |
307 | class AnimationNodeTransition : public AnimationNodeSync { |
308 | GDCLASS(AnimationNodeTransition, AnimationNodeSync); |
309 | |
310 | struct InputData { |
311 | bool auto_advance = false; |
312 | bool reset = true; |
313 | }; |
314 | Vector<InputData> input_data; |
315 | |
316 | StringName time = "time" ; |
317 | StringName prev_xfading = "prev_xfading" ; |
318 | StringName prev_index = "prev_index" ; |
319 | StringName current_index = PNAME("current_index" ); |
320 | StringName current_state = PNAME("current_state" ); |
321 | StringName transition_request = PNAME("transition_request" ); |
322 | |
323 | StringName prev_frame_current = "pf_current" ; |
324 | StringName prev_frame_current_idx = "pf_current_idx" ; |
325 | |
326 | double xfade_time = 0.0; |
327 | Ref<Curve> xfade_curve; |
328 | bool allow_transition_to_self = false; |
329 | |
330 | bool pending_update = false; |
331 | |
332 | protected: |
333 | bool _get(const StringName &p_path, Variant &r_ret) const; |
334 | bool _set(const StringName &p_path, const Variant &p_value); |
335 | static void _bind_methods(); |
336 | void _get_property_list(List<PropertyInfo> *p_list) const; |
337 | |
338 | public: |
339 | virtual void get_parameter_list(List<PropertyInfo> *r_list) const override; |
340 | virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; |
341 | virtual bool is_parameter_read_only(const StringName &p_parameter) const override; |
342 | |
343 | virtual String get_caption() const override; |
344 | |
345 | void set_input_count(int p_inputs); |
346 | |
347 | virtual bool add_input(const String &p_name) override; |
348 | virtual void remove_input(int p_index) override; |
349 | virtual bool set_input_name(int p_input, const String &p_name) override; |
350 | |
351 | void set_input_as_auto_advance(int p_input, bool p_enable); |
352 | bool is_input_set_as_auto_advance(int p_input) const; |
353 | |
354 | void set_input_reset(int p_input, bool p_enable); |
355 | bool is_input_reset(int p_input) const; |
356 | |
357 | void set_xfade_time(double p_fade); |
358 | double get_xfade_time() const; |
359 | |
360 | void set_xfade_curve(const Ref<Curve> &p_curve); |
361 | Ref<Curve> get_xfade_curve() const; |
362 | |
363 | void set_allow_transition_to_self(bool p_enable); |
364 | bool is_allow_transition_to_self() const; |
365 | |
366 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
367 | |
368 | AnimationNodeTransition(); |
369 | }; |
370 | |
371 | class AnimationNodeOutput : public AnimationNode { |
372 | GDCLASS(AnimationNodeOutput, AnimationNode); |
373 | |
374 | public: |
375 | virtual String get_caption() const override; |
376 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
377 | AnimationNodeOutput(); |
378 | }; |
379 | |
380 | ///// |
381 | |
382 | class AnimationNodeBlendTree : public AnimationRootNode { |
383 | GDCLASS(AnimationNodeBlendTree, AnimationRootNode); |
384 | |
385 | struct Node { |
386 | Ref<AnimationNode> node; |
387 | Vector2 position; |
388 | Vector<StringName> connections; |
389 | }; |
390 | |
391 | RBMap<StringName, Node, StringName::AlphCompare> nodes; |
392 | |
393 | Vector2 graph_offset; |
394 | |
395 | void _node_changed(const StringName &p_node); |
396 | |
397 | void _initialize_node_tree(); |
398 | |
399 | protected: |
400 | static void _bind_methods(); |
401 | bool _set(const StringName &p_name, const Variant &p_value); |
402 | bool _get(const StringName &p_name, Variant &r_ret) const; |
403 | void _get_property_list(List<PropertyInfo> *p_list) const; |
404 | |
405 | virtual void _tree_changed() override; |
406 | virtual void _animation_node_renamed(const ObjectID &p_oid, const String &p_old_name, const String &p_new_name) override; |
407 | virtual void _animation_node_removed(const ObjectID &p_oid, const StringName &p_node) override; |
408 | |
409 | virtual void reset_state() override; |
410 | |
411 | public: |
412 | enum ConnectionError { |
413 | CONNECTION_OK, |
414 | CONNECTION_ERROR_NO_INPUT, |
415 | CONNECTION_ERROR_NO_INPUT_INDEX, |
416 | CONNECTION_ERROR_NO_OUTPUT, |
417 | CONNECTION_ERROR_SAME_NODE, |
418 | CONNECTION_ERROR_CONNECTION_EXISTS, |
419 | //no need to check for cycles due to tree topology |
420 | }; |
421 | |
422 | void add_node(const StringName &p_name, Ref<AnimationNode> p_node, const Vector2 &p_position = Vector2()); |
423 | Ref<AnimationNode> get_node(const StringName &p_name) const; |
424 | void remove_node(const StringName &p_name); |
425 | void rename_node(const StringName &p_name, const StringName &p_new_name); |
426 | bool has_node(const StringName &p_name) const; |
427 | StringName get_node_name(const Ref<AnimationNode> &p_node) const; |
428 | Vector<StringName> get_node_connection_array(const StringName &p_name) const; |
429 | |
430 | void set_node_position(const StringName &p_node, const Vector2 &p_position); |
431 | Vector2 get_node_position(const StringName &p_node) const; |
432 | |
433 | virtual void get_child_nodes(List<ChildNode> *r_child_nodes) override; |
434 | |
435 | void connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node); |
436 | void disconnect_node(const StringName &p_node, int p_input_index); |
437 | |
438 | struct NodeConnection { |
439 | StringName input_node; |
440 | int input_index = 0; |
441 | StringName output_node; |
442 | }; |
443 | |
444 | ConnectionError can_connect_node(const StringName &p_input_node, int p_input_index, const StringName &p_output_node) const; |
445 | void get_node_connections(List<NodeConnection> *r_connections) const; |
446 | |
447 | virtual String get_caption() const override; |
448 | virtual double _process(double p_time, bool p_seek, bool p_is_external_seeking, bool p_test_only = false) override; |
449 | |
450 | void get_node_list(List<StringName> *r_list); |
451 | |
452 | void set_graph_offset(const Vector2 &p_graph_offset); |
453 | Vector2 get_graph_offset() const; |
454 | |
455 | virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) const override; |
456 | |
457 | AnimationNodeBlendTree(); |
458 | ~AnimationNodeBlendTree(); |
459 | }; |
460 | |
461 | VARIANT_ENUM_CAST(AnimationNodeBlendTree::ConnectionError) |
462 | |
463 | #endif // ANIMATION_BLEND_TREE_H |
464 | |