This commit is contained in:
Razmoth
2023-03-12 22:14:22 +04:00
parent 701d76faad
commit 63f4b24b71
29 changed files with 1533 additions and 2237 deletions

View File

@@ -14,10 +14,4 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="Keys.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project> </Project>

View File

@@ -443,7 +443,7 @@ namespace AssetStudio
foreach (var offset in offsets) foreach (var offset in offsets)
{ {
stream.Offset = offset; stream.Offset = offset;
var dummyPath = Path.Combine("//?/block:/", reader.FileName, offset.ToString("X8")); var dummyPath = Path.Combine(reader.FileName, offset.ToString("X8"));
var subReader = new FileReader(dummyPath, stream, true); var subReader = new FileReader(dummyPath, stream, true);
LoadBundleFile(subReader, reader.FullPath, offset); LoadBundleFile(subReader, reader.FullPath, offset);
} }
@@ -454,7 +454,7 @@ namespace AssetStudio
do do
{ {
stream.Offset = stream.RelativePosition; stream.Offset = stream.RelativePosition;
var dummyPath = Path.Combine("//?/block:/", reader.FileName, stream.RelativePosition.ToString("X8")); var dummyPath = Path.Combine(reader.FileName, stream.RelativePosition.ToString("X8"));
var subReader = new FileReader(dummyPath, stream, true); var subReader = new FileReader(dummyPath, stream, true);
LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition); LoadBundleFile(subReader, reader.FullPath, stream.RelativePosition);
} while (stream.Remaining > 0); } while (stream.Remaining > 0);
@@ -480,7 +480,7 @@ namespace AssetStudio
foreach (var offset in offsets) foreach (var offset in offsets)
{ {
stream.Offset = offset; stream.Offset = offset;
var dummyPath = Path.Combine("//?/blk:/", reader.FileName, offset.ToString("X8")); var dummyPath = Path.Combine(reader.FileName, offset.ToString("X8"));
var subReader = new FileReader(dummyPath, stream, true); var subReader = new FileReader(dummyPath, stream, true);
switch (subReader.FileType) switch (subReader.FileType)
{ {
@@ -499,7 +499,7 @@ namespace AssetStudio
do do
{ {
stream.Offset = stream.RelativePosition; stream.Offset = stream.RelativePosition;
var dummyPath = Path.Combine("//?/blk:/", reader.FileName, stream.RelativePosition.ToString("X8")); var dummyPath = Path.Combine(reader.FileName, stream.RelativePosition.ToString("X8"));
var subReader = new FileReader(dummyPath, stream, true); var subReader = new FileReader(dummyPath, stream, true);
switch (subReader.FileType) switch (subReader.FileType)
{ {
@@ -626,10 +626,10 @@ namespace AssetStudio
case ClassIDType.Animation: case ClassIDType.Animation:
obj = new Animation(objectReader); obj = new Animation(objectReader);
break; break;
case ClassIDType.AnimationClip: case ClassIDType.AnimationClip when ExportableTypes[ClassIDType.AnimationClip]:
obj = new AnimationClip(objectReader); obj = new AnimationClip(objectReader);
break; break;
case ClassIDType.Animator: case ClassIDType.Animator when ExportableTypes[ClassIDType.Animator]:
obj = new Animator(objectReader); obj = new Animator(objectReader);
break; break;
case ClassIDType.AnimatorController: case ClassIDType.AnimatorController:
@@ -638,7 +638,7 @@ namespace AssetStudio
case ClassIDType.AnimatorOverrideController: case ClassIDType.AnimatorOverrideController:
obj = new AnimatorOverrideController(objectReader); obj = new AnimatorOverrideController(objectReader);
break; break;
case ClassIDType.AssetBundle: case ClassIDType.AssetBundle when ExportableTypes[ClassIDType.AssetBundle]:
obj = new AssetBundle(objectReader); obj = new AssetBundle(objectReader);
break; break;
case ClassIDType.AudioClip: case ClassIDType.AudioClip:
@@ -647,30 +647,29 @@ namespace AssetStudio
case ClassIDType.Avatar: case ClassIDType.Avatar:
obj = new Avatar(objectReader); obj = new Avatar(objectReader);
break; break;
case ClassIDType.Font: case ClassIDType.Font when ExportableTypes[ClassIDType.Font]:
obj = new Font(objectReader); obj = new Font(objectReader);
break; break;
case ClassIDType.GameObject: case ClassIDType.GameObject when ExportableTypes[ClassIDType.GameObject]:
obj = new GameObject(objectReader); obj = new GameObject(objectReader);
break; break;
case ClassIDType.IndexObject: case ClassIDType.IndexObject when ExportableTypes[ClassIDType.MiHoYoBinData]:
obj = new IndexObject(objectReader); obj = new IndexObject(objectReader);
break; break;
case ClassIDType.Material: case ClassIDType.Material:
case ClassIDType.Material when ExportableTypes[ClassIDType.Material]:
obj = new Material(objectReader); obj = new Material(objectReader);
break; break;
case ClassIDType.Mesh: case ClassIDType.Mesh when ExportableTypes[ClassIDType.Mesh]:
obj = new Mesh(objectReader); obj = new Mesh(objectReader);
break; break;
case ClassIDType.MeshFilter: case ClassIDType.MeshFilter:
obj = new MeshFilter(objectReader); obj = new MeshFilter(objectReader);
break; break;
case ClassIDType.MeshRenderer: case ClassIDType.MeshRenderer when ExportableTypes[ClassIDType.Renderer]:
if (Renderer.Skipped)
goto default;
obj = new MeshRenderer(objectReader); obj = new MeshRenderer(objectReader);
break; break;
case ClassIDType.MiHoYoBinData: case ClassIDType.MiHoYoBinData when ExportableTypes[ClassIDType.MiHoYoBinData]:
obj = new MiHoYoBinData(objectReader); obj = new MiHoYoBinData(objectReader);
break; break;
case ClassIDType.MonoBehaviour: case ClassIDType.MonoBehaviour:
@@ -688,24 +687,22 @@ namespace AssetStudio
case ClassIDType.RectTransform: case ClassIDType.RectTransform:
obj = new RectTransform(objectReader); obj = new RectTransform(objectReader);
break; break;
case ClassIDType.Shader: case ClassIDType.Shader when ExportableTypes[ClassIDType.Shader]:
obj = new Shader(objectReader); obj = new Shader(objectReader);
break; break;
case ClassIDType.SkinnedMeshRenderer: case ClassIDType.SkinnedMeshRenderer when ExportableTypes[ClassIDType.Renderer]:
if (Renderer.Skipped)
goto default;
obj = new SkinnedMeshRenderer(objectReader); obj = new SkinnedMeshRenderer(objectReader);
break; break;
case ClassIDType.Sprite: case ClassIDType.Sprite when ExportableTypes[ClassIDType.Sprite]:
obj = new Sprite(objectReader); obj = new Sprite(objectReader);
break; break;
case ClassIDType.SpriteAtlas: case ClassIDType.SpriteAtlas:
obj = new SpriteAtlas(objectReader); obj = new SpriteAtlas(objectReader);
break; break;
case ClassIDType.TextAsset: case ClassIDType.TextAsset when ExportableTypes[ClassIDType.TextAsset]:
obj = new TextAsset(objectReader); obj = new TextAsset(objectReader);
break; break;
case ClassIDType.Texture2D: case ClassIDType.Texture2D when ExportableTypes[ClassIDType.Texture2D]:
obj = new Texture2D(objectReader); obj = new Texture2D(objectReader);
break; break;
case ClassIDType.Transform: case ClassIDType.Transform:

View File

@@ -15,7 +15,6 @@ namespace AssetStudio
BlocksInfoAtTheEnd = 0x80, BlocksInfoAtTheEnd = 0x80,
OldWebPluginCompatibility = 0x100, OldWebPluginCompatibility = 0x100,
BlockInfoNeedPaddingAtStart = 0x200, BlockInfoNeedPaddingAtStart = 0x200,
CNUnityEncryption = 0x400
} }
[Flags] [Flags]
@@ -23,7 +22,6 @@ namespace AssetStudio
{ {
CompressionTypeMask = 0x3f, CompressionTypeMask = 0x3f,
Streamed = 0x40, Streamed = 0x40,
CNUnity = 0x100
} }
public enum CompressionType public enum CompressionType
@@ -66,7 +64,6 @@ namespace AssetStudio
} }
private Game Game; private Game Game;
private CNUnity CNUnity;
public Header m_Header; public Header m_Header;
private Node[] m_DirectoryInfo; private Node[] m_DirectoryInfo;
@@ -311,30 +308,6 @@ namespace AssetStudio
private void ReadBlocksInfoAndDirectory(FileReader reader) private void ReadBlocksInfoAndDirectory(FileReader reader)
{ {
if (Game.Type.IsCNUnity())
{
ArchiveFlags mask;
var version = ParseVersion();
//Flag changed it in these versions
if (version[0] < 2020 || //2020 and earlier
(version[0] == 2020 && version[1] == 3 && version[2] <= 34) || //2020.3.34 and earlier
(version[0] == 2021 && version[1] == 3 && version[2] <= 2) || //2021.3.2 and earlier
(version[0] == 2022 && version[1] == 3 && version[2] <= 1)) //2022.3.1 and earlier
{
mask = ArchiveFlags.BlockInfoNeedPaddingAtStart;
}
else
{
mask = ArchiveFlags.CNUnityEncryption;
}
if ((m_Header.flags & mask) != 0)
{
CNUnity = new CNUnity(reader);
}
}
byte[] blocksInfoBytes; byte[] blocksInfoBytes;
if (m_Header.version >= 7 && !Game.Type.IsSRGroup()) if (m_Header.version >= 7 && !Game.Type.IsSRGroup())
{ {
@@ -424,7 +397,7 @@ namespace AssetStudio
}; };
} }
} }
if (!Game.Type.IsCNUnity() && (m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0) if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
{ {
reader.AlignStream(16); reader.AlignStream(16);
} }
@@ -460,10 +433,6 @@ namespace AssetStudio
{ {
compressedBytesSpan = Mr0kUtils.Decrypt(compressedBytesSpan, (Mr0k)Game); compressedBytesSpan = Mr0kUtils.Decrypt(compressedBytesSpan, (Mr0k)Game);
} }
if (Game.Type.IsCNUnity() && (blockInfo.flags & StorageBlockFlags.CNUnity) != 0)
{
CNUnity.DecryptBlock(compressedBytesSpan, compressedSize, i);
}
if (Game.Type.IsOPFP()) if (Game.Type.IsOPFP())
{ {
OPFPUtils.Decrypt(compressedBytesSpan, reader.FullPath); OPFPUtils.Decrypt(compressedBytesSpan, reader.FullPath);

View File

@@ -19,8 +19,6 @@ namespace AssetStudio
public abstract class Renderer : Component public abstract class Renderer : Component
{ {
public static bool Skipped;
public PPtr<Material>[] m_Materials; public PPtr<Material>[] m_Materials;
public StaticBatchInfo m_StaticBatchInfo; public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices; public uint[] m_SubsetIndices;

View File

@@ -1,158 +0,0 @@
using System;
using System.Text;
using System.Security.Cryptography;
namespace AssetStudio
{
public class CNUnity
{
private const string Signature = "#$unity3dchina!@";
public static ICryptoTransform Encryptor;
public byte[] Index = new byte[0x10];
public byte[] Sub = new byte[0x10];
public CNUnity(EndianBinaryReader reader)
{
reader.ReadUInt32();
var infoBytes = reader.ReadBytes(0x10);
var infoKey = reader.ReadBytes(0x10);
reader.Position += 1;
var signatureBytes = reader.ReadBytes(0x10);
var signatureKey = reader.ReadBytes(0x10);
reader.Position += 1;
DecryptKey(signatureKey, signatureBytes);
var str = Encoding.UTF8.GetString(signatureBytes);
if (str != Signature)
throw new Exception("Invalid Signature !!");
DecryptKey(infoKey, infoBytes);
infoBytes = infoBytes.ToUInt4Array();
infoBytes.AsSpan(0, 0x10).CopyTo(Index);
var subBytes = infoBytes.AsSpan(0x10, 0x10);
for (var i = 0; i < subBytes.Length; i++)
{
var idx = (i % 4 * 4) + (i / 4);
Sub[idx] = subBytes[i];
}
}
public static bool SetKey(Entry entry)
{
try
{
using var aes = Aes.Create();
aes.Mode = CipherMode.ECB;
aes.Key = entry.GenerateKey();
Encryptor = aes.CreateEncryptor();
}
catch(Exception e)
{
Logger.Error($"[CNUnity] Invalid key !!\n{e.Message}");
return false;
}
return true;
}
public void DecryptBlock(Span<byte> bytes, int size, int index)
{
var offset = 0;
while (offset < size)
{
offset += Decrypt(bytes[offset..], index++, size - offset);
}
}
private void DecryptKey(byte[] key, byte[] data)
{
if (Encryptor != null)
{
key = Encryptor.TransformFinalBlock(key, 0, key.Length);
for (int i = 0; i < 0x10; i++)
data[i] ^= key[i];
}
}
private int DecryptByte(Span<byte> bytes, ref int offset, ref int index)
{
var b = Sub[((index >> 2) & 3) + 4] + Sub[index & 3] + Sub[((index >> 4) & 3) + 8] + Sub[((byte)index >> 6) + 12];
bytes[offset] = (byte)((Index[bytes[offset] & 0xF] - b) & 0xF | 0x10 * (Index[bytes[offset] >> 4] - b));
b = bytes[offset];
offset++;
index++;
return b;
}
private int Decrypt(Span<byte> bytes, int index, int remaining)
{
var offset = 0;
var curByte = DecryptByte(bytes, ref offset, ref index);
var byteHigh = curByte >> 4;
var byteLow = curByte & 0xF;
if (byteHigh == 0xF)
{
int b;
do
{
b = DecryptByte(bytes, ref offset, ref index);
byteHigh += b;
} while (b == 0xFF);
}
offset += byteHigh;
if (offset < remaining)
{
DecryptByte(bytes, ref offset, ref index);
DecryptByte(bytes, ref offset, ref index);
if (byteLow == 0xF)
{
int b;
do
{
b = DecryptByte(bytes, ref offset, ref index);
} while(b == 0xFF);
}
}
return offset;
}
public record Entry
{
public string Name { get; private set; }
public string Key { get; private set; }
public Entry(string name, string key)
{
Name = name;
Key = key;
}
public bool Validate()
{
var bytes = GenerateKey();
if (bytes.Length != 0x10)
{
Logger.Warning($"[CNUnity] {this} has invalid key, size should be 16 bytes, skipping...");
return false;
}
return true;
}
public byte[] GenerateKey() => Convert.FromHexString(Key);
public override string ToString() => $"{Name} ({Key})";
}
}
}

View File

@@ -12,7 +12,6 @@ namespace AssetStudio
{ {
int index = 0; int index = 0;
Games.Add(index++, new(GameType.Normal)); Games.Add(index++, new(GameType.Normal));
Games.Add(index++, new Game(GameType.CNUnity));
Games.Add(index++, new Mhy0(GameType.GI, GIMhy0ShiftRow, GIMhy0Key, GIMhy0Mul, GIExpansionKey, GISBox, GIInitVector, GIInitSeed)); Games.Add(index++, new Mhy0(GameType.GI, GIMhy0ShiftRow, GIMhy0Key, GIMhy0Mul, GIExpansionKey, GISBox, GIInitVector, GIInitSeed));
Games.Add(index++, new Mr0k(GameType.GI_Pack, PackExpansionKey, blockKey: PackBlockKey)); Games.Add(index++, new Mr0k(GameType.GI_Pack, PackExpansionKey, blockKey: PackBlockKey));
Games.Add(index++, new Mr0k(GameType.GI_CB1)); Games.Add(index++, new Mr0k(GameType.GI_CB1));
@@ -31,6 +30,7 @@ namespace AssetStudio
Games.Add(index++, new Game(GameType.FantasyOfWind)); Games.Add(index++, new Game(GameType.FantasyOfWind));
Games.Add(index++, new Game(GameType.ShiningNikki)); Games.Add(index++, new Game(GameType.ShiningNikki));
} }
public static Game GetGame(GameType gameType) => GetGame((int)gameType);
public static Game GetGame(int index) public static Game GetGame(int index)
{ {
if (!Games.TryGetValue(index, out var format)) if (!Games.TryGetValue(index, out var format))
@@ -124,7 +124,6 @@ namespace AssetStudio
SR_CB3, SR_CB3,
TOT, TOT,
Naraka, Naraka,
CNUnity,
EnsembleStars, EnsembleStars,
OPFP, OPFP,
AlchemyStars, AlchemyStars,
@@ -147,7 +146,6 @@ namespace AssetStudio
public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3; public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3;
public static bool IsTOT(this GameType type) => type == GameType.TOT; public static bool IsTOT(this GameType type) => type == GameType.TOT;
public static bool IsNaraka(this GameType type) => type == GameType.Naraka; public static bool IsNaraka(this GameType type) => type == GameType.Naraka;
public static bool IsCNUnity(this GameType type) => type == GameType.CNUnity;
public static bool IsOPFP(this GameType type) => type == GameType.OPFP; public static bool IsOPFP(this GameType type) => type == GameType.OPFP;
public static bool IsGIGroup(this GameType type) => type switch public static bool IsGIGroup(this GameType type) => type switch
{ {

View File

@@ -1,70 +0,0 @@
[
{
"Name": "PGR GLB/KR",
"Key": "6B75726F6B75726F6B75726F6B75726F"
},
{
"Name": "PGR CN/JP/TW",
"Key": "7935585076714C4F72436F6B57524961"
},
{
"Name": "Archeland/Kalpa of Universe",
"Key": "426C61636B4A61636B50726F6A656374"
},
{
"Name": "Archeland 1.1.14",
"Key": "50726F6A65637441726368654C616E64"
},
{
"Name": "Neural Cloud",
"Key": "31636162383436663532393031633965"
},
{
"Name": "Higan: Eruthyll",
"Key": "45317832633361346C35693662377572"
},
{
"Name": "White Chord",
"Key": "79756C6F6E6731383638676E6F6C7579"
},
{
"Name": "Mecharashi",
"Key": "33384338334631333245374637413041"
},
{
"Name": "Castlevania: Moon Night Fantasy",
"Key": "31323334353637383132333435363738"
},
{
"Name": "Huā Yì Shān Xīn Zhī Yuè",
"Key": "494E484A6E68647970716B3534377864"
},
{
"Name": "Doula Continent",
"Key": "52346366773339474644326661785756"
},
{
"Name": "Bless Global",
"Key": "6C6F6E67747567616D652E796A66623F"
},
{
"Name": "Starside",
"Key": "41394A3542384D4A50554D3539464B57"
},
{
"Name": "Resonance Soltice",
"Key": "5265736F6E616E63655265626F726E52"
},
{
"Name": "Oblivion Override",
"Key": "7179666D6F6F6E323331323433343532"
},
{
"Name": "Dawnlands",
"Key": "636F6465737339353237636F64657373"
},
{
"Name": "BB",
"Key": "5F6C4E3F3A3F233F3F3F3F663F1A3F3F"
}
]

View File

@@ -1,68 +0,0 @@
using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Reflection;
namespace AssetStudio
{
public static class CNUnityKeyManager
{
public const string KeysFileName = "Keys.json";
private static List<CNUnity.Entry> Entries = new List<CNUnity.Entry>();
static CNUnityKeyManager()
{
var str = File.ReadAllText(KeysFileName);
Entries = JsonConvert.DeserializeObject<List<CNUnity.Entry>>(str);
}
public static void SaveEntries(List<CNUnity.Entry> entries)
{
Entries.Clear();
Entries.AddRange(entries);
var str = JsonConvert.SerializeObject(Entries);
File.WriteAllText(KeysFileName, str);
}
public static void SetKey(int index)
{
if (TryGetEntry(index, out var cnunity))
{
if (CNUnity.SetKey(cnunity))
{
Logger.Info($"[CNUnity] Selected Key is {cnunity}");
}
else
{
Logger.Info($"[CNUnity] No Key is selected !!");
}
}
}
public static bool TryGetEntry(int index, out CNUnity.Entry key)
{
try
{
if (index < 0 || index > Entries.Count)
{
throw new ArgumentOutOfRangeException();
}
key = Entries[index];
}
catch(Exception e)
{
Logger.Error($"[CNUnity] Invalid Index, check if list is not empty !!\n{e.Message}");
key = null;
return false;
}
return true;
}
public static CNUnity.Entry[] GetEntries() => Entries.ToArray();
}
}

View File

@@ -28,7 +28,7 @@ namespace AssetStudio
{ {
public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision, public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii) bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, bool exportUV0UV1, float scaleFactor, int versionIndex, bool isAscii)
{ {
var file = new FileInfo(path); var file = new FileInfo(path);
var dir = file.Directory; var dir = file.Directory;
@@ -43,7 +43,7 @@ namespace AssetStudio
var name = Path.GetFileName(path); var name = Path.GetFileName(path);
using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii)) using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, exportAllUvsAsDiffuseMaps, exportUV0UV1, scaleFactor, versionIndex, isAscii))
{ {
exporter.Initialize(); exporter.Initialize();
exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision); exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);

View File

@@ -16,11 +16,12 @@ namespace AssetStudio.FbxInterop
private readonly bool _castToBone; private readonly bool _castToBone;
private readonly float _boneSize; private readonly float _boneSize;
private readonly bool _exportAllUvsAsDiffuseMaps; private readonly bool _exportAllUvsAsDiffuseMaps;
private readonly bool _exportUV0UV1;
private readonly float _scaleFactor; private readonly float _scaleFactor;
private readonly int _versionIndex; private readonly int _versionIndex;
private readonly bool _isAscii; private readonly bool _isAscii;
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii) internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, bool exportUV0UV1, float scaleFactor, int versionIndex, bool isAscii)
{ {
_context = new FbxExporterContext(); _context = new FbxExporterContext();
@@ -31,6 +32,7 @@ namespace AssetStudio.FbxInterop
_castToBone = castToBone; _castToBone = castToBone;
_boneSize = boneSize; _boneSize = boneSize;
_exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps; _exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps;
_exportUV0UV1 = exportUV0UV1;
_scaleFactor = scaleFactor; _scaleFactor = scaleFactor;
_versionIndex = versionIndex; _versionIndex = versionIndex;
_isAscii = isAscii; _isAscii = isAscii;
@@ -173,7 +175,7 @@ namespace AssetStudio.FbxInterop
{ {
foreach (var meshFrame in meshFrames) foreach (var meshFrame in meshFrames)
{ {
_context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins, _exportAllUvsAsDiffuseMaps); _context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins, _exportAllUvsAsDiffuseMaps, _exportUV0UV1);
} }
} }

View File

@@ -173,12 +173,12 @@ namespace AssetStudio.FbxInterop
AsFbxPrepareMaterials(_pContext, materialCount, textureCount); AsFbxPrepareMaterials(_pContext, materialCount, textureCount);
} }
internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins, bool exportAllUvsAsDiffuseMaps) internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins, bool exportAllUvsAsDiffuseMaps, bool exportUV0UV1)
{ {
var meshNode = _frameToNode[meshFrame]; var meshNode = _frameToNode[meshFrame];
var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList); var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);
ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps); ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps, exportUV0UV1);
} }
private IntPtr ExportTexture(ImportedTexture texture) private IntPtr ExportTexture(ImportedTexture texture)
@@ -207,7 +207,7 @@ namespace AssetStudio.FbxInterop
return pTex; return pTex;
} }
private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps) private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps, bool exportUV0UV1)
{ {
var boneList = importedMesh.BoneList; var boneList = importedMesh.BoneList;
var totalBoneCount = 0; var totalBoneCount = 0;
@@ -253,6 +253,26 @@ namespace AssetStudio.FbxInterop
AsFbxMeshCreateElementNormal(mesh); AsFbxMeshCreateElementNormal(mesh);
} }
if (exportUV0UV1)
{
if (importedMesh.hasUV[0])
{
AsFbxMeshCreateDiffuseUV(mesh, 0);
}
if (importedMesh.hasUV[1])
{
if (exportAllUvsAsDiffuseMaps)
{
AsFbxMeshCreateDiffuseUV(mesh, 1);
}
else
{
AsFbxMeshCreateNormalMapUV(mesh, 1);
}
}
}
else
{
for (int i = 0; i < importedMesh.hasUV.Length; i++) for (int i = 0; i < importedMesh.hasUV.Length; i++)
{ {
if (!importedMesh.hasUV[i]) { continue; } if (!importedMesh.hasUV[i]) { continue; }
@@ -266,6 +286,7 @@ namespace AssetStudio.FbxInterop
AsFbxMeshCreateDiffuseUV(mesh, i); AsFbxMeshCreateDiffuseUV(mesh, i);
} }
} }
}
if (importedMesh.hasTangent) if (importedMesh.hasTangent)
{ {
@@ -367,7 +388,8 @@ namespace AssetStudio.FbxInterop
AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z); AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z);
} }
for (var uvIndex = 0; uvIndex < importedMesh.hasUV.Length; uvIndex += 1) var uvSize = exportUV0UV1 ? 2 : importedMesh.hasUV.Length;
for (var uvIndex = 0; uvIndex < uvSize; uvIndex += 1)
{ {
if (importedMesh.hasUV[uvIndex]) if (importedMesh.hasUV[uvIndex])
{ {

View File

@@ -76,18 +76,12 @@
<setting name="encrypted" serializeAs="String"> <setting name="encrypted" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="skipRenderer" serializeAs="String">
<value>False</value>
</setting>
<setting name="selectedGame" serializeAs="String"> <setting name="selectedGame" serializeAs="String">
<value>0</value> <value>0</value>
</setting> </setting>
<setting name="enableResolveDependencies" serializeAs="String"> <setting name="enableResolveDependencies" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="selectedCNUnityKey" serializeAs="String">
<value>0</value>
</setting>
<setting name="selectedAssetMapType" serializeAs="String"> <setting name="selectedAssetMapType" serializeAs="String">
<value>0</value> <value>0</value>
</setting> </setting>
@@ -100,6 +94,12 @@
<setting name="skipContainer" serializeAs="String"> <setting name="skipContainer" serializeAs="String">
<value>False</value> <value>False</value>
</setting> </setting>
<setting name="exportUV0UV1" serializeAs="String">
<value>False</value>
</setting>
<setting name="exportableTypes" serializeAs="String">
<value>{"GameObject":true,"Material":true,"Texture2D":true,"Mesh":true,"Renderer":true,"Shader":true,"TextAsset":true,"AnimationClip":true,"Font":true,"Sprite":true,"Animator":true,"MiHoYoBinData":true,"AssetBundle":true}</value>
</setting>
</AssetStudioGUI.Properties.Settings> </AssetStudioGUI.Properties.Settings>
</userSettings> </userSettings>
</configuration> </configuration>

File diff suppressed because it is too large Load Diff

View File

@@ -107,13 +107,17 @@ namespace AssetStudioGUI
displayAll.Checked = Properties.Settings.Default.displayAll; displayAll.Checked = Properties.Settings.Default.displayAll;
displayInfo.Checked = Properties.Settings.Default.displayInfo; displayInfo.Checked = Properties.Settings.Default.displayInfo;
enablePreview.Checked = Properties.Settings.Default.enablePreview; enablePreview.Checked = Properties.Settings.Default.enablePreview;
enableResolveDependencies.Checked = Properties.Settings.Default.enableResolveDependencies; assetsManager.ResolveDependencies = Properties.Settings.Default.enableResolveDependencies;
skipContainer.Checked = Properties.Settings.Default.skipContainer;
assetsManager.ResolveDependencies = enableResolveDependencies.Checked;
Renderer.Skipped = Properties.Settings.Default.skipRenderer;
MiHoYoBinData.Exportable = Properties.Settings.Default.exportMiHoYoBinData; MiHoYoBinData.Exportable = Properties.Settings.Default.exportMiHoYoBinData;
MiHoYoBinData.Encrypted = Properties.Settings.Default.encrypted; MiHoYoBinData.Encrypted = Properties.Settings.Default.encrypted;
MiHoYoBinData.Key = Properties.Settings.Default.key; MiHoYoBinData.Key = Properties.Settings.Default.key;
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
foreach (var exportable in types)
{
if (assetsManager.ExportableTypes.ContainsKey(exportable.Key))
assetsManager.ExportableTypes[exportable.Key] = exportable.Value;
}
} }
private void InitializeLogger() private void InitializeLogger()
@@ -152,7 +156,6 @@ namespace AssetStudioGUI
Logger.Info($"Target Game type is {Studio.Game.Type}"); Logger.Info($"Target Game type is {Studio.Game.Type}");
CABMapNameComboBox.SelectedIndexChanged += new EventHandler(specifyNameComboBox_SelectedIndexChanged); CABMapNameComboBox.SelectedIndexChanged += new EventHandler(specifyNameComboBox_SelectedIndexChanged);
CNUnityKeyManager.SetKey(Properties.Settings.Default.selectedCNUnityKey);
} }
private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e) private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e)
{ {
@@ -494,22 +497,6 @@ namespace AssetStudioGUI
Properties.Settings.Default.enablePreview = enablePreview.Checked; Properties.Settings.Default.enablePreview = enablePreview.Checked;
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
} }
private void enableResolveDependencies_CheckedChanged(object sender, EventArgs e)
{
Properties.Settings.Default.enableResolveDependencies = enableResolveDependencies.Checked;
Properties.Settings.Default.Save();
assetsManager.ResolveDependencies = enableResolveDependencies.Checked;
}
private void skipContainer_CheckedChanged(object sender, EventArgs e)
{
Properties.Settings.Default.skipContainer = skipContainer.Checked;
Properties.Settings.Default.Save();
SkipContainer = skipContainer.Checked;
}
private void displayAssetInfo_Check(object sender, EventArgs e) private void displayAssetInfo_Check(object sender, EventArgs e)
{ {
if (displayInfo.Checked && assetInfoLabel.Text != null) if (displayInfo.Checked && assetInfoLabel.Text != null)
@@ -529,6 +516,12 @@ namespace AssetStudioGUI
{ {
var exportOpt = new ExportOptions(); var exportOpt = new ExportOptions();
exportOpt.ShowDialog(this); exportOpt.ShowDialog(this);
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
foreach (var exportable in types)
{
if (assetsManager.ExportableTypes.ContainsKey(exportable.Key))
assetsManager.ExportableTypes[exportable.Key] = exportable.Value;
}
} }
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
@@ -1737,7 +1730,7 @@ namespace AssetStudioGUI
{ {
return; return;
} }
if (skipContainer.Checked) if (Properties.Settings.Default.skipContainer)
{ {
Logger.Info("Skip container is enabled, aborting..."); Logger.Info("Skip container is enabled, aborting...");
return; return;
@@ -1937,12 +1930,6 @@ namespace AssetStudioGUI
InvokeUpdate(miscToolStripMenuItem, true); InvokeUpdate(miscToolStripMenuItem, true);
} }
private void toolStripMenuItem23_Click(object sender, EventArgs e)
{
var form = new CNUnityForm();
form.Show();
}
private void resetToolStripMenuItem_Click(object sender, EventArgs e) private void resetToolStripMenuItem_Click(object sender, EventArgs e)
{ {
ResetForm(); ResetForm();
@@ -1978,7 +1965,7 @@ namespace AssetStudioGUI
private async void loadAIToolStripMenuItem_Click(object sender, EventArgs e) private async void loadAIToolStripMenuItem_Click(object sender, EventArgs e)
{ {
if (skipContainer.Checked) if (Properties.Settings.Default.skipContainer)
{ {
Logger.Info("Skip container is enabled, aborting..."); Logger.Info("Skip container is enabled, aborting...");
return; return;

View File

@@ -1,94 +0,0 @@
namespace AssetStudioGUI
{
partial class CNUnityForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.specifyCNUnityList = new System.Windows.Forms.DataGridView();
this.NameField = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.KeyField = new System.Windows.Forms.DataGridViewTextBoxColumn();
((System.ComponentModel.ISupportInitialize)(this.specifyCNUnityList)).BeginInit();
this.SuspendLayout();
//
// specifyCNUnityList
//
this.specifyCNUnityList.AllowUserToResizeColumns = false;
this.specifyCNUnityList.AllowUserToResizeRows = false;
this.specifyCNUnityList.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
this.specifyCNUnityList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.specifyCNUnityList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.NameField,
this.KeyField});
this.specifyCNUnityList.Dock = System.Windows.Forms.DockStyle.Fill;
this.specifyCNUnityList.Location = new System.Drawing.Point(0, 0);
this.specifyCNUnityList.MultiSelect = false;
this.specifyCNUnityList.Name = "specifyCNUnityList";
this.specifyCNUnityList.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
this.specifyCNUnityList.RowTemplate.Height = 25;
this.specifyCNUnityList.Size = new System.Drawing.Size(432, 229);
this.specifyCNUnityList.TabIndex = 0;
this.specifyCNUnityList.RowHeaderMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.specifyCNUnityList_RowHeaderMouseDoubleClick);
//
// NameField
//
this.NameField.HeaderText = "Name";
this.NameField.Name = "NameField";
this.NameField.Width = 140;
//
// KeyField
//
this.KeyField.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.KeyField.HeaderText = "Key";
this.KeyField.Name = "KeyField";
//
// CNUnityForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(432, 229);
this.Controls.Add(this.specifyCNUnityList);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CNUnityForm";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CNUnityForm";
this.TopMost = true;
((System.ComponentModel.ISupportInitialize)(this.specifyCNUnityList)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView specifyCNUnityList;
private System.Windows.Forms.DataGridViewTextBoxColumn NameField;
private System.Windows.Forms.DataGridViewTextBoxColumn KeyField;
}
}

View File

@@ -1,126 +0,0 @@
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using AssetStudio;
using System.Linq;
namespace AssetStudioGUI
{
public partial class CNUnityForm : Form
{
public CNUnityForm()
{
InitializeComponent();
var keys = CNUnityKeyManager.GetEntries();
for (int i = 0; i < keys.Length; i++)
{
var key = keys[i];
var rowIdx = specifyCNUnityList.Rows.Add();
specifyCNUnityList.Rows[rowIdx].Cells["NameField"].Value = key.Name;
specifyCNUnityList.Rows[rowIdx].Cells["KeyField"].Value = key.Key;
}
var index = Properties.Settings.Default.selectedCNUnityKey;
if (index >= specifyCNUnityList.RowCount)
{
index = 0;
}
specifyCNUnityList.CurrentCell = specifyCNUnityList.Rows[index].Cells[0];
}
private void OKbutton_Click(object sender, EventArgs e)
{
var keys = new List<CNUnity.Entry>();
for (int i = specifyCNUnityList.Rows.Count - 1; i >= 0; i--)
{
var row = specifyCNUnityList.Rows[i];
var name = row.Cells["NameField"].Value as string;
var key = row.Cells["KeyField"].Value as string;
if (!(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key)))
{
var cnunity = new CNUnity.Entry(name, key);
if (cnunity.Validate())
{
keys.Add(cnunity);
continue;
}
}
if (specifyCNUnityList.CurrentCell.RowIndex == row.Index)
{
var previousRow = specifyCNUnityList.Rows.Cast<DataGridViewRow>().ElementAtOrDefault(i - 1);
if (previousRow != null)
{
specifyCNUnityList.CurrentCell = previousRow.Cells[0];
}
}
if (i != specifyCNUnityList.RowCount - 1)
{
specifyCNUnityList.Rows.RemoveAt(i);
}
}
CNUnityKeyManager.SaveEntries(keys.Reverse<CNUnity.Entry>().ToList());
CNUnityKeyManager.SetKey(specifyCNUnityList.CurrentRow.Index);
Properties.Settings.Default.selectedCNUnityKey = specifyCNUnityList.CurrentRow.Index;
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
Close();
}
private void Cancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void specifyCNUnityList_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
{
var keys = new List<CNUnity.Entry>();
for (int i = specifyCNUnityList.Rows.Count - 1; i >= 0; i--)
{
var row = specifyCNUnityList.Rows[i];
var name = row.Cells["NameField"].Value as string;
var key = row.Cells["KeyField"].Value as string;
if (!(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key)))
{
var cnunity = new CNUnity.Entry(name, key);
if (cnunity.Validate())
{
keys.Add(cnunity);
continue;
}
}
if (specifyCNUnityList.CurrentCell.RowIndex == row.Index)
{
var previousRow = specifyCNUnityList.Rows.Cast<DataGridViewRow>().ElementAtOrDefault(i - 1);
if (previousRow != null)
{
specifyCNUnityList.CurrentCell = previousRow.Cells[0];
}
}
if (i != specifyCNUnityList.RowCount - 1)
{
specifyCNUnityList.Rows.RemoveAt(i);
}
}
CNUnityKeyManager.SaveEntries(keys.Reverse<CNUnity.Entry>().ToList());
CNUnityKeyManager.SetKey(specifyCNUnityList.CurrentRow.Index);
Properties.Settings.Default.selectedCNUnityKey = specifyCNUnityList.CurrentRow.Index;
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
Close();
}
}
}

View File

@@ -1,66 +0,0 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="NameField.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="KeyField.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
using AssetStudio; using AssetStudio;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
namespace AssetStudioGUI namespace AssetStudioGUI
@@ -31,19 +34,35 @@ namespace AssetStudioGUI
exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape; exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape;
castToBone.Checked = Properties.Settings.Default.castToBone; castToBone.Checked = Properties.Settings.Default.castToBone;
exportAllUvsAsDiffuseMaps.Checked = Properties.Settings.Default.exportAllUvsAsDiffuseMaps; exportAllUvsAsDiffuseMaps.Checked = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
exportUV0UV1.Checked = Properties.Settings.Default.exportUV0UV1;
boneSize.Value = Properties.Settings.Default.boneSize; boneSize.Value = Properties.Settings.Default.boneSize;
scaleFactor.Value = Properties.Settings.Default.scaleFactor; scaleFactor.Value = Properties.Settings.Default.scaleFactor;
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion; fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat; fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
skipRenderer.Checked = Properties.Settings.Default.skipRenderer;
exportMiHoYoBinData.Checked = Properties.Settings.Default.exportMiHoYoBinData;
collectAnimations.Checked = Properties.Settings.Default.collectAnimations; collectAnimations.Checked = Properties.Settings.Default.collectAnimations;
encrypted.Checked = Properties.Settings.Default.encrypted; encrypted.Checked = Properties.Settings.Default.encrypted;
key.Value = Properties.Settings.Default.key; key.Value = Properties.Settings.Default.key;
exportableTypes.Items.AddRange(Studio.assetsManager.ExportableTypes.Keys.Select(x => x.ToString()).ToArray());
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
foreach (var exportable in types)
{
var idx = exportableTypes.Items.IndexOf(exportable.Key.ToString());
if (idx != -1)
exportableTypes.SetItemChecked(idx, exportable.Value);
}
} }
private void OKbutton_Click(object sender, EventArgs e) private void OKbutton_Click(object sender, EventArgs e)
{ {
var types = new Dictionary<ClassIDType, bool>();
for (int i = 0; i < exportableTypes.Items.Count; i++)
{
var type = Enum.Parse<ClassIDType>(exportableTypes.Items[i].ToString());
var state = exportableTypes.GetItemChecked(i);
types.Add(type, state);
}
Properties.Settings.Default.exportableTypes = JsonConvert.SerializeObject(types);
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex; Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked; Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
Properties.Settings.Default.convertTexture = converttexture.Checked; Properties.Settings.Default.convertTexture = converttexture.Checked;
@@ -65,17 +84,15 @@ namespace AssetStudioGUI
Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked; Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked;
Properties.Settings.Default.castToBone = castToBone.Checked; Properties.Settings.Default.castToBone = castToBone.Checked;
Properties.Settings.Default.exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked; Properties.Settings.Default.exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;
Properties.Settings.Default.exportUV0UV1 = exportUV0UV1.Checked;
Properties.Settings.Default.boneSize = boneSize.Value; Properties.Settings.Default.boneSize = boneSize.Value;
Properties.Settings.Default.scaleFactor = scaleFactor.Value; Properties.Settings.Default.scaleFactor = scaleFactor.Value;
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex; Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex; Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex;
Properties.Settings.Default.skipRenderer = skipRenderer.Checked;
Properties.Settings.Default.exportMiHoYoBinData = exportMiHoYoBinData.Checked;
Properties.Settings.Default.collectAnimations = collectAnimations.Checked; Properties.Settings.Default.collectAnimations = collectAnimations.Checked;
Properties.Settings.Default.encrypted = encrypted.Checked; Properties.Settings.Default.encrypted = encrypted.Checked;
Properties.Settings.Default.key = (byte)key.Value; Properties.Settings.Default.key = (byte)key.Value;
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
Renderer.Skipped = !Properties.Settings.Default.skipRenderer;
MiHoYoBinData.Key = (byte)key.Value; MiHoYoBinData.Key = (byte)key.Value;
MiHoYoBinData.Encrypted = encrypted.Checked; MiHoYoBinData.Encrypted = encrypted.Checked;
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;

View File

@@ -60,13 +60,16 @@
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
</metadata> </metadata>
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>162, 17</value> <value>162, 17</value>
</metadata> </metadata>
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="skipToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>162, 17</value> <value>404, 17</value>
</metadata>
<metadata name="resolveToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>273, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>57</value>
</metadata> </metadata>
</root> </root>

View File

@@ -360,11 +360,12 @@ namespace AssetStudioGUI
var castToBone = Properties.Settings.Default.castToBone; var castToBone = Properties.Settings.Default.castToBone;
var boneSize = (int)Properties.Settings.Default.boneSize; var boneSize = (int)Properties.Settings.Default.boneSize;
var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps; var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
var exportUV0UV1 = Properties.Settings.Default.exportUV0UV1;
var scaleFactor = (float)Properties.Settings.Default.scaleFactor; var scaleFactor = (float)Properties.Settings.Default.scaleFactor;
var fbxVersion = Properties.Settings.Default.fbxVersion; var fbxVersion = Properties.Settings.Default.fbxVersion;
var fbxFormat = Properties.Settings.Default.fbxFormat; var fbxFormat = Properties.Settings.Default.fbxFormat;
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1); exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, exportUV0UV1, scaleFactor, fbxVersion, fbxFormat == 1);
} }
public static bool ExportDumpFile(AssetItem item, string exportPath) public static bool ExportDumpFile(AssetItem item, string exportPath)

