axmolengine / axmol

Axmol Engine – A Multi-platform Engine for Desktop, XBOX (UWP) and Mobile games. (A fork of Cocos2d-x-4.0)
https://axmol.dev
MIT License
928 stars 205 forks source link

FairyGUI: Problems with nine patch image when call "setContentScaleFactor" #1865

Closed paulocoutinhox closed 6 months ago

paulocoutinhox commented 6 months ago
  1. Set setContentScaleFactor in AppDelegate.cpp
  2. Load a FairyGUI with nine patch image

All devices show button wrong. If i keep only the below line in AppDelegate.cpp, it works:

glView->setDesignResolutionSize(frameSize.width, frameSize.height, ResolutionPolicy::SHOW_ALL);

But when i set setContentScaleFactor nine patch images break.

I made an open source sample with code and images:

https://github.com/paulocoutinhox/axmol-ninepatch

Screenshot about the problem:

image

rh101 commented 6 months ago

Is this only for FairyGUI, or also Axmol ui::Button?

paulocoutinhox commented 6 months ago

Hi,

I update the code with an axmol button too, and the problem is only with FairyGUI:

ss2

Demo is here: https://github.com/paulocoutinhox/axmol-ninepatch

paulocoutinhox commented 6 months ago

Hi,

Can someone help me here?

Thanks.

rh101 commented 6 months ago

If this was a bug in Axmol or FairyGUI, then it would be visible in the FairyGUI test project, but it's not. It is most likely that the corner insets that were set for the button in the FairyGUI editor are incorrect, but since the FairyGUI project file doesn't seem to be included in the repo, it's hard to tell. You'll have to verify that yourself.

Just to prove this point, go to this method:

void FUISprite::setScale9Grid(Rect* value)
{
    if (value == nullptr)
    {
        setCenterRectNormalized(Rect(0, 0, 1, 1));
        return;
    }

    Rect insets = *value;

    // When Insets == Zero --> we should use a 1/3 of its untrimmed size
    if (insets.equals(Rect::ZERO))
    {
        insets = Rect(_originalContentSize.width / 3.0f,
                      _originalContentSize.height / 3.0f,
                      _originalContentSize.width / 3.0f,
                      _originalContentSize.height / 3.0f);
    }

Comment out the line, if (insets.equals(Rect::ZERO)), to force it to use default inset values, and you will see that the button renders correctly.

paulocoutinhox commented 6 months ago

Im testing here, and appear that both problems is related to initial scale on AppDelegate

paulocoutinhox commented 6 months ago

I will close because it works when i set resolution on AppDelegate, so is something related to resolution.

paulocoutinhox commented 6 months ago

I solve the problems settings correct resolution in design resolution and the text problems is related to threads, because i call JNI somethings and it don't render when come from JNI call (i dont know why, but i call on callback the method runInAxmolThread). Thanks.

paulocoutinhox commented 6 months ago

Im reopening because any changes on resolution, it break the nine patch button on FairyGUI only (second button on image):

image

rh101 commented 6 months ago

@paulocoutinhox Please provide a sample application, one which also includes the working file for the FairyGUI editor.

Also, as I mentioned in my previous response, the values passed to the setScale9Grid in the Rect parameter are what affect the button insets, and if you hard-code them to some value, then they work, which could mean that the values set in the FairyGUI editor are incorrect. This is easily testable, as shown in my previous response.

paulocoutinhox commented 6 months ago

Hi,

My sample is here: https://github.com/paulocoutinhox/axmol-ninepatch

You can run normally and you will see the problem. It has all sample assets, the same of screenshot.

rh101 commented 6 months ago

My sample is here: https://github.com/paulocoutinhox/axmol-ninepatch

You can run normally and you will see the problem. It has all sample assets, the same of screenshot.

The FairyGUI project file is missing. It's the file you open up in the FairyGUI editor, from which you export the dialog.fui file.

paulocoutinhox commented 6 months ago

Im uploading...only some minutes

paulocoutinhox commented 6 months ago

Project is updated with FairyGUI project file: https://github.com/paulocoutinhox/axmol-ninepatch/tree/main/Extras/fairy-gui

Can you help me?

rh101 commented 6 months ago

Can you help me?

@paulocoutinhox I just spent some time looking at this, reproducing the issue you're seeing, but it made no sense at all to have such a bug, since the FairyGUI code seems to be correct, and similar to what is implemented in Axmol. All this time the assumption was that the graphics are correct, but, it turns out they are not.

Can you see what is wrong with the button graphic: image

If you're trying to create a scale9 sprite, the image needs to be correct, with all sides of the button image having the exact same empty space. As you can see in the above screenshot of the image, there are multiple issues, the biggest of which is that the image contains more empty space at the bottom than it does at the top, so of course the scale 9 insets will not work.

In addition to that, you're trying to show an image with the appearance of 3D as a 2D, which doesn't make sense, because the insets cannot work correctly on such an image; they will always be off. One possible way around this is to construct the button out of multiple layers to emulate 3D, something that has been done many times to fake the 3D effect.

So, in future, it's perhaps best to go through things carefully, and not always blame the code (your own code or the engine code), since it just ends up wasting time for all involved.

If after fixing the button graphic you still have some issue, then post more about it here, otherwise if not, then this is not an Axmol or FairyGUI bug, so please close this issue. Other than the incorrect button graphic, there is still an issue with the content scaling in the FairyGUI runtime, which should be now fixed in PR #1884

rh101 commented 6 months ago

@paulocoutinhox After using a button image that should work with scale9 slicing, there was still an issue with the content scaling. The FairyGUI loader doesn't seem to use the content scaling when loading the image to be used for the scale 9 sprite. Change the GImage::constructFromResource method to the code below and see if it works for you (after you fix the button image):

void GImage::constructFromResource()
{
    PackageItem* contentItem = _packageItem->getBranch();
    sourceSize.width         = contentItem->width;
    sourceSize.height        = contentItem->height;
    initSize                 = sourceSize;

    contentItem = contentItem->getHighResolution();
    contentItem->load();

    _content->setSpriteFrame(contentItem->spriteFrame);
    if (contentItem->scale9Grid)
    {
        const auto contentScaleFactor = AX_CONTENT_SCALE_FACTOR();

        auto scaledInsets = *contentItem->scale9Grid;

        scaledInsets.setRect(scaledInsets.origin.x / contentScaleFactor, scaledInsets.origin.y / contentScaleFactor,
                             scaledInsets.size.x / contentScaleFactor, scaledInsets.size.y / contentScaleFactor);

        ((FUISprite*)_content)->setScale9Grid(&scaledInsets);
    }
    else if (contentItem->scaleByTile)
        ((FUISprite*)_content)->setScaleByTile(true);

    setSize(sourceSize.width, sourceSize.height);
}