UABEA icon indicating copy to clipboard operation
UABEA copied to clipboard

Add Texture2D replacement feature to AssetTools.net

Open 1103945342 opened this issue 11 months ago • 9 comments

Dear nesrak1 I noticed that there is no Texture2D replacement feature in your other project AssetTools.net, but you have included it in this UABEA project. Are you interested in integrating the image replacement feature into AssetTools.net? This will bring great convenience. Thank you!

1103945342 avatar Jan 20 '25 09:01 1103945342

I noticed that there is no Texture2D replacement feature in your other project AssetTools.net

That's not true, it's right here:

https://github.com/nesrak1/AssetsTools.NET/tree/dev/AssetsTools.NET.Texture

nesrak1 avatar Jan 20 '25 14:01 nesrak1

I'm not sure how to use it. Would you mind giving me an example to help me understand how it works?

1103945342 avatar Jan 23 '25 06:01 1103945342

You can look at the tests here: https://github.com/nesrak1/AssetsTools.NET/blob/dev/AssetsTools.NET.Tests/Texture.cs

The wiki also talks about textures but it's a bit out of date.

nesrak1 avatar Jan 30 '25 15:01 nesrak1

I tested the project, and the encoding seems to have taken effect, but the actual situation is not as expected. When viewing it in UABEA, I noticed that the string path section should have no value, the UInt64 offset and unsigned int size values should be 0, and the TypelessData image data (0 items) value should not be empty. What could be causing this issue?

Image

1103945342 avatar Feb 04 '25 07:02 1103945342

Can you post your code?

nesrak1 avatar Feb 05 '25 02:02 nesrak1

    [Test]
    public void TestNativeWrite()
    {
        var level = 3;
        foreach (var format in formats)
        {
            try
            {
                Console.WriteLine($"encoding {format} on level {level}...");

                var am = new AssetsManager();
                var bunInst = am.LoadBundleFile("sprite_character_fighter_equipment_avatar_cap.npk", true);
                var fileInst = am.LoadAssetsFileFromBundle(bunInst, "CAB-1417699130952e4b9a84c8238b1098db");
                var bun = bunInst.file;
                var file = fileInst.file;

                var texInf = file.GetAssetsOfType(AssetClassID.Texture2D)[0];
                var texBf = am.GetBaseField(fileInst, texInf);
                var tex = TextureFile.ReadTextureFile(texBf);
                tex.m_TextureFormat = (int)format;
                tex.EncodeTextureImage("ft_cap17400a.img_0.png", level);
                tex.WriteTo(texBf);
                texInf.SetNewData(texBf);

                bun.BlockAndDirInfo.DirectoryInfos[0].SetNewData(file);
                bun.BlockAndDirInfo.DirectoryInfos[0].Name = $"CAB-texture-{format}";

                Console.WriteLine($"compressing bundle for {format}...");
                var writer = new AssetsFileWriter($"newimg_{format}_.npk");
                bun.Write(writer);
                writer.Close();

                am.UnloadAll();

                var newWriter = new AssetsFileWriter($"newimg_{format}.npk");
                var newBun = am.LoadBundleFile($"newimg_{format}_.npk");
                newBun.file.Pack(newWriter, AssetBundleCompressionType.LZ4);
                newWriter.Close();
                am.UnloadAll();
                Console.WriteLine($"successfully bundled.");

                File.Delete($"newimg_{format}_.npk");
            }
            catch (Exception e)
            {
                Assert.Fail($"failed to encode {format}: {e.Message}");
            }
        }

        Assert.Pass();
    }
}

}

1103945342 avatar Feb 05 '25 07:02 1103945342

Well, you pulled in the whole test. I would suggest using only the relevant parts so you don't create 40 different bundles each of a different format.

The reason it's not editing the right image is because the test expects only one image in the template bundle. Your bundle probably has way more than one texture, yet you still have this line which selects the first Texture2D:

var texInf = file.GetAssetsOfType(AssetClassID.Texture2D)[0];

nesrak1 avatar Feb 07 '25 14:02 nesrak1

