diff --git a/Source/Builder.csproj b/Source/Builder.csproj
index 4ab63184..1d18f912 100644
--- a/Source/Builder.csproj
+++ b/Source/Builder.csproj
@@ -679,6 +679,8 @@
+
+
diff --git a/Source/Config/ThingCategory.cs b/Source/Config/ThingCategory.cs
index e80cf043..c9849e47 100644
--- a/Source/Config/ThingCategory.cs
+++ b/Source/Config/ThingCategory.cs
@@ -179,6 +179,12 @@ namespace CodeImp.DoomBuilder.Config
#region ================== Methods
+ // This sorts the category, if preferred
+ internal void SortIfNeeded()
+ {
+ if(sorted) things.Sort();
+ }
+
// This adds a thing to the category
internal void AddThing(ThingTypeInfo t)
{
diff --git a/Source/Config/ThingTypeInfo.cs b/Source/Config/ThingTypeInfo.cs
index 64d485cf..bbb68e5a 100644
--- a/Source/Config/ThingTypeInfo.cs
+++ b/Source/Config/ThingTypeInfo.cs
@@ -32,7 +32,7 @@ using CodeImp.DoomBuilder.Decorate;
namespace CodeImp.DoomBuilder.Config
{
- public class ThingTypeInfo
+ public class ThingTypeInfo : IComparable
{
#region ================== Constants
@@ -229,6 +229,12 @@ namespace CodeImp.DoomBuilder.Config
hangs = actor.GetFlagValue("spawnceiling", false);
blocking = actor.GetFlagValue("solid", false) ? 2 : 0;
}
+
+ // This is used for sorting
+ public int CompareTo(ThingTypeInfo other)
+ {
+ return string.Compare(this.title, other.title, true);
+ }
#endregion
}
diff --git a/Source/Data/DataManager.cs b/Source/Data/DataManager.cs
index 95755f0e..fae0b58b 100644
--- a/Source/Data/DataManager.cs
+++ b/Source/Data/DataManager.cs
@@ -235,7 +235,7 @@ namespace CodeImp.DoomBuilder.Data
// Make DataLocation.type of type Type and assign the
// types of the desired reader classes.
- try
+ //try
{
// Choose container type
switch(dl.type)
@@ -256,6 +256,7 @@ namespace CodeImp.DoomBuilder.Data
break;
}
}
+ /*
catch(Exception e)
{
// Unable to load resource
@@ -264,6 +265,7 @@ namespace CodeImp.DoomBuilder.Data
General.ShowErrorMessage("Unable to load resources from location \"" + dl.location + "\". Please make sure the location is accessible and not in use by another program.", MessageBoxButtons.OK);
continue;
}
+ */
// Add container
if(c != null) containers.Add(c);
@@ -281,6 +283,9 @@ namespace CodeImp.DoomBuilder.Data
texturenames.Sort();
flatnames.Sort();
+ // Sort things
+ foreach(ThingCategory tc in thingcategories) tc.SortIfNeeded();
+
// Update the used textures
General.Map.Data.UpdateUsedTextures();
@@ -666,7 +671,10 @@ namespace CodeImp.DoomBuilder.Data
internal Stream GetPatchData(string pname)
{
Stream patch;
-
+ if(pname.ToUpperInvariant() == "WALL57_1")
+ {
+ int t = 5;
+ }
// Go for all opened containers
for(int i = containers.Count - 1; i >= 0; i--)
{
diff --git a/Source/Data/DirectoryReader.cs b/Source/Data/DirectoryReader.cs
index 3a0ff025..534b63bd 100644
--- a/Source/Data/DirectoryReader.cs
+++ b/Source/Data/DirectoryReader.cs
@@ -24,6 +24,7 @@ using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
+using System.Windows.Forms;
using CodeImp.DoomBuilder.IO;
#endregion
@@ -32,15 +33,22 @@ namespace CodeImp.DoomBuilder.Data
{
internal sealed class DirectoryReader : PK3StructuredReader
{
- #region ================== Constructor / Disposer
+ #region ================== Variables
+
+ private DirectoryFilesList files;
+
+ #endregion
+ #region ================== Constructor / Disposer
+
// Constructor
public DirectoryReader(DataLocation dl) : base(dl)
{
General.WriteLogLine("Opening directory resource '" + location.location + "'");
// Initialize
- Initialize(dl.location);
+ files = new DirectoryFilesList(dl.location, true);
+ Initialize();
// We have no destructor
GC.SuppressFinalize(this);
@@ -66,74 +74,53 @@ namespace CodeImp.DoomBuilder.Data
// This creates an image
protected override ImageData CreateImage(string name, string filename, bool flat)
{
- return new FileImage(name, filename, flat);
+ return new FileImage(name, Path.Combine(location.location, filename), flat);
}
// This returns true if the specified file exists
protected override bool FileExists(string filename)
{
- return File.Exists(filename);
+ return files.FileExists(filename);
}
// This returns all files in a given directory
protected override string[] GetAllFiles(string path, bool subfolders)
{
- if(Directory.Exists(path))
- {
- if(subfolders)
- return Directory.GetFiles(path, "*", SearchOption.AllDirectories);
- else
- return Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly);
- }
- else
- return new string[0];
+ return files.GetAllFiles(path, subfolders).ToArray();
}
// This returns all files in a given directory that match the given extension
protected override string[] GetFilesWithExt(string path, string extension, bool subfolders)
{
- if(Directory.Exists(path))
- {
- if(subfolders)
- return Directory.GetFiles(path, "*." + extension, SearchOption.AllDirectories);
- else
- return Directory.GetFiles(path, "*." + extension, SearchOption.TopDirectoryOnly);
- }
- else
- return new string[0];
+ return files.GetAllFiles(path, extension, subfolders).ToArray();
+ }
+
+ // This finds the first file that has the specific name, regardless of file extension
+ protected override string FindFirstFile(string beginswith, bool subfolders)
+ {
+ return files.GetFirstFile(beginswith, subfolders);
}
// This finds the first file that has the specific name, regardless of file extension
protected override string FindFirstFile(string path, string beginswith, bool subfolders)
{
- string[] files = GetAllFiles(path, subfolders);
- foreach(string f in files)
- {
- if(string.Compare(Path.GetFileNameWithoutExtension(f), beginswith, true) == 0)
- return f;
- }
-
- return null;
+ return files.GetFirstFile(path, beginswith, subfolders);
}
// This finds the first file that has the specific name
protected override string FindFirstFileWithExt(string path, string beginswith, bool subfolders)
{
- string[] files = GetAllFiles(path, subfolders);
- foreach(string f in files)
- {
- if(string.Compare(Path.GetFileName(f), beginswith, true) == 0)
- return f;
- }
-
- return null;
+ string title = Path.GetFileNameWithoutExtension(beginswith);
+ string ext = Path.GetExtension(beginswith);
+ if(ext.Length > 1) ext = ext.Substring(1); else ext = "";
+ return files.GetFirstFile(path, title, subfolders, ext);
}
// This loads an entire file in memory and returns the stream
// NOTE: Callers are responsible for disposing the stream!
protected override MemoryStream LoadFile(string filename)
{
- return new MemoryStream(File.ReadAllBytes(filename));
+ return new MemoryStream(File.ReadAllBytes(Path.Combine(location.location, filename)));
}
// This creates a temp file for the speciied file and return the absolute path to the temp file
@@ -142,7 +129,7 @@ namespace CodeImp.DoomBuilder.Data
{
// Just copy the file
string tempfile = General.MakeTempFilename(General.Map.TempPath, "wad");
- File.Copy(filename, tempfile);
+ File.Copy(Path.Combine(location.location, filename), tempfile);
return tempfile;
}
diff --git a/Source/Data/PK3Reader.cs b/Source/Data/PK3Reader.cs
index d918f9b7..58b19ea0 100644
--- a/Source/Data/PK3Reader.cs
+++ b/Source/Data/PK3Reader.cs
@@ -35,7 +35,7 @@ namespace CodeImp.DoomBuilder.Data
{
#region ================== Variables
- private List fileslist;
+ private DirectoryFilesList files;
#endregion
@@ -50,22 +50,25 @@ namespace CodeImp.DoomBuilder.Data
ZipInputStream zipstream = OpenPK3File();
// Make list of all files
- fileslist = new List();
+ List fileentries = new List();
ZipEntry entry = zipstream.GetNextEntry();
while(entry != null)
{
- if(entry.IsFile) fileslist.Add(entry.Name.ToLowerInvariant());
+ if(entry.IsFile) fileentries.Add(new DirectoryFileEntry(entry.Name));
// Next
entry = zipstream.GetNextEntry();
}
+ // Make files list
+ files = new DirectoryFilesList(fileentries);
+
// Done with the zip file
zipstream.Close();
zipstream.Dispose();
// Initialize without path (because we use paths relative to the PK3 file)
- Initialize("");
+ Initialize();
// We have no destructor
GC.SuppressFinalize(this);
@@ -109,120 +112,40 @@ namespace CodeImp.DoomBuilder.Data
// This returns true if the specified file exists
protected override bool FileExists(string filename)
{
- string lowfile = filename.ToLowerInvariant();
- foreach(string f in fileslist)
- {
- if((string.Compare(f, lowfile) == 0)) return true;
- }
-
- return false;
+ return files.FileExists(filename);
}
-
+
// This returns all files in a given directory
protected override string[] GetAllFiles(string path, bool subfolders)
{
- List matches = new List();
- string lowpath = path.ToLowerInvariant();
- if(subfolders)
- {
- foreach(string f in fileslist)
- {
- if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
- (Path.GetFileName(f).Length > 0))
- matches.Add(f);
- }
- }
- else
- {
- foreach(string f in fileslist)
- {
- if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
- (Path.GetFileName(f).Length > 0))
- matches.Add(f);
- }
- }
-
- return matches.ToArray();
+ return files.GetAllFiles(path, subfolders).ToArray();
}
// This returns all files in a given directory that match the given extension
protected override string[] GetFilesWithExt(string path, string extension, bool subfolders)
{
- List matches = new List();
- string lowpath = path.ToLowerInvariant();
- string lowext = "." + extension.ToLowerInvariant();
- if(subfolders)
- {
- foreach(string f in fileslist)
- {
- if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) && f.EndsWith(lowext))
- matches.Add(f);
- }
- }
- else
- {
- foreach(string f in fileslist)
- {
- if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) && f.EndsWith(lowext))
- matches.Add(f);
- }
- }
-
- return matches.ToArray();
+ return files.GetAllFiles(path, extension, subfolders).ToArray();
+ }
+
+ // This finds the first file that has the specific name, regardless of file extension
+ protected override string FindFirstFile(string beginswith, bool subfolders)
+ {
+ return files.GetFirstFile(beginswith, subfolders);
}
// This finds the first file that has the specific name, regardless of file extension
protected override string FindFirstFile(string path, string beginswith, bool subfolders)
{
- string lowpath = path.ToLowerInvariant();
- string lowbegin = beginswith.ToLowerInvariant();
- if(subfolders)
- {
- foreach(string f in fileslist)
- {
- if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
- (string.Compare(Path.GetFileNameWithoutExtension(f), lowbegin) == 0))
- return f;
- }
- }
- else
- {
- foreach(string f in fileslist)
- {
- if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
- (string.Compare(Path.GetFileNameWithoutExtension(f), lowbegin) == 0))
- return f;
- }
- }
-
- return null;
+ return files.GetFirstFile(path, beginswith, subfolders);
}
// This finds the first file that has the specific name
protected override string FindFirstFileWithExt(string path, string beginswith, bool subfolders)
{
- string lowpath = path.ToLowerInvariant();
- string lowbegin = beginswith.ToLowerInvariant();
- if(subfolders)
- {
- foreach(string f in fileslist)
- {
- if(Path.GetDirectoryName(f).StartsWith(lowpath, true, CultureInfo.InvariantCulture) &&
- (string.Compare(Path.GetFileName(f), lowbegin) == 0))
- return f;
- }
- }
- else
- {
- foreach(string f in fileslist)
- {
- if((string.Compare(Path.GetDirectoryName(f), lowpath) == 0) &&
- (string.Compare(Path.GetFileName(f), lowbegin) == 0))
- return f;
- }
- }
-
- return null;
+ string title = Path.GetFileNameWithoutExtension(beginswith);
+ string ext = Path.GetExtension(beginswith);
+ if(ext.Length > 1) ext = ext.Substring(1); else ext = "";
+ return files.GetFirstFile(path, title, subfolders, ext);
}
// This loads an entire file in memory and returns the stream
@@ -238,19 +161,24 @@ namespace CodeImp.DoomBuilder.Data
ZipEntry entry = zipstream.GetNextEntry();
while(entry != null)
{
- // Is this the entry we are looking for?
- if(string.Compare(entry.Name, filename, true) == 0)
+ if(entry.IsFile)
{
- int expectedsize = (int)entry.Size;
- if(expectedsize < 1) expectedsize = 1024;
- filedata = new MemoryStream(expectedsize);
- int readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
- while(readsize > 0)
+ string entryname = entry.Name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
+
+ // Is this the entry we are looking for?
+ if(string.Compare(entryname, filename, true) == 0)
{
- filedata.Write(copybuffer, 0, readsize);
- readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
+ int expectedsize = (int)entry.Size;
+ if(expectedsize < 1) expectedsize = 1024;
+ filedata = new MemoryStream(expectedsize);
+ int readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
+ while(readsize > 0)
+ {
+ filedata.Write(copybuffer, 0, readsize);
+ readsize = zipstream.Read(copybuffer, 0, copybuffer.Length);
+ }
+ break;
}
- break;
}
// Next
diff --git a/Source/Data/PK3StructuredReader.cs b/Source/Data/PK3StructuredReader.cs
index e6905969..68182e0d 100644
--- a/Source/Data/PK3StructuredReader.cs
+++ b/Source/Data/PK3StructuredReader.cs
@@ -48,14 +48,6 @@ namespace CodeImp.DoomBuilder.Data
private bool roottextures;
private bool rootflats;
- // Paths
- protected string rootpath;
- protected string patchespath;
- protected string texturespath;
- protected string flatspath;
- protected string hirespath;
- protected string spritespath;
-
// WAD files that must be loaded as well
private List wads;
@@ -76,18 +68,10 @@ namespace CodeImp.DoomBuilder.Data
}
// Call this to initialize this class
- protected virtual void Initialize(string rootpath)
+ protected virtual void Initialize()
{
- // Initialize
- this.rootpath = rootpath;
- this.patchespath = Path.Combine(rootpath, PATCHES_DIR);
- this.texturespath = Path.Combine(rootpath, TEXTURES_DIR);
- this.flatspath = Path.Combine(rootpath, FLATS_DIR);
- this.hirespath = Path.Combine(rootpath, HIRES_DIR);
- this.spritespath = Path.Combine(rootpath, SPRITES_DIR);
-
// Load all WAD files in the root as WAD resources
- string[] wadfiles = GetFilesWithExt(rootpath, "wad", false);
+ string[] wadfiles = GetFilesWithExt("", "wad", false);
wads = new List(wadfiles.Length);
foreach(string w in wadfiles)
{
@@ -181,19 +165,19 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as textures?
if(roottextures)
{
- collection = LoadDirectoryImages(rootpath, false);
+ collection = LoadDirectoryImages("", false);
AddImagesToList(images, collection);
}
// TODO: Add support for hires texture here
// Add images from texture directory
- collection = LoadDirectoryImages(texturespath, false);
+ collection = LoadDirectoryImages(TEXTURES_DIR, false);
AddImagesToList(images, collection);
// Load TEXTURE1 lump file
List imgset = new List();
- string texture1file = FindFirstFile(rootpath, "TEXTURE1", false);
+ string texture1file = FindFirstFile("TEXTURE1", false);
if((texture1file != null) && FileExists(texture1file))
{
MemoryStream filedata = LoadFile(texture1file);
@@ -202,7 +186,7 @@ namespace CodeImp.DoomBuilder.Data
}
// Load TEXTURE2 lump file
- string texture2file = FindFirstFile(rootpath, "TEXTURE2", false);
+ string texture2file = FindFirstFile("TEXTURE2", false);
if((texture2file != null) && FileExists(texture2file))
{
MemoryStream filedata = LoadFile(texture2file);
@@ -234,7 +218,7 @@ namespace CodeImp.DoomBuilder.Data
}
// If none of the wads provides patch names, let's see if we can
- string pnamesfile = FindFirstFile(rootpath, "PNAMES", false);
+ string pnamesfile = FindFirstFile("PNAMES", false);
if((pnamesfile != null) && FileExists(pnamesfile))
{
MemoryStream pnamesdata = LoadFile(pnamesfile);
@@ -261,7 +245,7 @@ namespace CodeImp.DoomBuilder.Data
}
// Find in patches directory
- string filename = FindFirstFile(patchespath, pname, true);
+ string filename = FindFirstFile(PATCHES_DIR, pname, true);
if((filename != null) && FileExists(filename))
{
return LoadFile(filename);
@@ -295,12 +279,12 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as flats?
if(rootflats)
{
- collection = LoadDirectoryImages(rootpath, true);
+ collection = LoadDirectoryImages("", true);
AddImagesToList(images, collection);
}
// Add images from flats directory
- collection = LoadDirectoryImages(flatspath, true);
+ collection = LoadDirectoryImages(FLATS_DIR, true);
AddImagesToList(images, collection);
return images;
@@ -326,7 +310,7 @@ namespace CodeImp.DoomBuilder.Data
}
// Find in sprites directory
- string filename = FindFirstFile(spritespath, pfilename, true);
+ string filename = FindFirstFile(SPRITES_DIR, pfilename, true);
if((filename != null) && FileExists(filename))
{
return LoadFile(filename);
@@ -351,7 +335,7 @@ namespace CodeImp.DoomBuilder.Data
}
// Find in sprites directory
- string filename = FindFirstFile(spritespath, pfilename, true);
+ string filename = FindFirstFile(SPRITES_DIR, pfilename, true);
if((filename != null) && FileExists(filename))
{
return true;
@@ -381,8 +365,7 @@ namespace CodeImp.DoomBuilder.Data
// Find in root directory
string filename = Path.GetFileName(pname);
string pathname = Path.GetDirectoryName(pname);
- string fullpath = Path.Combine(rootpath, pathname);
- string foundfile = filename.IndexOf('.') > -1 ? FindFirstFileWithExt(fullpath, filename, false) : FindFirstFile(fullpath, filename, false);
+ string foundfile = (filename.IndexOf('.') > -1) ? FindFirstFileWithExt(pathname, filename, false) : FindFirstFile(pathname, filename, false);
if((foundfile != null) && FileExists(foundfile))
{
return LoadFile(foundfile);
@@ -453,6 +436,9 @@ namespace CodeImp.DoomBuilder.Data
// This must return all files in a given directory that match the given extension
protected abstract string[] GetFilesWithExt(string path, string extension, bool subfolders);
+ // This must find the first file that has the specific name, regardless of file extension
+ protected abstract string FindFirstFile(string beginswith, bool subfolders);
+
// This must find the first file that has the specific name, regardless of file extension
protected abstract string FindFirstFile(string path, string beginswith, bool subfolders);
@@ -466,6 +452,26 @@ namespace CodeImp.DoomBuilder.Data
// This must create a temp file for the speciied file and return the absolute path to the temp file
// NOTE: Callers are responsible for removing the temp file when done!
protected abstract string CreateTempFile(string filename);
+
+ // This makes the path relative to the directory, if needed
+ protected virtual string MakeRelativePath(string anypath)
+ {
+ if(Path.IsPathRooted(anypath))
+ {
+ // Make relative
+ string lowpath = anypath.ToLowerInvariant();
+ string lowlocation = location.location.ToLowerInvariant();
+ if((lowpath.Length > (lowlocation.Length + 1)) && lowpath.StartsWith(lowlocation))
+ return anypath.Substring(lowlocation.Length + 1);
+ else
+ return anypath;
+ }
+ else
+ {
+ // Path is already relative
+ return anypath;
+ }
+ }
#endregion
}
diff --git a/Source/IO/DirectoryFileEntry.cs b/Source/IO/DirectoryFileEntry.cs
new file mode 100644
index 00000000..75250ad5
--- /dev/null
+++ b/Source/IO/DirectoryFileEntry.cs
@@ -0,0 +1,90 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.IO
+{
+ internal struct DirectoryFileEntry
+ {
+ // Example for: C:\WADs\Foo\Bar.WAD
+ // Created from: C:\WADs
+ // Members
+ public string filename; // bar.wad
+ public string filetitle; // bar
+ public string extension; // wad
+ public string path; // foo
+ public string filepathname; // Foo\Bar.WAD
+ public string filepathtitle; // Foo\Bar
+
+ // Constructor
+ public DirectoryFileEntry(string fullname, string frompath)
+ {
+ // Get the information we need
+ filename = Path.GetFileName(fullname);
+ filetitle = Path.GetFileNameWithoutExtension(fullname);
+ extension = Path.GetExtension(fullname);
+ if(extension.Length > 1)
+ extension = extension.Substring(1);
+ else
+ extension = "";
+ path = Path.GetDirectoryName(fullname);
+ if(path.Length > (frompath.Length + 1))
+ path = path.Substring(frompath.Length + 1);
+ else
+ path = "";
+ filepathname = Path.Combine(path, filename);
+ filepathtitle = Path.Combine(path, filetitle);
+
+ // Make some lowercase
+ filename = filename.ToLowerInvariant();
+ filetitle = filetitle.ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ path = path.ToLowerInvariant();
+ }
+
+ // Constructor
+ public DirectoryFileEntry(string fullname)
+ {
+ // Get the information we need
+ filename = Path.GetFileName(fullname);
+ filetitle = Path.GetFileNameWithoutExtension(fullname);
+ extension = Path.GetExtension(fullname);
+ if(extension.Length > 1)
+ extension = extension.Substring(1);
+ else
+ extension = "";
+ path = Path.GetDirectoryName(fullname);
+ filepathname = Path.Combine(path, filename);
+ filepathtitle = Path.Combine(path, filetitle);
+
+ // Make some lowercase
+ filename = filename.ToLowerInvariant();
+ filetitle = filetitle.ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ path = path.ToLowerInvariant();
+ }
+ }
+}
diff --git a/Source/IO/DirectoryFilesList.cs b/Source/IO/DirectoryFilesList.cs
new file mode 100644
index 00000000..e7400d30
--- /dev/null
+++ b/Source/IO/DirectoryFilesList.cs
@@ -0,0 +1,266 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.IO
+{
+ internal sealed class DirectoryFilesList
+ {
+ #region ================== Variables
+
+ private DirectoryFileEntry[] entries;
+ private Dictionary hashedentries;
+
+ #endregion
+
+ #region ================== Properties
+
+ public int Count { get { return entries.Length; } }
+
+ #endregion
+
+ #region ================== Constructor / Disposer
+
+ // Constructor to fill list from directory and optionally subdirectories
+ public DirectoryFilesList(string path, bool subdirectories)
+ {
+ path = Path.GetFullPath(path);
+ string[] files = Directory.GetFiles(path, "*", subdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
+ entries = new DirectoryFileEntry[files.Length];
+ hashedentries = new Dictionary(files.Length);
+ for(int i = 0; i < files.Length; i++)
+ {
+ entries[i] = new DirectoryFileEntry(files[i], path);
+ hashedentries.Add(entries[i].filepathname.ToLowerInvariant(), entries[i]);
+ }
+ }
+
+ // Constructor for custom list
+ public DirectoryFilesList(ICollection sourceentries)
+ {
+ int index = 0;
+ entries = new DirectoryFileEntry[sourceentries.Count];
+ hashedentries = new Dictionary(sourceentries.Count);
+ foreach(DirectoryFileEntry e in sourceentries)
+ {
+ entries[index] = e;
+ hashedentries.Add(e.filepathname.ToLowerInvariant(), e);
+ index++;
+ }
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ // This checks if a given file exists
+ // The given file path must not be absolute
+ public bool FileExists(string filepathname)
+ {
+ return hashedentries.ContainsKey(filepathname.ToLowerInvariant());
+ }
+
+ // This returns file information for the given file
+ // The given file path must not be absolute
+ public DirectoryFileEntry GetFileInfo(string filepathname)
+ {
+ return hashedentries[filepathname.ToLowerInvariant()];
+ }
+
+ // This returns a list of all files (filepathname)
+ public List GetAllFiles()
+ {
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++) files.Add(entries[i].filepathname);
+ return files;
+ }
+
+ // This returns a list of all files optionally with subdirectories included
+ public List GetAllFiles(bool subdirectories)
+ {
+ if(subdirectories)
+ return GetAllFiles();
+ else
+ {
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++)
+ if(entries[i].path.Length == 0) files.Add(entries[i].filepathname);
+ return files;
+ }
+ }
+
+ // This returns a list of all files that are in the given path and optionally in subdirectories
+ public List GetAllFiles(string path, bool subdirectories)
+ {
+ path = CorrectPath(path).ToLowerInvariant();
+ if(subdirectories)
+ {
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++)
+ if(entries[i].path == path) files.Add(entries[i].filepathname);
+ return files;
+ }
+ else
+ {
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++)
+ if(entries[i].path == path) files.Add(entries[i].filepathname);
+ return files;
+ }
+ }
+
+ // This returns a list of all files that are in the given path and subdirectories and have the given extension
+ public List GetAllFiles(string path, string extension)
+ {
+ path = CorrectPath(path).ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++)
+ if(entries[i].path.StartsWith(path) && (entries[i].extension == extension))
+ files.Add(entries[i].filepathname);
+ return files;
+ }
+
+ // This returns a list of all files that are in the given path (optionally in subdirectories) and have the given extension
+ public List GetAllFiles(string path, string extension, bool subdirectories)
+ {
+ if(subdirectories)
+ return GetAllFiles(path, extension);
+ else
+ {
+ path = CorrectPath(path).ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ List files = new List(entries.Length);
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].path == path) && (entries[i].extension == extension))
+ files.Add(entries[i].filepathname);
+ return files;
+ }
+ }
+
+ // This finds the first file that has the specified name, regardless of file extension
+ public string GetFirstFile(string title, bool subdirectories)
+ {
+ title = title.ToLowerInvariant();
+ if(subdirectories)
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if(entries[i].filetitle == title)
+ return entries[i].filepathname;
+ }
+ else
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && (entries[i].path.Length == 0))
+ return entries[i].filepathname;
+ }
+
+ return null;
+ }
+
+ // This finds the first file that has the specified name and extension
+ public string GetFirstFile(string title, bool subdirectories, string extension)
+ {
+ title = title.ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ if(subdirectories)
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && (entries[i].extension == extension))
+ return entries[i].filepathname;
+ }
+ else
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && (entries[i].path.Length == 0) && (entries[i].extension == extension))
+ return entries[i].filepathname;
+ }
+
+ return null;
+ }
+
+ // This finds the first file that has the specified name, regardless of file extension, and is in the given path
+ public string GetFirstFile(string path, string title, bool subdirectories)
+ {
+ title = title.ToLowerInvariant();
+ path = CorrectPath(path).ToLowerInvariant();
+ if(subdirectories)
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && entries[i].path.StartsWith(path))
+ return entries[i].filepathname;
+ }
+ else
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && (entries[i].path == path))
+ return entries[i].filepathname;
+ }
+
+ return null;
+ }
+
+ // This finds the first file that has the specified name, is in the given path and has the given extension
+ public string GetFirstFile(string path, string title, bool subdirectories, string extension)
+ {
+ title = title.ToLowerInvariant();
+ path = CorrectPath(path).ToLowerInvariant();
+ extension = extension.ToLowerInvariant();
+ if(subdirectories)
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && entries[i].path.StartsWith(path) && (entries[i].extension == extension))
+ return entries[i].filepathname;
+ }
+ else
+ {
+ for(int i = 0; i < entries.Length; i++)
+ if((entries[i].filetitle == title) && (entries[i].path == path) && (entries[i].extension == extension))
+ return entries[i].filepathname;
+ }
+
+ return null;
+ }
+
+ // This fixes a path so that it doesn't have the \ at the end
+ private string CorrectPath(string path)
+ {
+ if(path.Length > 0)
+ {
+ if((path[path.Length - 1] == Path.DirectorySeparatorChar) || (path[path.Length - 1] == Path.AltDirectorySeparatorChar))
+ return path.Substring(0, path.Length - 1);
+ else
+ return path;
+ }
+ else
+ {
+ return path;
+ }
+ }
+
+ #endregion
+ }
+}