33#include "../testResource.h"
34#include "renderer/CCRenderer.h"
35#include "renderer/backend/ProgramState.h"
36#include "renderer/ccShaders.h"
48ClippingNodeTests::ClippingNodeTests()
74 if (TestCase::init()) {
76 auto background = Sprite::create(
s_back3);
77 background->setAnchorPoint( Vec2::ZERO );
78 background->setPosition( Vec2::ZERO );
79 this->addChild(background, -1);
89 Director::getInstance()->getTextureCache()->removeUnusedTextures();
94 return "Clipping Demo";
117 auto s = Director::getInstance()->getWinSize();
125 clipper->setAnchorPoint(Vec2(0.5f, 0.5f));
126 clipper->setPosition(s.width / 2 - 50, s.height / 2 - 50);
137 return RepeatForever::create(RotateBy::create(1.0f, 90.0f));
142 auto scale = ScaleBy::create(1.33f, 1.5f);
143 return RepeatForever::create(Sequence::create(scale, scale->reverse(),
nullptr));
148 auto shape = DrawNode::create();
149 static Vec2 triangle[3];
150 triangle[0] = Vec2(-100, -100);
151 triangle[1] = Vec2(100, -100);
152 triangle[2] = Vec2(0, 100);
154 static Color4F green(0, 1, 0, 1);
155 shape->drawPolygon(triangle, 3, green, 0, green);
173 return ClippingNode::create();
186 return "Shape Basic Test";
191 return "A DrawNode as stencil and Sprite as content";
196 auto node = this->
shape();
213 return "Shape Inverted Basic Test";
218 return "A DrawNode as stencil and Sprite as content, inverted";
232 return "Sprite Basic Test";
237 return "A Sprite as stencil and DrawNode as content";
250 clipper->setAlphaThreshold(0.05f);
256 auto node = this->
shape();
265 return "Sprite No Alpha Basic Test";
270 return "A Sprite as stencil and DrawNode as content, no alpha";
284 return "Sprite Inverted Basic Test";
289 return "A Sprite as stencil and DrawNode as content, inverted";
295 clipper->setAlphaThreshold(0.05f);
304 return "Nested Test";
309 return "Nest 9 Clipping Nodes, max is usually 8";
314 static int depth = 9;
318 for (
int i = 0; i < depth; i++) {
320 int size = 225 - i * (225 / (depth * 2));
322 auto clipper = ClippingNode::create();
323 clipper->setContentSize(Size(size, size));
324 clipper->setAnchorPoint(Vec2(0.5f, 0.5f));
325 clipper->setPosition(parent->getContentSize().width / 2, parent->getContentSize().height / 2);
326 clipper->setAlphaThreshold(0.05f);
327 clipper->runAction(RepeatForever::create(RotateBy::create(i % 3 ? 1.33f : 1.66f, i % 2 ? 90.0f : -90.0f)));
328 parent->addChild(clipper);
331 stencil->setScale( 2.5f - (i * (2.5f / depth)) );
332 stencil->setAnchorPoint( Vec2(0.5f, 0.5f) );
333 stencil->setPosition(clipper->getContentSize().width / 2, clipper->getContentSize().height / 2);
334 stencil->setVisible(
false);
335 stencil->runAction(Sequence::createWithTwoActions(DelayTime::create(i), Show::create()));
336 clipper->setStencil(stencil);
338 clipper->addChild(stencil);
361 return "Touch/click to poke holes";
367 target->setAnchorPoint(Vec2::ZERO);
372 AffineTransform transform = AffineTransform::IDENTITY;
373 transform = AffineTransformScale(transform, target->getScale(), target->getScale());
375 _outerClipper->setContentSize(SizeApplyAffineTransform(target->getContentSize(), transform));
377 _outerClipper->setPosition(Vec2(this->getContentSize()) * 0.5f);
378 _outerClipper->runAction(RepeatForever::create(RotateBy::create(1, 45)));
382 auto holesClipper = ClippingNode::create();
383 holesClipper->setInverted(
true);
384 holesClipper->setAlphaThreshold( 0.05f );
386 holesClipper->addChild(target);
391 holesClipper->addChild(
_holes);
402 auto listener = EventListenerTouchAllAtOnce::create();
404 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,
this);
409 float scale = CCRANDOM_0_1() * 0.2 + 0.9;
410 float rotation = CCRANDOM_0_1() * 360;
412 auto hole = Sprite::create(
"Images/hole_effect.png");
413 hole->setPosition( point );
414 hole->setRotation( rotation );
415 hole->setScale( scale );
419 auto holeStencil = Sprite::create(
"Images/hole_stencil.png");
420 holeStencil->setPosition( point );
421 holeStencil->setRotation( rotation );
422 holeStencil->setScale( scale );
426 _outerClipper->runAction(Sequence::createWithTwoActions(ScaleBy::create(0.05f, 0.95f),
427 ScaleTo::create(0.125f, 1)));
433 Touch *touch = (Touch *)touches[0];
434 Vec2 point =
_outerClipper->convertToNodeSpace(Director::getInstance()->convertToGL(touch->getLocationInView()));
436 if (!rect.containsPoint(point))
return;
444 return "Scroll View Demo";
449 return "Move/drag to scroll the content";
454 auto clipper = ClippingNode::create();
456 clipper->setContentSize( Size(200.0f, 200.0f) );
457 clipper->setAnchorPoint( Vec2(0.5f, 0.5f) );
458 clipper->setPosition(this->getContentSize().width / 2, this->getContentSize().height / 2);
459 clipper->runAction(RepeatForever::create(RotateBy::create(1, 45)));
460 this->addChild(clipper);
462 auto stencil = DrawNode::create();
464 rectangle[0] = Vec2(0.0f, 0.0f);
465 rectangle[1] = Vec2(clipper->getContentSize().width, 0.0f);
466 rectangle[2] = Vec2(clipper->getContentSize().width, clipper->getContentSize().height);
467 rectangle[3] = Vec2(0.0f, clipper->getContentSize().height);
469 Color4F white(1, 1, 1, 1);
470 stencil->drawPolygon(rectangle, 4, white, 1, white);
471 clipper->setStencil(stencil);
473 auto content = Sprite::create(
s_back2);
475 content->setAnchorPoint( Vec2(0.5f, 0.5f) );
476 content->setPosition(clipper->getContentSize().width / 2, clipper->getContentSize().height / 2);
477 clipper->addChild(content);
481 auto listener = EventListenerTouchAllAtOnce::create();
485 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,
this);
490 Touch *touch = touches[0];
492 Vec2 point = clipper->convertToNodeSpace(Director::getInstance()->convertToGL(touch->getLocationInView()));
493 auto rect = Rect(0, 0, clipper->getContentSize().width, clipper->getContentSize().height);
501 Touch *touch = touches[0];
503 auto point = clipper->convertToNodeSpace(Director::getInstance()->convertToGL(touch->getLocationInView()));
506 content->setPosition(content->getPosition() + diff);
528 {0.7f, 0.7f, 0, 0.45f},
529 {0, 0.7f, 0.7f, 0.4f},
530 {0.7f, 0, 0.7f, 0.35f},
531 {0.7f, 0.7f, 0.7f, 0.3f},
540 return "Raw Stencil Tests";
553 sprite->setAnchorPoint( Vec2(0.5, 0) );
554 sprite->setScale( 2.5f );
558 sprite2->setAnchorPoint( Vec2(0.5, 0) );
559 sprite2->setScale( 2.5f );
568 auto renderer = Director::getInstance()->getRenderer();
570 renderer->setStencilTest(
true);
575 renderer->setStencilTest(
false);
579 auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_UCOLOR);
580 _programState =
new (std::nothrow) backend::ProgramState(program);
581 _locColor = _programState->getProgram()->getUniformLocation(
"u_color");
582 _locMVPMatrix = _programState->getProgram()->getUniformLocation(
"u_MVPMatrix");
583 const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
584 _programState->setUniform(
_locMVPMatrix, projectionMat.m,
sizeof(projectionMat.m));
588 auto winPoint = Vec2(Director::getInstance()->getWinSize());
591 blend.src = backend::BlendFactor::ONE;
592 blend.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
593 for (
int i = 0, cmdIndex = 0; i <
_planeCount; i++)
596 stencilPoint.x = winPoint.x;
600 cmd.init(_globalZOrder, blend);
604 Vec2(stencilPoint.x, 0.0f),
606 Vec2(0.0f, stencilPoint.y)
608 unsigned short indices[] = {0, 2, 1, 0, 3, 2};
609 cmd.createVertexBuffer(
sizeof(Vec2), 4, backend::BufferUsage::STATIC);
610 cmd.updateVertexBuffer(vertices,
sizeof(vertices));
611 cmd.createIndexBuffer(backend::IndexFormat::U_SHORT, 6, backend::BufferUsage::STATIC);
612 cmd.updateIndexBuffer(indices,
sizeof(indices));
613 cmd.getPipelineDescriptor().programState = _programState;
614 auto vertexLayout = _programState->getVertexLayout();
615 auto& attributes = _programState->getProgram()->getActiveAttributes();
616 auto iter = attributes.find(
"a_position");
617 if (iter != attributes.end())
618 vertexLayout->setAttribute(
"a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0,
false);
619 vertexLayout->setLayout(
sizeof(Vec2));
624 cmd2.init(_globalZOrder, blend);
628 Vec2(winPoint.x, 0.0f),
630 Vec2(0.0f, winPoint.y)
632 cmd2.createVertexBuffer(
sizeof(Vec2), 4, backend::BufferUsage::STATIC);
633 cmd2.updateVertexBuffer(vertices2,
sizeof(vertices2));
634 cmd2.createIndexBuffer(backend::IndexFormat::U_SHORT, 6, backend::BufferUsage::STATIC);
635 cmd2.updateIndexBuffer(indices,
sizeof(indices));
636 cmd2.getPipelineDescriptor().programState = _programState;
642 auto winPoint = Vec2(Director::getInstance()->getWinSize());
647 for (
int i = 0, cmdIndex = 0; i <
_planeCount; i++)
649 auto spritePoint = planeSize * i;
650 spritePoint.x += planeSize.x / 2;
652 _sprites.at(i)->setPosition( spritePoint );
655 renderer->clear(ClearFlag::STENCIL, Color4F::BLACK, 0.f, 0x0, _globalZOrder);
660 Director* director = Director::getInstance();
661 CCASSERT(
nullptr != director,
"Director is null when setting matrix stack");
662 director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
664 _modelViewTransform = this->transform(transform);
666 director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
671 director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
672 _modelViewTransform = this->transform(transform);
673 _sprites.at(i)->visit(renderer, _modelViewTransform, flags);
674 director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
683 float color[4] = {1.f, 1.f, 1.f, 1.f};
684 _programState->setUniform(
_locColor, color,
sizeof(color));
691 _programState->setUniform(
_locColor, (
void*)color,
sizeof(color));
696 auto renderer = Director::getInstance()->getRenderer();
697 unsigned int planeMask = 0x1 << plane;
698 renderer->setStencilWriteMask(planeMask);
699 renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, planeMask, planeMask);
700 renderer->setStencilOperation(backend::StencilOperation::REPLACE, backend::StencilOperation::KEEP, backend::StencilOperation::KEEP);
705 auto renderer = Director::getInstance()->getRenderer();
706 unsigned int planeMask = 0x1 << plane;
707 renderer->setStencilCompareFunction(backend::CompareFunction::EQUAL, planeMask, planeMask);
708 renderer->setStencilOperation(backend::StencilOperation::KEEP, backend::StencilOperation::KEEP, backend::StencilOperation::KEEP);
715 return "2:DepthMask:FALSE";
721 Director::getInstance()->getRenderer()->setDepthWrite(
false);
726 Director::getInstance()->getRenderer()->setDepthWrite(
true);
734 return "3:DepthTest:DISABLE,DepthMask:FALSE";
740 auto renderer = Director::getInstance()->getRenderer();
741 renderer->setDepthTest(
false);
742 renderer->setDepthWrite(
false);
747 Director::getInstance()->getRenderer()->setDepthWrite(
true);
756 auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST);
757 auto programState =
new backend::ProgramState(program);
766 return "4:DepthMask:FALSE,AlphaTest:ENABLE";
772 auto renderer = Director::getInstance()->getRenderer();
773 renderer->setDepthWrite(
false);
778 Director::getInstance()->getRenderer()->setDepthWrite(
true);
786 return "5:DepthTest:DISABLE,DepthMask:FALSE,AlphaTest:ENABLE";
792 auto renderer = Director::getInstance()->getRenderer();
793 renderer->setDepthWrite(
false);
794 renderer->setDepthTest(
false);
799 auto renderer = Director::getInstance()->getRenderer();
800 renderer->setDepthWrite(
false);
808 return "6:ManualClear,AlphaTest:ENABLE";
814 Director::getInstance()->getRenderer()->setStencilWriteMask(~0);
819 int planeMask = 0x1 << plane;
820 auto renderer = Director::getInstance()->getRenderer();
821 renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, planeMask, planeMask);
822 renderer->setStencilOperation(backend::StencilOperation::REPLACE, backend::StencilOperation::KEEP, backend::StencilOperation::KEEP);
823 renderer->setDepthTest(
false);
824 renderer->setDepthWrite(
false);
829 auto renderer = Director::getInstance()->getRenderer();
830 renderer->setDepthWrite(
true);
840 return "Clipping to RenderTexture";
845 return "Both should look the same";
850 auto button = MenuItemFont::create(
"Reproduce bug", [&](Ref *sender) {
851 std::vector<Node*> nodes;
852 enumerateChildren(
"remove me [0-9]", [&](Node *node) {
853 nodes.push_back(node);
856 for (
auto node : nodes)
858 this->removeChild(node);
863 auto s = Director::getInstance()->getWinSize();
865 auto menu = Menu::create(button,
nullptr);
866 menu->setPosition(Point(s.width/2, s.height/2));
867 this->addChild(menu, 1);
874 auto director = Director::getInstance();
875 Size visibleSize = director->getVisibleSize();
876 Point origin = director->getVisibleOrigin();
880 auto sprite = Sprite::create(
"Images/grossini.png");
883 sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
886 this->addChild(sprite, 0);
887 sprite->setName(
"remove me 0");
890 auto container = Node::create();
891 this->addChild(container);
892 container->setName(
"remove me 1");
894 auto stencil = DrawNode::create();
896 triangle[0] = Point(-50, -50);
897 triangle[1] = Point(50, -50);
898 triangle[2] = Point(0, 50);
899 Color4F green(0, 1, 0, 1);
900 stencil->drawPolygon(triangle, 3, green, 0, green);
902 auto clipper = ClippingNode::create();
903 clipper->setAnchorPoint(Point(0.5f, 0.5f));
904 clipper->setPosition( Point(visibleSize.width/2, visibleSize.height/2) );
905 clipper->setStencil(stencil);
906 clipper->setInverted(
true);
907 container->addChild(clipper, 1);
910 auto img = DrawNode::create();
911 triangle[0] = Point(-200, -200);
912 triangle[1] = Point(200, -200);
913 triangle[2] = Point(0, 200);
914 Color4F red(1, 0, 0, 1);
915 img->drawPolygon(triangle, 3, red, 0, red);
916 clipper->addChild(img);
921 auto director = Director::getInstance();
922 Size visibleSize = director->getVisibleSize();
923 Point origin = director->getVisibleOrigin();
927 auto sprite = Sprite::create(
"Images/grossini.png");
930 sprite->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
933 this->addChild(sprite, 0);
937 auto container = Node::create();
940 auto stencil = DrawNode::create();
942 triangle[0] = Point(-50, -50);
943 triangle[1] = Point(50, -50);
944 triangle[2] = Point(0, 50);
945 Color4F green(0, 1, 0, 1);
946 stencil->drawPolygon(triangle, 3, green, 0, green);
948 auto clipper = ClippingNode::create();
949 clipper->setAnchorPoint(Point(0.5f, 0.5f));
950 clipper->setPosition( Point(visibleSize.width/2, visibleSize.height/2) );
951 clipper->setStencil(stencil);
952 clipper->setInverted(
true);
953 container->addChild(clipper, 1);
956 auto img = DrawNode::create();
957 triangle[0] = Point(-200, -200);
958 triangle[1] = Point(200, -200);
959 triangle[2] = Point(0, 200);
960 Color4F red(1, 0, 0, 1);
961 img->drawPolygon(triangle, 3, red, 0, red);
962 clipper->addChild(img);
966 RenderTexture* rt = RenderTexture::create(visibleSize.width, visibleSize.height, backend::PixelFormat::RGBA8888, PixelFormat::D24S8);
967 rt->setPosition(visibleSize.width/2, visibleSize.height/2);
979 return "ClippingRectangleNode Test";
984 return "more effectively";
989 auto clipper = ClippingRectangleNode::create();
990 clipper->setClippingRegion(Rect(this->getContentSize().width / 2 - 100, this->getContentSize().height / 2 - 100, 200.0f, 200.0f));
992 this->addChild(clipper);
994 auto content = Sprite::create(
s_back2);
996 content->setAnchorPoint( Vec2(0.5f, 0.5f) );
997 content->setPosition(this->getContentSize().width / 2, this->getContentSize().height / 2);
998 clipper->addChild(content);
#define ADD_TEST_CASE(__className__)
static const float _alphaThreshold
static const float _planeColor[][4]
static const int _planeCount
virtual std::string title() const override
virtual bool init() override
virtual std::string title() const override
virtual cocos2d::Sprite * grossini()
virtual cocos2d::DrawNode * shape()
virtual void setup() override
virtual cocos2d::Action * actionScale()
virtual cocos2d::Action * actionRotate()
virtual cocos2d::Node * content()
virtual cocos2d::ClippingNode * clipper()
virtual std::string subtitle() const override
virtual cocos2d::Node * stencil()
virtual std::string subtitle() const override
virtual std::string title() const override
virtual void setup() override
virtual std::string title() const override
virtual void setup() override
virtual std::string subtitle() const override
void onTouchesBegan(const std::vector< cocos2d::Touch * > &touches, cocos2d::Event *event)
virtual void setup() override
cocos2d::Node * _holesStencil
void pokeHoleAtPoint(cocos2d::Vec2 point)
virtual std::string title() const override
cocos2d::ClippingNode * _outerClipper
virtual std::string subtitle() const override
virtual std::string title() const override
virtual void setup() override
virtual std::string subtitle() const override
virtual void setupStencilForClippingOnPlane(int plane) override
virtual void setupStencilForDrawingOnPlane(int plane) override
virtual std::string subtitle() const override
virtual void setupStencilForDrawingOnPlane(int plane) override
virtual std::string subtitle() const override
virtual void setupStencilForClippingOnPlane(int plane) override
virtual void setupStencilForClippingOnPlane(int plane) override
virtual void setupStencilForDrawingOnPlane(int plane) override
virtual std::string subtitle() const override
virtual void setupStencilForClippingOnPlane(int plane) override
virtual void setupStencilForDrawingOnPlane(int plane) override
virtual std::string subtitle() const override
virtual void setupStencilForClippingOnPlane(int plane) override
virtual std::string subtitle() const override
virtual void setup() override
virtual void setupStencilForDrawingOnPlane(int plane) override
virtual void setup() override
virtual std::string subtitle() const override
void onBeforeDrawSprite(int planeIndex)
cocos2d::Vector< cocos2d::Sprite * > _sprites
cocos2d::CallbackCommand _disableStencilCallback
cocos2d::backend::UniformLocation _locMVPMatrix
virtual void setupStencilForClippingOnPlane(int plane)
std::vector< cocos2d::CustomCommand > _renderCmds
virtual std::string title() const override
cocos2d::Vector< cocos2d::Sprite * > _spritesStencil
virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override
void onBeforeDrawClip(int planeIndex)
cocos2d::CallbackCommand _enableStencilCallback
cocos2d::backend::UniformLocation _locColor
virtual void setup() override
virtual void setupStencilForDrawingOnPlane(int plane)
virtual std::string subtitle() const override
virtual cocos2d::ClippingNode * clipper() override
virtual std::string title() const override
virtual std::string subtitle() const override
virtual cocos2d::Node * stencil() override
virtual std::string title() const override
virtual cocos2d::Node * content() override
virtual cocos2d::ClippingNode * clipper() override
virtual std::string subtitle() const override
virtual std::string title() const override
virtual std::string title() const override
virtual std::string subtitle() const override
virtual cocos2d::ClippingNode * clipper() override
virtual cocos2d::Node * content() override
virtual cocos2d::Node * stencil() override
virtual std::string subtitle() const override
virtual cocos2d::ClippingNode * clipper() override
virtual std::string title() const override
static const char s_back3[]
static const char s_pathBlock[]
static const char s_back2[]
static const char s_pathGrossini[]