LCOV - code coverage report
Current view: top level - xenolith/scene/actions - XLActionManager.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 145 168 86.3 %
Date: 2024-05-12 00:16:13 Functions: 24 25 96.0 %

          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 "XLActionManager.h"
      25             : #include "XLNode.h"
      26             : 
      27             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      28             : 
      29        3479 : ActionContainer::~ActionContainer() { }
      30             : 
      31        3479 : ActionContainer::ActionContainer(Node *t) : target(t) { }
      32             : 
      33          42 : ActionManager::~ActionManager() {
      34          21 :     removeAllActions();
      35          42 : }
      36             : 
      37          21 : ActionManager::ActionManager() { }
      38             : 
      39          21 : bool ActionManager::init() {
      40          21 :         return true;
      41             : }
      42             : 
      43        7913 : void ActionManager::addAction(Action *action, Node *target, bool paused) {
      44        7913 :         if (_inUpdate) {
      45        2811 :                 _pending.emplace_back(PendingAction{action, target, paused});
      46        2811 :                 return;
      47             :         }
      48             : 
      49        5102 :         XLASSERT(action != nullptr, "");
      50        5102 :         XLASSERT(target != nullptr, "");
      51             : 
      52        5102 :         auto it = _actions.find(target);
      53        5102 :         if (it == _actions.end()) {
      54        3479 :                 it = _actions.emplace(target).first;
      55        3479 :                 it->paused = paused;
      56             :         }
      57             : 
      58        5102 :         action->setContainer(target);
      59        5102 :         it->addItem(action);
      60        5102 :         action->startWithTarget(target);
      61             : }
      62             : 
      63          42 : void ActionManager::removeAllActions() {
      64          42 :         if (_inUpdate) {
      65          21 :                 auto it = _actions.begin();
      66         104 :                 while (it != _actions.end()) {
      67          83 :                         it->foreach([&] (Action *a) {
      68          80 :                                 a->invalidate();
      69          80 :                                 return true;
      70             :                         });
      71          83 :                         ++ it;
      72             :                 }
      73             :         } else {
      74          21 :                 _actions.clear();
      75             :         }
      76          42 : }
      77             : 
      78       69625 : void ActionManager::removeAllActionsFromTarget(Node *target) {
      79       69625 :         if (target == nullptr) {
      80           0 :                 return;
      81             :         }
      82             : 
      83       69625 :         if (_current && _current->target == target) {
      84          21 :                 _current->foreach([&] (Action *a) {
      85          42 :                         a->invalidate();
      86          42 :                         return true;
      87             :                 });
      88             :         } else {
      89       69604 :                 auto it = _actions.find(target);
      90       69604 :                 if (it != _actions.end()) {
      91         362 :                         if (_inUpdate) {
      92         294 :                                 it->foreach([&] (Action *a) {
      93         399 :                                         a->invalidate();
      94         399 :                                         return true;
      95             :                                 });
      96             :                         } else {
      97          68 :                                 _actions.erase(it);
      98             :                         }
      99             :                 }
     100             :         }
     101             : 
     102       69625 :         auto it = _pending.begin();
     103       73973 :         while (it != _pending.end()) {
     104        4348 :                 if (it->target == target) {
     105           0 :                         it = _pending.erase(it);
     106             :                 } else {
     107        4348 :                         ++ it;
     108             :                 }
     109             :         }
     110             : }
     111             : 
     112          21 : void ActionManager::removeAction(Action *action) {
     113          21 :         auto target = action->getContainer();
     114          21 :         if (_current && _current->target == target) {
     115           0 :                 action->invalidate();
     116             :         } else {
     117          21 :                 auto it = _actions.find(target);
     118          21 :                 if (it != _actions.end()) {
     119          21 :                         it->removeItem(action);
     120             :                 }
     121             :         }
     122             : 
     123          21 :         auto it = _pending.begin();
     124          42 :         while (it != _pending.end()) {
     125          21 :                 if (it->action == action) {
     126           0 :                         it = _pending.erase(it);
     127           0 :                         break;
     128             :                 } else {
     129          21 :                         ++ it;
     130             :                 }
     131             :         }
     132          21 : }
     133             : 
     134        2499 : void ActionManager::removeActionByTag(uint32_t tag, Node *target) {
     135        2499 :         if (_current && _current->target == target) {
     136           0 :                 if (_current->invalidateItemByTag(tag)) {
     137        1904 :                         return;
     138             :                 }
     139             :         } else {
     140        2499 :                 auto it = _actions.find(target);
     141        2499 :                 if (it != _actions.end()) {
     142        2115 :                         if (it->removeItemByTag(tag)) {
     143        1904 :                                 return;
     144             :                         }
     145             :                 }
     146             :         }
     147             : 
     148         595 :         auto it = _pending.begin();
     149         620 :         while (it != _pending.end()) {
     150          26 :                 if (it->target == target && it->action->getTag() == tag) {
     151           1 :                         it = _pending.erase(it);
     152           1 :                         break;
     153             :                 } else {
     154          25 :                         ++ it;
     155             :                 }
     156             :         }
     157             : }
     158             : 
     159         996 : void ActionManager::removeAllActionsByTag(uint32_t tag, Node *target) {
     160         996 :         if (_current && _current->target == target) {
     161           0 :                 _current->invalidateAllItemsByTag(tag);
     162             :         } else {
     163         996 :                 auto it = _actions.find(target);
     164         996 :                 if (it != _actions.end()) {
     165          70 :                         it->removeAllItemsByTag(tag);
     166             :                 }
     167             :         }
     168             : 
     169         996 :         auto it = _pending.begin();
     170         996 :         while (it != _pending.end()) {
     171           0 :                 if (it->target == target && it->action->getTag() == tag) {
     172           0 :                         it = _pending.erase(it);
     173             :                 } else {
     174           0 :                         ++ it;
     175             :                 }
     176             :         }
     177         996 : }
     178             : 
     179        1506 : Action *ActionManager::getActionByTag(uint32_t tag, const Node *target) const {
     180        1506 :         if (_current && _current->target == target) {
     181           0 :                 return _current->getItemByTag(tag);
     182             :         } else {
     183        1506 :                 auto it = _actions.find(target);
     184        1506 :                 if (it != _actions.end()) {
     185         167 :                         return it->getItemByTag(tag);
     186             :                 }
     187             :         }
     188             : 
     189        1339 :         auto it = _pending.begin();
     190        1339 :         while (it != _pending.end()) {
     191           0 :                 if (it->target == target && it->action->getTag() == tag) {
     192           0 :                         return it->action;
     193             :                 } else {
     194           0 :                         ++ it;
     195             :                 }
     196             :         }
     197             : 
     198        1339 :         return nullptr;
     199             : }
     200             : 
     201          21 : size_t ActionManager::getNumberOfRunningActionsInTarget(const Node *target) const {
     202          21 :         size_t pending = 0;
     203             : 
     204          21 :         auto it = _pending.begin();
     205          21 :         while (it != _pending.end()) {
     206           0 :                 if (it->target == target) {
     207           0 :                         ++ pending;
     208             :                 }
     209           0 :                 ++ it;
     210             :         }
     211             : 
     212          21 :         if (_current && _current->target == target) {
     213          21 :                 return _current->size() + pending;
     214             :         } else {
     215           0 :                 auto it = _actions.find(target);
     216           0 :                 if (it != _actions.end()) {
     217           0 :                         return it->size() + pending;
     218             :                 }
     219             :         }
     220           0 :         return 0;
     221             : }
     222             : 
     223         126 : void ActionManager::pauseTarget(Node *target) {
     224         126 :         auto it = _actions.find(target);
     225         126 :         if (it != _actions.end()) {
     226          42 :                 it->paused = true;
     227             :         }
     228         126 : }
     229             : 
     230          21 : void ActionManager::resumeTarget(Node *target) {
     231          21 :         auto it = _actions.find(target);
     232          21 :         if (it != _actions.end()) {
     233          21 :                 it->paused = false;
     234             :         }
     235          21 : }
     236             : 
     237          21 : Vector<Node *> ActionManager::pauseAllRunningActions() {
     238          21 :         Vector<Node *> ret;
     239         141 :         for (auto &it : _actions) {
     240         120 :                 it.paused = true;
     241         120 :                 ret.emplace_back(it.target);
     242             :         }
     243          21 :         return ret;
     244           0 : }
     245             : 
     246          21 : void ActionManager::resumeTargets(const Vector<Node*> &targetsToResume) {
     247         141 :         for (auto &target : targetsToResume) {
     248         120 :                 auto it = _actions.find(target);
     249         120 :                 if (it != _actions.end()) {
     250         120 :                         it->paused = false;
     251             :                 }
     252             :         }
     253          21 : }
     254             : 
     255             : /** Main loop of ActionManager. */
     256        9538 : void ActionManager::update(const UpdateTime &time) {
     257        9538 :         float dt = float(time.delta) / 1'000'000.0f;
     258        9538 :         _inUpdate = true;
     259        9538 :         auto it = _actions.begin();
     260       53597 :         while (it != _actions.end()) {
     261       44059 :                 _current = &(*it);
     262       44059 :                 _current->foreach([&] (Action *a) {
     263       50694 :                         if (a->getTarget()) {
     264       49170 :                                 a->step(dt);
     265       49170 :                                 if (a->isDone()) {
     266        2586 :                                         a->stop();
     267             :                                 }
     268             :                         } else {
     269        1524 :                                 a->stop();
     270             :                         }
     271       50694 :                         return true;
     272             :                 });
     273       44059 :                 _current = nullptr;
     274       44059 :                 ++ it;
     275             :         }
     276        9538 :         _inUpdate = false;
     277             : 
     278        9538 :         it = _actions.begin();
     279       53597 :         while (it != _actions.end()) {
     280       44059 :                 if (it->cleanup()) {
     281        3345 :                         auto iit = _actions.find(it->target);
     282        3345 :                         if (iit != _actions.end()) {
     283        3345 :                                 it = _actions.erase(it);
     284             :                         } else {
     285           0 :                                 log::debug("ActionManager", "update: ", time.app, " erase: ", (void *)it->target.get());
     286             :                         }
     287             :                 } else {
     288       40714 :                         ++ it;
     289             :                 }
     290             :         }
     291             : 
     292       12348 :         for (auto &it : _pending) {
     293        2810 :                 addAction(it.action, it.target, it.paused);
     294             :         }
     295        9538 :         _pending.clear();
     296        9538 : }
     297             : 
     298        9538 : bool ActionManager::empty() const {
     299        9538 :         return _actions.empty() && _pending.empty();
     300             : }
     301             : 
     302             : }

Generated by: LCOV version 1.14