LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d - XL2dSceneContent.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 180 392 45.9 %
Date: 2024-05-12 00:16:13 Functions: 22 45 48.9 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XL2dSceneContent.h"
      24             : #include "XL2dScene.h"
      25             : #include "XL2dFrameContext.h"
      26             : #include "XL2dSceneLayout.h"
      27             : #include "XL2dSceneLight.h"
      28             : #include "XLDirector.h"
      29             : #include "XLView.h"
      30             : #include "XLFrameInfo.h"
      31             : 
      32             : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
      33             : 
      34          10 : SceneContent2d::~SceneContent2d() { }
      35             : 
      36          10 : bool SceneContent2d::init() {
      37          10 :         if (!SceneContent::init()) {
      38           0 :                 return false;
      39             :         }
      40             : 
      41          10 :         _2dContext = Rc<FrameContext2d>::create();
      42          10 :         _frameContext = _2dContext;
      43             : 
      44          10 :         return true;
      45             : }
      46             : 
      47          10 : void SceneContent2d::onEnter(Scene *scene) {
      48          10 :         SceneContent::onEnter(scene);
      49             : 
      50          30 :         for (auto &it : _lights) {
      51          20 :                 it->onEnter(scene);
      52             :         }
      53          10 : }
      54             : 
      55          10 : void SceneContent2d::onExit() {
      56          30 :         for (auto &it : _lights) {
      57          20 :                 it->onExit();
      58             :         }
      59             : 
      60          10 :         SceneContent::onExit();
      61          10 : }
      62             : 
      63          20 : void SceneContent2d::onContentSizeDirty() {
      64          20 :         SceneContent::onContentSizeDirty();
      65             : 
      66          96 :         for (auto &node : _layouts) {
      67          76 :                 updateLayoutNode(node);
      68             :         }
      69             : 
      70          20 :         for (auto &overlay : _overlays) {
      71           0 :                 updateLayoutNode(overlay);
      72             :         }
      73          20 : }
      74             : 
      75           0 : void SceneContent2d::replaceLayout(SceneLayout2d *node) {
      76           0 :         if (!node || node->isRunning()) {
      77           0 :                 return;
      78             :         }
      79             : 
      80           0 :         if (_layouts.empty()) {
      81           0 :                 pushLayout(node);
      82           0 :                 return;
      83             :         }
      84             : 
      85           0 :         updateLayoutNode(node);
      86             : 
      87           0 :         ZOrder zIndex = -ZOrder(_layouts.size()) - ZOrder(2);
      88           0 :         for (auto n : _layouts) {
      89           0 :                 n->setLocalZOrder(zIndex);
      90           0 :                 zIndex ++;
      91           0 :         }
      92             : 
      93           0 :         _layouts.push_back(node);
      94           0 :         addChild(node, zIndex);
      95             : 
      96           0 :         for (auto &it : _layouts) {
      97           0 :                 if (it != node) {
      98           0 :                         it->onPopTransitionBegan(this, true);
      99             :                 } else {
     100           0 :                         it->onPush(this, true);
     101             :                 }
     102             :         }
     103             : 
     104           0 :         auto fn = [this, node] {
     105           0 :                 for (auto &it : _layouts) {
     106           0 :                         if (it != node) {
     107           0 :                                 it->onPop(this, true);
     108             :                         } else {
     109           0 :                                 it->onPushTransitionEnded(this, true);
     110             :                         }
     111             :                 }
     112           0 :                 replaceNodes();
     113           0 :                 updateBackButtonStatus();
     114           0 :         };
     115             : 
     116           0 :         if (auto enter = node->makeEnterTransition(this)) {
     117           0 :                 node->runAction(Rc<Sequence>::create(enter, fn));
     118             :         } else {
     119           0 :                 fn();
     120           0 :         }
     121             : }
     122             : 
     123         136 : void SceneContent2d::pushLayout(SceneLayout2d *node) {
     124         136 :         if (!node || node->isRunning()) {
     125           0 :                 return;
     126             :         }
     127             : 
     128         136 :         updateLayoutNode(node);
     129         136 :         pushNodeInternal(node, nullptr);
     130             : }
     131             : 
     132           0 : void SceneContent2d::replaceTopLayout(SceneLayout2d *node) {
     133           0 :         if (!node || node->isRunning()) {
     134           0 :                 return;
     135             :         }
     136             : 
     137           0 :         if (!_layouts.empty()) {
     138           0 :                 auto back = _layouts.back();
     139           0 :                 _layouts.pop_back();
     140           0 :                 back->onPopTransitionBegan(this, false);
     141             : 
     142             :                 // just push node, then silently remove previous
     143             : 
     144           0 :                 pushNodeInternal(node, [this, back] {
     145           0 :                         eraseLayout(back);
     146           0 :                         back->onPop(this, false);
     147           0 :                 });
     148           0 :         }
     149             : }
     150             : 
     151          10 : void SceneContent2d::popLayout(SceneLayout2d *node) {
     152          10 :         auto it = std::find(_layouts.begin(), _layouts.end(), node);
     153          10 :         if (it == _layouts.end()) {
     154           0 :                 return;
     155             :         }
     156             : 
     157          10 :         auto linkId = node->retain();
     158          10 :         _layouts.erase(it);
     159             : 
     160          10 :         node->onPopTransitionBegan(this, false);
     161          10 :         if (!_layouts.empty()) {
     162          10 :                 _layouts.back()->onForegroundTransitionBegan(this, node);
     163             :         }
     164             : 
     165          60 :         auto fn = [this, node, linkId] {
     166          10 :                 eraseLayout(node);
     167          10 :                 node->onPop(this, false);
     168          10 :                 if (!_layouts.empty()) {
     169          10 :                         _layouts.back()->onForeground(this, node);
     170             :                 }
     171          10 :                 node->release(linkId);
     172          20 :         };
     173             : 
     174          10 :         if (auto exit = node->makeExitTransition(this)) {
     175           0 :                 node->runAction(Rc<Sequence>::create(move(exit), fn));
     176             :         } else {
     177          10 :                 fn();
     178          10 :         }
     179             : }
     180             : 
     181         136 : void SceneContent2d::pushNodeInternal(SceneLayout2d *node, Function<void()> &&cb) {
     182         136 :         if (!_layouts.empty()) {
     183         126 :                 ZOrder zIndex = -ZOrder(_layouts.size()) - ZOrder(2);
     184         916 :                 for (auto &n : _layouts) {
     185         790 :                         n->setLocalZOrder(zIndex);
     186         790 :                         zIndex ++;
     187             :                 }
     188             :         }
     189             : 
     190         136 :         _layouts.push_back(node);
     191             : 
     192         136 :         updateLayoutNode(node);
     193         136 :         addChild(node, ZOrder(-1));
     194             : 
     195         136 :         if (_layouts.size() > 1) {
     196         126 :                 _layouts.at(_layouts.size() - 2)->onBackground(this, node);
     197             :         }
     198         136 :         node->onPush(this, false);
     199             : 
     200         932 :         auto fn = [this, node, cb = move(cb)] {
     201         136 :                 updateNodesVisibility();
     202         136 :                 updateBackButtonStatus();
     203         136 :                 if (_layouts.size() > 1) {
     204         126 :                         _layouts.at(_layouts.size() - 2)->onBackgroundTransitionEnded(this, node);
     205             :                 }
     206         136 :                 node->onPushTransitionEnded(this, false);
     207         136 :                 if (cb) {
     208           0 :                         cb();
     209             :                 }
     210         136 :         };
     211             : 
     212         136 :         if (auto enter = node->makeEnterTransition(this)) {
     213           0 :                 node->runAction(Rc<Sequence>::create(move(enter), move(fn)));
     214             :         } else {
     215         136 :                 fn();
     216         136 :         }
     217         136 : }
     218             : 
     219          10 : void SceneContent2d::eraseLayout(SceneLayout2d *node) {
     220          10 :         node->removeFromParent();
     221          10 :         if (!_layouts.empty()) {
     222          10 :                 ZOrder zIndex = -ZOrder(_layouts.size()) - ZOrder(2);
     223          66 :                 for (auto n : _layouts) {
     224          56 :                         n->setLocalZOrder(zIndex);
     225          56 :                         n->setVisible(false);
     226          56 :                         zIndex ++;
     227          56 :                 }
     228          10 :                 updateNodesVisibility();
     229             :         }
     230          10 :         updateBackButtonStatus();
     231          10 : }
     232             : 
     233           0 : void SceneContent2d::eraseOverlay(SceneLayout2d *l) {
     234           0 :         l->removeFromParent();
     235           0 :         if (!_overlays.empty()) {
     236           0 :                 ZOrder zIndex = ZOrder(1);
     237           0 :                 for (auto n : _overlays) {
     238           0 :                         n->setLocalZOrder(zIndex);
     239           0 :                         zIndex ++;
     240           0 :                 }
     241           0 :                 updateNodesVisibility();
     242             :         }
     243           0 :         updateBackButtonStatus();
     244           0 : }
     245             : 
     246           0 : void SceneContent2d::replaceNodes() {
     247           0 :         if (!_layouts.empty()) {
     248           0 :                 auto vec = _layouts;
     249           0 :                 for (auto &node : vec) {
     250           0 :                         if (node != _layouts.back()) {
     251           0 :                                 node->removeFromParent();
     252             :                         }
     253             :                 }
     254             : 
     255           0 :                 _layouts.erase(_layouts.begin(), _layouts.begin() + _layouts.size() - 1);
     256           0 :         }
     257           0 : }
     258             : 
     259         146 : void SceneContent2d::updateNodesVisibility() {
     260        1128 :         for (size_t i = 0; i < _layouts.size(); i++) {
     261         982 :                 if (i == _layouts.size() - 1) {
     262         146 :                         _layouts.at(i)->setVisible(true);
     263             :                 } else {
     264         836 :                         _layouts.at(i)->setVisible(false);
     265             :                 }
     266             :         }
     267             : 
     268         146 :         if (!_layouts.empty()) {
     269         146 :                 auto status = _layouts.back()->getDecorationStatus();
     270         146 :                 switch (status) {
     271          94 :                 case DecorationStatus::DontCare:
     272          94 :                         break;
     273          52 :                 case DecorationStatus::Visible:
     274          52 :                         showViewDecoration();
     275          52 :                         break;
     276           0 :                 case DecorationStatus::Hidden:
     277           0 :                         hideViewDecoration();
     278           0 :                         break;
     279             :                 }
     280             :         }
     281         146 : }
     282             : 
     283         146 : void SceneContent2d::updateBackButtonStatus() {
     284         146 :         if (!_overlays.empty() || _layouts.size() > 1 || _layouts.back()->hasBackButtonAction()) {
     285         136 :                 if (!_retainBackButton) {
     286          10 :                         _retainBackButton = true;
     287          10 :                         if (_director && !_backButtonRetained) {
     288          10 :                                 _director->getView()->retainBackButton();
     289          10 :                                 _backButtonRetained = true;
     290             :                         }
     291             :                 }
     292             :         } else {
     293          10 :                 _retainBackButton = false;
     294          10 :                 if (_director && _backButtonRetained) {
     295           0 :                         _director->getView()->releaseBackButton();
     296           0 :                         _backButtonRetained = false;
     297             :                 }
     298             :         }
     299         146 : }
     300             : 
     301          10 : SceneLayout2d *SceneContent2d::getTopLayout() {
     302          10 :         if (!_layouts.empty()) {
     303          10 :                 return _layouts.back();
     304             :         } else {
     305           0 :                 return nullptr;
     306             :         }
     307             : }
     308             : 
     309          10 : SceneLayout2d *SceneContent2d::getPrevLayout() {
     310          10 :         if (_layouts.size() > 1) {
     311          10 :                 return *(_layouts.end() - 2);
     312             :         }
     313           0 :         return nullptr;
     314             : }
     315             : 
     316           0 : bool SceneContent2d::popTopLayout() {
     317           0 :         if (!_overlays.empty()) {
     318           0 :                 popOverlay(_overlays.back());
     319           0 :                 return true;
     320             :         }
     321           0 :         if (_layouts.size() > 1) {
     322           0 :                 popLayout(_layouts.back());
     323           0 :                 return true;
     324             :         }
     325           0 :         return false;
     326             : }
     327             : 
     328           0 : bool SceneContent2d::isActive() const {
     329           0 :         return !_layouts.empty();
     330             : }
     331             : 
     332          10 : bool SceneContent2d::onBackButton() {
     333          10 :         if (_layouts.empty()) {
     334           0 :                 return false;
     335             :         } else {
     336          10 :                 if (!_overlays.empty()) {
     337           0 :                         if (!_overlays.back()->onBackButton()) {
     338           0 :                                 if (!popTopLayout()) {
     339           0 :                                         return false;
     340             :                                 } else {
     341           0 :                                         return true;
     342             :                                 }
     343             :                         } else {
     344           0 :                                 return true;
     345             :                         }
     346             :                 }
     347          10 :                 if (!_layouts.back()->onBackButton()) {
     348           0 :                         if (!popTopLayout()) {
     349           0 :                                 return false;
     350             :                         }
     351             :                 }
     352          10 :                 return true;
     353             :         }
     354             : }
     355             : 
     356          10 : size_t SceneContent2d::getLayoutsCount() const {
     357          10 :         return _layouts.size();
     358             : }
     359             : 
     360           0 : const Vector<Rc<SceneLayout2d>> &SceneContent2d::getLayouts() const {
     361           0 :         return _layouts;
     362             : }
     363             : 
     364           0 : const Vector<Rc<SceneLayout2d>> &SceneContent2d::getOverlays() const {
     365           0 :         return _overlays;
     366             : }
     367             : 
     368           0 : bool SceneContent2d::pushOverlay(SceneLayout2d *l) {
     369           0 :         if (!l || l->isRunning()) {
     370           0 :                 return false;
     371             :         }
     372             : 
     373           0 :         updateLayoutNode(l);
     374             : 
     375           0 :         ZOrder zIndex = ZOrder(_overlays.size() + 1);
     376             : 
     377           0 :         _overlays.push_back(l);
     378             : 
     379           0 :         addChild(l, zIndex);
     380             : 
     381           0 :         l->onPush(this, false);
     382             : 
     383           0 :         auto fn = [this, l] {
     384           0 :                 l->onPushTransitionEnded(this, false);
     385           0 :                 updateBackButtonStatus();
     386           0 :         };
     387             : 
     388           0 :         if (auto enter = l->makeEnterTransition(this)) {
     389           0 :                 l->runAction(Rc<Sequence>::create(move(enter), move(fn)), "ContentLayer.Transition"_tag);
     390             :         } else {
     391           0 :                 fn();
     392           0 :         }
     393             : 
     394           0 :         return true;
     395             : }
     396             : 
     397           0 : bool SceneContent2d::popOverlay(SceneLayout2d *l) {
     398           0 :         auto it = std::find(_overlays.begin(), _overlays.end(), l);
     399           0 :         if (it == _overlays.end()) {
     400           0 :                 return false;
     401             :         }
     402             : 
     403           0 :         auto linkId = l->retain();
     404           0 :         _overlays.erase(it);
     405           0 :         l->onPopTransitionBegan(this, false);
     406             : 
     407           0 :         auto fn = [this, l, linkId] {
     408           0 :                 eraseOverlay(l);
     409           0 :                 l->onPop(this, false);
     410           0 :                 l->release(linkId);
     411           0 :                 updateBackButtonStatus();
     412           0 :         };
     413             : 
     414           0 :         if (auto exit = l->makeExitTransition(this)) {
     415           0 :                 l->runAction(Rc<Sequence>::create(move(exit), move(fn)));
     416             :         } else {
     417           0 :                 fn();
     418           0 :         }
     419             : 
     420           0 :         return true;
     421             : }
     422             : 
     423         348 : void SceneContent2d::updateLayoutNode(SceneLayout2d *node) {
     424         348 :         auto mask = node->getDecodationMask();
     425             : 
     426         348 :         Vec2 pos = Vec2::ZERO;
     427         348 :         Size2 size = _contentSize;
     428         348 :         Padding effectiveDecorations;
     429             : 
     430         348 :         if (node->getTargetContentSize() != Size2::ZERO) {
     431           0 :                 size.width = std::min(size.width, node->getTargetContentSize().width);
     432           0 :                 size.height = std::min(size.height, node->getTargetContentSize().height);
     433             :         }
     434             : 
     435         348 :         if ((mask & DecorationMask::Top) != DecorationMask::None) {
     436         116 :                 size.height += _decorationPadding.top;
     437         116 :                 effectiveDecorations.top = _decorationPadding.top;
     438             :         }
     439         348 :         if ((mask & DecorationMask::Right) != DecorationMask::None) {
     440         116 :                 size.width += _decorationPadding.right;
     441         116 :                 effectiveDecorations.right = _decorationPadding.right;
     442             :         }
     443         348 :         if ((mask & DecorationMask::Left) != DecorationMask::None) {
     444         116 :                 size.width += _decorationPadding.left;
     445         116 :                 pos.x -= _decorationPadding.left;
     446         116 :                 effectiveDecorations.left = _decorationPadding.left;
     447             :         }
     448         348 :         if ((mask & DecorationMask::Bottom) != DecorationMask::None) {
     449         116 :                 size.height += _decorationPadding.bottom;
     450         116 :                 pos.y -= _decorationPadding.bottom;
     451         116 :                 effectiveDecorations.bottom = _decorationPadding.bottom;
     452             :         }
     453             : 
     454         348 :         node->setAnchorPoint(Anchor::BottomLeft);
     455         348 :         node->setDecorationPadding(effectiveDecorations);
     456         348 :         node->setPosition(pos);
     457         348 :         node->setContentSize(size);
     458         348 : }
     459             : 
     460          20 : bool SceneContent2d::addLight(SceneLight *light, uint64_t tag, StringView name) {
     461          20 :         if (tag != InvalidTag) {
     462           0 :                 if (_lightsByTag.find(tag) != _lightsByTag.end()) {
     463           0 :                         log::warn("Scene", "Light with tag ", tag, " is already defined");
     464           0 :                         return false;
     465             :                 }
     466             :         }
     467          20 :         if (!name.empty()) {
     468           0 :                 if (_lightsByName.find(name) != _lightsByName.end()) {
     469           0 :                         log::warn("Scene", "Light with name ", name, " is already defined");
     470           0 :                         return false;
     471             :                 }
     472             :         }
     473             : 
     474          20 :         if (light->getScene()) {
     475           0 :                 log::warn("Scene", "Light is already on scene");
     476           0 :                 return false;
     477             :         }
     478             : 
     479          20 :         switch (light->getType()) {
     480          20 :         case SceneLightType::Ambient:
     481          20 :                 if (_lightsAmbientCount >= config::MaxAmbientLights) {
     482           0 :                         log::warn("Scene", "Too many ambient lights");
     483           0 :                         return false;
     484             :                 }
     485          20 :                 break;
     486           0 :         case SceneLightType::Direct:
     487           0 :                 if (_lightsDirectCount >= config::MaxDirectLights) {
     488           0 :                         log::warn("Scene", "Too many direct lights");
     489           0 :                         return false;
     490             :                 }
     491           0 :                 break;
     492             :         }
     493             : 
     494          20 :         _lights.emplace_back(light);
     495             : 
     496          20 :         switch (light->getType()) {
     497          20 :         case SceneLightType::Ambient: ++ _lightsAmbientCount; break;
     498           0 :         case SceneLightType::Direct: ++ _lightsDirectCount; break;
     499             :         }
     500             : 
     501          20 :         if (tag != InvalidTag) {
     502           0 :                 light->setTag(tag);
     503           0 :                 _lightsByTag.emplace(tag, light);
     504             :         }
     505             : 
     506          20 :         if (!name.empty()) {
     507           0 :                 light->setName(name);
     508           0 :                 _lightsByName.emplace(light->getName(), light);
     509             :         }
     510             : 
     511          20 :         if (_running) {
     512           0 :                 light->onEnter(_scene);
     513             :         } else {
     514          20 :                 light->_scene = _scene;
     515             :         }
     516             : 
     517          20 :         return true;
     518             : }
     519             : 
     520           0 : SceneLight *SceneContent2d::getLightByTag(uint64_t tag) const {
     521           0 :         auto it = _lightsByTag.find(tag);
     522           0 :         if (it != _lightsByTag.end()) {
     523           0 :                 return it->second;
     524             :         }
     525           0 :         return nullptr;
     526             : }
     527             : 
     528           0 : SceneLight *SceneContent2d::getLightByName(StringView name) const {
     529           0 :         auto it = _lightsByName.find(name);
     530           0 :         if (it != _lightsByName.end()) {
     531           0 :                 return it->second;
     532             :         }
     533           0 :         return nullptr;
     534             : }
     535             : 
     536           0 : void SceneContent2d::removeLight(SceneLight *light) {
     537           0 :         if (light->getScene() != _scene) {
     538           0 :                 return;
     539             :         }
     540             : 
     541           0 :         auto it = _lights.begin();
     542           0 :         while (it != _lights.end()) {
     543           0 :                 if (*it == light) {
     544           0 :                         removeLight(it);
     545           0 :                         return;
     546             :                 }
     547           0 :                 ++ it;
     548             :         }
     549             : }
     550             : 
     551           0 : void SceneContent2d::removeLightByTag(uint64_t tag) {
     552           0 :         if (auto l = getLightByTag(tag)) {
     553           0 :                 removeLight(l);
     554             :         }
     555           0 : }
     556             : 
     557           0 : void SceneContent2d::removeLightByName(StringView name) {
     558           0 :         if (auto l = getLightByName(name)) {
     559           0 :                 removeLight(l);
     560             :         }
     561           0 : }
     562             : 
     563          10 : void SceneContent2d::removeAllLights() {
     564          10 :         auto it = _lights.begin();
     565          10 :         while (it != _lights.end()) {
     566           0 :                 it = removeLight(it);
     567             :         }
     568          10 : }
     569             : 
     570           0 : void SceneContent2d::removeAllLightsByType(SceneLightType type) {
     571           0 :         auto it = _lights.begin();
     572           0 :         while (it != _lights.end()) {
     573           0 :                 if ((*it)->getType() == type) {
     574           0 :                         it = removeLight(it);
     575             :                 } else {
     576           0 :                         ++ it;
     577             :                 }
     578             :         }
     579           0 : }
     580             : 
     581          10 : void SceneContent2d::setGlobalLight(const Color4F &color) {
     582          10 :         _globalLight = color;
     583          10 : }
     584             : 
     585           0 : const Color4F & SceneContent2d::getGlobalLight() const {
     586           0 :         return _globalLight;
     587             : }
     588             : 
     589        4650 : void SceneContent2d::draw(FrameInfo &info, NodeFlags flags) {
     590        4650 :         SceneContent::draw(info, flags);
     591             : 
     592        4650 :         FrameContextHandle2d *ctx = reinterpret_cast<FrameContextHandle2d *>(info.currentContext);
     593             : 
     594        4650 :         auto &constraints = _scene->getFrameConstraints();
     595             : 
     596        4650 :         Size2 scaledExtent(constraints.extent.width / constraints.density, constraints.extent.height / constraints.density);
     597             : 
     598        4650 :         ctx->lights.sceneDensity = constraints.density;
     599        4650 :         ctx->lights.shadowDensity = _shadowDensity;
     600        4650 :         ctx->lights.globalColor = _globalLight;
     601             : 
     602       13950 :         for (auto &it : _lights) {
     603        9300 :                 switch (it->getType()) {
     604        9300 :                 case SceneLightType::Ambient:
     605       18600 :                         ctx->lights.addAmbientLight(Vec4(it->getNormal().x / scaledExtent.width, -it->getNormal().y / scaledExtent.height,
     606       18600 :                                         it->getNormal().z, it->getNormal().w), it->getColor(), it->isSoftShadow());
     607        9300 :                         break;
     608           0 :                 case SceneLightType::Direct:
     609           0 :                         ctx->lights.addDirectLight(Vec4(it->getNormal().x / scaledExtent.width, -it->getNormal().y / scaledExtent.height,
     610           0 :                                         it->getNormal().z, it->getNormal().w), it->getColor(), it->getData());
     611           0 :                         break;
     612             :                 }
     613             :         }
     614        4650 : }
     615             : 
     616           0 : Vector<Rc<SceneLight>>::iterator SceneContent2d::removeLight(Vector<Rc<SceneLight>>::iterator itVec) {
     617           0 :         if ((*itVec)->isRunning()) {
     618           0 :                 (*itVec)->onExit();
     619             :         }
     620             : 
     621           0 :         if (!(*itVec)->getName().empty()) {
     622           0 :                 auto it = _lightsByName.find((*itVec)->getName());
     623           0 :                 if (it != _lightsByName.end()) {
     624           0 :                         _lightsByName.erase(it);
     625             :                 }
     626             :         }
     627             : 
     628           0 :         if ((*itVec)->getTag() != InvalidTag) {
     629           0 :                 auto it = _lightsByTag.find((*itVec)->getTag());
     630           0 :                 if (it != _lightsByTag.end()) {
     631           0 :                         _lightsByTag.erase(it);
     632             :                 }
     633             :         }
     634             : 
     635           0 :         switch ((*itVec)->getType()) {
     636           0 :         case SceneLightType::Ambient: -- _lightsAmbientCount; break;
     637           0 :         case SceneLightType::Direct: -- _lightsDirectCount; break;
     638             :         }
     639             : 
     640           0 :         return _lights.erase(itVec);
     641             : }
     642             : 
     643             : }

Generated by: LCOV version 1.14