Add Texture2D replacement feature to AssetTools.net
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!
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
I'm not sure how to use it. Would you mind giving me an example to help me understand how it works?
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.
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?
Can you post your code?
[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();
}
}
}
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];
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();
}
}
}`
Does TextureEncoderWrapper.NativeLibrariesSupported() return false? Did you build the native c++ texture library or copy it from uabeanext?
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.
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.
Thank you very much. I copied dll from the latest UabeaNext, which is now working normally on computers without C++ environment.