void RecursivelyCreateFolders(string package, string oldFilter, TexplorerTextureFolder topFolder, TreeTexInfo texture) { int dotInd = package.IndexOf('.') + 1; string name = package; if (dotInd != 0) name = package.Substring(0, dotInd).Trim('.'); string filter = oldFilter + '.' + name; filter = filter.Trim('.'); TexplorerTextureFolder newFolder = new TexplorerTextureFolder(name, filter, topFolder); // Add texture if part of this folder if (newFolder.Filter == texture.FullPackage) newFolder.Textures.Add(texture); TexplorerTextureFolder existingFolder = topFolder.Folders.FirstOrDefault(folder => newFolder.Name == folder.Name); if (existingFolder == null) // newFolder not found in existing folders { topFolder.Folders.Add(newFolder); AllFolders.Add(newFolder); // No more folders in package if (dotInd == 0) return; string newPackage = package.Substring(dotInd).Trim('.'); RecursivelyCreateFolders(newPackage, filter, newFolder, texture); } else { // No subfolders for newFolder yet, need to make them if there are any // Add texture if necessary if (existingFolder.Filter == texture.FullPackage) existingFolder.Textures.Add(texture); // No more folders in package if (dotInd == 0) return; string newPackage = package.Substring(dotInd).Trim('.'); RecursivelyCreateFolders(newPackage, filter, existingFolder, texture); } }
internal void ConstructTree() { DebugOutput.PrintLn($"Constructing ME{GameVersion}Tree..."); // Top all encompassing node TexplorerTextureFolder TopTextureFolder = new TexplorerTextureFolder("All Texture Files", null, null); // Normal nodes foreach (var tex in Textures) RecursivelyCreateFolders(tex.FullPackage, "", TopTextureFolder, tex); Console.WriteLine($"Total number of folders: {AllFolders.Count}"); // Alphabetical order TopTextureFolder.Folders = new MTRangedObservableCollection<TexplorerTextureFolder>(TopTextureFolder.Folders.OrderBy(p => p)); TextureFolders.Add(TopTextureFolder); // Only one item in this list. Chuckles. DebugOutput.PrintLn($"ME{GameVersion} Tree Constructed!"); }
TexplorerTextureFolder ReadTreeFolders(BinaryReader br, TexplorerTextureFolder parent) { TexplorerTextureFolder folder = new TexplorerTextureFolder(); AllFolders.Add(folder); folder.Parent = parent; // Details folder.Name = br.ReadString(); folder.Filter = br.ReadString(); // Folders int folderCount = br.ReadInt32(); if (folderCount != 0) for (int i = 0; i < folderCount; i++) folder.Folders.Add(ReadTreeFolders(br, folder)); // Textures var texCount = br.ReadInt32(); for (int i = 0; i < texCount; i++) folder.Textures.Add(Textures[br.ReadInt32()]); return folder; }
void WriteTreeFolders(BinaryWriter bw, TexplorerTextureFolder folder) { // Details bw.Write(folder.Name); bw.Write(folder.Filter); // Folders bw.Write(folder.Folders.Count); if (folder.Folders.Count != 0) foreach (var fold in folder.Folders) WriteTreeFolders(bw, fold); // Textures bw.Write(folder.Textures.Count); foreach (var tex in folder.Textures) // Write indexes of textures instead of entire textures bw.Write(Textures.IndexOf(tex)); }
public bool ReadFromFile(string fileName = null) { lock (Textures) { if (Textures.Count > 0) // When it comes back into this after Texplorer has been closed but the Toolset hasn't, it needs to "rebuild" itself i.e. mark itself as valid if it's been loaded previously. { Valid = true; return true; } } OnPropertyChanged(nameof(Exists)); string tempFilename = fileName; if (fileName == null) tempFilename = TreePath; if (!File.Exists(tempFilename)) return false; List<TreeTexInfo> TempTextures = new List<TreeTexInfo>(); try { using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(tempFilename))) { using (GZipStream compressed = new GZipStream(ms, CompressionMode.Decompress)) // Compressed for nice small trees { using (BinaryReader bin = new BinaryReader(compressed)) { // Check tree is suitable for this version int magic = bin.ReadInt32(); if (magic != 631991) { DebugOutput.PrintLn("Tree too old. Delete and rebuild tree."); return false; } // Tree is suitable. Begin reading int gameVersion = bin.ReadInt32(); if (GameDirecs.GameVersion != GameVersion) throw new InvalidOperationException($"Incorrect Tree Loaded. Expected: ME{GameDirecs.GameVersion}, Got: {GameVersion}"); TreeVersion = bin.ReadString(); // PCCS lock (ScannedPCCs) { int pccCount = bin.ReadInt32(); for (int i = 0; i < pccCount; i++) ScannedPCCs.Add(bin.ReadString()); } // Textures lock (Textures) { int texCount = bin.ReadInt32(); for (int i = 0; i < texCount; i++) { TreeTexInfo tex = new TreeTexInfo(GameDirecs); tex.TexName = bin.ReadString(); tex.Hash = bin.ReadUInt32(); //tex.StorageType = (Texture2D.storage)bin.ReadInt32(); tex.FullPackage = bin.ReadString(); tex.Format = (ImageEngineFormat)bin.ReadInt32(); Thumbnail thumb = new Thumbnail(GameDirecs.ThumbnailCachePath); thumb.Offset = bin.ReadInt64(); thumb.Length = bin.ReadInt32(); tex.Thumb = thumb; tex.Mips = bin.ReadInt32(); tex.Width = bin.ReadInt32(); tex.Height = bin.ReadInt32(); tex.LODGroup = bin.ReadString(); int numPccs = bin.ReadInt32(); for (int j = 0; j < numPccs; j++) { string userAgnosticPath = ScannedPCCs[bin.ReadInt32()]; int ExpID = bin.ReadInt32(); tex.PCCs.Add(new PCCEntry(Path.Combine(GameDirecs.BasePath, userAgnosticPath), ExpID, GameDirecs)); } TempTextures.Add(tex); } } lock (Textures) Textures.AddRange(TempTextures); // Sort ME1 files if (GameVersion == 1) ToolsetTextureEngine.ME1_SortTexturesPCCs(Textures); // Texture folders // Top all encompassing node lock (TextureFolders) { TexplorerTextureFolder TopTextureFolder = new TexplorerTextureFolder("All Texture Files", null, null); var folderCount = bin.ReadInt32(); var tempFolders = new List<TexplorerTextureFolder>(); for (int i = 0; i < folderCount; i++) { var folder = ReadTreeFolders(bin, TopTextureFolder); tempFolders.Add(folder); } TopTextureFolder.Folders.AddRange(tempFolders); TextureFolders.Add(TopTextureFolder); } } } } } catch (Exception e) { DebugOutput.PrintLn($"Failed to load tree: {fileName}. Reason: {e.ToString()}"); return false; } Valid = true; return true; }
public TexplorerTextureFolder(string folderName, string filter, TexplorerTextureFolder parent) : this() { Parent = parent; Name = folderName; Filter = filter; }