diff --git a/cocos/2d/CCNode.cpp b/cocos/2d/CCNode.cpp index dc8c0f39e5..b31d4b916f 100644 --- a/cocos/2d/CCNode.cpp +++ b/cocos/2d/CCNode.cpp @@ -1180,12 +1180,11 @@ uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFl } } - //remove this two line given that isVisitableByVisitingCamera should not affect the calculation of transform given that we are visiting scene - //without involving view and projection matrix. - -// if (!isVisitableByVisitingCamera()) -// return parentFlags; - + // Fixes Github issue #16100. Basically when having two cameras, one camera might set as dirty the + // node that is not visited by it, and might affect certain calculations. Besides, it is faster to do this. + if (!isVisitableByVisitingCamera()) + return parentFlags; + uint32_t flags = parentFlags; flags |= (_transformUpdated ? FLAGS_TRANSFORM_DIRTY : 0); flags |= (_contentSizeDirty ? FLAGS_CONTENT_SIZE_DIRTY : 0); diff --git a/cocos/2d/CCSprite.cpp b/cocos/2d/CCSprite.cpp index 810b35cb3d..72dcde3e6e 100644 --- a/cocos/2d/CCSprite.cpp +++ b/cocos/2d/CCSprite.cpp @@ -651,14 +651,15 @@ void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) } #if CC_USE_CULLING - // Don't do calculate the culling if the transform was not updated + // Don't calculate the culling if the transform was not updated auto visitingCamera = Camera::getVisitingCamera(); auto defaultCamera = Camera::getDefaultCamera(); if (visitingCamera == defaultCamera) { - _insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY)|| visitingCamera->isViewProjectionUpdated()) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds; + _insideBounds = ((flags & FLAGS_TRANSFORM_DIRTY) || visitingCamera->isViewProjectionUpdated()) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds; } else { + // XXX: this always return true since _insideBounds = renderer->checkVisibility(transform, _contentSize); } diff --git a/tests/cpp-tests/Classes/NodeTest/NodeTest.cpp b/tests/cpp-tests/Classes/NodeTest/NodeTest.cpp index deca07c968..ed92478a67 100644 --- a/tests/cpp-tests/Classes/NodeTest/NodeTest.cpp +++ b/tests/cpp-tests/Classes/NodeTest/NodeTest.cpp @@ -71,6 +71,7 @@ CocosNodeTests::CocosNodeTests() ADD_TEST_CASE(NodeNormalizedPositionTest2); ADD_TEST_CASE(NodeNormalizedPositionBugTest); ADD_TEST_CASE(NodeNameTest); + ADD_TEST_CASE(Issue16100Test); } TestCocosNodeDemo::TestCocosNodeDemo(void) @@ -1445,3 +1446,69 @@ void NodeNameTest::test(float dt) auto findChildren = utils::findChildren(*parent, "node"); CCAssert(findChildren.size() == 50, ""); } + +//------------------------------------------------------------------ +// +// Issue16100Test +// +//------------------------------------------------------------------ +void Issue16100Test::onEnter() +{ + TestCocosNodeDemo::onEnter(); + + // create user camera + auto s = Director::getInstance()->getWinSize(); + + auto delay = DelayTime::create(0.1f); + auto f = CallFunc::create([this, s]() + { + auto camera = Camera::createOrthographic(s.width * 2, s.height * 2, -1024, 1024); + camera->setCameraFlag(CameraFlag::USER1); + addChild(camera); + }); + this->runAction(Sequence::createWithTwoActions(delay, f)); + + // grossini using default camera + auto sprite = Sprite::create("Images/grossini.png"); + this->addChild(sprite); + + sprite->setPosition(-200,s.height/3); + auto moveby = MoveBy::create(2, Vec2(400,0)); + auto movebyback = moveby->reverse(); + auto seq = Sequence::create(moveby, movebyback, nullptr); + auto forever = RepeatForever::create(seq); + + sprite->runAction(forever); + + sprite->setCameraMask((int)CameraFlag::DEFAULT); + + + // grossini's sister using user camera + auto sister = Sprite::create("Images/grossinis_sister1.png"); + this->addChild(sister); + + sister->setPosition(-200,s.height*2/3); + auto moveby1 = MoveBy::create(2, Vec2(400,0)); + auto movebyback1 = moveby1->reverse(); + auto seq1 = Sequence::create(moveby1, movebyback1, nullptr); + auto forever1 = RepeatForever::create(seq1); + + sister->runAction(forever1); + sister->setCameraMask((int)CameraFlag::USER1); +} + +void Issue16100Test::onExit() +{ + TestCocosNodeDemo::onExit(); +} + +std::string Issue16100Test::title() const +{ + return "Issue 16100"; +} + +std::string Issue16100Test::subtitle() const +{ + return "Sprite should appear on the screen"; +} + diff --git a/tests/cpp-tests/Classes/NodeTest/NodeTest.h b/tests/cpp-tests/Classes/NodeTest/NodeTest.h index 7124f7a708..2e27ef14a5 100644 --- a/tests/cpp-tests/Classes/NodeTest/NodeTest.h +++ b/tests/cpp-tests/Classes/NodeTest/NodeTest.h @@ -330,4 +330,15 @@ public: void test(float dt); }; +class Issue16100Test : public TestCocosNodeDemo +{ +public: + CREATE_FUNC(Issue16100Test); + virtual std::string title() const override; + virtual std::string subtitle() const override; + + virtual void onEnter() override; + virtual void onExit() override; +}; + #endif