diff --git a/Build/Configurations/Boom.cfg b/Build/Configurations/Boom.cfg
index dc67aff7..64bc85b2 100644
--- a/Build/Configurations/Boom.cfg
+++ b/Build/Configurations/Boom.cfg
@@ -152,6 +152,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Eternity_Doom.cfg b/Build/Configurations/Eternity_Doom.cfg
index e41ae3c9..14ad8987 100644
--- a/Build/Configurations/Eternity_Doom.cfg
+++ b/Build/Configurations/Eternity_Doom.cfg
@@ -147,6 +147,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Eternity_DoomUDMF.cfg b/Build/Configurations/Eternity_DoomUDMF.cfg
index 9a215013..60e10bbd 100644
--- a/Build/Configurations/Eternity_DoomUDMF.cfg
+++ b/Build/Configurations/Eternity_DoomUDMF.cfg
@@ -152,6 +152,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Legacy.cfg b/Build/Configurations/Legacy.cfg
index 0e223341..8f675647 100644
--- a/Build/Configurations/Legacy.cfg
+++ b/Build/Configurations/Legacy.cfg
@@ -147,6 +147,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Risen3D.cfg b/Build/Configurations/Risen3D.cfg
index b694ae08..12274901 100644
--- a/Build/Configurations/Risen3D.cfg
+++ b/Build/Configurations/Risen3D.cfg
@@ -147,6 +147,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Skulltag_Doom.cfg b/Build/Configurations/Skulltag_Doom.cfg
index cc52ae9a..39b53a1c 100644
--- a/Build/Configurations/Skulltag_Doom.cfg
+++ b/Build/Configurations/Skulltag_Doom.cfg
@@ -155,6 +155,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/Skulltag_DoomHexen.cfg b/Build/Configurations/Skulltag_DoomHexen.cfg
index 33b0ced7..d526dfdb 100644
--- a/Build/Configurations/Skulltag_DoomHexen.cfg
+++ b/Build/Configurations/Skulltag_DoomHexen.cfg
@@ -166,6 +166,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/ZDoom_Doom.cfg b/Build/Configurations/ZDoom_Doom.cfg
index 0e7cecae..2d50e426 100644
--- a/Build/Configurations/ZDoom_Doom.cfg
+++ b/Build/Configurations/ZDoom_Doom.cfg
@@ -155,6 +155,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/ZDoom_DoomHexen.cfg b/Build/Configurations/ZDoom_DoomHexen.cfg
index 057de632..c29ba243 100644
--- a/Build/Configurations/ZDoom_DoomHexen.cfg
+++ b/Build/Configurations/ZDoom_DoomHexen.cfg
@@ -166,6 +166,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/ZDoom_DoomUDMF.cfg b/Build/Configurations/ZDoom_DoomUDMF.cfg
index f2e25fc4..518daf36 100644
--- a/Build/Configurations/ZDoom_DoomUDMF.cfg
+++ b/Build/Configurations/ZDoom_DoomUDMF.cfg
@@ -176,6 +176,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/ZDoom_HereticHexen.cfg b/Build/Configurations/ZDoom_HereticHexen.cfg
index ab6e7c75..c64ea8ae 100644
--- a/Build/Configurations/ZDoom_HereticHexen.cfg
+++ b/Build/Configurations/ZDoom_HereticHexen.cfg
@@ -165,6 +165,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Build/Configurations/ZDoom_Hexen.cfg b/Build/Configurations/ZDoom_Hexen.cfg
index 1a8f9a5f..db6cc4b4 100644
--- a/Build/Configurations/ZDoom_Hexen.cfg
+++ b/Build/Configurations/ZDoom_Hexen.cfg
@@ -165,6 +165,16 @@ flats
}
}
+// Colormap sources
+colormaps
+{
+ standard1
+ {
+ start = "C_START";
+ end = "C_END";
+ }
+}
+
/*
GAME DETECT PATTERN
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 8b032aac..103b8f03 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -667,12 +667,14 @@
ThingBrowserControl.cs
+
+
Form
@@ -872,4 +874,4 @@
-
\ No newline at end of file
+
diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs
index 124dfbb4..8d2e9fbc 100644
--- a/Source/Core/Config/GameConfiguration.cs
+++ b/Source/Core/Config/GameConfiguration.cs
@@ -83,6 +83,7 @@ namespace CodeImp.DoomBuilder.Config
private IDictionary flatranges;
private IDictionary patchranges;
private IDictionary spriteranges;
+ private IDictionary colormapranges;
// Things
private List defaultthingflags;
@@ -163,6 +164,7 @@ namespace CodeImp.DoomBuilder.Config
public IDictionary FlatRanges { get { return flatranges; } }
public IDictionary PatchRanges { get { return patchranges; } }
public IDictionary SpriteRanges { get { return spriteranges; } }
+ public IDictionary ColormapRanges { get { return colormapranges; } }
// Things
public ICollection DefaultThingFlags { get { return defaultthingflags; } }
@@ -276,6 +278,7 @@ namespace CodeImp.DoomBuilder.Config
flatranges = cfg.ReadSetting("flats", new Hashtable());
patchranges = cfg.ReadSetting("patches", new Hashtable());
spriteranges = cfg.ReadSetting("sprites", new Hashtable());
+ colormapranges = cfg.ReadSetting("colormaps", new Hashtable());
// Map lumps
LoadMapLumps();
diff --git a/Source/Core/Data/ColormapImage.cs b/Source/Core/Data/ColormapImage.cs
new file mode 100644
index 00000000..0e02ef38
--- /dev/null
+++ b/Source/Core/Data/ColormapImage.cs
@@ -0,0 +1,121 @@
+
+#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.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using CodeImp.DoomBuilder.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Data
+{
+ internal sealed class ColormapImage : ImageData
+ {
+ #region ================== Constructor / Disposer
+
+ // Constructor
+ public ColormapImage(string name)
+ {
+ // Initialize
+ SetName(name);
+
+ // We have no destructor
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ // This loads the image
+ protected override void LocalLoadImage()
+ {
+ Stream lumpdata;
+ MemoryStream mem;
+ IImageReader reader;
+ byte[] membytes;
+
+ // Leave when already loaded
+ if(this.IsImageLoaded) return;
+
+ lock(this)
+ {
+ // Get the lump data stream
+ lumpdata = General.Map.Data.GetColormapData(Name);
+ if(lumpdata != null)
+ {
+ // Copy lump data to memory
+ lumpdata.Seek(0, SeekOrigin.Begin);
+ membytes = new byte[(int)lumpdata.Length];
+ lumpdata.Read(membytes, 0, (int)lumpdata.Length);
+ mem = new MemoryStream(membytes);
+ mem.Seek(0, SeekOrigin.Begin);
+
+ // Get a reader for the data
+ reader = ImageDataFormat.GetImageReader(mem, ImageDataFormat.DOOMCOLORMAP, General.Map.Data.Palette);
+ if(reader is UnknownImageReader)
+ {
+ // Data is in an unknown format!
+ General.ErrorLogger.Add(ErrorType.Error, "Colormap lump '" + Name + "' data format could not be read. Does this lump contain valid colormap data at all?");
+ bitmap = null;
+ }
+ else
+ {
+ // Read data as bitmap
+ mem.Seek(0, SeekOrigin.Begin);
+ if(bitmap != null) bitmap.Dispose();
+ bitmap = reader.ReadAsBitmap(mem);
+ }
+
+ // Done
+ mem.Dispose();
+
+ if(bitmap != null)
+ {
+ // Get width and height from image
+ width = bitmap.Size.Width;
+ height = bitmap.Size.Height;
+ scaledwidth = (float)width * General.Map.Config.DefaultFlatScale;
+ scaledheight = (float)height * General.Map.Config.DefaultFlatScale;
+ }
+ else
+ {
+ loadfailed = true;
+ }
+ }
+ else
+ {
+ // Missing a patch lump!
+ General.ErrorLogger.Add(ErrorType.Error, "Missing colormap lump '" + Name + "'. Did you forget to include required resources?");
+ loadfailed = true;
+ }
+
+ // Pass on to base
+ base.LocalLoadImage();
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index e4faef9c..717130c9 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -207,8 +207,9 @@ namespace CodeImp.DoomBuilder.Data
// This loads all data resources
internal void Load(DataLocationList locations)
{
- int texcount, flatcount, spritecount, thingcount;
+ int texcount, flatcount, spritecount, thingcount, colormapcount;
Dictionary texturesonly = new Dictionary();
+ Dictionary colormapsonly = new Dictionary();
Dictionary flatsonly = new Dictionary();
DataReader c;
@@ -289,10 +290,18 @@ namespace CodeImp.DoomBuilder.Data
LoadPalette();
texcount = LoadTextures(texturesonly);
flatcount = LoadFlats(flatsonly);
+ colormapcount = LoadColormaps(colormapsonly);
thingcount = LoadDecorateThings();
spritecount = LoadSprites();
LoadInternalSprites();
-
+
+ // Process colormaps (we just put them in as textures)
+ foreach(KeyValuePair t in colormapsonly)
+ {
+ textures.Add(t.Key, t.Value);
+ texturenames.Add(t.Value.Name);
+ }
+
// Process textures
foreach(KeyValuePair t in texturesonly)
{
@@ -369,7 +378,7 @@ namespace CodeImp.DoomBuilder.Data
StartBackgroundLoader();
// Output info
- General.WriteLogLine("Loaded " + texcount + " textures, " + flatcount + " flats, " + spritecount + " sprites, " + thingcount + " decorate things");
+ General.WriteLogLine("Loaded " + texcount + " textures, " + flatcount + " flats, " + colormapcount + " colormaps, " + spritecount + " sprites, " + thingcount + " decorate things");
}
// This unloads all data
@@ -677,8 +686,60 @@ namespace CodeImp.DoomBuilder.Data
#endregion
+ #region ================== Colormaps
+
+ // This loads the colormaps
+ private int LoadColormaps(Dictionary list)
+ {
+ ICollection images;
+ int counter = 0;
+
+ // Go for all opened containers
+ foreach(DataReader dr in containers)
+ {
+ // Load colormaps
+ images = dr.LoadColormaps();
+ if(images != null)
+ {
+ // Go for all colormaps
+ foreach(ImageData img in images)
+ {
+ // Add or replace in flats list
+ list.Remove(img.LongName);
+ list.Add(img.LongName, img);
+ counter++;
+
+ // Add to preview manager
+ previews.AddImage(img);
+ }
+ }
+ }
+
+ // Output info
+ return counter;
+ }
+
+ // This returns a specific colormap stream
+ internal Stream GetColormapData(string pname)
+ {
+ Stream colormap;
+
+ // Go for all opened containers
+ for(int i = containers.Count - 1; i >= 0; i--)
+ {
+ // This contain provides this flat?
+ colormap = containers[i].GetColormapData(pname);
+ if(colormap != null) return colormap;
+ }
+
+ // No such patch found
+ return null;
+ }
+
+ #endregion
+
#region ================== Textures
-
+
// This loads the textures
private int LoadTextures(Dictionary list)
{
@@ -758,7 +819,7 @@ namespace CodeImp.DoomBuilder.Data
// No such patch found
return null;
}
-
+
// This returns an image by string
public ImageData GetTextureImage(string name)
{
diff --git a/Source/Core/Data/DataReader.cs b/Source/Core/Data/DataReader.cs
index e32837f9..84784514 100644
--- a/Source/Core/Data/DataReader.cs
+++ b/Source/Core/Data/DataReader.cs
@@ -102,6 +102,16 @@ namespace CodeImp.DoomBuilder.Data
#endregion
+ #region ================== Colormaps
+
+ // When implemented, this loads the colormaps
+ public virtual ICollection LoadColormaps() { return null; }
+
+ // When implemented, this returns the colormap lump
+ public virtual Stream GetColormapData(string pname) { return null; }
+
+ #endregion
+
#region ================== Textures
// When implemented, this should read the patch names
diff --git a/Source/Core/Data/DirectoryReader.cs b/Source/Core/Data/DirectoryReader.cs
index b26e982b..5258d1fc 100644
--- a/Source/Core/Data/DirectoryReader.cs
+++ b/Source/Core/Data/DirectoryReader.cs
@@ -137,6 +137,39 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
+ // This finds and returns a colormap stream
+ public override Stream GetColormapData(string pname)
+ {
+ // Error when suspended
+ if(issuspended) throw new Exception("Data reader is suspended");
+
+ // Find in any of the wad files
+ // Note the backward order, because the last wad's images have priority
+ for(int i = wads.Count - 1; i >= 0; i--)
+ {
+ Stream data = wads[i].GetColormapData(pname);
+ if(data != null) return data;
+ }
+
+ try
+ {
+ // Find in patches directory
+ string path = Path.Combine(COLORMAPS_DIR, Path.GetDirectoryName(pname));
+ string filename = FindFirstFile(path, Path.GetFileName(pname), true);
+ if((filename != null) && FileExists(filename))
+ {
+ return LoadFile(filename);
+ }
+ }
+ catch(Exception e)
+ {
+ General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading colormap '" + pname + "' from directory: " + e.Message);
+ }
+
+ // Nothing found
+ return null;
+ }
+
#endregion
#region ================== Sprites
@@ -215,9 +248,23 @@ namespace CodeImp.DoomBuilder.Data
}
// This creates an image
- protected override ImageData CreateImage(string name, string filename, bool flat)
+ protected override ImageData CreateImage(string name, string filename, int imagetype)
{
- return new FileImage(name, Path.Combine(location.location, filename), flat);
+ switch(imagetype)
+ {
+ case ImageDataFormat.DOOMFLAT:
+ return new FileImage(name, Path.Combine(location.location, filename), true);
+
+ case ImageDataFormat.DOOMPICTURE:
+ return new FileImage(name, Path.Combine(location.location, filename), false);
+
+ case ImageDataFormat.DOOMCOLORMAP:
+ return new ColormapImage(name);
+
+ default:
+ throw new ArgumentException("Invalid image format specified!");
+ return null;
+ }
}
// This returns true if the specified file exists
diff --git a/Source/Core/Data/ImageDataFormat.cs b/Source/Core/Data/ImageDataFormat.cs
index 86f4443c..5bfcc358 100644
--- a/Source/Core/Data/ImageDataFormat.cs
+++ b/Source/Core/Data/ImageDataFormat.cs
@@ -35,6 +35,7 @@ namespace CodeImp.DoomBuilder.Data
public const int UNKNOWN = 0; // No clue.
public const int DOOMPICTURE = 1; // Could be Doom Picture format (column list rendered data)
public const int DOOMFLAT = 2; // Could be Doom Flat format (raw 8-bit pixel data)
+ public const int DOOMCOLORMAP = 3; // Could be Doom Colormap format (raw 8-bit pixel palette mapping)
// File format signatures
private static readonly int[] PNG_SIGNATURE = new int[] { 137, 80, 78, 71, 13, 10, 26, 10 };
@@ -47,6 +48,7 @@ namespace CodeImp.DoomBuilder.Data
BinaryReader bindata = new BinaryReader(data);
DoomPictureReader picreader;
DoomFlatReader flatreader;
+ DoomColormapReader colormapreader;
// First check the formats that provide the means to 'ensure' that
// it actually is that format. Then guess the Doom image format.
@@ -87,6 +89,14 @@ namespace CodeImp.DoomBuilder.Data
flatreader = new DoomFlatReader(palette);
if(flatreader.Validate(data)) return flatreader;
}
+ // Could it be a doom colormap?
+ else if(guessformat == DOOMCOLORMAP)
+ {
+ // Check if data is valid for a doom colormap
+ data.Seek(0, SeekOrigin.Begin);
+ colormapreader = new DoomColormapReader(palette);
+ if(colormapreader.Validate(data)) return colormapreader;
+ }
// Format not supported
return new UnknownImageReader();
diff --git a/Source/Core/Data/PK3Reader.cs b/Source/Core/Data/PK3Reader.cs
index 6b35a7c4..c7abade9 100644
--- a/Source/Core/Data/PK3Reader.cs
+++ b/Source/Core/Data/PK3Reader.cs
@@ -153,6 +153,31 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
+ // This finds and returns a colormap stream
+ public override Stream GetColormapData(string pname)
+ {
+ // Error when suspended
+ if(issuspended) throw new Exception("Data reader is suspended");
+
+ // Find in any of the wad files
+ // Note the backward order, because the last wad's images have priority
+ for(int i = wads.Count - 1; i >= 0; i--)
+ {
+ Stream data = wads[i].GetColormapData(pname);
+ if(data != null) return data;
+ }
+
+ // Find in patches directory
+ string filename = FindFirstFile(COLORMAPS_DIR, pname, true);
+ if((filename != null) && FileExists(filename))
+ {
+ return LoadFile(filename);
+ }
+
+ // Nothing found
+ return null;
+ }
+
#endregion
#region ================== Sprites
@@ -219,9 +244,23 @@ namespace CodeImp.DoomBuilder.Data
}
// This creates an image
- protected override ImageData CreateImage(string name, string filename, bool flat)
+ protected override ImageData CreateImage(string name, string filename, int imagetype)
{
- return new PK3FileImage(this, name, filename, flat);
+ switch(imagetype)
+ {
+ case ImageDataFormat.DOOMFLAT:
+ return new PK3FileImage(this, name, filename, true);
+
+ case ImageDataFormat.DOOMPICTURE:
+ return new PK3FileImage(this, name, filename, false);
+
+ case ImageDataFormat.DOOMCOLORMAP:
+ return new ColormapImage(name);
+
+ default:
+ throw new ArgumentException("Invalid image format specified!");
+ return null;
+ }
}
// This returns true if the specified file exists
diff --git a/Source/Core/Data/PK3StructuredReader.cs b/Source/Core/Data/PK3StructuredReader.cs
index b58b3a64..e99a36d6 100644
--- a/Source/Core/Data/PK3StructuredReader.cs
+++ b/Source/Core/Data/PK3StructuredReader.cs
@@ -39,6 +39,7 @@ namespace CodeImp.DoomBuilder.Data
protected const string FLATS_DIR = "flats";
protected const string HIRES_DIR = "hires";
protected const string SPRITES_DIR = "sprites";
+ protected const string COLORMAPS_DIR = "colormaps";
#endregion
@@ -175,12 +176,12 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as textures?
if(roottextures)
{
- collection = LoadDirectoryImages("", false, false);
+ collection = LoadDirectoryImages("", ImageDataFormat.DOOMPICTURE, false);
AddImagesToList(images, collection);
}
// Add images from texture directory
- collection = LoadDirectoryImages(TEXTURES_DIR, false, true);
+ collection = LoadDirectoryImages(TEXTURES_DIR, ImageDataFormat.DOOMPICTURE, true);
AddImagesToList(images, collection);
// Load TEXTURE1 lump file
@@ -279,12 +280,12 @@ namespace CodeImp.DoomBuilder.Data
// Should we load the images in this directory as flats?
if(rootflats)
{
- collection = LoadDirectoryImages("", true, false);
+ collection = LoadDirectoryImages("", ImageDataFormat.DOOMFLAT, false);
AddImagesToList(images, collection);
}
// Add images from flats directory
- collection = LoadDirectoryImages(FLATS_DIR, true, true);
+ collection = LoadDirectoryImages(FLATS_DIR, ImageDataFormat.DOOMFLAT, true);
AddImagesToList(images, collection);
// Add images to the container-specific texture set
@@ -296,6 +297,38 @@ namespace CodeImp.DoomBuilder.Data
#endregion
+ #region ================== Colormaps
+
+ // This loads the textures
+ public override ICollection LoadColormaps()
+ {
+ Dictionary images = new Dictionary();
+ ICollection collection;
+
+ // Error when suspended
+ if(issuspended) throw new Exception("Data reader is suspended");
+
+ // Load from wad files
+ // Note the backward order, because the last wad's images have priority
+ for(int i = wads.Count - 1; i >= 0; i--)
+ {
+ collection = wads[i].LoadColormaps();
+ AddImagesToList(images, collection);
+ }
+
+ // Add images from flats directory
+ collection = LoadDirectoryImages(COLORMAPS_DIR, ImageDataFormat.DOOMCOLORMAP, true);
+ AddImagesToList(images, collection);
+
+ // Add images to the container-specific texture set
+ foreach(ImageData img in images.Values)
+ textureset.AddFlat(img);
+
+ return new List(images.Values);
+ }
+
+ #endregion
+
#region ================== Decorate
// This finds and returns a sprite stream
@@ -329,7 +362,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Methods
// This loads the images in this directory
- private ICollection LoadDirectoryImages(string path, bool flats, bool includesubdirs)
+ private ICollection LoadDirectoryImages(string path, int imagetype, bool includesubdirs)
{
List images = new List();
string[] files;
@@ -345,7 +378,7 @@ namespace CodeImp.DoomBuilder.Data
if(name.Length > 0)
{
// Add image to list
- images.Add(CreateImage(name, f, flats));
+ images.Add(CreateImage(name, f, imagetype));
}
else
{
@@ -371,7 +404,7 @@ namespace CodeImp.DoomBuilder.Data
}
// This must create an image
- protected abstract ImageData CreateImage(string name, string filename, bool flat);
+ protected abstract ImageData CreateImage(string name, string filename, int imagetype);
// This must return true if the specified file exists
protected abstract bool FileExists(string filename);
diff --git a/Source/Core/Data/WADReader.cs b/Source/Core/Data/WADReader.cs
index 1502cd3a..44a38f65 100644
--- a/Source/Core/Data/WADReader.cs
+++ b/Source/Core/Data/WADReader.cs
@@ -60,6 +60,7 @@ namespace CodeImp.DoomBuilder.Data
private List patchranges;
private List spriteranges;
private List textureranges;
+ private List colormapranges;
#endregion
@@ -84,12 +85,14 @@ namespace CodeImp.DoomBuilder.Data
spriteranges = new List();
flatranges = new List();
textureranges = new List();
+ colormapranges = new List();
// Find ranges
FindRanges(patchranges, General.Map.Config.PatchRanges, "patches");
FindRanges(spriteranges, General.Map.Config.SpriteRanges, "sprites");
FindRanges(flatranges, General.Map.Config.FlatRanges, "flats");
FindRanges(textureranges, General.Map.Config.TextureRanges, "textures");
+ FindRanges(colormapranges, General.Map.Config.ColormapRanges, "colormaps");
// We have no destructor
GC.SuppressFinalize(this);
@@ -195,6 +198,96 @@ namespace CodeImp.DoomBuilder.Data
#endregion
+ #region ================== Colormaps
+
+ // This loads the textures
+ public override ICollection LoadColormaps()
+ {
+ List images = new List();
+ string rangestart, rangeend;
+
+ // Error when suspended
+ if(issuspended) throw new Exception("Data reader is suspended");
+
+ // Read ranges from configuration
+ foreach(DictionaryEntry r in General.Map.Config.ColormapRanges)
+ {
+ // Read start and end
+ rangestart = General.Map.Config.ReadSetting("colormaps." + r.Key + ".start", "");
+ rangeend = General.Map.Config.ReadSetting("colormaps." + r.Key + ".end", "");
+ if((rangestart.Length > 0) && (rangeend.Length > 0))
+ {
+ // Load texture range
+ LoadColormapsRange(rangestart, rangeend, ref images);
+ }
+ }
+
+ // Add images to the container-specific texture set
+ foreach(ImageData img in images)
+ textureset.AddFlat(img);
+
+ // Return result
+ return images;
+ }
+
+ // This loads a range of colormaps
+ private void LoadColormapsRange(string startlump, string endlump, ref List images)
+ {
+ int startindex, endindex;
+ float defaultscale;
+ ColormapImage image;
+
+ // Determine default scale
+ defaultscale = General.Map.Config.DefaultTextureScale;
+
+ // Continue until no more start can be found
+ startindex = file.FindLumpIndex(startlump);
+ while(startindex > -1)
+ {
+ // Find end index
+ endindex = file.FindLumpIndex(endlump, startindex + 1);
+ if(endindex > -1)
+ {
+ // Go for all lumps between start and end exclusive
+ for(int i = startindex + 1; i < endindex; i++)
+ {
+ // Lump not zero-length?
+ if(file.Lumps[i].Length > 0)
+ {
+ // Make the image object
+ image = new ColormapImage(file.Lumps[i].Name);
+
+ // Add image to collection
+ images.Add(image);
+ }
+ }
+ }
+
+ // Find the next start
+ startindex = file.FindLumpIndex(startlump, startindex + 1);
+ }
+ }
+
+ // This finds and returns a colormap stream
+ public override Stream GetColormapData(string pname)
+ {
+ Lump lump;
+
+ // Error when suspended
+ if(issuspended) throw new Exception("Data reader is suspended");
+
+ // Find the lump in ranges
+ foreach(LumpRange range in colormapranges)
+ {
+ lump = file.FindLump(pname, range.start, range.end);
+ if(lump != null) return lump.Stream;
+ }
+
+ return null;
+ }
+
+ #endregion
+
#region ================== Textures
// This loads the textures
@@ -460,7 +553,7 @@ namespace CodeImp.DoomBuilder.Data
return null;
}
-
+
#endregion
#region ================== Flats
diff --git a/Source/Core/IO/DoomColormapReader.cs b/Source/Core/IO/DoomColormapReader.cs
new file mode 100644
index 00000000..8b9649b7
--- /dev/null
+++ b/Source/Core/IO/DoomColormapReader.cs
@@ -0,0 +1,242 @@
+
+#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;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Geometry;
+using System.Drawing;
+using CodeImp.DoomBuilder.Data;
+using CodeImp.DoomBuilder.Rendering;
+using System.Drawing.Imaging;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.IO
+{
+ internal unsafe class DoomColormapReader : IImageReader
+ {
+ #region ================== Variables
+
+ // Palette to use
+ private Playpal palette;
+
+ #endregion
+
+ #region ================== Constructor / Disposer
+
+ // Constructor
+ public DoomColormapReader(Playpal palette)
+ {
+ // Initialize
+ this.palette = palette;
+
+ // We have no destructor
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ // This validates the data as doom flat
+ public bool Validate(Stream stream)
+ {
+ int remainder;
+
+ // Check if the data can be divided by 256 (each palette is 256 bytes)
+ remainder = (int)stream.Length % 256;
+ if(remainder == 0)
+ {
+ // Success when not 0
+ return (stream.Length > 0);
+ }
+
+ // Format invalid
+ return false;
+ }
+
+ // This creates a Bitmap from the given data
+ // Returns null on failure
+ public Bitmap ReadAsBitmap(Stream stream, out int offsetx, out int offsety)
+ {
+ offsetx = int.MinValue;
+ offsety = int.MinValue;
+ return ReadAsBitmap(stream);
+ }
+
+ // This creates a Bitmap from the given data
+ // Returns null on failure
+ public Bitmap ReadAsBitmap(Stream stream)
+ {
+ BitmapData bitmapdata;
+ PixelColorBlock pixeldata;
+ PixelColor* targetdata;
+ int width, height;
+ Bitmap bmp;
+
+ // Read pixel data
+ pixeldata = ReadAsPixelData(stream, out width, out height);
+ if(pixeldata != null)
+ {
+ try
+ {
+ // Create bitmap and lock pixels
+ bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
+ bitmapdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
+ targetdata = (PixelColor*)bitmapdata.Scan0.ToPointer();
+
+ // Copy the pixels
+ General.CopyMemory(targetdata, pixeldata.Pointer, (uint)(width * height * sizeof(PixelColor)));
+
+ // Done
+ bmp.UnlockBits(bitmapdata);
+ }
+ catch(Exception e)
+ {
+ // Unable to make bitmap
+ General.ErrorLogger.Add(ErrorType.Error, "Unable to make Doom flat data. " + e.GetType().Name + ": " + e.Message);
+ return null;
+ }
+ }
+ else
+ {
+ // Failed loading picture
+ bmp = null;
+ }
+
+ // Return result
+ return bmp;
+ }
+
+ // This draws the picture to the given pixel color data
+ // Throws exception on failure
+ public unsafe void DrawToPixelData(Stream stream, PixelColor* target, int targetwidth, int targetheight, int x, int y)
+ {
+ Bitmap bmp;
+ BitmapData bmpdata;
+ PixelColor* pixels;
+ int ox, oy, tx, ty;
+ int width, height;
+
+ // Get bitmap
+ bmp = ReadAsBitmap(stream);
+ width = bmp.Size.Width;
+ height = bmp.Size.Height;
+
+ // Lock bitmap pixels
+ bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
+ pixels = (PixelColor*)bmpdata.Scan0.ToPointer();
+
+ // Go for all pixels in the original image
+ for(ox = 0; ox < width; ox++)
+ {
+ for(oy = 0; oy < height; oy++)
+ {
+ // Copy this pixel?
+ if(pixels[oy * width + ox].a > 0.5f)
+ {
+ // Calculate target pixel and copy when within bounds
+ tx = x + ox;
+ ty = y + oy;
+ if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
+ target[ty * targetwidth + tx] = pixels[oy * width + ox];
+ }
+ }
+ }
+
+ // Done
+ bmp.UnlockBits(bmpdata);
+ bmp.Dispose();
+ }
+
+ // This creates pixel color data from the given data
+ // Returns null on failure
+ private PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height)
+ {
+ BinaryReader reader = new BinaryReader(stream);
+ PixelColorBlock pixeldata = null;
+ byte[] bytes;
+
+ // Image will be 128x128
+ width = 128;
+ height = 128;
+
+#if !DEBUG
+ try
+ {
+#endif
+
+ // Allocate memory
+ pixeldata = new PixelColorBlock(width, height);
+ pixeldata.Clear();
+
+ // Read flat bytes from stream
+ bytes = new byte[width * height];
+ stream.Read(bytes, 0, width * height);
+
+ // Draw blocks using the palette
+ // We want to draw 8x8 blocks for each color
+ // 16 wide and 16 high
+ uint i = 0;
+ for(int by = 0; by < 16; by++)
+ {
+ for(int bx = 0; bx < 16; bx++)
+ {
+ PixelColor bc = palette[bytes[i++]];
+ PixelColor bc1 = General.Colors.CreateBrightVariant(palette[bytes[i++]]);
+ PixelColor bc2 = General.Colors.CreateDarkVariant(palette[bytes[i++]]);
+ for(int py = 0; py < 8; py++)
+ {
+ for(int px = 0; px < 8; px++)
+ {
+ int p = ((by * 8) + py) * width + (bx * 8) + px;
+
+ // We make the borders slightly brighter and darker
+ if((py == 0) || (px == 0))
+ pixeldata.Pointer[p] = bc1;
+ else if((py == 7) || (px == 7))
+ pixeldata.Pointer[p] = bc2;
+ else
+ pixeldata.Pointer[p] = bc;
+ }
+ }
+ }
+ }
+
+ // Return pointer
+ return pixeldata;
+
+#if !DEBUG
+ }
+ catch(Exception)
+ {
+ // Return nothing
+ return null;
+ }
+#endif
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Source/Core/Rendering/ColorCollection.cs b/Source/Core/Rendering/ColorCollection.cs
index 1f8aa6a7..994f5aaf 100644
--- a/Source/Core/Rendering/ColorCollection.cs
+++ b/Source/Core/Rendering/ColorCollection.cs
@@ -228,29 +228,41 @@ namespace CodeImp.DoomBuilder.Rendering
// This creates assist colors
internal void CreateAssistColors()
{
- Color4 o;
- Color4 c = new Color4(1f, 0f, 0f, 0f);
-
// Go for all colors
for(int i = 0; i < NUM_COLORS; i++)
{
- // Get original color
- o = colors[i].ToColorValue();
-
- // Create brighter color
- c.Red = Saturate(o.Red * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
- c.Green = Saturate(o.Green * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
- c.Blue = Saturate(o.Blue * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
- brightcolors[i] = PixelColor.FromInt(c.ToArgb());
-
- // Create darker color
- c.Red = Saturate(o.Red * DARK_MULTIPLIER + DARK_ADDITION);
- c.Green = Saturate(o.Green * DARK_MULTIPLIER + DARK_ADDITION);
- c.Blue = Saturate(o.Blue * DARK_MULTIPLIER + DARK_ADDITION);
- darkcolors[i] = PixelColor.FromInt(c.ToArgb());
+ // Create assist colors
+ brightcolors[i] = CreateBrightVariant(colors[i]);
+ darkcolors[i] = CreateDarkVariant(colors[i]);
}
}
+ // This creates a brighter color
+ public PixelColor CreateBrightVariant(PixelColor pc)
+ {
+ Color4 o = pc.ToColorValue();
+ Color4 c = new Color4(1f, 0f, 0f, 0f);
+
+ // Create brighter color
+ c.Red = Saturate(o.Red * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
+ c.Green = Saturate(o.Green * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
+ c.Blue = Saturate(o.Blue * BRIGHT_MULTIPLIER + BRIGHT_ADDITION);
+ return PixelColor.FromInt(c.ToArgb());
+ }
+
+ // This creates a darker color
+ public PixelColor CreateDarkVariant(PixelColor pc)
+ {
+ Color4 o = pc.ToColorValue();
+ Color4 c = new Color4(1f, 0f, 0f, 0f);
+
+ // Create darker color
+ c.Red = Saturate(o.Red * DARK_MULTIPLIER + DARK_ADDITION);
+ c.Green = Saturate(o.Green * DARK_MULTIPLIER + DARK_ADDITION);
+ c.Blue = Saturate(o.Blue * DARK_MULTIPLIER + DARK_ADDITION);
+ return PixelColor.FromInt(c.ToArgb());
+ }
+
// This saves colors to configuration
internal void SaveColors(Configuration cfg)
{