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
36class 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
45public:
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
69protected:
70 void _validate_property(PropertyInfo &p_property) const;
71 static void _bind_methods();
72
73private:
74 PlayMode play_mode = PLAY_MODE_FORWARD;
75 bool backward = false; // Only used by pingpong animation.
76};
77
78VARIANT_ENUM_CAST(AnimationNodeAnimation::PlayMode)
79
80class AnimationNodeSync : public AnimationNode {
81 GDCLASS(AnimationNodeSync, AnimationNode);
82
83protected:
84 bool sync = false;
85
86 static void _bind_methods();
87
88public:
89 void set_use_sync(bool p_sync);
90 bool is_using_sync() const;
91
92 AnimationNodeSync();
93};
94
95class AnimationNodeOneShot : public AnimationNodeSync {
96 GDCLASS(AnimationNodeOneShot, AnimationNodeSync);
97
98public:
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
111private:
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
130protected:
131 static void _bind_methods();
132
133public:
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
169VARIANT_ENUM_CAST(AnimationNodeOneShot::OneShotRequest)
170VARIANT_ENUM_CAST(AnimationNodeOneShot::MixMode)
171
172class AnimationNodeAdd2 : public AnimationNodeSync {
173 GDCLASS(AnimationNodeAdd2, AnimationNodeSync);
174
175 StringName add_amount = PNAME("add_amount");
176
177protected:
178 static void _bind_methods();
179
180public:
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
192class AnimationNodeAdd3 : public AnimationNodeSync {
193 GDCLASS(AnimationNodeAdd3, AnimationNodeSync);
194
195 StringName add_amount = PNAME("add_amount");
196
197protected:
198 static void _bind_methods();
199
200public:
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
212class AnimationNodeBlend2 : public AnimationNodeSync {
213 GDCLASS(AnimationNodeBlend2, AnimationNodeSync);
214
215 StringName blend_amount = PNAME("blend_amount");
216
217protected:
218 static void _bind_methods();
219
220public:
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
231class AnimationNodeBlend3 : public AnimationNodeSync {
232 GDCLASS(AnimationNodeBlend3, AnimationNodeSync);
233
234 StringName blend_amount = PNAME("blend_amount");
235
236protected:
237 static void _bind_methods();
238
239public:
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
249class AnimationNodeSub2 : public AnimationNodeSync {
250 GDCLASS(AnimationNodeSub2, AnimationNodeSync);
251
252 StringName sub_amount = PNAME("sub_amount");
253
254protected:
255 static void _bind_methods();
256
257public:
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
269class AnimationNodeTimeScale : public AnimationNode {
270 GDCLASS(AnimationNodeTimeScale, AnimationNode);
271
272 StringName scale = PNAME("scale");
273
274protected:
275 static void _bind_methods();
276
277public:
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
288class AnimationNodeTimeSeek : public AnimationNode {
289 GDCLASS(AnimationNodeTimeSeek, AnimationNode);
290
291 StringName seek_pos_request = PNAME("seek_request");
292
293protected:
294 static void _bind_methods();
295
296public:
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
307class 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
332protected:
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
338public:
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
371class AnimationNodeOutput : public AnimationNode {
372 GDCLASS(AnimationNodeOutput, AnimationNode);
373
374public:
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
382class 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
399protected:
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
411public:
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
461VARIANT_ENUM_CAST(AnimationNodeBlendTree::ConnectionError)
462
463#endif // ANIMATION_BLEND_TREE_H
464