Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UiLayout is not a necessary getClippingRect correction #19890

Closed
Rofl113 opened this issue Jul 2, 2019 · 1 comment
Closed

UiLayout is not a necessary getClippingRect correction #19890

Rofl113 opened this issue Jul 2, 2019 · 1 comment

Comments

@Rofl113
Copy link

Rofl113 commented Jul 2, 2019

  1. Sequencing:
    1.1 Create UiListView
    1.2 Set Anchor Point (0.0, 1.0)
    1.3 UiLayout::setClippingType(ClippingType::SCISSOR);
    1.4 Total: Anchor Point counted twice

  2. Possible location of the problem:
    2.1 Layout::getClippingRect
    UiLayout (ClippingType::SCISSOR) call func Layout::getClippingRect()
    If _clippingParent == nullptr:
    _clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x); _clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y); _clippingRect.size.width = scissorWidth; _clippingRect.size.height = scissorHeight;
    2.2 But the amendment (Anchor Point) is already inside the function convertToWorldSpace:
    Vec2 worldPos = convertToWorldSpace(Vec2::ZERO);

  3. Possible Solution:
    3.1 Correct function Layout::getClippingRect()
    If _clippingParent == nullptr:
    _clippingRect.origin.x = worldPos.x; _clippingRect.origin.y = worldPos.y; _clippingRect.size.width = scissorWidth; _clippingRect.size.height = scissorHeight;

@rh101
Copy link
Contributor

rh101 commented Nov 19, 2019

@minggo I just ran into this issue as well. It's easy to reproduce.

Expected:
image

Actual:
image

The problem only occurs if we use cocos2d::ui::Layout::ClippingType::SCISSOR and any anchor point that is not Vec2(0, 0).

This code reproduces it:

auto panel = cocos2d::ui::Layout::create();
panel->setBackGroundColor(Color3B::RED);
panel->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
panel->setClippingType(cocos2d::ui::Layout::ClippingType::SCISSOR);
panel->setPosition(visibleSize / 2);
panel->setAnchorPoint(Vec2::ANCHOR_MIDDLE); // 0.5, 0.5
panel->setClippingEnabled(true);
panel->setContentSize(visibleSize);
this->addChild(panel);

auto image = cocos2d::ui::ImageView::create("HelloWorld.png");
image->setPositionNormalized(Vec2(0.5f, 0.5f));
panel->addChild(image);

If you change the clipping type to STENCIL, then it works as intended, so the bug is directly related to the SCISSOR option.

As @Rofl113 pointed out, this calculation in Layout::getClippingRect() is not correct:

        ....
        else
        {
            _clippingRect.origin.x = worldPos.x - (scissorWidth * _anchorPoint.x);
            _clippingRect.origin.y = worldPos.y - (scissorHeight * _anchorPoint.y);
            _clippingRect.size.width = scissorWidth;
            _clippingRect.size.height = scissorHeight;
        }

The origin x and y will not be correct.

The solution that seems to work is this:

            _clippingRect.origin.x = worldPos.x;
            _clippingRect.origin.y = worldPos.y;

There is other code in Layout::getClippingRect() that has the issue as well:

        if (_clippingParent)
        {
            parentClippingRect = _clippingParent->getClippingRect();
            float finalX = worldPos.x - (scissorWidth * _anchorPoint.x);
            float finalY = worldPos.y - (scissorHeight * _anchorPoint.y);
            float finalWidth = scissorWidth;
            float finalHeight = scissorHeight;
            ...

Should be:

        if (_clippingParent)
        {
            parentClippingRect = _clippingParent->getClippingRect();
            float finalX = worldPos.x;
            float finalY = worldPos.y;
            float finalWidth = scissorWidth;
            float finalHeight = scissorHeight;
            ...

The _clippingParent section is only entered if the parent and child nodes are both being clipped, and you can reproduce it with this example:

auto panel = cocos2d::ui::Layout::create();
panel->setBackGroundColor(Color3B::RED);
panel->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
panel->setClippingType(cocos2d::ui::Layout::ClippingType::SCISSOR);
panel->setPosition(visibleSize / 2);
panel->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
panel->setClippingEnabled(true);
panel->setContentSize(visibleSize); // from the left to the screen end
this->addChild(panel);

auto panel2 = cocos2d::ui::Layout::create();
panel2->setBackGroundColor(Color3B::BLUE);
panel2->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID);
panel2->setClippingType(cocos2d::ui::Layout::ClippingType::SCISSOR);
panel2->setPosition(panel->getContentSize() / 2);
panel2->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
panel2->setClippingEnabled(true);
panel2->setContentSize(panel->getContentSize() / 2);
panel->addChild(panel2);

auto image = cocos2d::ui::ImageView::create("HelloWorld.png");
image->setPositionNormalized(Vec2(0.5f, 0.5f));
panel2->addChild(image);

Expected:
image

Actual:
image

rh101 added a commit to rh101/cocos2d-x that referenced this issue Dec 10, 2019
@minggo minggo closed this as completed Dec 11, 2019
minggo pushed a commit that referenced this issue Dec 11, 2019
minggo pushed a commit that referenced this issue Jan 6, 2020
* Fix for issue #19890

* Updated with better fix from the V3 PR #18651

* Formatting fix

* Fixed issue with incorrect type (double instead of float) when compiling on certain platforms.

* Another attempt to fix compilation issue
Xrysnow pushed a commit to Xrysnow/cocos2d-x that referenced this issue Jun 21, 2020
* Fix for issue cocos2d#19890

* Updated with better fix from the V3 PR cocos2d#18651

* Formatting fix

* Fixed issue with incorrect type (double instead of float) when compiling on certain platforms.

* Another attempt to fix compilation issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants