Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "XLAction.h"
25 : #include "XLNode.h"
26 :
27 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
28 :
29 : SP_COVERAGE_TRIVIAL
30 : Action::~Action() { }
31 :
32 13021 : Action::Action() { }
33 :
34 2495 : void Action::invalidate() {
35 2495 : if (_target) {
36 2450 : stop();
37 : }
38 2495 : }
39 :
40 15624 : void Action::stop() {
41 15624 : _target = nullptr;
42 15624 : }
43 :
44 1084 : bool Action::isDone() const {
45 1084 : return _target == nullptr;
46 : }
47 :
48 : SP_COVERAGE_TRIVIAL
49 : void Action::step(float dt) {
50 : log::warn("Action", "[step]: override me");
51 : }
52 :
53 : SP_COVERAGE_TRIVIAL
54 : void Action::update(float time) {
55 : log::warn("Action", "[update]: override me");
56 : }
57 :
58 12959 : void Action::startWithTarget(Node *aTarget) {
59 12959 : _target = aTarget;
60 12959 : }
61 :
62 5102 : void Action::setContainer(Node *container) {
63 5102 : _container = container;
64 5102 : }
65 :
66 0 : void Action::setTarget(Node *target) {
67 0 : _target = target;
68 0 : }
69 :
70 : SP_COVERAGE_TRIVIAL
71 : ActionInstant::~ActionInstant() { }
72 :
73 1891 : bool ActionInstant::init(bool runOnce) {
74 1891 : _duration = 0.0f;
75 1891 : _runOnce = runOnce;
76 1891 : return true;
77 : }
78 :
79 517 : void ActionInstant::step(float dt) {
80 517 : if (!_performed || !_runOnce) {
81 517 : update(1.0f);
82 517 : _performed = true;
83 : }
84 517 : }
85 :
86 42 : Show::~Show() { }
87 :
88 137 : void Show::update(float time) {
89 137 : _target->setVisible(true);
90 137 : }
91 :
92 42 : Hide::~Hide() { }
93 :
94 179 : void Hide::update(float time) {
95 179 : _target->setVisible(false);
96 179 : }
97 :
98 84 : ToggleVisibility::~ToggleVisibility() { }
99 :
100 148 : void ToggleVisibility::update(float time) {
101 148 : _target->setVisible(!_target->isVisible());
102 148 : }
103 :
104 42 : RemoveSelf::~RemoveSelf() { }
105 :
106 21 : bool RemoveSelf::init(bool isNeedCleanUp, bool runOnce) {
107 21 : if (!ActionInstant::init(runOnce)) {
108 0 : return false;
109 : }
110 :
111 21 : _isNeedCleanUp = isNeedCleanUp;
112 21 : return true;
113 : }
114 :
115 21 : void RemoveSelf::update(float time) {
116 21 : _target->removeFromParent(_isNeedCleanUp);
117 21 : }
118 :
119 42 : Place::~Place() { }
120 :
121 21 : bool Place::init(const Vec2 &pos, bool runOnce) {
122 21 : if (!ActionInstant::init(runOnce)) {
123 0 : return false;
124 : }
125 :
126 21 : _position = pos;
127 21 : return true;
128 : }
129 :
130 32 : void Place::update(float time) {
131 32 : _target->setPosition(_position);
132 32 : }
133 :
134 3530 : CallFunc::~CallFunc() { }
135 :
136 1765 : bool CallFunc::init(Function<void()> &&func, bool runOnce) {
137 1765 : if (!ActionInstant::init(runOnce)) {
138 0 : return false;
139 : }
140 :
141 1765 : _callback = move(func);
142 1765 : return true;
143 : }
144 :
145 1744 : void CallFunc::update(float time) {
146 1744 : _callback();
147 1744 : }
148 :
149 : SP_COVERAGE_TRIVIAL
150 : ActionInterval::~ActionInterval() { }
151 :
152 10997 : bool ActionInterval::init(float duration) {
153 10997 : _duration = duration;
154 :
155 : // prevent division by 0
156 : // This comparison could be in step:, but it might decrease the performance
157 : // by 3% in heavy based action games.
158 10997 : _duration = std::max(_duration, FLT_EPSILON);
159 10997 : if (_duration == 0) {
160 0 : _duration = FLT_EPSILON;
161 : }
162 :
163 10997 : _elapsed = 0;
164 10997 : _firstTick = true;
165 10997 : return true;
166 : }
167 :
168 13641 : void ActionInterval::stop() {
169 13641 : _elapsed = _duration;
170 13641 : Action::stop();
171 13641 : }
172 :
173 92329 : bool ActionInterval::isDone() const {
174 92329 : return _elapsed >= _duration;
175 : }
176 :
177 50513 : void ActionInterval::step(float dt) {
178 50513 : if (_firstTick) {
179 4057 : _firstTick = false;
180 4057 : _elapsed = 0;
181 : } else {
182 46456 : _elapsed += dt;
183 : }
184 :
185 50513 : this->update(math::clamp(_elapsed / _duration, 0.0f, 1.0f));
186 50513 : }
187 :
188 11068 : void ActionInterval::startWithTarget(Node *target) {
189 11068 : Action::startWithTarget(target);
190 11068 : _elapsed = 0.0f;
191 11068 : _firstTick = true;
192 11068 : }
193 :
194 21 : void ActionInterval::setDuration(float duration) {
195 21 : _duration = std::max(_duration, FLT_EPSILON);
196 21 : }
197 :
198 42 : Speed::~Speed() { }
199 :
200 21 : Speed::Speed() { }
201 :
202 21 : bool Speed::init(Rc<ActionInterval> &&action, float speed) {
203 21 : XLASSERT(action != nullptr, "action must not be NULL");
204 21 : setInnerAction(move(action));
205 21 : _speed = speed;
206 21 : return true;
207 : }
208 :
209 21 : void Speed::setInnerAction(Rc<ActionInterval> &&action) {
210 21 : if (_innerAction != action) {
211 21 : _innerAction = action;
212 : }
213 21 : }
214 :
215 21 : void Speed::startWithTarget(Node *target) {
216 21 : Action::startWithTarget(target);
217 21 : _innerAction->startWithTarget(target);
218 21 : setDuration(_innerAction->getDuration() * _speed);
219 21 : }
220 :
221 21 : void Speed::stop() {
222 21 : _innerAction->stop();
223 21 : Action::stop();
224 21 : }
225 :
226 242 : void Speed::step(float dt) {
227 242 : _innerAction->step(dt * _speed);
228 242 : }
229 :
230 473 : bool Speed::isDone() const {
231 473 : return _innerAction->isDone();
232 : }
233 :
234 4620 : Sequence::~Sequence() { }
235 :
236 2309 : void Sequence::stop(void) {
237 2309 : if (_prevTime < 1.0f && _currentIdx < _actions.size()) {
238 1155 : bool finalizeInstants = false;
239 1155 : auto front = _actions.begin() + _currentIdx;
240 1155 : auto end = _actions.end();
241 :
242 1155 : front->action->stop();
243 1155 : finalizeInstants = (_prevTime - std::numeric_limits<float>::epsilon()) >= front->maxThreshold;
244 1155 : ++ front;
245 1155 : ++ _currentIdx;
246 :
247 1155 : if (finalizeInstants) {
248 0 : while (front != end && front->threshold <= std::numeric_limits<float>::epsilon()) {
249 0 : front->action->startWithTarget(_target);
250 0 : front->action->update(1.0);
251 0 : front->action->stop();
252 :
253 0 : ++ front;
254 0 : ++ _currentIdx;
255 : }
256 : }
257 :
258 : // do not update any non-instant actions, just start-stop
259 2289 : while (front != end) {
260 1134 : front->action->startWithTarget(_target);
261 1134 : front->action->stop();
262 :
263 1134 : ++ front;
264 1134 : ++ _currentIdx;
265 : }
266 :
267 1155 : _prevTime = 1.0f;
268 : }
269 2309 : ActionInterval::stop();
270 2309 : }
271 :
272 24115 : void Sequence::update(float t) {
273 24115 : auto front = _actions.begin() + _currentIdx;
274 24115 : auto end = _actions.end();
275 :
276 24115 : auto dt = t - _prevTime;
277 :
278 : // assume monotonical progress
279 :
280 25884 : while (front != end && dt != 0) {
281 : // process instants
282 23036 : if (front->threshold <= std::numeric_limits<float>::epsilon()) {
283 : do {
284 684 : front->action->startWithTarget(_target);
285 684 : front->action->update(1.0);
286 684 : front->action->stop();
287 :
288 684 : ++ front;
289 684 : ++ _currentIdx;
290 684 : } while (front != end && front->threshold == 0.0f);
291 :
292 : // start next non-instant
293 684 : if (front == end) {
294 69 : _prevTime = t;
295 115 : return;
296 : } else {
297 615 : front->action->startWithTarget(_target);
298 615 : front->action->update(0.0);
299 : }
300 : }
301 :
302 22967 : auto timeFromActionStart = t - front->minThreshold;
303 22967 : auto actionRelativeTime = timeFromActionStart / front->threshold;
304 :
305 22967 : if (actionRelativeTime >= 1.0f - std::numeric_limits<float>::epsilon() || t == 1.0f) {
306 1815 : front->action->update(1.0f);
307 1815 : dt = t - front->maxThreshold;
308 1815 : front->action->stop();
309 :
310 1815 : ++ front;
311 1815 : ++ _currentIdx;
312 :
313 : // start next non-instant
314 1815 : if (front == end) {
315 46 : _prevTime = t;
316 46 : return;
317 1769 : } else if (front->threshold > std::numeric_limits<float>::epsilon()) {
318 46 : front->action->startWithTarget(_target);
319 46 : front->action->update(0.0);
320 : }
321 : } else {
322 21152 : front->action->update(actionRelativeTime);
323 21152 : dt = 0.0f;
324 21152 : break;
325 : }
326 : }
327 :
328 24000 : auto tmp = front;
329 25039 : while (front != end && front->threshold <= std::numeric_limits<float>::epsilon()) {
330 1039 : front->action->startWithTarget(_target);
331 1039 : front->action->update(1.0);
332 1039 : front->action->stop();
333 :
334 1039 : ++ front;
335 1039 : ++ _currentIdx;
336 : }
337 :
338 24000 : if (front != end && tmp != front) {
339 0 : front->action->startWithTarget(_target);
340 0 : front->action->update(0.0);
341 : }
342 :
343 24000 : _prevTime = t;
344 : }
345 :
346 2309 : void Sequence::startWithTarget(Node *target) {
347 2309 : ActionInterval::startWithTarget(target);
348 2309 : float threshold = 0.0f;
349 8178 : for (auto &it : _actions) {
350 5869 : it.minThreshold = threshold;
351 5869 : it.threshold = it.action->getDuration() / _duration;
352 5869 : threshold += it.threshold;
353 5869 : it.maxThreshold = threshold;
354 : }
355 :
356 : // start first action if it's not instant
357 2309 : if (_actions.front().threshold != 0.0f) {
358 2309 : _actions.front().action->startWithTarget(_target);
359 : }
360 :
361 2309 : _prevTime = 0.0f;
362 2309 : _currentIdx = 0;
363 2309 : }
364 :
365 2310 : bool Sequence::reserve(size_t s) {
366 2310 : _actions.reserve(s);
367 2310 : return true;
368 : }
369 :
370 1744 : bool Sequence::addAction(Function<void()> &&cb) {
371 1744 : auto a = Rc<CallFunc>::create(move(cb));
372 3488 : return addAction(a.get());
373 1744 : }
374 :
375 2879 : bool Sequence::addAction(float time) {
376 2879 : auto a = Rc<DelayTime>::create(time);
377 5758 : return addAction(a.get());
378 2879 : }
379 :
380 21 : bool Sequence::addAction(TimeInterval ival) {
381 21 : auto a = Rc<DelayTime>::create(ival.toFloatSeconds());
382 42 : return addAction(a.get());
383 21 : }
384 :
385 5871 : bool Sequence::addAction(Action *a) {
386 5871 : _duration += a->getDuration();
387 5871 : _actions.emplace_back(ActionData{a});
388 5871 : return true;
389 : }
390 :
391 58 : Spawn::~Spawn() { }
392 :
393 39 : void Spawn::stop(void) {
394 39 : if (_prevTime < 1.0f) {
395 150 : for (auto &it : _actions) {
396 123 : if (it.threshold >= _prevTime) {
397 96 : it.action->stop();
398 : }
399 : }
400 27 : _prevTime = 1.0f;
401 : }
402 39 : ActionInterval::stop();
403 39 : }
404 :
405 366 : void Spawn::update(float t) {
406 2032 : for (auto &it : _actions) {
407 1666 : if (t >= it.threshold && _prevTime < it.threshold) {
408 33 : it.action->update(1.0f);
409 33 : it.action->stop();
410 1633 : } else if (t < it.threshold) {
411 1320 : it.action->update( t * it.threshold );
412 : }
413 : }
414 :
415 366 : _prevTime = t;
416 366 : }
417 :
418 29 : void Spawn::startWithTarget(Node *target) {
419 29 : ActionInterval::startWithTarget(target);
420 158 : for (auto &it : _actions) {
421 129 : it.threshold = it.action->getDuration() / _duration - std::numeric_limits<float>::epsilon();
422 129 : it.action->startWithTarget(target);
423 : }
424 :
425 29 : _prevTime = - std::numeric_limits<float>::epsilon() * 2;
426 29 : }
427 :
428 29 : bool Spawn::reserve(size_t s) {
429 29 : _actions.reserve(s);
430 29 : return true;
431 : }
432 :
433 21 : bool Spawn::addAction(Function<void()> &&cb) {
434 21 : auto a = Rc<CallFunc>::create(move(cb));
435 42 : return addAction(a.get());
436 21 : }
437 :
438 21 : bool Spawn::addAction(float time) {
439 21 : auto a = Rc<DelayTime>::create(time);
440 42 : return addAction(a.get());
441 21 : }
442 :
443 129 : bool Spawn::addAction(Action *a) {
444 129 : _duration = std::max(_duration, a->getDuration());
445 129 : _actions.emplace_back(ActionData{a});
446 129 : return true;
447 : }
448 :
449 : SP_COVERAGE_TRIVIAL
450 : Repeat::~Repeat() {
451 : _innerAction = nullptr;
452 : }
453 :
454 21 : bool Repeat::init(Rc<ActionInterval> &&action, uint32_t times) {
455 21 : float d = action->getDuration() * times;
456 :
457 21 : if (ActionInterval::init(d)) {
458 21 : _times = times;
459 21 : setInnerAction(move(action));
460 21 : _actionInstant = dynamic_cast<ActionInstant *>(action.get()) ? true : false;
461 21 : if (_actionInstant) {
462 0 : _times -= 1;
463 : }
464 21 : _total = 0;
465 21 : return true;
466 : }
467 :
468 0 : return false;
469 : }
470 :
471 21 : void Repeat::setInnerAction(Rc<ActionInterval> &&action) {
472 21 : if (_innerAction != action) {
473 21 : _innerAction = move(action);
474 : }
475 21 : }
476 :
477 1333 : void Repeat::stop() {
478 1333 : _innerAction->stop();
479 1333 : ActionInterval::stop();
480 1333 : }
481 :
482 242 : void Repeat::update(float dt) {
483 242 : if (dt >= _nextDt) {
484 42 : while (dt > _nextDt && _total < _times) {
485 21 : _innerAction->update(1.0f);
486 21 : ++ _total;
487 :
488 21 : _innerAction->stop();
489 21 : _innerAction->startWithTarget(_target);
490 21 : _nextDt = _innerAction->getDuration() / _duration * (_total + 1);
491 : }
492 :
493 21 : if (dt >= 1.0f && _total < _times) {
494 0 : ++ _total;
495 : }
496 :
497 : // don't set an instant action back or update it, it has no use because it has no duration
498 21 : if (!_actionInstant) {
499 21 : if (_total == _times) {
500 0 : _innerAction->update(1);
501 0 : _innerAction->stop();
502 : } else {
503 21 : _innerAction->update(dt - (_nextDt - _innerAction->getDuration() / _duration));
504 : }
505 : }
506 : } else {
507 221 : _innerAction->update(fmodf(dt * _times, 1.0f));
508 : }
509 242 : }
510 :
511 21 : void Repeat::startWithTarget(Node *target) {
512 21 : _total = 0;
513 21 : _nextDt = _innerAction->getDuration() / _duration;
514 21 : ActionInterval::startWithTarget(target);
515 21 : _innerAction->startWithTarget(target);
516 21 : }
517 :
518 1796 : bool Repeat::isDone() const {
519 1796 : return _total == _times;
520 : }
521 :
522 : SP_COVERAGE_TRIVIAL
523 : RepeatForever::~RepeatForever() {
524 : _innerAction = nullptr;
525 : }
526 :
527 112 : bool RepeatForever::init(ActionInterval *action) {
528 112 : _innerAction = action;
529 112 : return true;
530 : }
531 :
532 112 : void RepeatForever::startWithTarget(Node *target) {
533 112 : ActionInterval::startWithTarget(target);
534 112 : _innerAction->startWithTarget(target);
535 112 : }
536 :
537 4062 : void RepeatForever::step(float dt) {
538 4062 : _innerAction->step(dt);
539 4062 : if (_innerAction->isDone()) {
540 52 : float diff = _innerAction->getElapsed() - _innerAction->getDuration();
541 52 : if (diff > _innerAction->getDuration()) {
542 0 : diff = fmodf(diff, _innerAction->getDuration());
543 : }
544 52 : _innerAction->startWithTarget(_target);
545 52 : _innerAction->step(0.0f);
546 52 : _innerAction->step(diff);
547 : }
548 4062 : }
549 :
550 8102 : bool RepeatForever::isDone() const {
551 8102 : return false;
552 : }
553 :
554 6178 : DelayTime::~DelayTime() { }
555 :
556 25081 : void DelayTime::update(float time) { }
557 :
558 42 : TintTo::~TintTo() { }
559 :
560 21 : bool TintTo::init(float duration, const Color4F &to, ColorMask mask) {
561 21 : if (!ActionInterval::init(duration)) {
562 0 : return false;
563 : }
564 :
565 21 : _to = to;
566 21 : _mask = mask;
567 :
568 21 : return true;
569 : }
570 :
571 21 : void TintTo::startWithTarget(Node *target) {
572 21 : ActionInterval::startWithTarget(target);
573 21 : if (target) {
574 21 : _from = target->getColor();
575 21 : _to.setUnmasked(_from, _mask);
576 : }
577 21 : }
578 :
579 284 : void TintTo::update(float time) {
580 284 : _target->setColor(progress(_from, _to, time), true);
581 284 : }
582 :
583 855 : bool ActionProgress::init(float duration, UpdateCallback &&update, StartCallback &&start, StopCallback &&stop) {
584 855 : return init(duration, 0.0f, 1.0f, move(update), move(start), move(stop));
585 : }
586 :
587 798 : bool ActionProgress::init(float duration, float targetProgress, UpdateCallback &&update, StartCallback &&start, StopCallback &&stop) {
588 798 : return init(duration, 0.0f, targetProgress, move(update), move(start), move(stop));
589 : }
590 :
591 1674 : bool ActionProgress::init(float duration, float sourceProgress, float targetProgress,
592 : UpdateCallback &&update, StartCallback &&start, StopCallback &&stop) {
593 1674 : if (!ActionInterval::init(duration)) {
594 0 : return false;
595 : }
596 :
597 1674 : _sourceProgress = sourceProgress;
598 1674 : _targetProgress = targetProgress;
599 1674 : _onUpdate = move(update);
600 1674 : _onStart = move(start);
601 1674 : _onStop = move(stop);
602 :
603 1674 : return true;
604 : }
605 :
606 1678 : void ActionProgress::startWithTarget(Node *t) {
607 1678 : ActionInterval::startWithTarget(t);
608 1678 : _stopped = false;
609 1678 : if (_onStart) {
610 721 : _onStart();
611 : }
612 1678 : }
613 :
614 12621 : void ActionProgress::update(float time) {
615 12621 : if (_onUpdate) {
616 12621 : _onUpdate(_sourceProgress + (_targetProgress - _sourceProgress) * time);
617 : }
618 12621 : }
619 :
620 1581 : void ActionProgress::stop() {
621 1581 : if (!_stopped && _onStop) {
622 700 : _onStop();
623 : }
624 1581 : _stopped = true;
625 1581 : ActionInterval::stop();
626 1581 : }
627 :
628 806 : bool MoveTo::init(float duration, const Vec2 &position) {
629 806 : if (!ActionInterval::init(duration)) {
630 0 : return false;
631 : }
632 :
633 806 : _endPosition = Vec3(position.x, position.y, nan());
634 806 : return true;
635 : }
636 :
637 21 : bool MoveTo::init(float duration, const Vec3 &position) {
638 21 : if (!ActionInterval::init(duration)) {
639 0 : return false;
640 : }
641 :
642 21 : _endPosition = position;
643 21 : return true;
644 : }
645 :
646 848 : void MoveTo::startWithTarget(Node *target) {
647 848 : ActionInterval::startWithTarget(target);
648 848 : _startPosition = target->getPosition();
649 848 : if (isnan(_endPosition.z)) {
650 806 : _endPosition.z = _startPosition.z;
651 : }
652 848 : }
653 :
654 8496 : void MoveTo::update(float time) {
655 8496 : _target->setPosition(progress(_startPosition, _endPosition, time));
656 8496 : }
657 :
658 21 : bool ScaleTo::init(float duration, float scale) {
659 21 : if (!ActionInterval::init(duration)) {
660 0 : return false;
661 : }
662 :
663 21 : _endScale = Vec3(scale, scale, scale);
664 21 : return true;
665 : }
666 :
667 21 : bool ScaleTo::init(float duration, const Vec3 &scale) {
668 21 : if (!ActionInterval::init(duration)) {
669 0 : return false;
670 : }
671 :
672 21 : _endScale = scale;
673 21 : return true;
674 : }
675 :
676 63 : void ScaleTo::startWithTarget(Node *target) {
677 63 : ActionInterval::startWithTarget(target);
678 63 : _startScale = target->getScale();
679 63 : }
680 :
681 547 : void ScaleTo::update(float time) {
682 547 : _target->setScale(progress(_startScale, _endScale, time));
683 547 : }
684 :
685 8 : bool ResizeTo::init(float duration, const Size2 &size) {
686 8 : if (!ActionInterval::init(duration)) {
687 0 : return false;
688 : }
689 :
690 8 : _endSize = size;
691 8 : return true;
692 : }
693 :
694 8 : void ResizeTo::startWithTarget(Node *target) {
695 8 : ActionInterval::startWithTarget(target);
696 8 : _startSize = target->getContentSize();
697 8 : }
698 :
699 82 : void ResizeTo::update(float time) {
700 82 : _target->setContentSize(progress(_startSize, _endSize, time));
701 82 : }
702 :
703 1277 : bool FadeTo::init(float duration, float target) {
704 1277 : if (!ActionInterval::init(duration)) {
705 0 : return false;
706 : }
707 :
708 1277 : _endOpacity = target;
709 1277 : return true;
710 : }
711 :
712 1276 : void FadeTo::startWithTarget(Node *target) {
713 1276 : ActionInterval::startWithTarget(target);
714 1276 : _startOpacity = target->getOpacity();
715 1276 : }
716 :
717 1312 : void FadeTo::update(float time) {
718 1312 : _target->setOpacity(progress(_startOpacity, _endOpacity, time));
719 1312 : }
720 :
721 42 : bool RenderContinuously::init() {
722 42 : _innerAction = Rc<RepeatForever>::create(Rc<DelayTime>::create(1.0f));
723 :
724 42 : if (_innerAction) {
725 42 : return ActionInterval::init(_innerAction->getDuration());
726 : }
727 0 : return false;
728 : }
729 :
730 21 : bool RenderContinuously::init(float duration) {
731 21 : _innerAction = Rc<DelayTime>::create(1.0f);
732 :
733 21 : if (_innerAction) {
734 21 : return ActionInterval::init(_innerAction->getDuration());
735 : }
736 0 : return false;
737 : }
738 :
739 1756 : void RenderContinuously::step(float dt) {
740 1756 : ActionInterval::step(dt);
741 1756 : _innerAction->step(dt);
742 1756 : }
743 :
744 63 : void RenderContinuously::startWithTarget(Node *target) {
745 63 : ActionInterval::startWithTarget(target);
746 63 : _innerAction->startWithTarget(target);
747 63 : }
748 :
749 2040 : void RenderContinuously::update(float time) {
750 : // do nothing
751 2040 : }
752 :
753 3521 : bool RenderContinuously::isDone(void) const {
754 3521 : return _innerAction->isDone();
755 : }
756 :
757 51 : void RenderContinuously::stop() {
758 51 : _innerAction->stop();
759 51 : ActionInterval::stop();
760 51 : }
761 :
762 :
763 : }
|