is ASTC coding not currently supported? I get the following error in my test: TestNativeWrite (141ms): 错误消息: failed to encode ASTC_RGB_4x4: The current texture format is not supported for encoding. 堆栈跟踪: at AssetsTools.NET.Tests.TextureTests.TestNativeWrite() in F:\AssetTools.net\AssetsTools.NET\AssetsTools.NET.Tests\Texture.cs:line 89 encoding ASTC_RGB_4x4 on level 3...

it‘s my code:

`namespace AssetsTools.NET.Tests

{ public class TextureTests { private static TextureFormat[] formats = { TextureFormat.ASTC_RGB_4x4, TextureFormat.ASTC_RGB_5x5, TextureFormat.ASTC_RGB_6x6, TextureFormat.ASTC_RGB_8x8, TextureFormat.ASTC_RGB_10x10, TextureFormat.ASTC_RGB_12x12, TextureFormat.ASTC_RGBA_4x4, TextureFormat.ASTC_RGBA_5x5, TextureFormat.ASTC_RGBA_6x6, TextureFormat.ASTC_RGBA_8x8, TextureFormat.ASTC_RGBA_10x10, TextureFormat.ASTC_RGBA_12x12 };

    [SetUp]
    public void Setup()
    {
    }

    [Test]
    public void TestNativeWrite()
    {
        var level = 3;
        foreach (var format in formats)
        {
            try
            {
                Console.WriteLine($"encoding {format} on level {level}...");

                var am = new AssetsManager();
                var bunInst = am.LoadBundleFile("sprite_character_swordman_equipment_avatar_skin.npk", true);
                var fileInst = am.LoadAssetsFileFromBundle(bunInst, "CAB-231de340c3ae8e28133284eab93f5ac2");
                var bun = bunInst.file;
                var file = fileInst.file;

                var texInf = file.GetAssetsOfType(AssetClassID.Texture2D)
                    .Select(inf => {
                        var baseField = am.GetBaseField(fileInst, inf);
                        var name = baseField["m_Name"].Value.ToString();
                        return new { Info = inf, Name = name };
                    })
                    .FirstOrDefault(x => x.Name == "sm_body_pants_town.img_0")?.Info;

                if (texInf == null)
                {
                    throw new Exception("Could not find texture with name 'sm_body_pants_town.img_0'");
                }

                var texBf = am.GetBaseField(fileInst, texInf);
                var tex = TextureFile.ReadTextureFile(texBf);
                tex.m_TextureFormat = (int)format;
                tex.EncodeTextureImage("sm_body_pants_town.img_0.png", level);
                tex.WriteTo(texBf);
                texInf.SetNewData(texBf);

                bun.BlockAndDirInfo.DirectoryInfos[0].SetNewData(file);
                bun.BlockAndDirInfo.DirectoryInfos[0].Name = $"CAB-texture-{format}";

                Console.WriteLine($"compressing bundle for {format}...");
                var writer = new AssetsFileWriter($"newimg_{format}_.npk");
                bun.Write(writer);
                writer.Close();

                am.UnloadAll();

                var newWriter = new AssetsFileWriter($"newimg_{format}.npk");
                var newBun = am.LoadBundleFile($"newimg_{format}.npk");
                newBun.file.Pack(newWriter, AssetBundleCompressionType.LZ4);
                newWriter.Close();
                am.UnloadAll();
                Console.WriteLine($"successfully bundled.");

                File.Delete($"newimg_{format}_.npk");
            }
            catch (Exception e)
            {
                Assert.Fail($"failed to encode {format}: {e.Message}");
            }
        }

        Assert.Pass();
    }
}

}`

1103945342 avatar Feb 16 '25 16:02 1103945342

Does TextureEncoderWrapper.NativeLibrariesSupported() return false? Did you build the native c++ texture library or copy it from uabeanext?

nesrak1 avatar Feb 16 '25 16:02 nesrak1

I copied the texture library directly from uabeanext, and it is now working properly. However, the texture library does not work on computers without a C++environment, which causes inconvenience for distribution.

1103945342 avatar Mar 19 '25 03:03 1103945342

When did you copy the library from UABAENext? I was notified that it was compiled with debug mode recently and I have already uploaded a new library in release mode that doesn't require vc++ debug libraries.

nesrak1 avatar Mar 19 '25 04:03 nesrak1

Thank you very much. I copied dll from the latest UabeaNext, which is now working normally on computers without C++ environment.

1103945342 avatar Mar 19 '25 07:03 1103945342