Binary file not shown.

Binary file not shown.

View File

@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -311,18 +311,6 @@ namespace AssetStudioGUI.Properties {
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool skipRenderer {
get {
return ((bool)(this["skipRenderer"]));
}
set {
this["skipRenderer"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]
@@ -347,18 +335,6 @@ namespace AssetStudioGUI.Properties {
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int selectedCNUnityKey {
get {
return ((int)(this["selectedCNUnityKey"]));
}
set {
this["selectedCNUnityKey"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")] [global::System.Configuration.DefaultSettingValueAttribute("0")]
@@ -406,5 +382,31 @@ namespace AssetStudioGUI.Properties {
this["skipContainer"] = value; this["skipContainer"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool exportUV0UV1 {
get {
return ((bool)(this["exportUV0UV1"]));
}
set {
this["exportUV0UV1"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("{\"GameObject\":true,\"Material\":true,\"Texture2D\":true,\"Mesh\":true,\"Renderer\":true,\"" +
"Shader\":true,\"TextAsset\":true,\"AnimationClip\":true,\"Font\":true,\"Sprite\":true,\"An" +
"imator\":true,\"MiHoYoBinData\":true,\"AssetBundle\":true}")]
public string exportableTypes {
get {
return ((string)(this["exportableTypes"]));
}
set {
this["exportableTypes"] = value;
}
}
} }
} }

View File

@@ -74,18 +74,12 @@
<Setting Name="encrypted" Type="System.Boolean" Scope="User"> <Setting Name="encrypted" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="skipRenderer" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="selectedGame" Type="System.Int32" Scope="User"> <Setting Name="selectedGame" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value> <Value Profile="(Default)">0</Value>
</Setting> </Setting>
<Setting Name="enableResolveDependencies" Type="System.Boolean" Scope="User"> <Setting Name="enableResolveDependencies" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="selectedCNUnityKey" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="selectedAssetMapType" Type="System.Int32" Scope="User"> <Setting Name="selectedAssetMapType" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value> <Value Profile="(Default)">0</Value>
</Setting> </Setting>
@@ -98,5 +92,11 @@
<Setting Name="skipContainer" Type="System.Boolean" Scope="User"> <Setting Name="skipContainer" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value> <Value Profile="(Default)">False</Value>
</Setting> </Setting>
<Setting Name="exportUV0UV1" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="exportableTypes" Type="System.String" Scope="User">
<Value Profile="(Default)">{"GameObject":true,"Material":true,"Texture2D":true,"Mesh":true,"Renderer":true,"Shader":true,"TextAsset":true,"AnimationClip":true,"Font":true,"Sprite":true,"Animator":true,"MiHoYoBinData":true,"AssetBundle":true}</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@@ -4,6 +4,13 @@ using AssetStudio.PInvoke;
namespace ACLLibs namespace ACLLibs
{ {
public struct DecompressedClip
{
public IntPtr Values;
public int ValuesCount;
public IntPtr Times;
public int TimesCount;
}
public static class ACL public static class ACL
{ {
private const string DLL_NAME = "acl"; private const string DLL_NAME = "acl";
@@ -13,27 +20,30 @@ namespace ACLLibs
} }
public static void DecompressAll(byte[] data, out float[] values, out float[] times) public static void DecompressAll(byte[] data, out float[] values, out float[] times)
{ {
var pinned = GCHandle.Alloc(data, GCHandleType.Pinned); var decompressedClip = new DecompressedClip();
var pData = pinned.AddrOfPinnedObject(); DecompressAll(data, ref decompressedClip);
DecompressAll(pData, out var pValues, out var numValues, out var pTimes, out var numTimes);
pinned.Free();
values = new float[numValues]; values = new float[decompressedClip.ValuesCount];
Marshal.Copy(pValues, values, 0, numValues); Marshal.Copy(decompressedClip.Values, values, 0, decompressedClip.ValuesCount);
times = new float[numTimes]; times = new float[decompressedClip.TimesCount];
Marshal.Copy(pTimes, times, 0, numTimes); Marshal.Copy(decompressedClip.Times, times, 0, decompressedClip.TimesCount);
Dispose(ref decompressedClip);
} }
#region importfunctions #region importfunctions
[DllImport(DLL_NAME)] [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); private static extern void DecompressAll(byte[] data, ref DecompressedClip decompressedClip);
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern void Dispose(ref DecompressedClip decompressedClip);
#endregion #endregion
} }
public static partial class SRACL public static class SRACL
{ {
private const string DLL_NAME = "sracl"; private const string DLL_NAME = "sracl";
static SRACL() static SRACL()
@@ -42,22 +52,25 @@ namespace ACLLibs
} }
public static void DecompressAll(byte[] data, out float[] values, out float[] times) public static void DecompressAll(byte[] data, out float[] values, out float[] times)
{ {
var pinned = GCHandle.Alloc(data, GCHandleType.Pinned); var decompressedClip = new DecompressedClip();
var pData = pinned.AddrOfPinnedObject(); DecompressAll(data, ref decompressedClip);
DecompressAll(pData, out var pValues, out var numValues, out var pTimes, out var numTimes);
pinned.Free();
values = new float[numValues]; values = new float[decompressedClip.ValuesCount];
Marshal.Copy(pValues, values, 0, numValues); Marshal.Copy(decompressedClip.Values, values, 0, decompressedClip.ValuesCount);
times = new float[numTimes]; times = new float[decompressedClip.TimesCount];
Marshal.Copy(pTimes, times, 0, numTimes); Marshal.Copy(decompressedClip.Times, times, 0, decompressedClip.TimesCount);
Dispose(ref decompressedClip);
} }
#region importfunctions #region importfunctions
[DllImport(DLL_NAME)] [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern void DecompressAll(IntPtr data, out IntPtr pValues, out int numValues, out IntPtr pTimes, out int numTimes); private static extern void DecompressAll(byte[] data, ref DecompressedClip decompressedClip);
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern void Dispose(ref DecompressedClip decompressedClip);
#endregion #endregion
} }

View File

@@ -3,9 +3,9 @@
public static class ModelExporter public static class ModelExporter
{ {
public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision, public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii) bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, bool exportUV0UV1, float scaleFactor, int versionIndex, bool isAscii)
{ {
Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allNodes, skins, animation, blendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii); Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allNodes, skins, animation, blendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, exportUV0UV1, scaleFactor, versionIndex, isAscii);
} }
} }
} }