animation_player.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /**************************************************************************/
  2. /* animation_player.cpp */
  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. #include "animation_player.h"
  31. #include "animation_player.compat.inc"
  32. #include "core/config/engine.h"
  33. bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
  34. String name = p_name;
  35. if (name.begins_with("playback/play")) { // For backward compatibility.
  36. set_current_animation(p_value);
  37. } else if (name.begins_with("next/")) {
  38. String which = name.get_slicec('/', 1);
  39. animation_set_next(which, p_value);
  40. } else if (p_name == SceneStringName(blend_times)) {
  41. Array array = p_value;
  42. int len = array.size();
  43. ERR_FAIL_COND_V(len % 3, false);
  44. for (int i = 0; i < len / 3; i++) {
  45. StringName from = array[i * 3 + 0];
  46. StringName to = array[i * 3 + 1];
  47. float time = array[i * 3 + 2];
  48. set_blend_time(from, to, time);
  49. }
  50. #ifndef DISABLE_DEPRECATED
  51. } else if (p_name == "method_call_mode") {
  52. set_callback_mode_method(static_cast<AnimationCallbackModeMethod>((int)p_value));
  53. } else if (p_name == "playback_process_mode") {
  54. set_callback_mode_process(static_cast<AnimationCallbackModeProcess>((int)p_value));
  55. } else if (p_name == "playback_active") {
  56. set_active(p_value);
  57. #endif // DISABLE_DEPRECATED
  58. } else {
  59. return false;
  60. }
  61. return true;
  62. }
  63. bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
  64. String name = p_name;
  65. if (name == "playback/play") { // For backward compatibility.
  66. r_ret = get_current_animation();
  67. } else if (name.begins_with("next/")) {
  68. String which = name.get_slicec('/', 1);
  69. r_ret = animation_get_next(which);
  70. } else if (p_name == SceneStringName(blend_times)) {
  71. Vector<BlendKey> keys;
  72. for (const KeyValue<BlendKey, double> &E : blend_times) {
  73. keys.ordered_insert(E.key);
  74. }
  75. Array array;
  76. for (int i = 0; i < keys.size(); i++) {
  77. array.push_back(keys[i].from);
  78. array.push_back(keys[i].to);
  79. array.push_back(blend_times.get(keys[i]));
  80. }
  81. r_ret = array;
  82. #ifndef DISABLE_DEPRECATED
  83. } else if (name == "method_call_mode") {
  84. r_ret = get_callback_mode_method();
  85. } else if (name == "playback_process_mode") {
  86. r_ret = get_callback_mode_process();
  87. } else if (name == "playback_active") {
  88. r_ret = is_active();
  89. #endif // DISABLE_DEPRECATED
  90. } else {
  91. return false;
  92. }
  93. return true;
  94. }
  95. void AnimationPlayer::_validate_property(PropertyInfo &p_property) const {
  96. if (Engine::get_singleton()->is_editor_hint() && p_property.name == "current_animation") {
  97. List<String> names;
  98. for (const KeyValue<StringName, AnimationData> &E : animation_set) {
  99. names.push_back(E.key);
  100. }
  101. names.push_front("[stop]");
  102. String hint;
  103. for (List<String>::Element *E = names.front(); E; E = E->next()) {
  104. if (E != names.front()) {
  105. hint += ",";
  106. }
  107. hint += E->get();
  108. }
  109. p_property.hint_string = hint;
  110. } else if (!auto_capture && p_property.name.begins_with("playback_auto_capture_")) {
  111. p_property.usage = PROPERTY_USAGE_NONE;
  112. }
  113. }
  114. void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
  115. List<PropertyInfo> anim_names;
  116. for (const KeyValue<StringName, AnimationData> &E : animation_set) {
  117. AHashMap<StringName, StringName>::ConstIterator F = animation_next_set.find(E.key);
  118. if (F && F->value != StringName()) {
  119. anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
  120. }
  121. }
  122. for (const PropertyInfo &E : anim_names) {
  123. p_list->push_back(E);
  124. }
  125. p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
  126. }
  127. void AnimationPlayer::_notification(int p_what) {
  128. switch (p_what) {
  129. case NOTIFICATION_READY: {
  130. if (!Engine::get_singleton()->is_editor_hint() && animation_set.has(autoplay)) {
  131. set_active(active);
  132. play(autoplay);
  133. _check_immediately_after_start();
  134. }
  135. } break;
  136. }
  137. }
  138. void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_internal_seeked, bool p_started, bool p_is_current) {
  139. double speed = speed_scale * cd.speed_scale;
  140. bool backwards = std::signbit(speed); // Negative zero means playing backwards too.
  141. double delta = p_started ? 0 : p_delta * speed;
  142. double next_pos = cd.pos + delta;
  143. double start = cd.get_start_time();
  144. double end = cd.get_end_time();
  145. Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE;
  146. switch (cd.from->animation->get_loop_mode()) {
  147. case Animation::LOOP_NONE: {
  148. if (Animation::is_less_approx(next_pos, start)) {
  149. next_pos = start;
  150. } else if (Animation::is_greater_approx(next_pos, end)) {
  151. next_pos = end;
  152. }
  153. delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here).
  154. } break;
  155. case Animation::LOOP_LINEAR: {
  156. if (Animation::is_less_approx(next_pos, start) && Animation::is_greater_or_equal_approx(cd.pos, start)) {
  157. looped_flag = Animation::LOOPED_FLAG_START;
  158. }
  159. if (Animation::is_greater_approx(next_pos, end) && Animation::is_less_or_equal_approx(cd.pos, end)) {
  160. looped_flag = Animation::LOOPED_FLAG_END;
  161. }
  162. next_pos = Math::fposmod(next_pos - start, end - start) + start;
  163. } break;
  164. case Animation::LOOP_PINGPONG: {
  165. if (Animation::is_less_approx(next_pos, start) && Animation::is_greater_or_equal_approx(cd.pos, start)) {
  166. cd.speed_scale *= -1.0;
  167. looped_flag = Animation::LOOPED_FLAG_START;
  168. }
  169. if (Animation::is_greater_approx(next_pos, end) && Animation::is_less_or_equal_approx(cd.pos, end)) {
  170. cd.speed_scale *= -1.0;
  171. looped_flag = Animation::LOOPED_FLAG_END;
  172. }
  173. next_pos = Math::pingpong(next_pos - start, end - start) + start;
  174. } break;
  175. default:
  176. break;
  177. }
  178. double prev_pos = cd.pos; // The animation may be changed during process, so it is safer that the state is changed before process.
  179. // End detection.
  180. if (p_is_current) {
  181. if (cd.from->animation->get_loop_mode() == Animation::LOOP_NONE) {
  182. if (!backwards && Animation::is_less_or_equal_approx(prev_pos, end) && Math::is_equal_approx(next_pos, end)) {
  183. // Playback finished.
  184. next_pos = end; // Snap to the edge.
  185. end_reached = true;
  186. end_notify = Animation::is_less_approx(prev_pos, end); // Notify only if not already at the end.
  187. p_blend = 1.0;
  188. }
  189. if (backwards && Animation::is_greater_or_equal_approx(prev_pos, start) && Math::is_equal_approx(next_pos, start)) {
  190. // Playback finished.
  191. next_pos = start; // Snap to the edge.
  192. end_reached = true;
  193. end_notify = Animation::is_greater_approx(prev_pos, start); // Notify only if not already at the beginning.
  194. p_blend = 1.0;
  195. }
  196. }
  197. }
  198. cd.pos = next_pos;
  199. PlaybackInfo pi;
  200. if (p_started) {
  201. pi.time = prev_pos;
  202. pi.delta = 0;
  203. pi.start = start;
  204. pi.end = end;
  205. pi.seeked = true;
  206. } else {
  207. pi.time = next_pos;
  208. pi.delta = delta;
  209. pi.start = start;
  210. pi.end = end;
  211. pi.seeked = p_seeked;
  212. }
  213. if (Math::is_zero_approx(pi.delta) && backwards) {
  214. pi.delta = -0.0; // Sign is needed to handle converted Continuous track from Discrete track correctly.
  215. }
  216. // Immediately after playback, discrete keys should be retrieved with EXACT mode since behind keys must be ignored at that time.
  217. pi.is_external_seeking = !p_internal_seeked && !p_started;
  218. pi.looped_flag = looped_flag;
  219. pi.weight = p_blend;
  220. make_animation_instance(cd.from->name, pi);
  221. }
  222. float AnimationPlayer::get_current_blend_amount() {
  223. Playback &c = playback;
  224. float blend = 1.0;
  225. for (const Blend &b : c.blend) {
  226. blend = blend - b.blend_left;
  227. }
  228. return MAX(0, blend);
  229. }
  230. void AnimationPlayer::_blend_playback_data(double p_delta, bool p_started) {
  231. Playback &c = playback;
  232. bool seeked = c.seeked; // The animation may be changed during process, so it is safer that the state is changed before process.
  233. bool internal_seeked = c.internal_seeked;
  234. if (!Math::is_zero_approx(p_delta)) {
  235. c.seeked = false;
  236. c.internal_seeked = false;
  237. }
  238. // Second, process current animation to check if the animation end reached.
  239. _process_playback_data(c.current, p_delta, get_current_blend_amount(), seeked, internal_seeked, p_started, true);
  240. // Finally, if not end the animation, do blending.
  241. if (end_reached) {
  242. playback.blend.clear();
  243. return;
  244. }
  245. List<List<Blend>::Element *> to_erase;
  246. for (List<Blend>::Element *E = c.blend.front(); E; E = E->next()) {
  247. Blend &b = E->get();
  248. b.blend_left = MAX(0, b.blend_left - Math::abs(speed_scale * p_delta) / b.blend_time);
  249. if (Animation::is_less_or_equal_approx(b.blend_left, 0)) {
  250. to_erase.push_back(E);
  251. b.blend_left = CMP_EPSILON; // May want to play last frame.
  252. }
  253. // Note: There may be issues if an animation event triggers an animation change while this blend is active,
  254. // so it is best to use "deferred" calls instead of "immediate" for animation events that can trigger new animations.
  255. _process_playback_data(b.data, p_delta, b.blend_left, false, false, false);
  256. }
  257. for (List<Blend>::Element *&E : to_erase) {
  258. c.blend.erase(E);
  259. }
  260. }
  261. bool AnimationPlayer::_blend_pre_process(double p_delta, int p_track_count, const AHashMap<NodePath, int> &p_track_map) {
  262. if (!playback.current.from) {
  263. _set_process(false);
  264. return false;
  265. }
  266. tmp_from = playback.current.from->animation->get_instance_id();
  267. end_reached = false;
  268. end_notify = false;
  269. bool started = playback.started; // The animation may be changed during process, so it is safer that the state is changed before process.
  270. if (playback.started) {
  271. playback.started = false;
  272. }
  273. AnimationData *prev_from = playback.current.from;
  274. _blend_playback_data(p_delta, started);
  275. if (prev_from != playback.current.from) {
  276. return false; // Animation has been changed in the process (may be caused by method track), abort process.
  277. }
  278. return true;
  279. }
  280. void AnimationPlayer::_blend_capture(double p_delta) {
  281. blend_capture(p_delta * Math::abs(speed_scale));
  282. }
  283. void AnimationPlayer::_blend_post_process() {
  284. if (end_reached) {
  285. // If the method track changes current animation, the animation is not finished.
  286. if (tmp_from == playback.current.from->animation->get_instance_id()) {
  287. if (playback_queue.size()) {
  288. String old = playback.assigned;
  289. play(playback_queue.front()->get());
  290. String new_name = playback.assigned;
  291. playback_queue.pop_front();
  292. if (end_notify) {
  293. emit_signal(SceneStringName(animation_changed), old, new_name);
  294. }
  295. } else {
  296. _clear_caches();
  297. playing = false;
  298. _set_process(false);
  299. if (end_notify) {
  300. emit_signal(SceneStringName(animation_finished), playback.assigned);
  301. emit_signal(SNAME("current_animation_changed"), "");
  302. if (movie_quit_on_finish && OS::get_singleton()->has_feature("movie")) {
  303. print_line(vformat("Movie Maker mode is enabled. Quitting on animation finish as requested by: %s", get_path()));
  304. get_tree()->quit();
  305. }
  306. }
  307. }
  308. }
  309. end_reached = false;
  310. end_notify = false;
  311. }
  312. tmp_from = ObjectID();
  313. }
  314. void AnimationPlayer::queue(const StringName &p_name) {
  315. if (!is_playing()) {
  316. play(p_name);
  317. } else {
  318. playback_queue.push_back(p_name);
  319. }
  320. }
  321. Vector<String> AnimationPlayer::get_queue() {
  322. Vector<String> ret;
  323. for (const StringName &E : playback_queue) {
  324. ret.push_back(E);
  325. }
  326. return ret;
  327. }
  328. void AnimationPlayer::clear_queue() {
  329. playback_queue.clear();
  330. }
  331. void AnimationPlayer::play_backwards(const StringName &p_name, double p_custom_blend) {
  332. play(p_name, p_custom_blend, -1, true);
  333. }
  334. void AnimationPlayer::play_section_with_markers_backwards(const StringName &p_name, const StringName &p_start_marker, const StringName &p_end_marker, double p_custom_blend) {
  335. play_section_with_markers(p_name, p_start_marker, p_end_marker, p_custom_blend, -1, true);
  336. }
  337. void AnimationPlayer::play_section_backwards(const StringName &p_name, double p_start_time, double p_end_time, double p_custom_blend) {
  338. play_section(p_name, p_start_time, p_end_time, p_custom_blend, -1, true);
  339. }
  340. void AnimationPlayer::play(const StringName &p_name, double p_custom_blend, float p_custom_scale, bool p_from_end) {
  341. if (auto_capture) {
  342. play_with_capture(p_name, auto_capture_duration, p_custom_blend, p_custom_scale, p_from_end, auto_capture_transition_type, auto_capture_ease_type);
  343. } else {
  344. _play(p_name, p_custom_blend, p_custom_scale, p_from_end);
  345. }
  346. }
  347. void AnimationPlayer::_play(const StringName &p_name, double p_custom_blend, float p_custom_scale, bool p_from_end) {
  348. play_section_with_markers(p_name, StringName(), StringName(), p_custom_blend, p_custom_scale, p_from_end);
  349. }
  350. void AnimationPlayer::play_section_with_markers(const StringName &p_name, const StringName &p_start_marker, const StringName &p_end_marker, double p_custom_blend, float p_custom_scale, bool p_from_end) {
  351. StringName name = p_name;
  352. if (name == StringName()) {
  353. name = playback.assigned;
  354. }
  355. ERR_FAIL_COND_MSG(!animation_set.has(name), vformat("Animation not found: %s.", name));
  356. Ref<Animation> animation = animation_set[name].animation;
  357. ERR_FAIL_COND_MSG(p_start_marker == p_end_marker && p_start_marker, vformat("Start marker and end marker cannot be the same marker: %s.", p_start_marker));
  358. ERR_FAIL_COND_MSG(p_start_marker && !animation->has_marker(p_start_marker), vformat("Marker %s not found in animation: %s.", p_start_marker, name));
  359. ERR_FAIL_COND_MSG(p_end_marker && !animation->has_marker(p_end_marker), vformat("Marker %s not found in animation: %s.", p_end_marker, name));
  360. double start_time = p_start_marker ? animation->get_marker_time(p_start_marker) : -1;
  361. double end_time = p_end_marker ? animation->get_marker_time(p_end_marker) : -1;
  362. ERR_FAIL_COND_MSG(p_start_marker && p_end_marker && Animation::is_greater_approx(start_time, end_time), vformat("End marker %s is placed earlier than start marker %s in animation: %s.", p_end_marker, p_start_marker, name));
  363. if (p_start_marker && Animation::is_less_approx(start_time, 0)) {
  364. WARN_PRINT_ED(vformat("Negative time start marker: %s is invalid in the section, so the start of the animation: %s is used instead.", p_start_marker, playback.current.from->animation->get_name()));
  365. }
  366. if (p_end_marker && Animation::is_less_approx(end_time, 0)) {
  367. WARN_PRINT_ED(vformat("Negative time end marker: %s is invalid in the section, so the end of the animation: %s is used instead.", p_end_marker, playback.current.from->animation->get_name()));
  368. }
  369. play_section(name, start_time, end_time, p_custom_blend, p_custom_scale, p_from_end);
  370. }
  371. void AnimationPlayer::play_section(const StringName &p_name, double p_start_time, double p_end_time, double p_custom_blend, float p_custom_scale, bool p_from_end) {
  372. StringName name = p_name;
  373. if (name == StringName()) {
  374. name = playback.assigned;
  375. }
  376. ERR_FAIL_COND_MSG(!animation_set.has(name), vformat("Animation not found: %s.", name));
  377. ERR_FAIL_COND_MSG(p_start_time >= 0 && p_end_time >= 0 && Math::is_equal_approx(p_start_time, p_end_time), "Start time and end time must not equal to each other.");
  378. ERR_FAIL_COND_MSG(p_start_time >= 0 && p_end_time >= 0 && Animation::is_greater_approx(p_start_time, p_end_time), vformat("Start time %f is greater than end time %f.", p_start_time, p_end_time));
  379. Playback &c = playback;
  380. if (c.current.from) {
  381. double blend_time = 0.0;
  382. // Find if it can blend.
  383. BlendKey bk;
  384. bk.from = c.current.from->name;
  385. bk.to = name;
  386. if (Animation::is_greater_or_equal_approx(p_custom_blend, 0)) {
  387. blend_time = p_custom_blend;
  388. } else if (blend_times.has(bk)) {
  389. blend_time = blend_times[bk];
  390. } else {
  391. bk.from = "*";
  392. if (blend_times.has(bk)) {
  393. blend_time = blend_times[bk];
  394. } else {
  395. bk.from = c.current.from->name;
  396. bk.to = "*";
  397. if (blend_times.has(bk)) {
  398. blend_time = blend_times[bk];
  399. }
  400. }
  401. }
  402. if (Animation::is_less_approx(p_custom_blend, 0) && Math::is_zero_approx(blend_time) && default_blend_time) {
  403. blend_time = default_blend_time;
  404. }
  405. if (Animation::is_greater_approx(blend_time, 0)) {
  406. Blend b;
  407. b.data = c.current;
  408. b.blend_left = get_current_blend_amount();
  409. b.blend_time = blend_time;
  410. c.blend.push_back(b);
  411. } else {
  412. c.blend.clear();
  413. }
  414. }
  415. if (get_current_animation() != p_name) {
  416. _clear_playing_caches();
  417. }
  418. c.current.from = &animation_set[name];
  419. c.current.speed_scale = p_custom_scale;
  420. c.current.start_time = p_start_time;
  421. c.current.end_time = p_end_time;
  422. double start = playback.current.get_start_time();
  423. double end = playback.current.get_end_time();
  424. if (!end_reached) {
  425. playback_queue.clear();
  426. }
  427. if (c.assigned != name) { // Reset.
  428. c.current.pos = p_from_end ? end : start;
  429. c.assigned = name;
  430. emit_signal(SNAME("current_animation_changed"), c.assigned);
  431. } else {
  432. if (p_from_end && Math::is_equal_approx(c.current.pos, start)) {
  433. // Animation reset but played backwards, set position to the end.
  434. seek_internal(end, true, true, true);
  435. } else if (!p_from_end && Math::is_equal_approx(c.current.pos, end)) {
  436. // Animation resumed but already ended, set position to the beginning.
  437. seek_internal(start, true, true, true);
  438. } else if (playing) {
  439. return;
  440. }
  441. }
  442. c.seeked = false;
  443. c.started = true;
  444. _set_process(true); // Always process when starting an animation.
  445. playing = true;
  446. emit_signal(SceneStringName(animation_started), c.assigned);
  447. if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
  448. return; // No next in this case.
  449. }
  450. StringName next = animation_get_next(p_name);
  451. if (next != StringName() && animation_set.has(next)) {
  452. queue(next);
  453. }
  454. }
  455. void AnimationPlayer::_capture(const StringName &p_name, bool p_from_end, double p_duration, Tween::TransitionType p_trans_type, Tween::EaseType p_ease_type) {
  456. StringName name = p_name;
  457. if (name == StringName()) {
  458. name = playback.assigned;
  459. }
  460. Ref<Animation> anim = get_animation(name);
  461. if (anim.is_null() || !anim->is_capture_included()) {
  462. return;
  463. }
  464. if (std::signbit(p_duration)) {
  465. double max_dur = 0;
  466. double current_pos = playback.current.pos;
  467. if (playback.assigned != name) {
  468. current_pos = p_from_end ? anim->get_length() : 0;
  469. }
  470. for (int i = 0; i < anim->get_track_count(); i++) {
  471. if (anim->track_get_type(i) != Animation::TYPE_VALUE) {
  472. continue;
  473. }
  474. if (anim->value_track_get_update_mode(i) != Animation::UPDATE_CAPTURE) {
  475. continue;
  476. }
  477. if (anim->track_get_key_count(i) == 0) {
  478. continue;
  479. }
  480. max_dur = MAX(max_dur, p_from_end ? current_pos - anim->track_get_key_time(i, anim->track_get_key_count(i) - 1) : anim->track_get_key_time(i, 0) - current_pos);
  481. }
  482. p_duration = max_dur;
  483. }
  484. if (Math::is_zero_approx(p_duration)) {
  485. return;
  486. }
  487. capture(name, p_duration, p_trans_type, p_ease_type);
  488. }
  489. void AnimationPlayer::play_with_capture(const StringName &p_name, double p_duration, double p_custom_blend, float p_custom_scale, bool p_from_end, Tween::TransitionType p_trans_type, Tween::EaseType p_ease_type) {
  490. _capture(p_name, p_from_end, p_duration, p_trans_type, p_ease_type);
  491. _play(p_name, p_custom_blend, p_custom_scale, p_from_end);
  492. }
  493. bool AnimationPlayer::is_playing() const {
  494. return playing;
  495. }
  496. void AnimationPlayer::set_current_animation(const String &p_animation) {
  497. if (p_animation == "[stop]" || p_animation.is_empty()) {
  498. stop();
  499. } else if (!is_playing()) {
  500. play(p_animation);
  501. } else if (playback.assigned != p_animation) {
  502. float speed = playback.current.speed_scale;
  503. play(p_animation, -1.0, speed, std::signbit(speed));
  504. } else {
  505. // Same animation, do not replay from start.
  506. }
  507. }
  508. String AnimationPlayer::get_current_animation() const {
  509. return (is_playing() ? playback.assigned : "");
  510. }
  511. void AnimationPlayer::set_assigned_animation(const String &p_animation) {
  512. if (is_playing()) {
  513. float speed = playback.current.speed_scale;
  514. play(p_animation, -1.0, speed, std::signbit(speed));
  515. } else {
  516. ERR_FAIL_COND_MSG(!animation_set.has(p_animation), vformat("Animation not found: %s.", p_animation));
  517. playback.current.pos = 0;
  518. playback.current.from = &animation_set[p_animation];
  519. playback.current.start_time = -1;
  520. playback.current.end_time = -1;
  521. playback.assigned = p_animation;
  522. emit_signal(SNAME("current_animation_changed"), playback.assigned);
  523. }
  524. }
  525. String AnimationPlayer::get_assigned_animation() const {
  526. return playback.assigned;
  527. }
  528. void AnimationPlayer::pause() {
  529. _stop_internal(false, false);
  530. }
  531. void AnimationPlayer::stop(bool p_keep_state) {
  532. _stop_internal(true, p_keep_state);
  533. }
  534. void AnimationPlayer::set_speed_scale(float p_speed) {
  535. speed_scale = p_speed;
  536. }
  537. float AnimationPlayer::get_speed_scale() const {
  538. return speed_scale;
  539. }
  540. float AnimationPlayer::get_playing_speed() const {
  541. if (!playing) {
  542. return 0;
  543. }
  544. return speed_scale * playback.current.speed_scale;
  545. }
  546. void AnimationPlayer::seek_internal(double p_time, bool p_update, bool p_update_only, bool p_is_internal_seek) {
  547. if (!active) {
  548. return;
  549. }
  550. bool is_backward = Animation::is_less_approx(p_time, playback.current.pos);
  551. _check_immediately_after_start();
  552. playback.current.pos = p_time;
  553. if (!playback.current.from) {
  554. if (playback.assigned) {
  555. ERR_FAIL_COND_MSG(!animation_set.has(playback.assigned), vformat("Animation not found: %s.", playback.assigned));
  556. playback.current.from = &animation_set[playback.assigned];
  557. }
  558. if (!playback.current.from) {
  559. return; // There is no animation.
  560. }
  561. }
  562. double start = playback.current.get_start_time();
  563. double end = playback.current.get_end_time();
  564. // Clamp the seek position.
  565. p_time = CLAMP(p_time, start, end);
  566. playback.seeked = true;
  567. playback.internal_seeked = p_is_internal_seek;
  568. if (p_update) {
  569. _process_animation(is_backward ? -0.0 : 0.0, p_update_only);
  570. playback.seeked = false; // If animation was proceeded here, no more seek in internal process.
  571. }
  572. }
  573. void AnimationPlayer::seek(double p_time, bool p_update, bool p_update_only) {
  574. seek_internal(p_time, p_update, p_update_only);
  575. }
  576. void AnimationPlayer::advance(double p_time) {
  577. _check_immediately_after_start();
  578. AnimationMixer::advance(p_time);
  579. }
  580. void AnimationPlayer::_check_immediately_after_start() {
  581. if (playback.started) {
  582. _process_animation(0); // Force process current key for Discrete/Method/Audio/AnimationPlayback. Then, started flag is cleared.
  583. }
  584. }
  585. bool AnimationPlayer::is_valid() const {
  586. return (playback.current.from);
  587. }
  588. double AnimationPlayer::get_current_animation_position() const {
  589. ERR_FAIL_NULL_V_MSG(playback.current.from, 0, "AnimationPlayer has no current animation.");
  590. return playback.current.pos;
  591. }
  592. double AnimationPlayer::get_current_animation_length() const {
  593. ERR_FAIL_NULL_V_MSG(playback.current.from, 0, "AnimationPlayer has no current animation.");
  594. return playback.current.from->animation->get_length();
  595. }
  596. void AnimationPlayer::set_section_with_markers(const StringName &p_start_marker, const StringName &p_end_marker) {
  597. ERR_FAIL_NULL_MSG(playback.current.from, "AnimationPlayer has no current animation.");
  598. ERR_FAIL_COND_MSG(p_start_marker == p_end_marker && p_start_marker, vformat("Start marker and end marker cannot be the same marker: %s.", p_start_marker));
  599. ERR_FAIL_COND_MSG(p_start_marker && !playback.current.from->animation->has_marker(p_start_marker), vformat("Marker %s not found in animation: %s.", p_start_marker, playback.current.from->animation->get_name()));
  600. ERR_FAIL_COND_MSG(p_end_marker && !playback.current.from->animation->has_marker(p_end_marker), vformat("Marker %s not found in animation: %s.", p_end_marker, playback.current.from->animation->get_name()));
  601. double start_time = p_start_marker ? playback.current.from->animation->get_marker_time(p_start_marker) : -1;
  602. double end_time = p_end_marker ? playback.current.from->animation->get_marker_time(p_end_marker) : -1;
  603. if (p_start_marker && Animation::is_less_approx(start_time, 0)) {
  604. WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_start_marker, playback.current.from->animation->get_name()));
  605. }
  606. if (p_end_marker && Animation::is_less_approx(end_time, 0)) {
  607. WARN_PRINT_ONCE_ED(vformat("Marker %s time must be positive in animation: %s.", p_end_marker, playback.current.from->animation->get_name()));
  608. }
  609. set_section(start_time, end_time);
  610. }
  611. void AnimationPlayer::set_section(double p_start_time, double p_end_time) {
  612. ERR_FAIL_NULL_MSG(playback.current.from, "AnimationPlayer has no current animation.");
  613. ERR_FAIL_COND_MSG(Animation::is_greater_or_equal_approx(p_start_time, 0) && Animation::is_greater_or_equal_approx(p_end_time, 0) && Animation::is_greater_or_equal_approx(p_start_time, p_end_time), vformat("Start time %f is greater than end time %f.", p_start_time, p_end_time));
  614. playback.current.start_time = p_start_time;
  615. playback.current.end_time = p_end_time;
  616. playback.current.pos = CLAMP(playback.current.pos, playback.current.get_start_time(), playback.current.get_end_time());
  617. }
  618. void AnimationPlayer::reset_section() {
  619. playback.current.start_time = -1;
  620. playback.current.end_time = -1;
  621. }
  622. double AnimationPlayer::get_section_start_time() const {
  623. ERR_FAIL_NULL_V_MSG(playback.current.from, playback.current.start_time, "AnimationPlayer has no current animation.");
  624. return playback.current.get_start_time();
  625. }
  626. double AnimationPlayer::get_section_end_time() const {
  627. ERR_FAIL_NULL_V_MSG(playback.current.from, playback.current.end_time, "AnimationPlayer has no current animation.");
  628. return playback.current.get_end_time();
  629. }
  630. bool AnimationPlayer::has_section() const {
  631. return Animation::is_greater_or_equal_approx(playback.current.start_time, 0) || Animation::is_greater_or_equal_approx(playback.current.end_time, 0);
  632. }
  633. void AnimationPlayer::set_autoplay(const String &p_name) {
  634. if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) {
  635. WARN_PRINT("Setting autoplay after the node has been added to the scene has no effect.");
  636. }
  637. autoplay = p_name;
  638. }
  639. String AnimationPlayer::get_autoplay() const {
  640. return autoplay;
  641. }
  642. void AnimationPlayer::set_movie_quit_on_finish_enabled(bool p_enabled) {
  643. movie_quit_on_finish = p_enabled;
  644. }
  645. bool AnimationPlayer::is_movie_quit_on_finish_enabled() const {
  646. return movie_quit_on_finish;
  647. }
  648. void AnimationPlayer::_stop_internal(bool p_reset, bool p_keep_state) {
  649. _clear_caches();
  650. Playback &c = playback;
  651. // c.blend.clear();
  652. double start = c.current.from ? playback.current.get_start_time() : 0;
  653. if (p_reset) {
  654. c.blend.clear();
  655. if (p_keep_state) {
  656. c.current.pos = start;
  657. } else {
  658. is_stopping = true;
  659. seek_internal(start, true, true, true);
  660. is_stopping = false;
  661. }
  662. c.current.from = nullptr;
  663. c.current.speed_scale = 1;
  664. emit_signal(SNAME("current_animation_changed"), "");
  665. }
  666. _set_process(false);
  667. playback_queue.clear();
  668. playing = false;
  669. }
  670. void AnimationPlayer::animation_set_next(const StringName &p_animation, const StringName &p_next) {
  671. ERR_FAIL_COND_MSG(!animation_set.has(p_animation), vformat("Animation not found: %s.", p_animation));
  672. animation_next_set[p_animation] = p_next;
  673. }
  674. StringName AnimationPlayer::animation_get_next(const StringName &p_animation) const {
  675. if (!animation_next_set.has(p_animation)) {
  676. return StringName();
  677. }
  678. return animation_next_set[p_animation];
  679. }
  680. void AnimationPlayer::set_default_blend_time(double p_default) {
  681. default_blend_time = p_default;
  682. }
  683. double AnimationPlayer::get_default_blend_time() const {
  684. return default_blend_time;
  685. }
  686. void AnimationPlayer::set_blend_time(const StringName &p_animation1, const StringName &p_animation2, double p_time) {
  687. ERR_FAIL_COND_MSG(!animation_set.has(p_animation1), vformat("Animation not found: %s.", p_animation1));
  688. ERR_FAIL_COND_MSG(!animation_set.has(p_animation2), vformat("Animation not found: %s.", p_animation2));
  689. ERR_FAIL_COND_MSG(p_time < 0, "Blend time cannot be smaller than 0.");
  690. BlendKey bk;
  691. bk.from = p_animation1;
  692. bk.to = p_animation2;
  693. if (Math::is_zero_approx(p_time)) {
  694. blend_times.erase(bk);
  695. } else {
  696. blend_times[bk] = p_time;
  697. }
  698. }
  699. double AnimationPlayer::get_blend_time(const StringName &p_animation1, const StringName &p_animation2) const {
  700. BlendKey bk;
  701. bk.from = p_animation1;
  702. bk.to = p_animation2;
  703. if (blend_times.has(bk)) {
  704. return blend_times[bk];
  705. } else {
  706. return 0;
  707. }
  708. }
  709. void AnimationPlayer::set_auto_capture(bool p_auto_capture) {
  710. auto_capture = p_auto_capture;
  711. notify_property_list_changed();
  712. }
  713. bool AnimationPlayer::is_auto_capture() const {
  714. return auto_capture;
  715. }
  716. void AnimationPlayer::set_auto_capture_duration(double p_auto_capture_duration) {
  717. auto_capture_duration = p_auto_capture_duration;
  718. }
  719. double AnimationPlayer::get_auto_capture_duration() const {
  720. return auto_capture_duration;
  721. }
  722. void AnimationPlayer::set_auto_capture_transition_type(Tween::TransitionType p_auto_capture_transition_type) {
  723. auto_capture_transition_type = p_auto_capture_transition_type;
  724. }
  725. Tween::TransitionType AnimationPlayer::get_auto_capture_transition_type() const {
  726. return auto_capture_transition_type;
  727. }
  728. void AnimationPlayer::set_auto_capture_ease_type(Tween::EaseType p_auto_capture_ease_type) {
  729. auto_capture_ease_type = p_auto_capture_ease_type;
  730. }
  731. Tween::EaseType AnimationPlayer::get_auto_capture_ease_type() const {
  732. return auto_capture_ease_type;
  733. }
  734. #ifdef TOOLS_ENABLED
  735. void AnimationPlayer::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
  736. const String pf = p_function;
  737. if (p_idx == 0 && (pf == "play" || pf == "play_backwards" || pf == "has_animation" || pf == "queue")) {
  738. List<StringName> al;
  739. get_animation_list(&al);
  740. for (const StringName &name : al) {
  741. r_options->push_back(String(name).quote());
  742. }
  743. }
  744. AnimationMixer::get_argument_options(p_function, p_idx, r_options);
  745. }
  746. #endif
  747. void AnimationPlayer::_animation_removed(const StringName &p_name, const StringName &p_library) {
  748. AnimationMixer::_animation_removed(p_name, p_library);
  749. StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name));
  750. if (!animation_set.has(name)) {
  751. return; // No need to update because not the one from the library being used.
  752. }
  753. _animation_set_cache_update();
  754. // Erase blends if needed
  755. List<BlendKey> to_erase;
  756. for (const KeyValue<BlendKey, double> &E : blend_times) {
  757. BlendKey bk = E.key;
  758. if (bk.from == name || bk.to == name) {
  759. to_erase.push_back(bk);
  760. }
  761. }
  762. while (to_erase.size()) {
  763. blend_times.erase(to_erase.front()->get());
  764. to_erase.pop_front();
  765. }
  766. }
  767. void AnimationPlayer::_rename_animation(const StringName &p_from_name, const StringName &p_to_name) {
  768. AnimationMixer::_rename_animation(p_from_name, p_to_name);
  769. // Rename autoplay or blends if needed.
  770. List<BlendKey> to_erase;
  771. HashMap<BlendKey, double, BlendKey> to_insert;
  772. for (const KeyValue<BlendKey, double> &E : blend_times) {
  773. BlendKey bk = E.key;
  774. BlendKey new_bk = bk;
  775. bool erase = false;
  776. if (bk.from == p_from_name) {
  777. new_bk.from = p_to_name;
  778. erase = true;
  779. }
  780. if (bk.to == p_from_name) {
  781. new_bk.to = p_to_name;
  782. erase = true;
  783. }
  784. if (erase) {
  785. to_erase.push_back(bk);
  786. to_insert[new_bk] = E.value;
  787. }
  788. }
  789. while (to_erase.size()) {
  790. blend_times.erase(to_erase.front()->get());
  791. to_erase.pop_front();
  792. }
  793. while (to_insert.size()) {
  794. blend_times[to_insert.begin()->key] = to_insert.begin()->value;
  795. to_insert.remove(to_insert.begin());
  796. }
  797. if (autoplay == p_from_name) {
  798. autoplay = p_to_name;
  799. }
  800. }
  801. void AnimationPlayer::_bind_methods() {
  802. ClassDB::bind_method(D_METHOD("animation_set_next", "animation_from", "animation_to"), &AnimationPlayer::animation_set_next);
  803. ClassDB::bind_method(D_METHOD("animation_get_next", "animation_from"), &AnimationPlayer::animation_get_next);
  804. ClassDB::bind_method(D_METHOD("set_blend_time", "animation_from", "animation_to", "sec"), &AnimationPlayer::set_blend_time);
  805. ClassDB::bind_method(D_METHOD("get_blend_time", "animation_from", "animation_to"), &AnimationPlayer::get_blend_time);
  806. ClassDB::bind_method(D_METHOD("set_default_blend_time", "sec"), &AnimationPlayer::set_default_blend_time);
  807. ClassDB::bind_method(D_METHOD("get_default_blend_time"), &AnimationPlayer::get_default_blend_time);
  808. ClassDB::bind_method(D_METHOD("set_auto_capture", "auto_capture"), &AnimationPlayer::set_auto_capture);
  809. ClassDB::bind_method(D_METHOD("is_auto_capture"), &AnimationPlayer::is_auto_capture);
  810. ClassDB::bind_method(D_METHOD("set_auto_capture_duration", "auto_capture_duration"), &AnimationPlayer::set_auto_capture_duration);
  811. ClassDB::bind_method(D_METHOD("get_auto_capture_duration"), &AnimationPlayer::get_auto_capture_duration);
  812. ClassDB::bind_method(D_METHOD("set_auto_capture_transition_type", "auto_capture_transition_type"), &AnimationPlayer::set_auto_capture_transition_type);
  813. ClassDB::bind_method(D_METHOD("get_auto_capture_transition_type"), &AnimationPlayer::get_auto_capture_transition_type);
  814. ClassDB::bind_method(D_METHOD("set_auto_capture_ease_type", "auto_capture_ease_type"), &AnimationPlayer::set_auto_capture_ease_type);
  815. ClassDB::bind_method(D_METHOD("get_auto_capture_ease_type"), &AnimationPlayer::get_auto_capture_ease_type);
  816. ClassDB::bind_method(D_METHOD("play", "name", "custom_blend", "custom_speed", "from_end"), &AnimationPlayer::play, DEFVAL(StringName()), DEFVAL(-1), DEFVAL(1.0), DEFVAL(false));
  817. ClassDB::bind_method(D_METHOD("play_section_with_markers", "name", "start_marker", "end_marker", "custom_blend", "custom_speed", "from_end"), &AnimationPlayer::play_section_with_markers, DEFVAL(StringName()), DEFVAL(StringName()), DEFVAL(StringName()), DEFVAL(-1), DEFVAL(1.0), DEFVAL(false));
  818. ClassDB::bind_method(D_METHOD("play_section", "name", "start_time", "end_time", "custom_blend", "custom_speed", "from_end"), &AnimationPlayer::play_section, DEFVAL(StringName()), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1), DEFVAL(1.0), DEFVAL(false));
  819. ClassDB::bind_method(D_METHOD("play_backwards", "name", "custom_blend"), &AnimationPlayer::play_backwards, DEFVAL(StringName()), DEFVAL(-1));
  820. ClassDB::bind_method(D_METHOD("play_section_with_markers_backwards", "name", "start_marker", "end_marker", "custom_blend"), &AnimationPlayer::play_section_with_markers_backwards, DEFVAL(StringName()), DEFVAL(StringName()), DEFVAL(StringName()), DEFVAL(-1));
  821. ClassDB::bind_method(D_METHOD("play_section_backwards", "name", "start_time", "end_time", "custom_blend"), &AnimationPlayer::play_section_backwards, DEFVAL(StringName()), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
  822. ClassDB::bind_method(D_METHOD("play_with_capture", "name", "duration", "custom_blend", "custom_speed", "from_end", "trans_type", "ease_type"), &AnimationPlayer::play_with_capture, DEFVAL(StringName()), DEFVAL(-1.0), DEFVAL(-1), DEFVAL(1.0), DEFVAL(false), DEFVAL(Tween::TRANS_LINEAR), DEFVAL(Tween::EASE_IN));
  823. ClassDB::bind_method(D_METHOD("pause"), &AnimationPlayer::pause);
  824. ClassDB::bind_method(D_METHOD("stop", "keep_state"), &AnimationPlayer::stop, DEFVAL(false));
  825. ClassDB::bind_method(D_METHOD("is_playing"), &AnimationPlayer::is_playing);
  826. ClassDB::bind_method(D_METHOD("set_current_animation", "animation"), &AnimationPlayer::set_current_animation);
  827. ClassDB::bind_method(D_METHOD("get_current_animation"), &AnimationPlayer::get_current_animation);
  828. ClassDB::bind_method(D_METHOD("set_assigned_animation", "animation"), &AnimationPlayer::set_assigned_animation);
  829. ClassDB::bind_method(D_METHOD("get_assigned_animation"), &AnimationPlayer::get_assigned_animation);
  830. ClassDB::bind_method(D_METHOD("queue", "name"), &AnimationPlayer::queue);
  831. ClassDB::bind_method(D_METHOD("get_queue"), &AnimationPlayer::get_queue);
  832. ClassDB::bind_method(D_METHOD("clear_queue"), &AnimationPlayer::clear_queue);
  833. ClassDB::bind_method(D_METHOD("set_speed_scale", "speed"), &AnimationPlayer::set_speed_scale);
  834. ClassDB::bind_method(D_METHOD("get_speed_scale"), &AnimationPlayer::get_speed_scale);
  835. ClassDB::bind_method(D_METHOD("get_playing_speed"), &AnimationPlayer::get_playing_speed);
  836. ClassDB::bind_method(D_METHOD("set_autoplay", "name"), &AnimationPlayer::set_autoplay);
  837. ClassDB::bind_method(D_METHOD("get_autoplay"), &AnimationPlayer::get_autoplay);
  838. ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation);
  839. ClassDB::bind_method(D_METHOD("find_animation_library", "animation"), &AnimationPlayer::find_animation_library);
  840. ClassDB::bind_method(D_METHOD("set_movie_quit_on_finish_enabled", "enabled"), &AnimationPlayer::set_movie_quit_on_finish_enabled);
  841. ClassDB::bind_method(D_METHOD("is_movie_quit_on_finish_enabled"), &AnimationPlayer::is_movie_quit_on_finish_enabled);
  842. ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position);
  843. ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length);
  844. ClassDB::bind_method(D_METHOD("set_section_with_markers", "start_marker", "end_marker"), &AnimationPlayer::set_section_with_markers, DEFVAL(StringName()), DEFVAL(StringName()));
  845. ClassDB::bind_method(D_METHOD("set_section", "start_time", "end_time"), &AnimationPlayer::set_section, DEFVAL(-1), DEFVAL(-1));
  846. ClassDB::bind_method(D_METHOD("reset_section"), &AnimationPlayer::reset_section);
  847. ClassDB::bind_method(D_METHOD("get_section_start_time"), &AnimationPlayer::get_section_start_time);
  848. ClassDB::bind_method(D_METHOD("get_section_end_time"), &AnimationPlayer::get_section_end_time);
  849. ClassDB::bind_method(D_METHOD("has_section"), &AnimationPlayer::has_section);
  850. ClassDB::bind_method(D_METHOD("seek", "seconds", "update", "update_only"), &AnimationPlayer::seek, DEFVAL(false), DEFVAL(false));
  851. ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR), "set_current_animation", "get_current_animation");
  852. ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_assigned_animation", "get_assigned_animation");
  853. ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_autoplay", "get_autoplay");
  854. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_length");
  855. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "current_animation_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_current_animation_position");
  856. ADD_GROUP("Playback Options", "playback_");
  857. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playback_auto_capture"), "set_auto_capture", "is_auto_capture");
  858. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_auto_capture_duration", PROPERTY_HINT_NONE, "suffix:s"), "set_auto_capture_duration", "get_auto_capture_duration");
  859. ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_auto_capture_transition_type", PROPERTY_HINT_ENUM, "Linear,Sine,Quint,Quart,Quad,Expo,Elastic,Cubic,Circ,Bounce,Back,Spring"), "set_auto_capture_transition_type", "get_auto_capture_transition_type");
  860. ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_auto_capture_ease_type", PROPERTY_HINT_ENUM, "In,Out,InOut,OutIn"), "set_auto_capture_ease_type", "get_auto_capture_ease_type");
  861. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01,suffix:s"), "set_default_blend_time", "get_default_blend_time");
  862. ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed_scale", PROPERTY_HINT_RANGE, "-4,4,0.001,or_less,or_greater"), "set_speed_scale", "get_speed_scale");
  863. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "movie_quit_on_finish"), "set_movie_quit_on_finish_enabled", "is_movie_quit_on_finish_enabled");
  864. ADD_SIGNAL(MethodInfo(SNAME("current_animation_changed"), PropertyInfo(Variant::STRING, "name")));
  865. ADD_SIGNAL(MethodInfo(SNAME("animation_changed"), PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name")));
  866. }
  867. AnimationPlayer::AnimationPlayer() {
  868. }
  869. AnimationPlayer::~AnimationPlayer() {
  870. }