Read a single image from the FairyGUI atlas in the unity editor

reason

I want to be able to access the small pictures in the FairyGUI atlas through the editor extension, but I just searched and couldn’t find the interface to make one myself.

method

Use UIPackage.GetItemByURL to obtain thumbnail information. Copy the small picture from the atlas. If it is rotated, just rotate it 90 degrees.
The small picture in the atlas may be rotated. You can determine whether it is rotated in the atlas by accessing NTexture.rotated.

Get the starting position of the small picture in the atlas

The X offset coordinate can be directly uvRect.min.x * nativeTexture.width to get the real X offset
Y coordinate, which can be obtained in turn according to the uvRect assignment. The original formula is

uvRect.min.y = 1 - region.yMax / _nativeTexture.height

Then the real formula is

y = (1 - startOffset.y) * nativeTexture.height - textureSize.y

It is nothing more than the law of interaction. Restore public NTexture(Texture texture, Rect region) to construct the incoming region parameters

After obtaining the offset and size, you only need to use RenderTexture to read the small image.

        RenderTexture renderTex = RenderTexture.GetTemporary(nativeTexture.width, nativeTexture.height, 24, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
        Graphics.Blit(nativeTexture, renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;

        Texture2D resultTexture = new Texture2D(textureSize.x, textureSize.y, nativeTexture.format, false);
        resultTexture.ReadPixels(new Rect((int)startOffset.x, (int)startOffset.y, textureSize.x, textureSize.y), 0, 0);
        resultTexture.Apply();

        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(renderTex);

How to restore the small pictures in the album that are rotated?

Texture2D.GetPixel and Texture2D.SetPixel interfaces are very slow to read and write.
You can directly use GetPixelData or GetPixels to export the image data array. After the operation is completed, refresh the image data.
Use Color or Color32 format to read according to the nativeTexture.format type.

var colorArray = resultTexture.GetPixelData<Color32>(0)

After having the array, simply reverse rotate the array data by 90 to get the original small picture.

for (int i = 0; i < textureSize.x; i++)
{
    
    
    for (int j = 0; j < textureSize.y; j++)
    {
    
    
        colors[i * textureSize.y + j] = colorArray[textureSize.x - 1 - i + j * textureSize.x];
    }
}

Complete code

    public Texture GetTexture(string url)
    {
    
    
        PackageItem packageItem = UIPackage.GetItemByURL(url);
        if (packageItem == null)
            return null;

        NTexture nTexture = packageItem.texture;
        Texture2D nativeTexture = nTexture.nativeTexture as Texture2D;

        var startOffset = nTexture.uvRect.min;
        var textureSize = new Vector2Int(nTexture.width, nTexture.height);
        if (nTexture.rotated)
            textureSize = new Vector2Int(nTexture.height, nTexture.width);
        startOffset.x *= nativeTexture.width;
        startOffset.y = (1 - startOffset.y) * nativeTexture.height - textureSize.y;


        RenderTexture renderTex = RenderTexture.GetTemporary(nativeTexture.width, nativeTexture.height, 24, RenderTextureFormat.Default, RenderTextureReadWrite.Linear);
        Graphics.Blit(nativeTexture, renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;

        Texture2D resultTexture = new Texture2D(textureSize.x, textureSize.y, nativeTexture.format, false);
        resultTexture.ReadPixels(new Rect((int)startOffset.x, (int)startOffset.y, textureSize.x, textureSize.y), 0, 0);
        resultTexture.Apply();

        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(renderTex);

        if (nTexture.rotated)
        {
    
    
            var colorArray = resultTexture.GetPixelData<Color32>(0);
            Texture2D rotationTexture = new Texture2D(textureSize.y, textureSize.x, nativeTexture.format, false);
            var colors = rotationTexture.GetPixelData<Color32>(0);

            for (int i = 0; i < textureSize.x; i++)
            {
    
    
                for (int j = 0; j < textureSize.y; j++)
                {
    
    
                    colors[i * textureSize.y + j] = colorArray[textureSize.x - 1 - i + j * textureSize.x];
                }
            }

            rotationTexture.SetPixelData(colors, 0);
            rotationTexture.Apply();
            Object.Destroy(resultTexture);
            resultTexture = rotationTexture;
        }

        return resultTexture;
    }

Guess you like

Origin blog.csdn.net/qq_17813937/article/details/132794145