tween.cpp 26 KB

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