tween.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /**************************************************************************/
  2. /* tween.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 "tween.h"
  31. #include "scene/animation/easing_equations.h"
  32. #include "scene/main/node.h"
  33. #include "scene/resources/animation.h"
  34. #define CHECK_VALID() \
  35. ERR_FAIL_COND_V_MSG(!valid, nullptr, "Tween invalid. Either finished or created outside scene tree."); \
  36. ERR_FAIL_COND_V_MSG(started, nullptr, "Can't append to a Tween that has started. Use stop() first.");
  37. Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = {
  38. { &Linear::in, &Linear::in, &Linear::in, &Linear::in }, // Linear is the same for each easing.
  39. { &Sine::in, &Sine::out, &Sine::in_out, &Sine::out_in },
  40. { &Quint::in, &Quint::out, &Quint::in_out, &Quint::out_in },
  41. { &Quart::in, &Quart::out, &Quart::in_out, &Quart::out_in },
  42. { &Quad::in, &Quad::out, &Quad::in_out, &Quad::out_in },
  43. { &Expo::in, &Expo::out, &Expo::in_out, &Expo::out_in },
  44. { &Elastic::in, &Elastic::out, &Elastic::in_out, &Elastic::out_in },
  45. { &Cubic::in, &Cubic::out, &Cubic::in_out, &Cubic::out_in },
  46. { &Circ::in, &Circ::out, &Circ::in_out, &Circ::out_in },
  47. { &Bounce::in, &Bounce::out, &Bounce::in_out, &Bounce::out_in },
  48. { &Back::in, &Back::out, &Back::in_out, &Back::out_in },
  49. { &Spring::in, &Spring::out, &Spring::in_out, &Spring::out_in },
  50. };
  51. void Tweener::set_tween(const Ref<Tween> &p_tween) {
  52. tween_id = p_tween->get_instance_id();
  53. }
  54. void Tweener::start() {
  55. elapsed_time = 0;
  56. finished = false;
  57. }
  58. Ref<Tween> Tweener::_get_tween() {
  59. return ObjectDB::get_ref<Tween>(tween_id);
  60. }
  61. void Tweener::_finish() {
  62. finished = true;
  63. emit_signal(SceneStringName(finished));
  64. }
  65. void Tweener::_bind_methods() {
  66. ADD_SIGNAL(MethodInfo("finished"));
  67. }
  68. void Tween::_start_tweeners() {
  69. if (tweeners.is_empty()) {
  70. dead = true;
  71. ERR_FAIL_MSG("Tween without commands, aborting.");
  72. }
  73. for (Ref<Tweener> &tweener : tweeners.write[current_step]) {
  74. tweener->start();
  75. }
  76. }
  77. void Tween::_stop_internal(bool p_reset) {
  78. running = false;
  79. if (p_reset) {
  80. started = false;
  81. dead = false;
  82. total_time = 0;
  83. }
  84. }
  85. Ref<PropertyTweener> Tween::tween_property(const Object *p_target, const NodePath &p_property, Variant p_to, double p_duration) {
  86. ERR_FAIL_NULL_V(p_target, nullptr);
  87. CHECK_VALID();
  88. Vector<StringName> property_subnames = p_property.get_as_property_path().get_subnames();
  89. #ifdef DEBUG_ENABLED
  90. bool prop_valid;
  91. const Variant &prop_value = p_target->get_indexed(property_subnames, &prop_valid);
  92. ERR_FAIL_COND_V_MSG(!prop_valid, nullptr, vformat("The tweened property \"%s\" does not exist in object \"%s\".", p_property, p_target));
  93. #else
  94. const Variant &prop_value = p_target->get_indexed(property_subnames);
  95. #endif
  96. if (!Animation::validate_type_match(prop_value, p_to)) {
  97. return nullptr;
  98. }
  99. Ref<PropertyTweener> tweener;
  100. tweener.instantiate(p_target, property_subnames, p_to, p_duration);
  101. append(tweener);
  102. return tweener;
  103. }
  104. Ref<IntervalTweener> Tween::tween_interval(double p_time) {
  105. CHECK_VALID();
  106. Ref<IntervalTweener> tweener;
  107. tweener.instantiate(p_time);
  108. append(tweener);
  109. return tweener;
  110. }
  111. Ref<CallbackTweener> Tween::tween_callback(const Callable &p_callback) {
  112. CHECK_VALID();
  113. Ref<CallbackTweener> tweener;
  114. tweener.instantiate(p_callback);
  115. append(tweener);
  116. return tweener;
  117. }
  118. Ref<MethodTweener> Tween::tween_method(const Callable &p_callback, const Variant p_from, Variant p_to, double p_duration) {
  119. CHECK_VALID();
  120. if (!Animation::validate_type_match(p_from, p_to)) {
  121. return nullptr;
  122. }
  123. Ref<MethodTweener> tweener;
  124. tweener.instantiate(p_callback, p_from, p_to, p_duration);
  125. append(tweener);
  126. return tweener;
  127. }
  128. Ref<SubtweenTweener> Tween::tween_subtween(const Ref<Tween> &p_subtween) {
  129. CHECK_VALID();
  130. // Ensure that the subtween being added is not null.
  131. ERR_FAIL_COND_V(p_subtween.is_null(), nullptr);
  132. Ref<SubtweenTweener> tweener;
  133. tweener.instantiate(p_subtween);
  134. // Remove the tween from its parent tree, if it has one.
  135. // If the user created this tween without a parent tree attached,
  136. // then this step isn't necessary.
  137. if (tweener->subtween->parent_tree != nullptr) {
  138. tweener->subtween->parent_tree->remove_tween(tweener->subtween);
  139. }
  140. append(tweener);
  141. return tweener;
  142. }
  143. void Tween::append(Ref<Tweener> p_tweener) {
  144. p_tweener->set_tween(this);
  145. if (parallel_enabled) {
  146. current_step = MAX(current_step, 0);
  147. } else {
  148. current_step++;
  149. }
  150. parallel_enabled = default_parallel;
  151. tweeners.resize(current_step + 1);
  152. tweeners.write[current_step].push_back(p_tweener);
  153. }
  154. void Tween::stop() {
  155. _stop_internal(true);
  156. }
  157. void Tween::pause() {
  158. _stop_internal(false);
  159. }
  160. void Tween::play() {
  161. ERR_FAIL_COND_MSG(!valid, "Tween invalid. Either finished or created outside scene tree.");
  162. ERR_FAIL_COND_MSG(dead, "Can't play finished Tween, use stop() first to reset its state.");
  163. running = true;
  164. }
  165. void Tween::kill() {
  166. running = false; // For the sake of is_running().
  167. valid = false;
  168. dead = true;
  169. }
  170. bool Tween::is_running() {
  171. return running;
  172. }
  173. bool Tween::is_valid() {
  174. return valid;
  175. }
  176. void Tween::clear() {
  177. valid = false;
  178. tweeners.clear();
  179. }
  180. Ref<Tween> Tween::bind_node(const Node *p_node) {
  181. ERR_FAIL_NULL_V(p_node, this);
  182. bound_node = p_node->get_instance_id();
  183. is_bound = true;
  184. return this;
  185. }
  186. Ref<Tween> Tween::set_process_mode(TweenProcessMode p_mode) {
  187. process_mode = p_mode;
  188. return this;
  189. }
  190. Tween::TweenProcessMode Tween::get_process_mode() const {
  191. return process_mode;
  192. }
  193. Ref<Tween> Tween::set_pause_mode(TweenPauseMode p_mode) {
  194. pause_mode = p_mode;
  195. return this;
  196. }
  197. Tween::TweenPauseMode Tween::get_pause_mode() const {
  198. return pause_mode;
  199. }
  200. Ref<Tween> Tween::set_ignore_time_scale(bool p_ignore) {
  201. ignore_time_scale = p_ignore;
  202. return this;
  203. }
  204. bool Tween::is_ignoring_time_scale() const {
  205. return ignore_time_scale;
  206. }
  207. Ref<Tween> Tween::set_parallel(bool p_parallel) {
  208. default_parallel = p_parallel;
  209. parallel_enabled = p_parallel;
  210. return this;
  211. }
  212. Ref<Tween> Tween::set_loops(int p_loops) {
  213. loops = p_loops;
  214. return this;
  215. }
  216. int Tween::get_loops_left() const {
  217. if (loops <= 0) {
  218. return -1; // Infinite loop.
  219. } else {
  220. return loops - loops_done;
  221. }
  222. }
  223. Ref<Tween> Tween::set_speed_scale(float p_speed) {
  224. speed_scale = p_speed;
  225. return this;
  226. }
  227. Ref<Tween> Tween::set_trans(TransitionType p_trans) {
  228. default_transition = p_trans;
  229. return this;
  230. }
  231. Tween::TransitionType Tween::get_trans() const {
  232. return default_transition;
  233. }
  234. Ref<Tween> Tween::set_ease(EaseType p_ease) {
  235. default_ease = p_ease;
  236. return this;
  237. }
  238. Tween::EaseType Tween::get_ease() const {
  239. return default_ease;
  240. }
  241. Ref<Tween> Tween::parallel() {
  242. parallel_enabled = true;
  243. return this;
  244. }
  245. Ref<Tween> Tween::chain() {
  246. parallel_enabled = false;
  247. return this;
  248. }
  249. bool Tween::custom_step(double p_delta) {
  250. ERR_FAIL_COND_V_MSG(in_step, true, "Can't call custom_step() during another Tween step.");
  251. bool r = running;
  252. running = true;
  253. bool ret = step(p_delta);
  254. running = running && r; // Running might turn false when Tween finished.
  255. return ret;
  256. }
  257. bool Tween::step(double p_delta) {
  258. if (dead) {
  259. return false;
  260. }
  261. if (is_bound) {
  262. Node *node = get_bound_node();
  263. if (node) {
  264. if (!node->is_inside_tree()) {
  265. return true;
  266. }
  267. } else {
  268. return false;
  269. }
  270. }
  271. if (!running) {
  272. return true;
  273. }
  274. in_step = true;
  275. if (!started) {
  276. if (tweeners.is_empty()) {
  277. String tween_id;
  278. Node *node = get_bound_node();
  279. if (node) {
  280. tween_id = vformat("Tween (bound to %s)", node->is_inside_tree() ? (String)node->get_path() : (String)node->get_name());
  281. } else {
  282. tween_id = to_string();
  283. }
  284. in_step = false;
  285. ERR_FAIL_V_MSG(false, tween_id + ": started with no Tweeners.");
  286. }
  287. current_step = 0;
  288. loops_done = 0;
  289. total_time = 0;
  290. _start_tweeners();
  291. started = true;
  292. }
  293. double rem_delta = p_delta * speed_scale;
  294. bool step_active = false;
  295. total_time += rem_delta;
  296. #ifdef DEBUG_ENABLED
  297. double initial_delta = rem_delta;
  298. bool potential_infinite = false;
  299. #endif
  300. while (running && rem_delta > 0) {
  301. double step_delta = rem_delta;
  302. step_active = false;
  303. for (Ref<Tweener> &tweener : tweeners.write[current_step]) {
  304. // Modified inside Tweener.step().
  305. double temp_delta = rem_delta;
  306. // Turns to true if any Tweener returns true (i.e. is still not finished).
  307. step_active = tweener->step(temp_delta) || step_active;
  308. step_delta = MIN(temp_delta, step_delta);
  309. }
  310. rem_delta = step_delta;
  311. if (!step_active) {
  312. emit_signal(SNAME("step_finished"), current_step);
  313. current_step++;
  314. if (current_step == tweeners.size()) {
  315. loops_done++;
  316. if (loops_done == loops) {
  317. running = false;
  318. dead = true;
  319. emit_signal(SceneStringName(finished));
  320. break;
  321. } else {
  322. emit_signal(SNAME("loop_finished"), loops_done);
  323. current_step = 0;
  324. _start_tweeners();
  325. #ifdef DEBUG_ENABLED
  326. if (loops <= 0 && Math::is_equal_approx(rem_delta, initial_delta)) {
  327. if (!potential_infinite) {
  328. potential_infinite = true;
  329. } else {
  330. // Looped twice without using any time, this is 100% certain infinite loop.
  331. in_step = false;
  332. ERR_FAIL_V_MSG(false, "Infinite loop detected. Check set_loops() description for more info.");
  333. }
  334. }
  335. #endif
  336. }
  337. } else {
  338. _start_tweeners();
  339. }
  340. }
  341. }
  342. in_step = false;
  343. return true;
  344. }
  345. bool Tween::can_process(bool p_tree_paused) const {
  346. if (is_bound && pause_mode == TWEEN_PAUSE_BOUND) {
  347. Node *node = get_bound_node();
  348. if (node) {
  349. return node->is_inside_tree() && node->can_process();
  350. }
  351. }
  352. return !p_tree_paused || pause_mode == TWEEN_PAUSE_PROCESS;
  353. }
  354. Node *Tween::get_bound_node() const {
  355. if (is_bound) {
  356. return ObjectDB::get_instance<Node>(bound_node);
  357. } else {
  358. return nullptr;
  359. }
  360. }
  361. double Tween::get_total_time() const {
  362. return total_time;
  363. }
  364. real_t Tween::run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t p_time, real_t p_initial, real_t p_delta, real_t p_duration) {
  365. if (p_duration == 0) {
  366. // Special case to avoid dividing by 0 in equations.
  367. return p_initial + p_delta;
  368. }
  369. interpolater func = interpolaters[p_trans_type][p_ease_type];
  370. return func(p_time, p_initial, p_delta, p_duration);
  371. }
  372. Variant Tween::interpolate_variant(const Variant &p_initial_val, const Variant &p_delta_val, double p_time, double p_duration, TransitionType p_trans, EaseType p_ease) {
  373. ERR_FAIL_INDEX_V(p_trans, TransitionType::TRANS_MAX, Variant());
  374. ERR_FAIL_INDEX_V(p_ease, EaseType::EASE_MAX, Variant());
  375. Variant ret = Animation::add_variant(p_initial_val, p_delta_val);
  376. ret = Animation::interpolate_variant(p_initial_val, ret, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration), p_initial_val.is_string());
  377. return ret;
  378. }
  379. String Tween::to_string() {
  380. String ret = Object::to_string();
  381. Node *node = get_bound_node();
  382. if (node) {
  383. ret += vformat(" (bound to %s)", node->get_name());
  384. }
  385. return ret;
  386. }
  387. void Tween::_bind_methods() {
  388. ClassDB::bind_method(D_METHOD("tween_property", "object", "property", "final_val", "duration"), &Tween::tween_property);
  389. ClassDB::bind_method(D_METHOD("tween_interval", "time"), &Tween::tween_interval);
  390. ClassDB::bind_method(D_METHOD("tween_callback", "callback"), &Tween::tween_callback);
  391. ClassDB::bind_method(D_METHOD("tween_method", "method", "from", "to", "duration"), &Tween::tween_method);
  392. ClassDB::bind_method(D_METHOD("tween_subtween", "subtween"), &Tween::tween_subtween);
  393. ClassDB::bind_method(D_METHOD("custom_step", "delta"), &Tween::custom_step);
  394. ClassDB::bind_method(D_METHOD("stop"), &Tween::stop);
  395. ClassDB::bind_method(D_METHOD("pause"), &Tween::pause);
  396. ClassDB::bind_method(D_METHOD("play"), &Tween::play);
  397. ClassDB::bind_method(D_METHOD("kill"), &Tween::kill);
  398. ClassDB::bind_method(D_METHOD("get_total_elapsed_time"), &Tween::get_total_time);
  399. ClassDB::bind_method(D_METHOD("is_running"), &Tween::is_running);
  400. ClassDB::bind_method(D_METHOD("is_valid"), &Tween::is_valid);
  401. ClassDB::bind_method(D_METHOD("bind_node", "node"), &Tween::bind_node);
  402. ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Tween::set_process_mode);
  403. ClassDB::bind_method(D_METHOD("set_pause_mode", "mode"), &Tween::set_pause_mode);
  404. ClassDB::bind_method(D_METHOD("set_ignore_time_scale", "ignore"), &Tween::set_ignore_time_scale, DEFVAL(true));
  405. ClassDB::bind_method(D_METHOD("set_parallel", "parallel"), &Tween::set_parallel, DEFVAL(true));
  406. ClassDB::bind_method(D_METHOD("set_loops", "loops"), &Tween::set_loops, DEFVAL(0));
  407. ClassDB::bind_method(D_METHOD("get_loops_left"), &Tween::get_loops_left);
  408. ClassDB::bind_method(D_METHOD("set_speed_scale", "speed"), &Tween::set_speed_scale);
  409. ClassDB::bind_method(D_METHOD("set_trans", "trans"), &Tween::set_trans);
  410. ClassDB::bind_method(D_METHOD("set_ease", "ease"), &Tween::set_ease);
  411. ClassDB::bind_method(D_METHOD("parallel"), &Tween::parallel);
  412. ClassDB::bind_method(D_METHOD("chain"), &Tween::chain);
  413. ClassDB::bind_static_method("Tween", D_METHOD("interpolate_value", "initial_value", "delta_value", "elapsed_time", "duration", "trans_type", "ease_type"), &Tween::interpolate_variant);
  414. ADD_SIGNAL(MethodInfo("step_finished", PropertyInfo(Variant::INT, "idx")));
  415. ADD_SIGNAL(MethodInfo("loop_finished", PropertyInfo(Variant::INT, "loop_count")));
  416. ADD_SIGNAL(MethodInfo("finished"));
  417. BIND_ENUM_CONSTANT(TWEEN_PROCESS_PHYSICS);
  418. BIND_ENUM_CONSTANT(TWEEN_PROCESS_IDLE);
  419. BIND_ENUM_CONSTANT(TWEEN_PAUSE_BOUND);
  420. BIND_ENUM_CONSTANT(TWEEN_PAUSE_STOP);
  421. BIND_ENUM_CONSTANT(TWEEN_PAUSE_PROCESS);
  422. BIND_ENUM_CONSTANT(TRANS_LINEAR);
  423. BIND_ENUM_CONSTANT(TRANS_SINE);
  424. BIND_ENUM_CONSTANT(TRANS_QUINT);
  425. BIND_ENUM_CONSTANT(TRANS_QUART);
  426. BIND_ENUM_CONSTANT(TRANS_QUAD);
  427. BIND_ENUM_CONSTANT(TRANS_EXPO);
  428. BIND_ENUM_CONSTANT(TRANS_ELASTIC);
  429. BIND_ENUM_CONSTANT(TRANS_CUBIC);
  430. BIND_ENUM_CONSTANT(TRANS_CIRC);
  431. BIND_ENUM_CONSTANT(TRANS_BOUNCE);
  432. BIND_ENUM_CONSTANT(TRANS_BACK);
  433. BIND_ENUM_CONSTANT(TRANS_SPRING);
  434. BIND_ENUM_CONSTANT(EASE_IN);
  435. BIND_ENUM_CONSTANT(EASE_OUT);
  436. BIND_ENUM_CONSTANT(EASE_IN_OUT);
  437. BIND_ENUM_CONSTANT(EASE_OUT_IN);
  438. }
  439. Tween::Tween() {
  440. ERR_FAIL_MSG("Tween can't be created directly. Use create_tween() method.");
  441. }
  442. Tween::Tween(SceneTree *p_parent_tree) {
  443. parent_tree = p_parent_tree;
  444. valid = true;
  445. }
  446. double PropertyTweener::_get_custom_interpolated_value(const Variant &p_value) {
  447. const Variant *argptr = &p_value;
  448. Variant result;
  449. Callable::CallError ce;
  450. custom_method.callp(&argptr, 1, result, ce);
  451. if (ce.error != Callable::CallError::CALL_OK) {
  452. ERR_FAIL_V_MSG(false, "Error calling custom method from PropertyTweener: " + Variant::get_callable_error_text(custom_method, &argptr, 1, ce) + ".");
  453. } else if (result.get_type() != Variant::FLOAT) {
  454. ERR_FAIL_V_MSG(false, vformat("Wrong return type in PropertyTweener custom method. Expected float, got %s.", Variant::get_type_name(result.get_type())));
  455. }
  456. return result;
  457. }
  458. Ref<PropertyTweener> PropertyTweener::from(const Variant &p_value) {
  459. Ref<Tween> tween = _get_tween();
  460. ERR_FAIL_COND_V(tween.is_null(), nullptr);
  461. Variant from_value = p_value;
  462. if (!Animation::validate_type_match(final_val, from_value)) {
  463. return nullptr;
  464. }
  465. initial_val = from_value;
  466. do_continue = false;
  467. return this;
  468. }
  469. Ref<PropertyTweener> PropertyTweener::from_current() {
  470. do_continue = false;
  471. return this;
  472. }
  473. Ref<PropertyTweener> PropertyTweener::as_relative() {
  474. relative = true;
  475. return this;
  476. }
  477. Ref<PropertyTweener> PropertyTweener::set_trans(Tween::TransitionType p_trans) {
  478. trans_type = p_trans;
  479. return this;
  480. }
  481. Ref<PropertyTweener> PropertyTweener::set_ease(Tween::EaseType p_ease) {
  482. ease_type = p_ease;
  483. return this;
  484. }
  485. Ref<PropertyTweener> PropertyTweener::set_custom_interpolator(const Callable &p_method) {
  486. custom_method = p_method;
  487. return this;
  488. }
  489. Ref<PropertyTweener> PropertyTweener::set_delay(double p_delay) {
  490. delay = p_delay;
  491. return this;
  492. }
  493. void PropertyTweener::start() {
  494. Tweener::start();
  495. Object *target_instance = ObjectDB::get_instance(target);
  496. if (!target_instance) {
  497. return;
  498. }
  499. if (do_continue) {
  500. if (Math::is_zero_approx(delay)) {
  501. initial_val = target_instance->get_indexed(property);
  502. } else {
  503. do_continue_delayed = true;
  504. }
  505. }
  506. if (relative) {
  507. final_val = Animation::add_variant(initial_val, base_final_val);
  508. }
  509. delta_val = Animation::subtract_variant(final_val, initial_val);
  510. }
  511. bool PropertyTweener::step(double &r_delta) {
  512. if (finished) {
  513. // This is needed in case there's a parallel Tweener with longer duration.
  514. return false;
  515. }
  516. Object *target_instance = ObjectDB::get_instance(target);
  517. if (!target_instance) {
  518. _finish();
  519. return false;
  520. }
  521. elapsed_time += r_delta;
  522. if (elapsed_time < delay) {
  523. r_delta = 0;
  524. return true;
  525. } else if (do_continue_delayed && !Math::is_zero_approx(delay)) {
  526. initial_val = target_instance->get_indexed(property);
  527. delta_val = Animation::subtract_variant(final_val, initial_val);
  528. do_continue_delayed = false;
  529. }
  530. Ref<Tween> tween = _get_tween();
  531. double time = MIN(elapsed_time - delay, duration);
  532. if (time < duration) {
  533. if (custom_method.is_valid()) {
  534. const Variant t = tween->interpolate_variant(0.0, 1.0, time, duration, trans_type, ease_type);
  535. double result = _get_custom_interpolated_value(t);
  536. target_instance->set_indexed(property, Animation::interpolate_variant(initial_val, final_val, result));
  537. } else {
  538. target_instance->set_indexed(property, tween->interpolate_variant(initial_val, delta_val, time, duration, trans_type, ease_type));
  539. }
  540. r_delta = 0;
  541. return true;
  542. } else {
  543. if (custom_method.is_valid()) {
  544. double final_t = _get_custom_interpolated_value(1.0);
  545. target_instance->set_indexed(property, Animation::interpolate_variant(initial_val, final_val, final_t));
  546. } else {
  547. target_instance->set_indexed(property, final_val);
  548. }
  549. r_delta = elapsed_time - delay - duration;
  550. _finish();
  551. return false;
  552. }
  553. }
  554. void PropertyTweener::set_tween(const Ref<Tween> &p_tween) {
  555. Tweener::set_tween(p_tween);
  556. if (trans_type == Tween::TRANS_MAX) {
  557. trans_type = p_tween->get_trans();
  558. }
  559. if (ease_type == Tween::EASE_MAX) {
  560. ease_type = p_tween->get_ease();
  561. }
  562. }
  563. void PropertyTweener::_bind_methods() {
  564. ClassDB::bind_method(D_METHOD("from", "value"), &PropertyTweener::from);
  565. ClassDB::bind_method(D_METHOD("from_current"), &PropertyTweener::from_current);
  566. ClassDB::bind_method(D_METHOD("as_relative"), &PropertyTweener::as_relative);
  567. ClassDB::bind_method(D_METHOD("set_trans", "trans"), &PropertyTweener::set_trans);
  568. ClassDB::bind_method(D_METHOD("set_ease", "ease"), &PropertyTweener::set_ease);
  569. ClassDB::bind_method(D_METHOD("set_custom_interpolator", "interpolator_method"), &PropertyTweener::set_custom_interpolator);
  570. ClassDB::bind_method(D_METHOD("set_delay", "delay"), &PropertyTweener::set_delay);
  571. }
  572. PropertyTweener::PropertyTweener(const Object *p_target, const Vector<StringName> &p_property, const Variant &p_to, double p_duration) {
  573. target = p_target->get_instance_id();
  574. property = p_property;
  575. initial_val = p_target->get_indexed(property);
  576. base_final_val = p_to;
  577. final_val = base_final_val;
  578. duration = p_duration;
  579. if (p_target->is_ref_counted()) {
  580. ref_copy = p_target;
  581. }
  582. }
  583. PropertyTweener::PropertyTweener() {
  584. ERR_FAIL_MSG("PropertyTweener can't be created directly. Use the tween_property() method in Tween.");
  585. }
  586. bool IntervalTweener::step(double &r_delta) {
  587. if (finished) {
  588. return false;
  589. }
  590. elapsed_time += r_delta;
  591. if (elapsed_time < duration) {
  592. r_delta = 0;
  593. return true;
  594. } else {
  595. r_delta = elapsed_time - duration;
  596. _finish();
  597. return false;
  598. }
  599. }
  600. IntervalTweener::IntervalTweener(double p_time) {
  601. duration = p_time;
  602. }
  603. IntervalTweener::IntervalTweener() {
  604. ERR_FAIL_MSG("IntervalTweener can't be created directly. Use the tween_interval() method in Tween.");
  605. }
  606. Ref<CallbackTweener> CallbackTweener::set_delay(double p_delay) {
  607. delay = p_delay;
  608. return this;
  609. }
  610. bool CallbackTweener::step(double &r_delta) {
  611. if (finished) {
  612. return false;
  613. }
  614. if (!callback.is_valid()) {
  615. _finish();
  616. return false;
  617. }
  618. elapsed_time += r_delta;
  619. if (elapsed_time >= delay) {
  620. Variant result;
  621. Callable::CallError ce;
  622. callback.callp(nullptr, 0, result, ce);
  623. if (ce.error != Callable::CallError::CALL_OK) {
  624. ERR_FAIL_V_MSG(false, "Error calling method from CallbackTweener: " + Variant::get_callable_error_text(callback, nullptr, 0, ce) + ".");
  625. }
  626. r_delta = elapsed_time - delay;
  627. _finish();
  628. return false;
  629. }
  630. r_delta = 0;
  631. return true;
  632. }
  633. void CallbackTweener::_bind_methods() {
  634. ClassDB::bind_method(D_METHOD("set_delay", "delay"), &CallbackTweener::set_delay);
  635. }
  636. CallbackTweener::CallbackTweener(const Callable &p_callback) {
  637. callback = p_callback;
  638. Object *callback_instance = p_callback.get_object();
  639. if (callback_instance && callback_instance->is_ref_counted()) {
  640. ref_copy = callback_instance;
  641. }
  642. }
  643. CallbackTweener::CallbackTweener() {
  644. ERR_FAIL_MSG("CallbackTweener can't be created directly. Use the tween_callback() method in Tween.");
  645. }
  646. Ref<MethodTweener> MethodTweener::set_delay(double p_delay) {
  647. delay = p_delay;
  648. return this;
  649. }
  650. Ref<MethodTweener> MethodTweener::set_trans(Tween::TransitionType p_trans) {
  651. trans_type = p_trans;
  652. return this;
  653. }
  654. Ref<MethodTweener> MethodTweener::set_ease(Tween::EaseType p_ease) {
  655. ease_type = p_ease;
  656. return this;
  657. }
  658. bool MethodTweener::step(double &r_delta) {
  659. if (finished) {
  660. return false;
  661. }
  662. if (!callback.is_valid()) {
  663. _finish();
  664. return false;
  665. }
  666. elapsed_time += r_delta;
  667. if (elapsed_time < delay) {
  668. r_delta = 0;
  669. return true;
  670. }
  671. Ref<Tween> tween = _get_tween();
  672. Variant current_val;
  673. double time = MIN(elapsed_time - delay, duration);
  674. if (time < duration) {
  675. current_val = tween->interpolate_variant(initial_val, delta_val, time, duration, trans_type, ease_type);
  676. } else {
  677. current_val = final_val;
  678. }
  679. const Variant **argptr = (const Variant **)alloca(sizeof(Variant *));
  680. argptr[0] = &current_val;
  681. Variant result;
  682. Callable::CallError ce;
  683. callback.callp(argptr, 1, result, ce);
  684. if (ce.error != Callable::CallError::CALL_OK) {
  685. ERR_FAIL_V_MSG(false, "Error calling method from MethodTweener: " + Variant::get_callable_error_text(callback, argptr, 1, ce) + ".");
  686. }
  687. if (time < duration) {
  688. r_delta = 0;
  689. return true;
  690. } else {
  691. r_delta = elapsed_time - delay - duration;
  692. _finish();
  693. return false;
  694. }
  695. }
  696. void MethodTweener::set_tween(const Ref<Tween> &p_tween) {
  697. Tweener::set_tween(p_tween);
  698. if (trans_type == Tween::TRANS_MAX) {
  699. trans_type = p_tween->get_trans();
  700. }
  701. if (ease_type == Tween::EASE_MAX) {
  702. ease_type = p_tween->get_ease();
  703. }
  704. }
  705. void MethodTweener::_bind_methods() {
  706. ClassDB::bind_method(D_METHOD("set_delay", "delay"), &MethodTweener::set_delay);
  707. ClassDB::bind_method(D_METHOD("set_trans", "trans"), &MethodTweener::set_trans);
  708. ClassDB::bind_method(D_METHOD("set_ease", "ease"), &MethodTweener::set_ease);
  709. }
  710. MethodTweener::MethodTweener(const Callable &p_callback, const Variant &p_from, const Variant &p_to, double p_duration) {
  711. callback = p_callback;
  712. initial_val = p_from;
  713. delta_val = Animation::subtract_variant(p_to, p_from);
  714. final_val = p_to;
  715. duration = p_duration;
  716. Object *callback_instance = p_callback.get_object();
  717. if (callback_instance && callback_instance->is_ref_counted()) {
  718. ref_copy = callback_instance;
  719. }
  720. }
  721. MethodTweener::MethodTweener() {
  722. ERR_FAIL_MSG("MethodTweener can't be created directly. Use the tween_method() method in Tween.");
  723. }
  724. void SubtweenTweener::start() {
  725. Tweener::start();
  726. // Reset the subtween.
  727. subtween->stop();
  728. // It's possible that a subtween could be killed before it is started;
  729. // if so, we just want to skip it entirely.
  730. if (subtween->is_valid()) {
  731. subtween->play();
  732. } else {
  733. _finish();
  734. }
  735. }
  736. bool SubtweenTweener::step(double &r_delta) {
  737. if (finished) {
  738. return false;
  739. }
  740. elapsed_time += r_delta;
  741. if (elapsed_time < delay) {
  742. r_delta = 0;
  743. return true;
  744. }
  745. if (!subtween->step(r_delta)) {
  746. r_delta = elapsed_time - delay - subtween->get_total_time();
  747. _finish();
  748. return false;
  749. }
  750. r_delta = 0;
  751. return true;
  752. }
  753. Ref<SubtweenTweener> SubtweenTweener::set_delay(double p_delay) {
  754. delay = p_delay;
  755. return this;
  756. }
  757. void SubtweenTweener::_bind_methods() {
  758. ClassDB::bind_method(D_METHOD("set_delay", "delay"), &SubtweenTweener::set_delay);
  759. }
  760. SubtweenTweener::SubtweenTweener(const Ref<Tween> &p_subtween) {
  761. subtween = p_subtween;
  762. }
  763. SubtweenTweener::SubtweenTweener() {
  764. ERR_FAIL_MSG("SubtweenTweener can't be created directly. Use the tween_subtween() method in Tween.");
  765. }