private static SyntaxTree Parse(SourceText sourceText, Func <UnityParser, SyntaxNode> parseFunc) { var lexer = new UnityLexer(sourceText); var parser = new UnityParser(lexer); var result = new SyntaxTree(sourceText, syntaxTree => parseFunc(parser)); Debug.WriteLine(DateTime.Now + " - Finished parsing"); return(result); }
public Unity3dEditor(UnityParser parser, bool showContents) { Parser = parser; VirtualAnimators = new HashSet<Animator>(); if (Parser.Cabinet.Bundle != null) { for (int i = 0; i < Parser.Cabinet.Bundle.m_Container.Count; i++) { AssetInfo info = Parser.Cabinet.Bundle.m_Container[i].Value; if (info.asset.m_PathID == 0) { string msg = "Invalid container entry for " + Parser.Cabinet.Bundle.m_Container[i].Key; if (msgFilter.Add(msg)) { Report.ReportLog(msg); } continue; } if (info.asset.m_FileID == 0 && info.asset.asset.classID1 == UnityClassID.GameObject) { bool animatorFound = false; int nextPreloadIdx = info.preloadIndex + info.preloadSize; for (int j = info.preloadIndex; j < nextPreloadIdx; j++) { PPtr<Object> preTabEntry = Parser.Cabinet.Bundle.m_PreloadTable[j]; if (preTabEntry.m_FileID == 0 && preTabEntry.asset.classID1 == UnityClassID.Animator) { animatorFound = true; break; } } if (!animatorFound) { CreateVirtualAnimator(info.asset.asset); } } } } if (showContents) { string[] names = GetAssetNames(false); for (int i = 0; i < names.Length; i++) { Component asset = Parser.Cabinet.Components[i]; Console.WriteLine("PathID=" + asset.pathID.ToString("D") + " id1=" + (int)asset.classID1 + "/" + asset.classID1 + " id2=" + asset.classID2 + " " + names[i]); } } }
public static string AddFirstNewPathID(UnityParser originalParser, UnityParser modParser, string path) { int firstNewPathID = -1; for (int i = 0; i < modParser.Cabinet.Components.Count; i++) { int pathID = modParser.Cabinet.Components[i].pathID; Component comp = originalParser.Cabinet.FindComponent(pathID); if (comp == null) { firstNewPathID = pathID; break; } } return Path.GetDirectoryName(path) + @"\" + Path.GetFileNameWithoutExtension(path) + "-" + firstNewPathID + Path.GetExtension(path); }
private static SyntaxTree Parse(SourceText sourceText, Func <UnityParser, SyntaxNode> parseFunc) { var pretokenizer = new UnityPretokenizer(sourceText); var pretokenizedTokens = pretokenizer.GetTokens(); var lexer = new UnityLexer(sourceText, pretokenizedTokens); var parser = new UnityParser(lexer); var result = new SyntaxTree(sourceText, syntaxTree => { var node = parseFunc(parser); node.SetSyntaxTree(syntaxTree); return(node); }); Debug.WriteLine(DateTime.Now + " - Finished parsing"); return(result); }
public UnityConverter(UnityParser parser, List<MeshRenderer> sMeshes, bool skins) { foreach (SkinnedMeshRenderer sMesh in sMeshes) { Transform rootBone = sMesh.m_RootBone.instance; if (rootBone != null) { while (rootBone.Parent != null) { rootBone = rootBone.Parent; } if (FrameList == null) { ConvertFrames(rootBone, null); } else if (FrameList[0].Name != rootBone.m_GameObject.instance.m_Name) { FrameList[0].Name = "Joined_Root"; } } } if (skins) { foreach (Component asset in parser.Cabinet.Components) { if (asset.classID1 == UnityClassID.Avatar) { avatar = parser.Cabinet.LoadComponent(asset.pathID); break; } } } ConvertMeshRenderers(sMeshes, skins, false); AnimationList = new List<ImportedAnimation>(); }
public static void ReplaceTexture(UnityParser parser, ImportedTexture texture) { Texture2D tex = parser.GetTexture(Path.GetFileNameWithoutExtension(texture.Name)); if (tex == null) { parser.AddTexture(texture); return; } ReplaceTexture(tex, texture); }
public static void ReplaceMaterial(UnityParser parser, ImportedMaterial material) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component comp = parser.Cabinet.Components[i]; if (comp.classID1 == UnityClassID.Material) { Material mat = parser.Cabinet.LoadComponent(comp.pathID); if (mat.m_Name == material.Name) { ReplaceMaterial(mat, material); return; } } } throw new Exception("Replacing a material currently requires an existing material with the same name"); }
public static BackgroundWorker SaveMod(UnityParser modParser, string path, bool background) { return modParser.WriteArchive(path, false, null, background, true); }
public static void ReplaceTextAsset(UnityParser parser, string path) { TextAsset ta = TextAsset.Import(path); if (ta.m_Script.Length > 0) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component asset = parser.Cabinet.Components[i]; if (asset.classID1 == UnityClassID.TextAsset) { TextAsset taic = parser.Cabinet.LoadComponent(asset.pathID); if (taic.m_Name == ta.m_Name) { taic.m_Script = ta.m_Script; return; } } } } }
public static void ReplaceShader(UnityParser parser, string path) { Shader s = Shader.Import(path); if (s.m_Script.Length > 0) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component asset = parser.Cabinet.Components[i]; if (asset.classID1 == UnityClassID.Shader) { Shader sic = parser.Cabinet.LoadComponent(asset.pathID); if (sic.m_Name == s.m_Name) { sic.m_Script = s.m_Script; return; } } } } }
public static void ReplaceAudioClip(UnityParser parser, string path) { AudioClip ac = AudioClip.Import(path); if (ac.m_AudioData.Length > 0) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component asset = parser.Cabinet.Components[i]; if (asset.classID1 == UnityClassID.AudioClip) { AudioClip acic = parser.Cabinet.LoadComponent(asset.pathID); if (acic.m_Name == ac.m_Name) { acic.m_AudioData = ac.m_AudioData; return; } } } } }
public static UnityParser DeployCollect(UnityParser parser, object[] animatorEditors, object[] singleAssets) { HashSet<Component> collection = new HashSet<Component>(); if (animatorEditors != null) { AnimatorEditor[] editors = Utility.Convert<AnimatorEditor>(animatorEditors); foreach (AnimatorEditor animEditor in editors) { Collect(animEditor, collection); } } if (singleAssets != null) { double[] singles = Utility.Convert<double>(singleAssets); foreach (int pathID in singles) { Component asset = parser.Cabinet.LoadComponent(pathID); collection.Add(asset); } } collection.Remove(null); UnityParser p = new UnityParser(parser); p.Cabinet.Components.AddRange(collection); p.Cabinet.Components.Sort ( delegate(Component a, Component b) { return a.pathID - b.pathID; } ); if (parser.Cabinet.Bundle != null) { parser.Cabinet.Bundle.Clone(p.Cabinet); } return p; }
public Unity3dEditor(UnityParser parser) : this(parser, false) { }
public AssetCabinet(Stream stream, UnityParser parser) { Parser = parser; BinaryReader reader = new BinaryReader(stream); UsedLength = reader.ReadInt32BE(); ContentLengthCopy = reader.ReadInt32BE(); Format = reader.ReadInt32BE(); DataPosition = reader.ReadInt32BE(); Unknown6 = reader.ReadInt32BE(); Version = reader.ReadName0(); Unknown7 = reader.ReadInt32(); int numTypes = reader.ReadInt32(); Types = new List<TypeDefinition>(numTypes); for (int i = 0; i < numTypes; i++) { TypeDefinition t = new TypeDefinition(); t.typeId = reader.ReadInt32(); t.definitions = new TypeDefinitionString(); ReadType(reader, t.definitions); Types.Add(t); } Unknown8 = reader.ReadInt32(); int numComponents = reader.ReadInt32(); Components = new List<Component>(numComponents); for (int i = 0; i < numComponents; i++) { int pathID = reader.ReadInt32(); uint offset = (uint)(parser.HeaderLength + parser.Offset) + (uint)DataPosition + reader.ReadUInt32(); uint size = reader.ReadUInt32(); NotLoaded comp = new NotLoaded(this, pathID, (UnityClassID)reader.ReadInt32(), (UnityClassID)reader.ReadInt32()); comp.offset = offset; comp.size = size; Components.Add(comp); } int numRefs = reader.ReadInt32(); References = new Reference[numRefs]; for (int i = 0; i < numRefs; i++) { References[i] = new Reference(); References[i].guid = new Guid(reader.ReadBytes(16)); References[i].type = reader.ReadInt32(); References[i].filePath = reader.ReadName0(); References[i].assetPath = reader.ReadName0(); } if (stream.Position != UsedLength + (parser.HeaderLength + parser.Offset) + 0x13) { Report.ReportLog("Unexpected Length Pos=" + stream.Position.ToString("X") + " UsedLength=" + UsedLength.ToString("X")); } long padding = (stream.Position + 16) & ~(long)15; if (padding != parser.HeaderLength + parser.Offset + DataPosition) { Report.ReportLog("Unexpected DataPosition"); } RemovedList = new List<NotLoaded>(); loadingReferencials = false; reported = new HashSet<string>(); for (int i = 0; i < Components.Count; i++) { Component asset = Components[i]; if (asset.classID1 == UnityClassID.AssetBundle) { Bundle = LoadComponent(stream, i, (NotLoaded)asset); break; } } }
public static void MergeTexture(UnityParser parser, ImportedTexture texture) { Operations.ReplaceTexture(parser, texture); }
public static bool ApplyMod(UnityParser parser, UnityParser modParser, bool saveOriginals) { UnityParser originals = new UnityParser(parser); int firstNewPathID = -1; for (int i = 0; i < modParser.Cabinet.Components.Count; i++) { int pathID = modParser.Cabinet.Components[i].pathID; Component comp = parser.Cabinet.FindComponent(pathID); if (comp != null) { originals.Cabinet.Components.Add(comp); } else { if (firstNewPathID < 0) { firstNewPathID = pathID; } originals.Cabinet.Components.Add(modParser.Cabinet.Components[i]); } } Match m = Regex.Match(modParser.FilePath, @"(--*\d+)\.", RegexOptions.CultureInvariant); int idx = m.Success ? m.Groups[1].Index : modParser.FilePath.Length; string originalsName = modParser.FilePath.Substring(0, idx) + "-org-" + firstNewPathID + Path.GetExtension(parser.FilePath); if (File.Exists(originalsName)) { Report.ReportLog(Path.GetFileName(modParser.FilePath) + " has already been applied."); return false; } if (saveOriginals) { originals.WriteArchive(originalsName, false, null, false, true); } bool success = true; using (Stream stream = File.OpenRead(modParser.FilePath)) { m = Regex.Match(modParser.FilePath, @"-(-*\d+)\.", RegexOptions.CultureInvariant); if (!m.Success || !int.TryParse(m.Groups[1].Value, out firstNewPathID)) { Report.ReportLog("Warning! Mod filename \"" + Path.GetFileName(modParser.FilePath) + "\" is malformed or lies in a folder with a confusing name."); firstNewPathID = -1; } List<KeyValuePair<string, AssetInfo>> srcContainer = null; for (int i = 0; i < modParser.Cabinet.Components.Count; i++) { Component src = modParser.Cabinet.Components[i]; NotLoaded asset = src as NotLoaded; if (asset != null) { src = modParser.Cabinet.LoadComponent(stream, i, asset); } if (firstNewPathID == -1 || src.pathID < firstNewPathID) { Component dest = parser.Cabinet.FindComponent(src.pathID); if (dest.classID2 == src.classID2) { if (src.classID2 == UnityClassID.AssetBundle) { srcContainer = ((AssetBundle)src).m_Container; } else { parser.Cabinet.ReplaceSubfile(dest, src); } if (parser.Cabinet.Bundle != null) { switch (src.classID2) { case UnityClassID.Animator: parser.Cabinet.Bundle.RegisterForUpdate(((Animator)src).m_GameObject.asset); break; case UnityClassID.MeshRenderer: case UnityClassID.SkinnedMeshRenderer: case UnityClassID.Material: case UnityClassID.Shader: case UnityClassID.Texture2D: parser.Cabinet.Bundle.RegisterForUpdate(src); break; } } } else { Report.ReportLog("Unexpected asset in " + Path.GetFileName(parser.FilePath) + " with PathID=" + src.pathID + " was not replaced."); success = false; } } else { parser.Cabinet.ReplaceSubfile(-1, src, null); if (parser.Cabinet.Bundle != null) { switch (src.classID2) { case UnityClassID.TextAsset: case UnityClassID.Material: case UnityClassID.MonoBehaviour: case UnityClassID.Shader: case UnityClassID.Texture2D: parser.Cabinet.Bundle.AddComponent(src); break; } } } } if (parser.Cabinet.Bundle != null && modParser.Cabinet.Bundle != null) { for (int j = 0; j < srcContainer.Count; ) { var firstEntry = srcContainer[j++]; Component firstAsset = ((NotLoaded)firstEntry.Value.asset.asset).replacement; if (firstAsset == null) { continue; } if (parser.Cabinet.Bundle.FindComponent(firstEntry.Key, firstEntry.Value.asset.asset.classID2) == null) { List<Component> entries = new List<Component>(); entries.Add(firstAsset); while (j < srcContainer.Count && srcContainer[j].Key == firstEntry.Key && srcContainer[j].Value.preloadIndex == firstEntry.Value.preloadIndex) { Component asset = ((NotLoaded)srcContainer[j++].Value.asset.asset).replacement; entries.Add(asset); } parser.Cabinet.Bundle.AddComponents(firstEntry.Key, entries); } else { parser.Cabinet.Bundle.RegisterForUpdate(firstAsset); } } Unity3dEditor editor = new Unity3dEditor(modParser); foreach (Animator vAnim in editor.VirtualAnimators) { Component gameObj = parser.Cabinet.FindComponent(vAnim.m_GameObject.asset.pathID); parser.Cabinet.Bundle.AddComponent(gameObj); } } } return success; }
public static void ExportTextAsset(UnityParser parser, string name, string path) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component asset = parser.Cabinet.Components[i]; if (asset.classID1 == UnityClassID.TextAsset) { TextAsset taic = parser.Cabinet.LoadComponent(asset.pathID); if (name == "*" || taic.m_Name == name) { taic.Export(path); } } } }
public static void ExportAudioClip(UnityParser parser, string name, string path) { for (int i = 0; i < parser.Cabinet.Components.Count; i++) { Component asset = parser.Cabinet.Components[i]; if (asset.classID1 == UnityClassID.AudioClip) { AudioClip ac = parser.Cabinet.LoadComponent(asset.pathID); if (name == "*" || ac.m_Name == name) { ac.Export(path); } } } }
public static void getShaderNameFromFile(string fileName) { try { Console.WriteLine("Reading: " + fileName); UnityParser unityParser = new UnityParser(fileName); int count = unityParser.Cabinet.Components.Count; string text = fileName.Substring(fileName.IndexOf("abdata") + 7); for (int i = 0; i < count; i++) { try { switch (unityParser.Cabinet.Components[i].classID()) { case UnityClassID.MeshRenderer: case UnityClassID.ParticleRenderer: case UnityClassID.TrailRenderer: case UnityClassID.LineRenderer: case UnityClassID.SkinnedMeshRenderer: case UnityClassID.ParticleSystemRenderer: foreach (dynamic item in unityParser.Cabinet.LoadComponent(unityParser.Cabinet.Components[i].pathID).m_Materials) { Material material = (Material)((PPtr <Material>)item).asset; Component component = material.m_Shader.asset; try { string shader_name = ""; //Note: Make sure the main Shader discovery process is all within FileID == 0 // Which means it is in the same abdata and not relying on external files. // HPI will never be able to handle manifests & external files properly // for HS1 items. // if (material.m_Shader.m_FileID == 0) if (material.m_Shader.m_FileID == 0 && material.m_Shader.m_PathID != 0) { //shader_name = ((component is NotLoaded) ? // ((NotLoaded)component).Name : // ((component.file.VersionNumber < AssetCabinet.VERSION_5_5_0) ? // ((Shader)component).m_Name : // ((Shader)component).m_ParsedForm.m_Name) // ); //long _dummy_ = 0; ////Note: Not only we want to avoid empty shader names, but some modder strangely //// renames shaders into random numbers. We don't want those either. //if ((shader_name.Equals("") || long.TryParse(shader_name, out _dummy_)) && // material.m_Shader.m_PathID != 0) //{ // component = unityParser.Cabinet.LoadComponent(material.m_Shader.m_PathID); // Shader shader = (Shader)component; // if (shader != null) // { // string shader_script = shader.m_Script; // if (shader_script != null && shader_script.Length > 0) // { // shader_script = shader_script.Substring(shader_script.IndexOf("\"") + 1); // shader_name = shader_script.Substring(0, shader_script.IndexOf("\"")); // } // } // //Shader.m_Script seem to start with [[Shader "name"...]], so we just grab the string in between // //the first quote and the second quote? That easy? //} if (component.file.VersionNumber < AssetCabinet.VERSION_5_5_0) { Shader shader = (Shader)unityParser.Cabinet.LoadComponent(material.m_Shader.m_PathID); if (shader != null) { string shader_script = shader.m_Script; if (shader_script != null && shader_script.Length > 0) { shader_script = shader_script.Substring(shader_script.IndexOf("\"") + 1); shader_name = shader_script.Substring(0, shader_script.IndexOf("\"")); } } //Shader.m_Script seem to start with [[Shader "name"...]], so we just grab the string in between //the first quote and the second quote. But this seems to be also true for Unity 5.3 shaders. } //If trying to get the Unity 5.3 shader.m_Script somehow fails, try the basic m_Name. if (shader_name.Equals("")) { shader_name = ((component is NotLoaded) ? ((NotLoaded)component).Name : ((component.file.VersionNumber < AssetCabinet.VERSION_5_5_0) ? ((Shader)component).m_Name : ((Shader)component).m_ParsedForm.m_Name) ); } //The last resort is still the PathID, as long as the PathID isn't 0. if (shader_name.Equals("")) { shader_name = material.m_Shader.m_PathID.ToString(); } } else { switch (material.m_Shader.m_PathID) { case 6: shader_name = "Normal-VertexLit"; break; case 7: shader_name = "Normal-Diffuse"; break; case -9046184444883282072: shader_name = "Shader Forge/PBRsp_texture_alpha_culloff"; break; default: shader_name = "Standard"; break; } //Note: For certain objects relying on unity_builtin_extra's shaders, // Usually they are just for Diffuse or VertexLit, which are just // Standard since Unity 5. // There will be other mod packs with expectation of a manifest, // for such mods, they could use whatever shaders that HPI will never // be able to identify within the scope of the same abdata // so that has to be ruled out as impossible for the foreseeable future. } Console.WriteLine(text + " - " + material.m_Name + " - " + shader_name + " - " + material.m_CustomRenderQueue); ret[text.Replace("\\", "/") + "|" + material.m_Name] = shader_name + "," + material.m_CustomRenderQueue; } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.WriteLine(ex.StackTrace); } } break; } } catch (Exception) { } } unityParser.Dispose(); } catch (Exception ex3) { Console.WriteLine(ex3.ToString()); Console.WriteLine(ex3.StackTrace); } }
public static void MergeTexture(UnityParser parser, string path) { ImportedTexture texture = new ImportedTexture(path); MergeTexture(parser, texture); }
public static bool RemoveMod(UnityParser parser, UnityParser originalsParser, bool deleteOriginals) { Match m = Regex.Match(originalsParser.FilePath, @"-(-*\d+)\.", RegexOptions.CultureInvariant); int firstNewPathID = -1; if (!m.Success || !int.TryParse(m.Groups[1].Value, out firstNewPathID)) { Report.ReportLog("Warning! Mod filename \"" + Path.GetFileName(originalsParser.FilePath) + "\" is malformed or lies in a folder with a confusing name."); firstNewPathID = -1; } bool error = false; for (int i = originalsParser.Cabinet.Components.Count - 1; i >= 0; i--) { int pathID = originalsParser.Cabinet.Components[i].pathID; Component comp = parser.Cabinet.FindComponent(pathID); if (comp != null) { if (comp.classID2 == originalsParser.Cabinet.Components[i].classID2) { if (firstNewPathID == -1 || pathID < firstNewPathID) { parser.Cabinet.ReplaceSubfile(comp, originalsParser.Cabinet.Components[i]); } else { if (parser.Cabinet.Components.IndexOf(comp) == parser.Cabinet.Components.Count - 1) { parser.Cabinet.RemoveSubfile(comp); } else { Report.ReportLog("Asset with PathID=" + pathID + " is not located at the end. Other mods will become unremovable when this asset would be removed."); error = true; } } } else { Report.ReportLog("Unexpected asset in " + Path.GetFileName(parser.FilePath) + " with PathID=" + pathID + " was not " + (firstNewPathID == -1 || pathID < firstNewPathID ? "replaced." : "removed.")); error = true; } } else { Report.ReportLog("Asset with PathID=" + pathID + " is not present in " + Path.GetFileName(parser.FilePath)); error = true; } } if (error) { Report.ReportLog(Path.GetFileName(originalsParser.FilePath) + " was partially removed. Saving " + Path.GetFileName(parser.FilePath) + " may corrupt the file."); return false; } if (deleteOriginals) { parser.DeleteModFiles.Add(originalsParser.Cabinet); } return true; }
public AssetCabinet(AssetCabinet source, UnityParser parser) { Parser = parser; Format = source.Format; Unknown6 = source.Unknown6; Version = (string)source.Version.Clone(); Unknown7 = source.Unknown7; int numTypes = source.Types.Count; Types = new List<TypeDefinition>(numTypes); for (int i = 0; i < numTypes; i++) { TypeDefinition t = source.Types[i]; Types.Add(t); } Unknown8 = source.Unknown8; int numComponents = source.Components.Count; Components = new List<Component>(numComponents); int numRefs = source.References.Length; References = new Reference[numRefs]; for (int i = 0; i < numRefs; i++) { References[i] = source.References[i]; } RemovedList = new List<NotLoaded>(); loadingReferencials = false; reported = new HashSet<string>(); }
public static void MergeTextures(UnityParser parser, string folder) { DirectoryInfo dir = new DirectoryInfo(folder); if (!dir.Exists) { throw new Exception("Directory <" + folder + "> does not exist"); } foreach (FileInfo file in dir.EnumerateFiles()) { MergeTexture(parser, file.FullName); } }