Added UnityCN.
This commit is contained in:
@@ -15,5 +15,11 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="ZstdSharp.Port" Version="0.7.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Keys.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace AssetStudio
|
||||
BlocksInfoAtTheEnd = 0x80,
|
||||
OldWebPluginCompatibility = 0x100,
|
||||
BlockInfoNeedPaddingAtStart = 0x200,
|
||||
UnityCNEncryption = 0x400
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -66,6 +67,7 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
private Game Game;
|
||||
private UnityCN UnityCN;
|
||||
|
||||
public Header m_Header;
|
||||
private Node[] m_DirectoryInfo;
|
||||
@@ -75,6 +77,7 @@ namespace AssetStudio
|
||||
|
||||
|
||||
private bool HasUncompressedDataHash = true;
|
||||
private bool HasBlockInfoNeedPaddingAtStart = true;
|
||||
|
||||
public BundleFile(FileReader reader, Game game)
|
||||
{
|
||||
@@ -100,6 +103,10 @@ namespace AssetStudio
|
||||
case "UnityFS":
|
||||
case "ENCR":
|
||||
ReadHeader(reader);
|
||||
if (game.Type.IsUnityCN())
|
||||
{
|
||||
ReadUnityCN(reader);
|
||||
}
|
||||
ReadBlocksInfoAndDirectory(reader);
|
||||
using (var blocksStream = CreateBlocksStream(reader.FullPath))
|
||||
{
|
||||
@@ -312,6 +319,32 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadUnityCN(EndianBinaryReader reader)
|
||||
{
|
||||
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;
|
||||
HasBlockInfoNeedPaddingAtStart = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = ArchiveFlags.UnityCNEncryption;
|
||||
HasBlockInfoNeedPaddingAtStart = true;
|
||||
}
|
||||
|
||||
if ((m_Header.flags & mask) != 0)
|
||||
{
|
||||
UnityCN = new UnityCN(reader);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(FileReader reader)
|
||||
{
|
||||
byte[] blocksInfoBytes;
|
||||
@@ -403,7 +436,7 @@ namespace AssetStudio
|
||||
};
|
||||
}
|
||||
}
|
||||
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
|
||||
if (HasBlockInfoNeedPaddingAtStart && (m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
@@ -439,14 +472,18 @@ namespace AssetStudio
|
||||
{
|
||||
compressedBytesSpan = Mr0kUtils.Decrypt(compressedBytesSpan, (Mr0k)Game);
|
||||
}
|
||||
if (Game.Type.IsOPFP())
|
||||
if (Game.Type.IsUnityCN() && ((int)blockInfo.flags & 0x100) != 0)
|
||||
{
|
||||
OPFPUtils.Decrypt(compressedBytesSpan, reader.FullPath);
|
||||
UnityCN.DecryptBlock(compressedBytes, compressedSize, i);
|
||||
}
|
||||
if (Game.Type.IsNetEase() && i == 0)
|
||||
{
|
||||
NetEaseUtils.Decrypt(compressedBytesSpan);
|
||||
}
|
||||
if (Game.Type.IsOPFP())
|
||||
{
|
||||
OPFPUtils.Decrypt(compressedBytesSpan, reader.FullPath);
|
||||
}
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var uncompressedBytesSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
|
||||
|
||||
158
AssetStudio/Crypto/UnityCN.cs
Normal file
158
AssetStudio/Crypto/UnityCN.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class UnityCN
|
||||
{
|
||||
private const string Signature = "#$unity3dchina!@";
|
||||
|
||||
private static ICryptoTransform Encryptor;
|
||||
|
||||
public byte[] Index = new byte[0x10];
|
||||
public byte[] Sub = new byte[0x10];
|
||||
|
||||
public UnityCN(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 = Convert.FromHexString(entry.Key);
|
||||
|
||||
Encryptor = aes.CreateEncryptor();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"[UnityCN] 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.Slice(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 class 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 = Convert.FromHexString(Key);
|
||||
if (bytes.Length != 0x10)
|
||||
{
|
||||
Logger.Warning($"[UnityCN] {this} has invalid key, size should be 16 bytes, skipping...");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Name} ({Key})";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace AssetStudio
|
||||
{
|
||||
int index = 0;
|
||||
Games.Add(index++, new(GameType.Normal));
|
||||
Games.Add(index++, new(GameType.UnityCN));
|
||||
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_CB1));
|
||||
@@ -116,6 +117,7 @@ namespace AssetStudio
|
||||
public enum GameType
|
||||
{
|
||||
Normal,
|
||||
UnityCN,
|
||||
GI,
|
||||
GI_Pack,
|
||||
GI_CB1,
|
||||
@@ -142,6 +144,7 @@ namespace AssetStudio
|
||||
public static class GameTypes
|
||||
{
|
||||
public static bool IsNormal(this GameType type) => type == GameType.Normal;
|
||||
public static bool IsUnityCN(this GameType type) => type == GameType.UnityCN;
|
||||
public static bool IsGI(this GameType type) => type == GameType.GI;
|
||||
public static bool IsGIPack(this GameType type) => type == GameType.GI_Pack;
|
||||
public static bool IsGICB1(this GameType type) => type == GameType.GI_CB1;
|
||||
|
||||
86
AssetStudio/Keys.json
Normal file
86
AssetStudio/Keys.json
Normal file
@@ -0,0 +1,86 @@
|
||||
[
|
||||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"Name": "Dynasty Legends 2",
|
||||
"Key": "746169686567616D6573323032323032"
|
||||
},
|
||||
{
|
||||
"Name": "Evernight CN",
|
||||
"Key": "68687878747478736868787874747873"
|
||||
},
|
||||
{
|
||||
"Name": "Xintianlong Babu",
|
||||
"Key": "61323562623133346363326464333265"
|
||||
},
|
||||
{
|
||||
"Name": "Frostpunk: Beyond the Ice",
|
||||
"Key": "7368756978696E673838383838383838"
|
||||
}
|
||||
]
|
||||
74
AssetStudio/UnityCNManager.cs
Normal file
74
AssetStudio/UnityCNManager.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class UnityCNManager
|
||||
{
|
||||
public const string KeysFileName = "Keys.json";
|
||||
|
||||
private static List<UnityCN.Entry> Entries = new List<UnityCN.Entry>();
|
||||
|
||||
static UnityCNManager()
|
||||
{
|
||||
var str = File.ReadAllText(KeysFileName);
|
||||
Entries = JsonConvert.DeserializeObject<List<UnityCN.Entry>>(str);
|
||||
}
|
||||
|
||||
public static void SaveEntries(List<UnityCN.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 unityCN))
|
||||
{
|
||||
if (UnityCN.SetKey(unityCN))
|
||||
{
|
||||
Logger.Info($"[UnityCN] Selected Key is {unityCN}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"[UnityCN] No Key is selected !!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error("Invalid Key !!");
|
||||
Logger.Warning(GetEntries().Select(x => x.ToString()).ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetEntry(int index, out UnityCN.Entry key)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (index < 0 || index > Entries.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
key = Entries[index];
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.Error($"[UnityCN] Invalid Index, check if list is not empty !!\n{e.Message}");
|
||||
key = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static UnityCN.Entry[] GetEntries() => Entries.ToArray();
|
||||
|
||||
public new static string ToString() => string.Join("\n", GetEntries().Select((x, i) => $"{i}: {x.Name}"));
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace AssetStudioCLI
|
||||
optionsBinder.NameFilter,
|
||||
optionsBinder.ContainerFilter,
|
||||
optionsBinder.GameName,
|
||||
optionsBinder.KeyIndex,
|
||||
optionsBinder.MapOp,
|
||||
optionsBinder.MapType,
|
||||
optionsBinder.MapName,
|
||||
@@ -50,6 +51,7 @@ namespace AssetStudioCLI
|
||||
public Regex[] NameFilter { get; set; }
|
||||
public Regex[] ContainerFilter { get; set; }
|
||||
public string GameName { get; set; }
|
||||
public int KeyIndex { get; set; }
|
||||
public MapOpType MapOp { get; set; }
|
||||
public ExportListType MapType { get; set; }
|
||||
public string MapName { get; set; }
|
||||
@@ -69,6 +71,7 @@ namespace AssetStudioCLI
|
||||
public readonly Option<Regex[]> NameFilter;
|
||||
public readonly Option<Regex[]> ContainerFilter;
|
||||
public readonly Option<string> GameName;
|
||||
public readonly Option<int> KeyIndex;
|
||||
public readonly Option<MapOpType> MapOp;
|
||||
public readonly Option<ExportListType> MapType;
|
||||
public readonly Option<string> MapName;
|
||||
@@ -88,6 +91,7 @@ namespace AssetStudioCLI
|
||||
NameFilter = new Option<Regex[]>("--names", result => result.Tokens.Select(x => new Regex(x.Value, RegexOptions.IgnoreCase)).ToArray(), false, "Specify name regex filter(s).") { AllowMultipleArgumentsPerToken = true };
|
||||
ContainerFilter = new Option<Regex[]>("--containers", result => result.Tokens.Select(x => new Regex(x.Value, RegexOptions.IgnoreCase)).ToArray(), false, "Specify container regex filter(s).") { AllowMultipleArgumentsPerToken = true };
|
||||
GameName = new Option<string>("--game", $"Specify Game.") { IsRequired = true };
|
||||
KeyIndex = new Option<int>("--key_index", "Specify key index.") { ArgumentHelpName = UnityCNManager.ToString() };
|
||||
MapOp = new Option<MapOpType>("--map_op", "Specify which map to build.");
|
||||
MapType = new Option<ExportListType>("--map_type", "AssetMap output type.");
|
||||
MapName = new Option<string>("--map_name", () => "assets_map", "Specify AssetMap file name.");
|
||||
@@ -141,6 +145,7 @@ namespace AssetStudioCLI
|
||||
GroupAssetsType.SetDefaultValue(AssetGroupOption.ByType);
|
||||
MapOp.SetDefaultValue(MapOpType.None);
|
||||
MapType.SetDefaultValue(ExportListType.XML);
|
||||
KeyIndex.SetDefaultValue(0);
|
||||
}
|
||||
|
||||
public void FilterValidator(OptionResult result)
|
||||
@@ -174,6 +179,7 @@ namespace AssetStudioCLI
|
||||
NameFilter = bindingContext.ParseResult.GetValueForOption(NameFilter),
|
||||
ContainerFilter = bindingContext.ParseResult.GetValueForOption(ContainerFilter),
|
||||
GameName = bindingContext.ParseResult.GetValueForOption(GameName),
|
||||
KeyIndex = bindingContext.ParseResult.GetValueForOption(KeyIndex),
|
||||
MapOp = bindingContext.ParseResult.GetValueForOption(MapOp),
|
||||
MapType = bindingContext.ParseResult.GetValueForOption(MapType),
|
||||
MapName = bindingContext.ParseResult.GetValueForOption(MapName),
|
||||
|
||||
@@ -25,6 +25,19 @@ namespace AssetStudioCLI
|
||||
return;
|
||||
}
|
||||
|
||||
if (game.Type.IsUnityCN())
|
||||
{
|
||||
if (!UnityCNManager.TryGetEntry(o.KeyIndex, out var unityCN))
|
||||
{
|
||||
Console.WriteLine("Invalid key index !!");
|
||||
Console.WriteLine($"Available Options: \n{UnityCNManager.ToString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
UnityCN.SetKey(unityCN);
|
||||
Logger.Info($"[UnityCN] Selected Key is {unityCN}");
|
||||
}
|
||||
|
||||
Studio.Game = game;
|
||||
Logger.Default = new ConsoleLogger();
|
||||
AssetsHelper.Minimal = Settings.Default.minimalAssetMap;
|
||||
|
||||
@@ -109,6 +109,9 @@
|
||||
<setting name="enableModelPreview" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="selectedUnityCNKey" serializeAs="String">
|
||||
<value>0</value>
|
||||
</setting>
|
||||
</AssetStudioGUI.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
69
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
69
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@@ -44,12 +44,15 @@ namespace AssetStudioGUI
|
||||
abortStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
displayAll = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
|
||||
enablePreview = new System.Windows.Forms.ToolStripMenuItem();
|
||||
enableModelPreview = new System.Windows.Forms.ToolStripMenuItem();
|
||||
modelsOnly = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
|
||||
displayInfo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
enableResolveDependencies = new System.Windows.Forms.ToolStripMenuItem();
|
||||
skipContainer = new System.Windows.Forms.ToolStripMenuItem();
|
||||
displayInfo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
|
||||
toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();
|
||||
toolStripMenuItem18 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -164,9 +167,8 @@ namespace AssetStudioGUI
|
||||
exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
|
||||
toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
|
||||
toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
|
||||
specifyUnityCNKey = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
|
||||
menuStrip1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
|
||||
splitContainer1.Panel1.SuspendLayout();
|
||||
@@ -258,7 +260,7 @@ namespace AssetStudioGUI
|
||||
//
|
||||
// optionsToolStripMenuItem
|
||||
//
|
||||
optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { displayAll, toolStripSeparator10, enablePreview, enableModelPreview, modelsOnly, toolStripSeparator11, displayInfo, enableResolveDependencies, skipContainer, toolStripSeparator12, toolStripMenuItem14, toolStripMenuItem18, toolStripMenuItem19, showExpOpt });
|
||||
optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { displayAll, toolStripSeparator10, enablePreview, enableModelPreview, modelsOnly, toolStripSeparator11, displayInfo, enableResolveDependencies, skipContainer, toolStripSeparator12, toolStripMenuItem14, specifyUnityCNKey, toolStripSeparator13, toolStripMenuItem18, toolStripMenuItem19, showExpOpt });
|
||||
optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
optionsToolStripMenuItem.Text = "Options";
|
||||
@@ -272,6 +274,11 @@ namespace AssetStudioGUI
|
||||
displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can export the RAW file.";
|
||||
displayAll.CheckedChanged += displayAll_CheckedChanged;
|
||||
//
|
||||
// toolStripSeparator10
|
||||
//
|
||||
toolStripSeparator10.Name = "toolStripSeparator10";
|
||||
toolStripSeparator10.Size = new System.Drawing.Size(222, 6);
|
||||
//
|
||||
// enablePreview
|
||||
//
|
||||
enablePreview.Checked = true;
|
||||
@@ -299,6 +306,22 @@ namespace AssetStudioGUI
|
||||
modelsOnly.Text = "Filter models only";
|
||||
modelsOnly.CheckedChanged += modelsOnly_CheckedChanged;
|
||||
//
|
||||
// toolStripSeparator11
|
||||
//
|
||||
toolStripSeparator11.Name = "toolStripSeparator11";
|
||||
toolStripSeparator11.Size = new System.Drawing.Size(222, 6);
|
||||
//
|
||||
// displayInfo
|
||||
//
|
||||
displayInfo.Checked = true;
|
||||
displayInfo.CheckOnClick = true;
|
||||
displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
displayInfo.Name = "displayInfo";
|
||||
displayInfo.Size = new System.Drawing.Size(225, 22);
|
||||
displayInfo.Text = "Display asset information";
|
||||
displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, format, audio bitrate, etc.";
|
||||
displayInfo.CheckedChanged += displayAssetInfo_Check;
|
||||
//
|
||||
// enableResolveDependencies
|
||||
//
|
||||
enableResolveDependencies.Checked = true;
|
||||
@@ -316,20 +339,13 @@ namespace AssetStudioGUI
|
||||
skipContainer.Name = "skipContainer";
|
||||
skipContainer.Size = new System.Drawing.Size(225, 22);
|
||||
skipContainer.Text = "Skip container recovery";
|
||||
skipContainer.ToolTipText = "Skips the container recovery step.\nImproves loading when dealing with a large num" +
|
||||
"ber of files.";
|
||||
skipContainer.ToolTipText = "Skips the container recovery step.\nImproves loading when dealing with a large number of files.";
|
||||
skipContainer.CheckedChanged += skipContainer_CheckedChanged;
|
||||
//
|
||||
// displayInfo
|
||||
// toolStripSeparator12
|
||||
//
|
||||
displayInfo.Checked = true;
|
||||
displayInfo.CheckOnClick = true;
|
||||
displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
displayInfo.Name = "displayInfo";
|
||||
displayInfo.Size = new System.Drawing.Size(225, 22);
|
||||
displayInfo.Text = "Display asset information";
|
||||
displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, format, audio bitrate, etc.";
|
||||
displayInfo.CheckedChanged += displayAssetInfo_Check;
|
||||
toolStripSeparator12.Name = "toolStripSeparator12";
|
||||
toolStripSeparator12.Size = new System.Drawing.Size(222, 6);
|
||||
//
|
||||
// toolStripMenuItem14
|
||||
//
|
||||
@@ -1292,20 +1308,17 @@ namespace AssetStudioGUI
|
||||
showOriginalFileToolStripMenuItem.Visible = false;
|
||||
showOriginalFileToolStripMenuItem.Click += showOriginalFileToolStripMenuItem_Click;
|
||||
//
|
||||
// toolStripSeparator10
|
||||
// specifyUnityCNKey
|
||||
//
|
||||
toolStripSeparator10.Name = "toolStripSeparator10";
|
||||
toolStripSeparator10.Size = new System.Drawing.Size(222, 6);
|
||||
specifyUnityCNKey.Name = "specifyUnityCNKey";
|
||||
specifyUnityCNKey.Size = new System.Drawing.Size(225, 22);
|
||||
specifyUnityCNKey.Text = "Specify UnityCN Key";
|
||||
specifyUnityCNKey.Click += specifyUnityCNKey_Click;
|
||||
//
|
||||
// toolStripSeparator11
|
||||
// toolStripSeparator13
|
||||
//
|
||||
toolStripSeparator11.Name = "toolStripSeparator11";
|
||||
toolStripSeparator11.Size = new System.Drawing.Size(222, 6);
|
||||
//
|
||||
// toolStripSeparator12
|
||||
//
|
||||
toolStripSeparator12.Name = "toolStripSeparator12";
|
||||
toolStripSeparator12.Size = new System.Drawing.Size(222, 6);
|
||||
toolStripSeparator13.Name = "toolStripSeparator13";
|
||||
toolStripSeparator13.Size = new System.Drawing.Size(222, 6);
|
||||
//
|
||||
// AssetStudioGUIForm
|
||||
//
|
||||
@@ -1491,6 +1504,8 @@ namespace AssetStudioGUI
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator10;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator11;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator12;
|
||||
private System.Windows.Forms.ToolStripMenuItem specifyUnityCNKey;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator13;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ namespace AssetStudioGUI
|
||||
Logger.Info($"Target Game type is {Studio.Game.Type}");
|
||||
|
||||
MapNameComboBox.SelectedIndexChanged += new EventHandler(specifyNameComboBox_SelectedIndexChanged);
|
||||
UnityCNManager.SetKey(Properties.Settings.Default.selectedUnityCNKey);
|
||||
}
|
||||
private void AssetStudioGUIForm_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
@@ -274,6 +275,10 @@ namespace AssetStudioGUI
|
||||
{
|
||||
productName = Studio.Game.Name;
|
||||
}
|
||||
else if (Studio.Game.Type.IsUnityCN() && UnityCNManager.TryGetEntry(Properties.Settings.Default.selectedUnityCNKey, out var unityCN))
|
||||
{
|
||||
productName = unityCN.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
productName = "no productName";
|
||||
@@ -2300,6 +2305,12 @@ namespace AssetStudioGUI
|
||||
assetBrowser.Show();
|
||||
}
|
||||
|
||||
private void specifyUnityCNKey_Click(object sender, EventArgs e)
|
||||
{
|
||||
var unitycn = new UnityCNForm();
|
||||
unitycn.Show();
|
||||
}
|
||||
|
||||
#region FMOD
|
||||
private void FMODinit()
|
||||
{
|
||||
|
||||
@@ -120,9 +120,6 @@
|
||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>312, 17</value>
|
||||
</metadata>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>432, 17</value>
|
||||
</metadata>
|
||||
<data name="fontPreviewBox.Text" xml:space="preserve">
|
||||
<value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ
|
||||
1234567890.:,;'\"(!?)+-*/=
|
||||
@@ -141,6 +138,9 @@ The quick brown fox jumps over the lazy dog. 1234567890
|
||||
|
||||
The quick brown fox jumps over the lazy dog. 1234567890</value>
|
||||
</data>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>432, 17</value>
|
||||
</metadata>
|
||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>553, 17</value>
|
||||
</metadata>
|
||||
|
||||
@@ -120,6 +120,12 @@
|
||||
<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="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">
|
||||
<value>162, 17</value>
|
||||
</metadata>
|
||||
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>162, 17</value>
|
||||
</metadata>
|
||||
@@ -129,6 +135,9 @@
|
||||
<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="skipToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>404, 17</value>
|
||||
</metadata>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>57</value>
|
||||
</metadata>
|
||||
|
||||
13
AssetStudioGUI/Properties/Settings.Designer.cs
generated
13
AssetStudioGUI/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.6.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -442,5 +442,16 @@ namespace AssetStudioGUI.Properties {
|
||||
this["enableModelPreview"] = value;
|
||||
}
|
||||
}
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("0")]
|
||||
public int selectedUnityCNKey {
|
||||
get {
|
||||
return ((int)(this["selectedUnityCNKey"]));
|
||||
}
|
||||
set {
|
||||
this["selectedUnityCNKey"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,5 +107,8 @@
|
||||
<Setting Name="enableModelPreview" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="selectedUnityCNKey" Type="System.Int32" Scope="User">
|
||||
<Value Profile="(Default)">0</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
94
AssetStudioGUI/UnityCNForm.Designer.cs
generated
Normal file
94
AssetStudioGUI/UnityCNForm.Designer.cs
generated
Normal file
@@ -0,0 +1,94 @@
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
partial class UnityCNForm
|
||||
{
|
||||
/// <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.specifyUnityCNList = new System.Windows.Forms.DataGridView();
|
||||
this.NameField = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.KeyField = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
((System.ComponentModel.ISupportInitialize)(this.specifyUnityCNList)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// specifyUnityCNList
|
||||
//
|
||||
this.specifyUnityCNList.AllowUserToResizeColumns = false;
|
||||
this.specifyUnityCNList.AllowUserToResizeRows = false;
|
||||
this.specifyUnityCNList.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
|
||||
this.specifyUnityCNList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.specifyUnityCNList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.NameField,
|
||||
this.KeyField});
|
||||
this.specifyUnityCNList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.specifyUnityCNList.Location = new System.Drawing.Point(0, 0);
|
||||
this.specifyUnityCNList.MultiSelect = false;
|
||||
this.specifyUnityCNList.Name = "specifyUnityCNList";
|
||||
this.specifyUnityCNList.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
|
||||
this.specifyUnityCNList.RowTemplate.Height = 25;
|
||||
this.specifyUnityCNList.Size = new System.Drawing.Size(408, 204);
|
||||
this.specifyUnityCNList.TabIndex = 0;
|
||||
this.specifyUnityCNList.RowHeaderMouseDoubleClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.specifyUnityCNList_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";
|
||||
//
|
||||
// UnityCNForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(408, 204);
|
||||
this.Controls.Add(this.specifyUnityCNList);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "UnityCNForm";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "UnityCNForm";
|
||||
this.TopMost = true;
|
||||
((System.ComponentModel.ISupportInitialize)(this.specifyUnityCNList)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.DataGridView specifyUnityCNList;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn NameField;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn KeyField;
|
||||
}
|
||||
}
|
||||
77
AssetStudioGUI/UnityCNForm.cs
Normal file
77
AssetStudioGUI/UnityCNForm.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Collections.Generic;
|
||||
using AssetStudio;
|
||||
using System.Linq;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
public partial class UnityCNForm : Form
|
||||
{
|
||||
public UnityCNForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var keys = UnityCNManager.GetEntries();
|
||||
|
||||
for (int i = 0; i < keys.Length; i++)
|
||||
{
|
||||
var key = keys[i];
|
||||
var rowIdx = specifyUnityCNList.Rows.Add();
|
||||
|
||||
specifyUnityCNList.Rows[rowIdx].Cells["NameField"].Value = key.Name;
|
||||
specifyUnityCNList.Rows[rowIdx].Cells["KeyField"].Value = key.Key;
|
||||
}
|
||||
|
||||
var index = Properties.Settings.Default.selectedUnityCNKey;
|
||||
if (index >= specifyUnityCNList.RowCount)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
specifyUnityCNList.CurrentCell = specifyUnityCNList.Rows[index].Cells[0];
|
||||
}
|
||||
|
||||
private void specifyUnityCNList_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
||||
{
|
||||
var keys = new List<UnityCN.Entry>();
|
||||
for (int i = specifyUnityCNList.Rows.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var row = specifyUnityCNList.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 unityCN = new UnityCN.Entry(name, key);
|
||||
|
||||
if (unityCN.Validate())
|
||||
{
|
||||
keys.Add(unityCN);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (specifyUnityCNList.CurrentCell.RowIndex == row.Index)
|
||||
{
|
||||
var previousRow = specifyUnityCNList.Rows.Cast<DataGridViewRow>().ElementAtOrDefault(i - 1);
|
||||
if (previousRow != null)
|
||||
{
|
||||
specifyUnityCNList.CurrentCell = previousRow.Cells[0];
|
||||
}
|
||||
}
|
||||
if (i != specifyUnityCNList.RowCount - 1)
|
||||
{
|
||||
specifyUnityCNList.Rows.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
UnityCNManager.SaveEntries(keys.Reverse<UnityCN.Entry>().ToList());
|
||||
UnityCNManager.SetKey(specifyUnityCNList.CurrentRow.Index);
|
||||
|
||||
Properties.Settings.Default.selectedUnityCNKey = specifyUnityCNList.CurrentRow.Index;
|
||||
Properties.Settings.Default.Save();
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
AssetStudioGUI/UnityCNForm.resx
Normal file
126
AssetStudioGUI/UnityCNForm.resx
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<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>
|
||||
Reference in New Issue
Block a user