public GameObject RecurseGameObjects(AssetFileInfoEx info, bool topRoot, bool hideOnCreation = false) { AssetTypeValueField gameObject = am.GetATI(assetsFile, info).GetBaseField(); string name = gameObject.Get("m_Name").GetValue().AsString(); AssetTypeValueField m_Component = gameObject.Get("m_Component").Get("Array"); AssetsManager.AssetExternal transformComponent = am.GetExtAsset(assetsFileInstance, m_Component[0].Get("component")); AssetTypeValueField transform = transformComponent.instance.GetBaseField(); if (name == "TileMap Render Data" || name == "Template-TileMap (1) Render Data") //should be .EndsWith(" Render Data") { return(TilemapRenderData(transform, name)); } if (topRoot && transform.Get("m_Father").Get("m_PathID").GetValue().AsInt64() != 0) { return(null); } if (!topRoot && transform.Get("m_Father").Get("m_PathID").GetValue().AsInt64() == 0) { return(null); } GameObject gameObjectInstance = new GameObject(name); //if this object or parent object is mask bool isMask = hideOnCreation; int m_Tag = (ushort)gameObject.Get("m_Tag").GetValue().AsUInt(); if (m_Tag >= 20000) { int tagIndex = m_Tag - 20000; gameObjectInstance.tag = UnityEditorInternal.InternalEditorUtility.tags[tagIndex]; } else if (m_Tag != 0) { string[] tags = new[] { "Respawn", "Finished", "EditorOnly", "MainCamera", "Player", "GameController" }; gameObjectInstance.tag = tags[m_Tag - 1]; } gameObjectInstance.layer = (int)gameObject.Get("m_Layer").GetValue().AsUInt(); EditDiffer differ = gameObjectInstance.AddComponent <EditDiffer>(); differ.fileId = 0; differ.pathId = info.index; differ.origPathId = differ.pathId; Transform transformInstance = gameObjectInstance.transform; AssetTypeValueField m_LocalPosition = transform.Get("m_LocalPosition"); AssetTypeValueField m_LocalRotation = transform.Get("m_LocalRotation"); AssetTypeValueField m_LocalScale = transform.Get("m_LocalScale"); Vector3 localPosition = GetVector3(m_LocalPosition); Quaternion localRotation = GetQuaternion(m_LocalRotation); Vector3 localScale = GetVector3(m_LocalScale); for (uint i = 1; i < m_Component.GetValue().AsArray().size; i++) { //faster to check for only info but also keeps us from reading //particle systems which tend to update literally every minor update //if we end up needing more types we can use typetree2cldb on an editor file AssetsManager.AssetExternal component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component"), true); if (component.info.curFileType == SPRITERENDERER) { component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component")); AssetTypeValueField baseField = component.instance.GetBaseField(); AssetTypeValueField m_Sprite = baseField.Get("m_Sprite"); int fileId = m_Sprite.Get("m_FileID").GetValue().AsInt(); long pathId = m_Sprite.Get("m_PathID").GetValue().AsInt64(); AssetsManager.AssetExternal sprite = am.GetExtAsset(assetsFileInstance, m_Sprite); if (sprite.info == null) //spriterenderer with no sprite lol { continue; } AssetsFileInstance spriteInst; if (m_Sprite.Get("m_FileID").GetValue().AsInt() == 0) { spriteInst = assetsFileInstance; } else { spriteInst = assetsFileInstance.dependencies[m_Sprite.Get("m_FileID").GetValue().AsInt() - 1]; } Sprite spriteInstance = bundleAssets[assetMap[new AssetID(Path.GetFileName(spriteInst.path), pathId)]] as Sprite; SpriteRenderer sr = gameObjectInstance.AddComponent <SpriteRenderer>(); string[] sortingLayers = new[] { "Default", "Far BG 2", "Far BG 1", "Mid BG", "Immediate BG", "Actors", "Player", "Tiles", "MID Dressing", "Immediate FG", "Far FG", "Vignette", "Over", "HUD" }; sr.sortingLayerName = sortingLayers[baseField.Get("m_SortingLayer").GetValue().AsInt()]; sr.sortingOrder = baseField.Get("m_SortingOrder").GetValue().AsInt(); sr.sprite = spriteInstance; AssetTypeValueField m_Materials = baseField.Get("m_Materials").Get("Array"); if (m_Materials.GetValue().AsArray().size > 0) { AssetTypeValueField m_Material = m_Materials[0]; int matFileId = m_Material.Get("m_FileID").GetValue().AsInt(); long matPathId = m_Material.Get("m_PathID").GetValue().AsInt64(); AssetsFileInstance materialInst; if (m_Material.Get("m_FileID").GetValue().AsInt() == 0) { materialInst = assetsFileInstance; } else { materialInst = assetsFileInstance.dependencies[matFileId - 1]; } if (assetMap.ContainsKey(new AssetID(Path.GetFileName(materialInst.path), matPathId))) { Material mat = bundleAssets[assetMap[new AssetID(Path.GetFileName(materialInst.path), matPathId)]] as Material; if (mat.shader.name != "Sprites/Lit") //honestly this shader confuses me. it is the only shader { //with no code and only references the generic material sr.material = mat; } //else //{ // mat.shader = sr.sharedMaterial.shader; // sr.sharedMaterial = mat; //} if (mat.shader.name == "Hollow Knight/Grass-Default" || mat.shader.name == "Hollow Knight/Grass-Diffuse") { sr.sharedMaterial.SetFloat("_SwayAmount", 0f); //stops grass animation } } //else //{ // Debug.Log("failed to find " + Path.GetFileName(materialInst.path) + "/" + matPathId + ".dat"); //} } } if (component.info.curFileType == MONOBEHAVIOUR) { component = am.GetExtAsset(assetsFileInstance, m_Component[i].Get("component")); AssetTypeValueField baseField = component.instance.GetBaseField(); int monoTypeId = assetsFileInstance.file.typeTree.pTypes_Unity5[component.info.curFileTypeOrIndex].scriptIndex; if (!monoBehaviourIds.ContainsKey(monoTypeId)) { //map out the monobehaviour script indexes to their name for fast lookup AssetTypeValueField m_Script = baseField.Get("m_Script"); AssetsManager.AssetExternal script = am.GetExtAsset(assetsFileInstance, m_Script); string scriptName = script.instance.GetBaseField().Get("m_Name").GetValue().AsString(); monoBehaviourIds[monoTypeId] = scriptName; } if (monoBehaviourIds[monoTypeId] == "tk2dSprite") { string managedPath = Path.Combine(Path.GetDirectoryName(assetsFileInstance.path), "Managed"); baseField = am.GetMonoBaseFieldCached(assetsFileInstance, component.info, managedPath); AssetTypeValueField collection = baseField.Get("collection"); int _spriteId = baseField.Get("_spriteId").GetValue().AsInt(); int fileId = collection.Get("m_FileID").GetValue().AsInt(); //long pathId = collection.Get("m_PathID").GetValue().AsInt64(); AssetsManager.AssetExternal sprite = am.GetExtAsset(assetsFileInstance, collection); if (sprite.info == null) { continue; } AssetsFileInstance spriteFileInstance = assetsFileInstance.dependencies[fileId - 1]; AssetTypeValueField spriteBaseField = am.GetMonoBaseFieldCached(spriteFileInstance, sprite.info, managedPath); //this is a bad hack but it works for some reason so here it is //the reason the pivot is being set and not the actual position //is so we don't modify the values on the transform component Texture2D image = spriteLoader.LoadTK2dSpriteNative(am, spriteBaseField, spriteFileInstance, _spriteId); AssetTypeValueField boundsData = spriteBaseField.Get("spriteDefinitions")[(uint)_spriteId].Get("boundsData")[0]; float xOff = boundsData.Get("x").GetValue().AsFloat() * 100; float yOff = boundsData.Get("y").GetValue().AsFloat() * 100; Vector2 offset = new Vector2((image.width / 2f - xOff) / image.width, (image.height / 2f - yOff) / image.height); Sprite spriteInstance = Sprite.Create(image, new Rect(0, 0, image.width, image.height), offset, 100f); SpriteRenderer sr = gameObjectInstance.AddComponent <SpriteRenderer>(); sr.sortingLayerName = "Default"; sr.sortingOrder = 0; sr.sprite = spriteInstance; } else if (monoBehaviourIds[monoTypeId] == "PlayMakerFSM") { //string managedPath = Path.Combine(Path.GetDirectoryName(assetsFileInstance.path), "Managed"); //baseField = am.GetMonoBaseFieldCached(assetsFileInstance, component.info, managedPath); string fsmName = ReadFSMName(component.info, assetsFileInstance.file.reader);//baseField.Get("fsm").Get("name").GetValue().AsString(); if (fsmName == "remasker" || fsmName == "unmasker" || fsmName == "remasker_inverse" || fsmName == "Remove") { isMask = true; } } } } transformInstance.localScale = localScale; transformInstance.localPosition = localPosition; transformInstance.localRotation = localRotation; Renderer ren = gameObjectInstance.GetComponent <Renderer>(); if (isMask && ren != null) { ren.enabled = false; } AssetTypeValueField childrenArray = transform.Get("m_Children").Get("Array"); uint childrenCount = childrenArray.GetValue().AsArray().size; for (uint i = 0; i < childrenCount; i++) { AssetTypeValueField childTf = am.GetExtAsset(assetsFileInstance, childrenArray[i]).instance.GetBaseField(); AssetFileInfoEx childGo = am.GetExtAsset(assetsFileInstance, childTf.Get("m_GameObject")).info; RecurseGameObjects(childGo, false, isMask).transform.SetParent(transformInstance, false); } return(gameObjectInstance); }