miauw, lots more added/changed

This commit is contained in:
codeimp 2007-06-24 18:56:43 +00:00
parent b7c0958af4
commit b9a6bfb3ea
30 changed files with 1256 additions and 281 deletions

View file

@ -1,10 +1,10 @@
mainwindow
{
positionx = 209;
positionx = 124;
windowstate = 2;
positiony = 137;
sizeheight = 572;
sizewidth = 739;
sizeheight = 388;
sizewidth = 530;
positiony = 35;
}

View file

@ -2,6 +2,12 @@
Doom Builder Script highlighting definitions for ACS
\*******************************************************************/
// Compiler settings
compiler = "acc.exe";
parameters = "%FI %FO";
resultlump = "BEHAVIOR";
// Editor settings
casesensitive = 0;
insertcase = 0; // 0=Normal, 1=Lowercase, 2=Uppercase
linecomment = "//";

View file

@ -81,8 +81,8 @@
<Compile Include="General\General.cs" />
<Compile Include="IO\ClippedStream.cs" />
<Compile Include="IO\DoomMapSetIO.cs" />
<Compile Include="IO\IMapSetIO.cs" />
<Compile Include="IO\Lump.cs" />
<Compile Include="IO\MapSetIO.cs" />
<Compile Include="IO\WAD.cs" />
<Compile Include="Interface\MainForm.cs">
<SubType>Form</SubType>

View file

@ -28,6 +28,7 @@ using CodeImp.DoomBuilder.Interface;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using System.Diagnostics;
#endregion
@ -83,6 +84,31 @@ namespace CodeImp.DoomBuilder.Editing
#endregion
#region ================== Static Methods
// This creates an instance of a specific mode
public static EditMode Create(Type modetype, object[] args)
{
try
{
// Create new mode
return (EditMode)General.ThisAssembly.CreateInstance(modetype.FullName, false,
BindingFlags.Default, null, args, CultureInfo.CurrentCulture, new object[0]);
}
// Catch errors
catch(TargetInvocationException e)
{
// Throw the actual exception
Debug.WriteLine(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
Debug.WriteLine(e.InnerException.Source + " throws " + e.InnerException.GetType().Name + ":");
Debug.WriteLine(e.InnerException.Message);
Debug.WriteLine(e.InnerException.StackTrace);
throw e.InnerException;
}
}
#endregion
#region ================== Methods
// Optional interface methods

View file

@ -52,8 +52,35 @@ namespace CodeImp.DoomBuilder.Editing
// Constructor
public FrozenOverviewMode()
{
// Initialize
float left = float.MaxValue;
float top = float.MaxValue;
float right = float.MinValue;
float bottom = float.MinValue;
float scalew, scaleh, scale;
float width, height;
// Go for all vertices
foreach(Vertex v in General.Map.Data.Vertices)
{
// Adjust boundaries by vertices
if(v.Position.x < left) left = v.Position.x;
if(v.Position.x > right) right = v.Position.x;
if(v.Position.y < top) top = v.Position.y;
if(v.Position.y > bottom) bottom = v.Position.y;
}
// Calculate width/height
width = (right - left);
height = (bottom - top);
// Calculate scale to view map at
scalew = (float)General.Map.Graphics.RenderTarget.ClientSize.Width / (width * 1.1f);
scaleh = (float)General.Map.Graphics.RenderTarget.ClientSize.Height / (height * 1.1f);
if(scalew < scaleh) scale = scalew; else scale = scaleh;
// Change the view to see the whole map
renderer.ScaleView(scale);
renderer.PositionView(left + (right - left) * 0.5f, top + (bottom - top) * 0.5f);
}
// Diposer
@ -79,7 +106,7 @@ namespace CodeImp.DoomBuilder.Editing
if(renderer.StartRendering())
{
renderer.RenderLinedefs(General.Map.Data.Linedefs);
//renderer.RenderVertices(General.Map.Data.Vertices);
renderer.FinishRendering();
}
}

View file

@ -28,6 +28,7 @@ using CodeImp.DoomBuilder.Interface;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Runtime.InteropServices;
#endregion
@ -35,6 +36,13 @@ namespace CodeImp.DoomBuilder
{
internal static class General
{
#region ================== API Declarations
[DllImport("user32.dll")]
public static extern int LockWindowUpdate(IntPtr hwnd);
#endregion
#region ================== Constants
// Files and Folders
@ -373,5 +381,31 @@ namespace CodeImp.DoomBuilder
}
#endregion
#region ================== Tools
// This returns a unique temp filename
public static string MakeTempFilename()
{
string filename;
string chars = "abcdefghijklmnopqrstuvwxyz1234567890";
Random rnd = new Random();
int i;
do
{
// Generate a filename
filename = "";
for(i = 0; i < 8; i++) filename += chars[rnd.Next(chars.Length)];
filename = Path.Combine(temppath, filename + ".tmp");
}
// Continue while file is not unique
while(File.Exists(filename));
// Return the filename
return filename;
}
#endregion
}
}

View file

@ -39,6 +39,8 @@ namespace CodeImp.DoomBuilder
{
#region ================== Constants
private const string TEMP_MAP_HEADER = "TEMPMAP";
#endregion
#region ================== Variables
@ -54,6 +56,7 @@ namespace CodeImp.DoomBuilder
private Configuration config;
private EditMode mode;
private Graphics graphics;
private WAD tempwad;
// Disposing
private bool isdisposed = false;
@ -89,9 +92,16 @@ namespace CodeImp.DoomBuilder
if(!isdisposed)
{
// Dispose
tempwad.Dispose();
data.Dispose();
mode.Dispose();
graphics.Dispose();
// Remove temp file
try { File.Delete(tempwad.Filename); } catch(Exception) { }
// We may spend some time to clean things up here
GC.Collect();
// Done
isdisposed = true;
@ -129,6 +139,9 @@ namespace CodeImp.DoomBuilder
// Initializes for an existing map
public bool InitializeOpenMap(string filepathname, MapOptions options)
{
WAD mapwad;
MapSetIO mapio;
// Apply settings
this.filetitle = Path.GetFileName(filepathname);
this.filepathname = filepathname;
@ -140,6 +153,23 @@ namespace CodeImp.DoomBuilder
config = General.LoadGameConfiguration(options.ConfigFile);
data = new MapSet();
// Create temp wadfile
tempwad = new WAD(General.MakeTempFilename());
// Now open the map file
mapwad = new WAD(filepathname, true);
// Copy the map lumps to the temp file
CopyLumpsByType(mapwad, options.CurrentName, tempwad, TEMP_MAP_HEADER,
true, true, true, true);
// Close the map file
mapwad.Dispose();
// Read the map from temp file
mapio = MapSetIO.Create(config.ReadSetting("formatinterface", ""), tempwad);
data = mapio.Read(new MapSet(), TEMP_MAP_HEADER);
// Initiate graphics
if(!graphics.Initialize()) return false;
@ -154,28 +184,121 @@ namespace CodeImp.DoomBuilder
#region ================== Methods
// This copies specific map lumps from one WAD to another
private void CopyLumpsByType(WAD source, string sourcemapname,
WAD target, string targetmapname,
bool copyrequired, bool copyblindcopy,
bool copynodebuild, bool copyscript)
{
bool lumprequired, lumpblindcopy, lumpnodebuild;
string lumpscript;
int srcindex, tgtindex;
IDictionary maplumps;
Lump lump, newlump;
// Find the map header in target
tgtindex = target.FindLumpIndex(targetmapname);
// If this header doesnt exists in the target
// then insert at the end of the target
tgtindex = target.Lumps.Count;
// Remove the lumps from target
RemoveLumpsByType(target, targetmapname, copyrequired,
copyblindcopy, copynodebuild, copyscript);
// Find the map header in source
srcindex = source.FindLumpIndex(sourcemapname);
if(srcindex > -1)
{
// Copy the map header from source to target
newlump = target.Insert(targetmapname, tgtindex++, source.Lumps[srcindex].Length);
source.Lumps[srcindex].CopyTo(newlump);
// Go for all the map lump names
maplumps = config.ReadSetting("maplumpnames", new Hashtable());
foreach(DictionaryEntry ml in maplumps)
{
// Read lump settings from map config
lumprequired = config.ReadSetting("maplumpnames." + ml.Key + ".required", false);
lumpblindcopy = config.ReadSetting("maplumpnames." + ml.Key + ".blindcopy", false);
lumpnodebuild = config.ReadSetting("maplumpnames." + ml.Key + ".nodebuild", false);
lumpscript = config.ReadSetting("maplumpnames." + ml.Key + ".script", "");
// Check if this lump should be copied
if((lumprequired && copyrequired) || (lumpblindcopy && copyblindcopy) ||
(lumpnodebuild && copynodebuild) || ((lumpscript != "") && copyscript))
{
// Find the lump in the source
lump = source.FindLump(ml.Key.ToString(), srcindex, srcindex + maplumps.Count + 2);
if(lump != null)
{
// Copy the lump to the target
newlump = target.Insert(ml.Key.ToString(), tgtindex++, lump.Length);
lump.CopyTo(newlump);
}
}
}
}
}
// This copies specific map lumps from one WAD to another
private void RemoveLumpsByType(WAD source, string sourcemapname,
bool copyrequired, bool copyblindcopy,
bool copynodebuild, bool copyscript)
{
bool lumprequired, lumpblindcopy, lumpnodebuild;
string nextlumpname, lumpscript;
int index;
// Find the map header in target
index = source.FindLumpIndex(sourcemapname);
if(index > -1)
{
// Remove the header from target
source.RemoveAt(index);
// Get the name of the next lump
if(index < source.Lumps.Count) nextlumpname = source.Lumps[index].Name;
else nextlumpname = "";
// Do we recognize this lump type?
while(config.ReadSetting("maplumpnames." + nextlumpname, (IDictionary)null) != null)
{
// Read lump settings from map config
lumprequired = config.ReadSetting("maplumpnames." + nextlumpname + ".required", false);
lumpblindcopy = config.ReadSetting("maplumpnames." + nextlumpname + ".blindcopy", false);
lumpnodebuild = config.ReadSetting("maplumpnames." + nextlumpname + ".nodebuild", false);
lumpscript = config.ReadSetting("maplumpnames." + nextlumpname + ".script", "");
// Check if this lump will be copied from source
if((lumprequired && copyrequired) || (lumpblindcopy && copyblindcopy) ||
(lumpnodebuild && copynodebuild) || ((lumpscript != "") && copyscript))
{
// Then remove it from target
source.RemoveAt(index);
}
else
{
// Advance to the next lump
index++;
}
// Get the name of the next lump
if(index < source.Lumps.Count) nextlumpname = source.Lumps[index].Name;
else nextlumpname = "";
}
}
}
// This changes editing mode
public void ChangeMode(Type modetype, params object[] args)
{
// Dispose current mode
if(mode != null) mode.Dispose();
try
{
// Create new mode
mode = (EditMode)General.ThisAssembly.CreateInstance(modetype.FullName, false,
BindingFlags.Default, null, args, CultureInfo.CurrentCulture, new object[0]);
}
// Catch errors
catch(TargetInvocationException e)
{
// Throw the actual exception
Debug.WriteLine(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
Debug.WriteLine(e.InnerException.Source + " throws " + e.InnerException.GetType().Name + ":");
Debug.WriteLine(e.InnerException.Message);
Debug.WriteLine(e.InnerException.StackTrace);
throw e.InnerException;
}
// Create a new mode
mode = EditMode.Create(modetype, args);
// Redraw the display
mode.RedrawDisplay();

View file

@ -105,7 +105,7 @@ namespace CodeImp.DoomBuilder.IO
public override int Read(byte[] buffer, int offset, int count)
{
// Check if this exceeds limits
if((basestream.Position + count) > (this.offset + this.length))
if((this.position + count) > (this.length + 1))
throw new ArgumentException("Attempted to read outside the range of the stream.");
// Seek if needed
@ -113,6 +113,7 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position += count;
return basestream.Read(buffer, offset, count);
}
@ -120,7 +121,7 @@ namespace CodeImp.DoomBuilder.IO
public override void Write(byte[] buffer, int offset, int count)
{
// Check if this exceeds limits
if((basestream.Position + count) > (this.offset + this.length))
if((this.position + count) > (this.length + 1))
throw new ArgumentException("Attempted to write outside the range of the stream.");
// Seek if needed
@ -128,6 +129,7 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position += count;
basestream.Write(buffer, offset, count);
}
@ -142,7 +144,7 @@ namespace CodeImp.DoomBuilder.IO
throw new ArgumentException("Attempted to seek outside the range of the stream.");
// Seek
return basestream.Seek(this.offset + offset, SeekOrigin.Begin) - this.offset;
position = basestream.Seek(this.offset + offset, SeekOrigin.Begin) - this.offset;
}
// Seeking from current position
else if(origin == SeekOrigin.Current)
@ -152,7 +154,7 @@ namespace CodeImp.DoomBuilder.IO
throw new ArgumentException("Attempted to seek outside the range of the stream.");
// Seek
return basestream.Seek(this.offset + this.position + offset, SeekOrigin.Begin) - this.offset;
position = basestream.Seek(this.offset + this.position + offset, SeekOrigin.Begin) - this.offset;
}
// Seeking from end
else
@ -162,8 +164,11 @@ namespace CodeImp.DoomBuilder.IO
throw new ArgumentException("Attempted to seek outside the range of the stream.");
// Seek
return basestream.Seek(this.offset + this.length + offset, SeekOrigin.Begin) - this.offset;
position = basestream.Seek(this.offset + this.length + offset, SeekOrigin.Begin) - this.offset;
}
// Return new position
return position;
}
// Change the length of the steam
@ -177,7 +182,7 @@ namespace CodeImp.DoomBuilder.IO
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
// Check if this exceeds limits
if((basestream.Position + count) > (this.offset + this.length))
if((this.position + count) > (this.length + 1))
throw new ArgumentException("Attempted to read outside the range of the stream.");
// Seek if needed
@ -185,6 +190,7 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read
position += count;
return base.BeginRead(buffer, offset, count, callback, state);
}
@ -192,7 +198,7 @@ namespace CodeImp.DoomBuilder.IO
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
// Check if this exceeds limits
if((basestream.Position + count) > (this.offset + this.length))
if((this.position + count) > (this.length + 1))
throw new ArgumentException("Attempted to write outside the range of the stream.");
// Seek if needed
@ -200,6 +206,7 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Write
position += count;
return base.BeginWrite(buffer, offset, count, callback, state);
}
@ -215,7 +222,7 @@ namespace CodeImp.DoomBuilder.IO
public override int ReadByte()
{
// Check if this exceeds limits
if((basestream.Position + 1) > (this.offset + this.length))
if((this.position + 1) > (this.length + 1))
throw new ArgumentException("Attempted to read outside the range of the stream.");
// Seek if needed
@ -223,6 +230,7 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position++;
return basestream.ReadByte();
}
@ -230,7 +238,7 @@ namespace CodeImp.DoomBuilder.IO
public override void WriteByte(byte value)
{
// Check if this exceeds limits
if((basestream.Position + 1) > (this.offset + this.length))
if((this.position + 1) > (this.length + 1))
throw new ArgumentException("Attempted to write outside the range of the stream.");
// Seek if needed
@ -238,9 +246,19 @@ namespace CodeImp.DoomBuilder.IO
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position++;
basestream.WriteByte(value);
}
// This returns all the bytes in the stream
public byte[] ReadAllBytes()
{
byte[] bytes = new byte[length];
Seek(0, SeekOrigin.Begin);
Read(bytes, 0, length);
return bytes;
}
#endregion
}
}

View file

@ -1,59 +1,301 @@
#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;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal class DoomMapSetIO : IDisposable
internal class DoomMapSetIO : MapSetIO
{
#region ================== Constants
#endregion
#region ================== Variables
// Disposing
private bool isdisposed = false;
#endregion
#region ================== Properties
// Disposing
public bool IsDisposed { get { return isdisposed; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public DoomMapSetIO()
public DoomMapSetIO(WAD wad) : base(wad)
{
// Initialize
// We have no destructor
GC.SuppressFinalize(this);
}
// Diposer
public void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
// Clean up
// Done
isdisposed = true;
}
}
#endregion
#region ================== Reading
#region ================== Methods
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
int firstindex;
Dictionary<int, Vertex> vertexlink;
Dictionary<int, Sector> sectorlink;
// Find the index where first map lump begins
firstindex = wad.FindLumpIndex(mapname) + 1;
// Read vertices
vertexlink = ReadVertices(map, firstindex);
// Read sectors
sectorlink = ReadSectors(map, firstindex);
// Read linedefs and sidedefs
ReadLinedefs(map, firstindex, vertexlink, sectorlink);
// Read things
ReadThings(map, firstindex);
// Return result;
return map;
}
// This reads the THINGS from WAD file
private void ReadThings(MapSet map, int firstindex)
{
MemoryStream mem;
BinaryReader reader;
int num, i, x, y, type, flags;
float angle;
Thing t;
// Get the lump from wad file
Lump lump = wad.FindLump("THINGS", firstindex);
if(lump == null) throw new Exception("Could not find required lump THINGS!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 10;
reader = new BinaryReader(mem);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
x = reader.ReadInt16();
y = reader.ReadInt16();
angle = reader.ReadInt16(); // TODO: Fix this!
type = reader.ReadUInt16();
flags = reader.ReadUInt16();
// Create new item
t = map.CreateThing();
t.Update(type, new Vector3D(x, y, 0f), angle, flags, 0, 0, Thing.EMPTY_ARGS);
t.DetermineSector();
}
// Done
mem.Dispose();
}
// This reads the VERTICES from WAD file
// Returns a lookup table with indices
private Dictionary<int, Vertex> ReadVertices(MapSet map, int firstindex)
{
MemoryStream mem;
Dictionary<int, Vertex> link;
BinaryReader reader;
int num, i, x, y;
Vertex v;
// Get the lump from wad file
Lump lump = wad.FindLump("VERTEXES", firstindex);
if(lump == null) throw new Exception("Could not find required lump VERTEXES!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 4;
reader = new BinaryReader(mem);
// Create lookup table
link = new Dictionary<int, Vertex>(num);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
x = reader.ReadInt16();
y = reader.ReadInt16();
// Create new item
v = map.CreateVertex(new Vector2D(x, y));
// Add it to the lookup table
link.Add(i, v);
}
// Done
mem.Dispose();
// Return lookup table
return link;
}
// This reads the SECTORS from WAD file
// Returns a lookup table with indices
private Dictionary<int, Sector> ReadSectors(MapSet map, int firstindex)
{
MemoryStream mem;
Dictionary<int, Sector> link;
BinaryReader reader;
int num, i, hfloor, hceil, bright, special, tag;
string tfloor, tceil;
Sector s;
// Get the lump from wad file
Lump lump = wad.FindLump("SECTORS", firstindex);
if(lump == null) throw new Exception("Could not find required lump SECTORS!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 26;
reader = new BinaryReader(mem);
// Create lookup table
link = new Dictionary<int, Sector>(num);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
hfloor = reader.ReadInt16();
hceil = reader.ReadInt16();
tfloor = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
tceil = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
bright = reader.ReadInt16();
special = reader.ReadUInt16();
tag = reader.ReadUInt16();
// Create new item
s = map.CreateSector();
s.Update(hfloor, hceil, tfloor, tceil, special, tag);
// Add it to the lookup table
link.Add(i, s);
}
// Done
mem.Dispose();
// Return lookup table
return link;
}
// This reads the LINEDEFS and SIDEDEFS from WAD file
private void ReadLinedefs(MapSet map, int firstindex,
Dictionary<int, Vertex> vertexlink, Dictionary<int, Sector> sectorlink)
{
MemoryStream linedefsmem, sidedefsmem;
BinaryReader readline, readside;
Lump linedefslump, sidedefslump;
int num, i, offsetx, offsety, v1, v2;
int s1, s2, flags, action, tag, sc;
string thigh, tmid, tlow;
Linedef l;
Sidedef s;
// Get the linedefs lump from wad file
linedefslump = wad.FindLump("LINEDEFS", firstindex);
if(linedefslump == null) throw new Exception("Could not find required lump LINEDEFS!");
// Get the sidedefs lump from wad file
sidedefslump = wad.FindLump("SIDEDEFS", firstindex);
if(sidedefslump == null) throw new Exception("Could not find required lump SIDEDEFS!");
// Prepare to read the items
linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes());
sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes());
num = (int)linedefslump.Stream.Length / 14;
readline = new BinaryReader(linedefsmem);
readside = new BinaryReader(sidedefsmem);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
v1 = readline.ReadUInt16();
v2 = readline.ReadUInt16();
flags = readline.ReadUInt16();
action = readline.ReadUInt16();
tag = readline.ReadUInt16();
s1 = readline.ReadUInt16();
s2 = readline.ReadUInt16();
// Create new item
l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(flags, tag, action, Linedef.EMPTY_ARGS);
// Line has a front side?
if(s1 != ushort.MaxValue)
{
// Read front sidedef
sidedefsmem.Seek(s1 * 30, SeekOrigin.Begin);
offsetx = readside.ReadInt16();
offsety = readside.ReadInt16();
thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
sc = readside.ReadUInt16();
// Create front sidedef
s = map.CreateSidedef(l, true, sectorlink[sc]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
}
// Line has a back side?
if(s2 != ushort.MaxValue)
{
// Read back sidedef
sidedefsmem.Seek(s2 * 30, SeekOrigin.Begin);
offsetx = readside.ReadInt16();
offsety = readside.ReadInt16();
thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
sc = readside.ReadUInt16();
// Create back sidedef
s = map.CreateSidedef(l, false, sectorlink[sc]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
}
}
// Done
linedefsmem.Dispose();
sidedefsmem.Dispose();
}
#endregion
#region ================== Writing
// This writes a MapSet to the file
public override void Write(MapSet map, string mapname, int position)
{
}
#endregion
}
}

View file

@ -1,36 +0,0 @@
#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 CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal interface IMapSetIO : IDisposable
{
// Methods
MapSet Read(string mapname);
void Write(MapSet map, string mapname);
}
}

View file

@ -73,8 +73,8 @@ namespace CodeImp.DoomBuilder.IO
this.length = length;
// Make uppercase name
this.name = MakeNormalName(fixedname, owner.Encoding).ToUpperInvariant();
this.fixedname = MakeFixedName(name, owner.Encoding);
this.name = MakeNormalName(fixedname, WAD.ENCODING).ToUpperInvariant();
this.fixedname = MakeFixedName(name, WAD.ENCODING);
// We have no destructor
GC.SuppressFinalize(this);
@ -100,7 +100,7 @@ namespace CodeImp.DoomBuilder.IO
#region ================== Methods
// This makes the normal name from fixed name
private static string MakeNormalName(byte[] fixedname, Encoding encoding)
public static string MakeNormalName(byte[] fixedname, Encoding encoding)
{
int length = 0;
@ -124,6 +124,18 @@ namespace CodeImp.DoomBuilder.IO
return fixedname;
}
// This copies lump data to another lump
public void CopyTo(Lump lump)
{
BinaryReader reader;
// Create a reader
reader = new BinaryReader(stream);
// Copy bytes over
lump.Stream.Write(reader.ReadBytes((int)stream.Length), 0, (int)stream.Length);
}
// String representation
public override string ToString()
{

124
Source/IO/MapSetIO.cs Normal file
View file

@ -0,0 +1,124 @@
#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 System.Reflection;
using System.Diagnostics;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal abstract class MapSetIO
{
#region ================== Constants
#endregion
#region ================== Variables
// WAD File
protected WAD wad;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Disposer
// Constructor
public MapSetIO(WAD wad)
{
// Initialize
this.wad = wad;
}
// Destructor
~MapSetIO()
{
// Clean up
wad = null;
}
#endregion
#region ================== Static Methods
// This returns and instance of the specified IO class
public static MapSetIO Create(string classname, WAD wadfile)
{
object[] args;
MapSetIO result;
string fullname;
try
{
// Create arguments
args = new object[1];
args[0] = wadfile;
// Make the full class name
fullname = "CodeImp.DoomBuilder.IO." + classname;
// Create IO class
result = (MapSetIO)General.ThisAssembly.CreateInstance(fullname, false,
BindingFlags.Default, null, args, CultureInfo.CurrentCulture, new object[0]);
// Check result
if(result != null)
{
// Success
return result;
}
else
{
// No such class
throw new ArgumentException("No such map format interface found: \"" + classname + "\"");
}
}
// Catch errors
catch(TargetInvocationException e)
{
// Throw the actual exception
Debug.WriteLine(DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
Debug.WriteLine(e.InnerException.Source + " throws " + e.InnerException.GetType().Name + ":");
Debug.WriteLine(e.InnerException.Message);
Debug.WriteLine(e.InnerException.StackTrace);
throw e.InnerException;
}
}
#endregion
#region ================== Methods
// Required implementations
public abstract MapSet Read(MapSet map, string mapname);
public abstract void Write(MapSet map, string mapname, int position);
#endregion
}
}

View file

@ -35,18 +35,19 @@ namespace CodeImp.DoomBuilder.IO
public const string TYPE_IWAD = "IWAD";
public const string TYPE_PWAD = "PWAD";
// Encoder
public static readonly Encoding ENCODING = Encoding.ASCII;
#endregion
#region ================== Variables
// File objects
private string filename;
private FileStream file;
private BinaryReader reader;
private BinaryWriter writer;
// Encoder
private readonly Encoding encoding = Encoding.ASCII;
// Header
private string type;
private int numlumps;
@ -63,8 +64,9 @@ namespace CodeImp.DoomBuilder.IO
#region ================== Properties
public string Filename { get { return filename; } }
public string Type { get { return type; } }
public Encoding Encoding { get { return encoding; } }
public Encoding Encoding { get { return ENCODING; } }
public bool IsReadOnly { get { return isreadonly; } }
public bool IsDisposed { get { return isdisposed; } }
public List<Lump> Lumps { get { return lumps; } }
@ -137,17 +139,43 @@ namespace CodeImp.DoomBuilder.IO
share = FileShare.Read;
}
// Keep filename
filename = pathfilename;
// Open the file stream
file = File.Open(pathfilename, FileMode.OpenOrCreate, access, share);
// Create file handling tools
reader = new BinaryReader(file, encoding);
if(!isreadonly) writer = new BinaryWriter(file, encoding);
reader = new BinaryReader(file, ENCODING);
if(!isreadonly) writer = new BinaryWriter(file, ENCODING);
// Read information from file
ReadHeaders();
// Is the WAD file zero length?
if(file.Length == 0)
{
// Create the headers in file
CreateHeaders();
}
else
{
// Read information from file
ReadHeaders();
}
}
// This creates new file headers
private void CreateHeaders()
{
// Default settings
type = TYPE_PWAD;
lumpsoffset = 12;
// New lumps array
lumps = new List<Lump>(numlumps);
// Write the headers
WriteHeaders();
}
// This reads the WAD header and lumps table
private void ReadHeaders()
{
@ -161,7 +189,7 @@ namespace CodeImp.DoomBuilder.IO
file.Seek(0, SeekOrigin.Begin);
// Read WAD type
type = encoding.GetString(reader.ReadBytes(4));
type = ENCODING.GetString(reader.ReadBytes(4));
// Number of lumps
numlumps = reader.ReadInt32();
@ -196,7 +224,7 @@ namespace CodeImp.DoomBuilder.IO
file.Seek(0, SeekOrigin.Begin);
// Write WAD type
writer.Write(encoding.GetBytes(type));
writer.Write(ENCODING.GetBytes(type));
// Number of lumps
writer.Write(numlumps);
@ -245,7 +273,7 @@ namespace CodeImp.DoomBuilder.IO
file.SetLength(file.Length + datalength + 16);
// Create the lump
lump = new Lump(file, this, Lump.MakeFixedName(name, encoding), lumpsoffset, datalength);
lump = new Lump(file, this, Lump.MakeFixedName(name, ENCODING), lumpsoffset, datalength);
lumps.Insert(position, lump);
// Advance lumps table offset
@ -257,6 +285,20 @@ namespace CodeImp.DoomBuilder.IO
// Return the new lump
return lump;
}
// This removes a lump from the WAD file by index
public void RemoveAt(int index)
{
Lump l;
// Remove from list
l = lumps[index];
lumps.RemoveAt(index);
l.Dispose();
// Write the new headers
WriteHeaders();
}
// This removes a lump from the WAD file
public void Remove(Lump lump)
@ -272,31 +314,61 @@ namespace CodeImp.DoomBuilder.IO
// This finds a lump by name, returns null when not found
public Lump FindLump(string name)
{
// Do search
return FindLump(name, 0, lumps.Count - 1);
int index = FindLumpIndex(name);
if(index == -1)
return null;
else
return lumps[index];
}
// This finds a lump by name, returns null when not found
public Lump FindLump(string name, int start)
{
// Do search
return FindLump(name, start, lumps.Count - 1);
int index = FindLumpIndex(name, start);
if(index == -1)
return null;
else
return lumps[index];
}
// This finds a lump by name, returns null when not found
public Lump FindLump(string name, int start, int end)
{
int index = FindLumpIndex(name, start, end);
if(index == -1)
return null;
else
return lumps[index];
}
// This finds a lump by name, returns null when not found
public int FindLumpIndex(string name)
{
// Do search
return FindLumpIndex(name, 0, lumps.Count - 1);
}
// This finds a lump by name, returns null when not found
public int FindLumpIndex(string name, int start)
{
// Do search
return FindLumpIndex(name, start, lumps.Count - 1);
}
// This finds a lump by name, returns -1 when not found
public int FindLumpIndex(string name, int start, int end)
{
byte[] fixedname;
// Fix end when it exceeds length
if(end > (lumps.Count - 1)) end = lumps.Count - 1;
// Make sure name is in uppercase
name = name.ToUpperInvariant();
// Make fixed name
fixedname = Lump.MakeFixedName(name, encoding);
fixedname = Lump.MakeFixedName(name, ENCODING);
// Loop through the lumps
for(int i = start; i <= end; i++)
{
@ -307,13 +379,13 @@ namespace CodeImp.DoomBuilder.IO
if(lumps[i].Name.StartsWith(name, false, CultureInfo.InvariantCulture))
{
// Found the lump!
return lumps[i];
return i;
}
}
}
// Nothing found
return null;
return -1;
}
#endregion

View file

@ -230,6 +230,7 @@ namespace CodeImp.DoomBuilder.Interface
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "Doom Builder";
this.Resize += new System.EventHandler(this.MainForm_Resize);
this.Move += new System.EventHandler(this.MainForm_Move);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.ResizeEnd += new System.EventHandler(this.MainForm_ResizeEnd);

View file

@ -40,7 +40,8 @@ namespace CodeImp.DoomBuilder.Interface
// Position/size
private Point lastposition;
private Size lastsize;
private bool displayresized = true;
// Mouse in display
private bool mouseinside;
@ -60,7 +61,7 @@ namespace CodeImp.DoomBuilder.Interface
{
// Setup controls
InitializeComponent();
// Keep last position and size
lastposition = this.Location;
lastsize = this.Size;
@ -103,6 +104,14 @@ namespace CodeImp.DoomBuilder.Interface
}
}
// Window resizes
private void MainForm_Resize(object sender, EventArgs e)
{
// Resizing
//this.SuspendLayout();
//resized = true;
}
// Window was resized
private void MainForm_ResizeEnd(object sender, EventArgs e)
{
@ -121,7 +130,10 @@ namespace CodeImp.DoomBuilder.Interface
int windowstate;
// Determine window state to save
if(this.WindowState != FormWindowState.Minimized) windowstate = (int)this.WindowState; else windowstate = (int)FormWindowState.Normal;
if(this.WindowState != FormWindowState.Minimized)
windowstate = (int)this.WindowState;
else
windowstate = (int)FormWindowState.Normal;
// Save settings to configuration
General.Settings.WriteSetting("mainwindow.positionx", lastposition.X);
@ -184,8 +196,8 @@ namespace CodeImp.DoomBuilder.Interface
// Display needs repainting
private void display_Paint(object sender, PaintEventArgs e)
{
// Repaint on demand
if(General.Map != null) redrawtimer.Enabled = true;
// Request redraw
if(!redrawtimer.Enabled) redrawtimer.Enabled = true;
}
// Redraw requested
@ -193,22 +205,40 @@ namespace CodeImp.DoomBuilder.Interface
{
// Disable timer (only redraw once)
redrawtimer.Enabled = false;
// Resume control layouts
if(displayresized) General.LockWindowUpdate(IntPtr.Zero);
// Redraw now
if(General.Map != null) General.Map.Mode.RedrawDisplay();
// Map opened?
if(General.Map != null)
{
// Display was resized?
if(displayresized)
{
// Reset graphics to match changes
General.Map.Graphics.Reset();
// Make sure control is repainted
display.Update();
}
// Redraw now
General.Map.Mode.RedrawDisplay();
}
// Display resize is done
displayresized = false;
}
// Display size changes
private void display_Resize(object sender, EventArgs e)
{
// Reset graphics to match changes
if(General.Map != null) General.Map.Graphics.Reset();
// Resizing
if(!displayresized) General.LockWindowUpdate(display.Handle);
displayresized = true;
// Make sure control is repainted
display.Update();
// Redraw display
if(General.Map != null) General.Map.Mode.RedrawDisplay();
// Request redraw
if(!redrawtimer.Enabled) redrawtimer.Enabled = true;
}
// Mouse click

View file

@ -117,12 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menumain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="menumain.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="menumain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="toolbar.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View file

@ -164,6 +164,7 @@ namespace CodeImp.DoomBuilder.Interface
this.resources.Name = "resources";
this.resources.Size = new System.Drawing.Size(321, 88);
this.resources.TabIndex = 10;
this.resources.DoubleClick += new System.EventHandler(this.resources_DoubleClick);
this.resources.SelectedIndexChanged += new System.EventHandler(this.resources_SelectedIndexChanged);
//
// apply

View file

@ -167,5 +167,12 @@ namespace CodeImp.DoomBuilder.Interface
editresource.Enabled = (resources.SelectedIndex > -1);
deleteresource.Enabled = (resources.SelectedIndex > -1);
}
// Resource doubleclicked
private void resources_DoubleClick(object sender, EventArgs e)
{
// Click Edit Resource
if(resources.SelectedIndex > -1) editresource.PerformClick();
}
}
}

View file

@ -28,6 +28,7 @@ namespace CodeImp.DoomBuilder.Interface
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.ColumnHeader columnHeader1;
this.panelres = new System.Windows.Forms.GroupBox();
this.deleteresource = new System.Windows.Forms.Button();
this.editresource = new System.Windows.Forms.Button();
@ -39,9 +40,14 @@ namespace CodeImp.DoomBuilder.Interface
this.cancel = new System.Windows.Forms.Button();
this.config = new System.Windows.Forms.ComboBox();
this.mapslist = new System.Windows.Forms.ListView();
columnHeader1 = new System.Windows.Forms.ColumnHeader();
this.panelres.SuspendLayout();
this.SuspendLayout();
//
// columnHeader1
//
columnHeader1.Text = "Map name";
//
// panelres
//
this.panelres.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@ -98,6 +104,7 @@ namespace CodeImp.DoomBuilder.Interface
this.resources.Name = "resources";
this.resources.Size = new System.Drawing.Size(321, 88);
this.resources.TabIndex = 10;
this.resources.DoubleClick += new System.EventHandler(this.resources_DoubleClick);
this.resources.SelectedIndexChanged += new System.EventHandler(this.resources_SelectedIndexChanged);
//
// label1
@ -153,7 +160,8 @@ namespace CodeImp.DoomBuilder.Interface
//
// mapslist
//
this.mapslist.AutoArrange = false;
this.mapslist.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
columnHeader1});
this.mapslist.FullRowSelect = true;
this.mapslist.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.mapslist.HideSelection = false;
@ -167,6 +175,7 @@ namespace CodeImp.DoomBuilder.Interface
this.mapslist.TabIndex = 18;
this.mapslist.UseCompatibleStateImageBehavior = false;
this.mapslist.View = System.Windows.Forms.View.List;
this.mapslist.DoubleClick += new System.EventHandler(this.mapslist_DoubleClick);
//
// OpenMapOptionsForm
//

View file

@ -26,6 +26,7 @@ using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Map;
using System.IO;
using System.Collections;
using System.Diagnostics;
#endregion
@ -208,10 +209,13 @@ namespace CodeImp.DoomBuilder.Interface
// Make sure this lump is not part of the map
if(!maplumpnames.Contains(wadfile.Lumps[scanindex].Name))
{
// Check the required map lumps
// Reset check
lumpsfound = 0;
checkoffset = 1;
do
// Continue while still within bounds and lumps are still recognized
while(((scanindex + checkoffset) < wadfile.Lumps.Count) &&
maplumpnames.Contains(wadfile.Lumps[scanindex + checkoffset].Name))
{
// Count the lump when it is marked as required
lumpname = wadfile.Lumps[scanindex + checkoffset].Name;
@ -220,9 +224,6 @@ namespace CodeImp.DoomBuilder.Interface
// Check the next lump
checkoffset++;
}
// Continue while still within bounds and lumps are still recognized
while(((scanindex + checkoffset) < wadfile.Lumps.Count) &&
maplumpnames.Contains(wadfile.Lumps[scanindex + checkoffset].Name));
// Map found? Then add it to the list
if(lumpsfound >= lumpsrequired)
@ -272,7 +273,7 @@ namespace CodeImp.DoomBuilder.Interface
// Apply changes
options.ClearResources();
options.ConfigFile = General.Configs[config.SelectedIndex].filename;
options.CurrentName = mapslist.SelectedItems[0].ToString();
options.CurrentName = mapslist.SelectedItems[0].Text;
foreach(ResourceLocation res in resources.Items) options.AddResource(res);
// Hide window
@ -360,5 +361,19 @@ namespace CodeImp.DoomBuilder.Interface
// Load settings
LoadSettings();
}
// Map name doubleclicked
private void mapslist_DoubleClick(object sender, EventArgs e)
{
// Click OK
if(mapslist.SelectedItems.Count > 0) apply.PerformClick();
}
// Resource doubeclicked
private void resources_DoubleClick(object sender, EventArgs e)
{
// Click Edit Resource
if(resources.SelectedIndex > -1) editresource.PerformClick();
}
}
}

View file

@ -117,6 +117,9 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="columnHeader1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="panelres.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View file

@ -22,6 +22,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.Text;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering;
using Microsoft.DirectX.Direct3D;
#endregion
@ -31,6 +33,8 @@ namespace CodeImp.DoomBuilder.Map
{
#region ================== Constants
public static readonly byte[] EMPTY_ARGS = new byte[5];
#endregion
#region ================== Variables
@ -55,6 +59,7 @@ namespace CodeImp.DoomBuilder.Map
private float lengthsq;
private float length;
//private float angle;
private PTVertex[] lineverts;
// Properties
private int flags;
@ -69,6 +74,7 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Properties
public PTVertex[] LineVertices { get { return lineverts; } }
public Vertex Start { get { return start; } }
public Vertex End { get { return end; } }
public Sidedef Front { get { return front; } }
@ -87,6 +93,7 @@ namespace CodeImp.DoomBuilder.Map
this.mainlistitem = listitem;
this.start = start;
this.end = end;
this.lineverts = new PTVertex[4];
// Attach to vertices
startvertexlistitem = start.AttachLinedef(this);
@ -136,10 +143,30 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Management
// This attaches a sidedef on the front
public void AttachFront(Sidedef s) { if(front == null) front = s; else throw new Exception("Linedef already has a front Sidedef."); }
public void AttachFront(Sidedef s)
{
// No sidedef here yet?
if(front == null)
{
// Attach and recalculate
front = s;
Recalculate();
}
else throw new Exception("Linedef already has a front Sidedef.");
}
// This attaches a sidedef on the back
public void AttachBack(Sidedef s) { if(back == null) back = s; else throw new Exception("Linedef already has a back Sidedef."); }
public void AttachBack(Sidedef s)
{
// No sidedef here yet?
if(back == null)
{
// Attach and recalculate
back = s;
Recalculate();
}
else throw new Exception("Linedef already has a back Sidedef.");
}
// This detaches a sidedef from the front
public void DetachSidedef(Sidedef s) { if(front == s) front = null; else if(back == s) back = null; else throw new Exception("Specified Sidedef is not attached to this Linedef."); }
@ -147,13 +174,52 @@ namespace CodeImp.DoomBuilder.Map
// This recalculates cached values
public void Recalculate()
{
Vector2D delta;
Vector2D normal;
int color;
// Delta vector
Vector2D delta = end.Position - start.Position;
delta = end.Position - start.Position;
// Recalculate values
lengthsq = delta.GetLengthSq();
length = (float)Math.Sqrt(lengthsq);
normal = new Vector2D(delta.x / length, delta.y / length);
//angle = delta.GetAngle();
// Single sided?
if((front == null) || (back == null))
{
// Line has an action?
if(action != 0)
color = Graphics.RGB(140, 255, 140);
else
color = Graphics.RGB(255, 255, 255);
}
else
{
// Line has an action?
if(action != 0)
color = Graphics.RGB(50, 140, 50);
else
color = Graphics.RGB(140, 140, 140);
}
// Create line normal
lineverts[0].x = start.Position.x + delta.x * 0.5f;
lineverts[0].y = start.Position.y + delta.y * 0.5f;
lineverts[1].x = lineverts[0].x + normal.y * 100f;
lineverts[1].y = lineverts[0].y - normal.x * 100f;
lineverts[0].c = color;
lineverts[1].c = color;
// Create line vertices
lineverts[2].x = start.Position.x;
lineverts[2].y = start.Position.y;
lineverts[3].x = end.Position.x;
lineverts[3].y = end.Position.y;
lineverts[2].c = color;
lineverts[3].c = color;
}
// This copies all properties to another line
@ -168,7 +234,7 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#region ================== Mathematics
#region ================== Methods
// This returns the shortest distance from given coordinates to line
public float DistanceToSq(Vector2D p, bool bounded)
@ -210,5 +276,19 @@ namespace CodeImp.DoomBuilder.Map
}
#endregion
#region ================== Changes
// This updates all properties
public void Update(int flags, int tag, int action, byte[] args)
{
// Apply changes
this.flags = flags;
this.tag = tag;
this.action = action;
this.args = args;
}
#endregion
}
}

View file

@ -111,6 +111,9 @@ namespace CodeImp.DoomBuilder.Map
sidedefs = null;
sectors = null;
things = null;
// We may spend some time to clean things up here
GC.Collect();
// Done
isdisposed = true;
@ -178,7 +181,7 @@ namespace CodeImp.DoomBuilder.Map
foreach(Thing t in things)
{
// Make new thing
Thing nt = newset.CreateThing(t.Type, t.Position);
Thing nt = newset.CreateThing();
// Copy properties
t.CopyPropertiesTo(nt);
@ -269,7 +272,7 @@ namespace CodeImp.DoomBuilder.Map
}
// This creates a new thing
public Thing CreateThing(int type, Vector2D pos)
public Thing CreateThing()
{
LinkedListNode<Thing> listitem;
Thing t;
@ -278,7 +281,7 @@ namespace CodeImp.DoomBuilder.Map
listitem = new LinkedListNode<Thing>(null);
// Make the thing
t = new Thing(this, listitem, type, pos);
t = new Thing(this, listitem);
listitem.Value = t;
// Add thing to the list

View file

@ -152,5 +152,21 @@ namespace CodeImp.DoomBuilder.Map
}
#endregion
#region ================== Changes
// This updates all properties
public void Update(int hfloor, int hceil, string tfloor, string tceil, int special, int tag)
{
// Apply changes
this.floorheight = hfloor;
this.ceilheight = hceil;
this.floortexname = tfloor;
this.ceiltexname = tceil;
this.special = special;
this.tag = tag;
}
#endregion
}
}

View file

@ -133,5 +133,20 @@ namespace CodeImp.DoomBuilder.Map
}
#endregion
#region ================== Changes
// This updates all properties
public void Update(int offsetx, int offsety, string thigh, string tmid, string tlow)
{
// Apply changes
this.offsetx = offsetx;
this.offsety = offsety;
this.texnamehigh = thigh;
this.texnamemid = tmid;
this.texnamelow = tlow;
}
#endregion
}
}

View file

@ -31,6 +31,8 @@ namespace CodeImp.DoomBuilder.Map
{
#region ================== Constants
public static readonly byte[] EMPTY_ARGS = new byte[5];
#endregion
#region ================== Variables
@ -47,8 +49,12 @@ namespace CodeImp.DoomBuilder.Map
// Properties
private int type;
private Vector2D pos;
private Vector3D pos;
private float angle;
private int flags;
private int tag;
private int action;
private byte[] args;
// Disposing
private bool isdisposed = false;
@ -58,7 +64,7 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Properties
public int Type { get { return type; } }
public Vector2D Position { get { return pos; } }
public Vector3D Position { get { return pos; } }
public bool IsDisposed { get { return isdisposed; } }
#endregion
@ -66,16 +72,11 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Constructor / Disposer
// Constructor
public Thing(MapSet map, LinkedListNode<Thing> listitem, int type, Vector2D pos)
public Thing(MapSet map, LinkedListNode<Thing> listitem)
{
// Initialize
this.map = map;
this.mainlistitem = listitem;
this.type = type;
this.pos = pos;
// Determine current sector
DetermineSector();
// We have no destructor
GC.SuppressFinalize(this);
@ -108,6 +109,20 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Management
// This copies all properties to another thing
public void CopyPropertiesTo(Thing t)
{
// Copy properties
t.type = type;
t.angle = angle;
t.pos = pos;
t.flags = flags;
t.tag = tag;
t.action = action;
t.args = EMPTY_ARGS;
args.CopyTo(t.args, 0);
}
// This determines which sector the thing is in and links it
public void DetermineSector()
{
@ -154,13 +169,39 @@ namespace CodeImp.DoomBuilder.Map
sectorlistitem = sector.AttachThing(this);
}
}
#endregion
#region ================== Changes
// This copies all properties to another thing
public void CopyPropertiesTo(Thing t)
// This moves the thing
// NOTE: This does not update sector! (call DetermineSector)
public void Move(Vector3D newpos)
{
// Copy properties
t.type = type;
t.angle = angle;
// Change position
pos = newpos;
}
// This rotates the thing
public void Rotate(float newangle)
{
// Change angle
angle = newangle;
}
// This updates all properties
// NOTE: This does not update sector! (call DetermineSector)
public void Update(int type, Vector3D pos, float angle,
int flags, int tag, int action, byte[] args)
{
// Apply changes
this.type = type;
this.pos = pos;
this.angle = angle;
this.flags = flags;
this.tag = tag;
this.action = action;
this.args = args;
}
#endregion

View file

@ -133,7 +133,7 @@ namespace CodeImp.DoomBuilder.Map
#endregion
#region ================== Mathematics
#region ================== Methods
// This returns the distance from given coordinates
public float DistanceToSq(Vector2D p)
@ -149,13 +149,21 @@ namespace CodeImp.DoomBuilder.Map
return delta.GetLength();
}
#endregion
#region ================== Tools
// This finds the line closest to the specified position
public Linedef NearestLinedef(Vector2D pos) { return MapSet.NearestLinedef(linedefs, pos); }
#endregion
#region ================== Changes
// This moves the vertex
// NOTE: This does not recalculate lines!
public void Move(Vector2D newpos)
{
// Change position
pos = newpos;
}
#endregion
}
}

View file

@ -27,6 +27,8 @@ using System.Reflection;
using System.Drawing;
using Microsoft.DirectX.Direct3D;
using System.ComponentModel;
using Microsoft.DirectX;
using CodeImp.DoomBuilder.Geometry;
#endregion
@ -49,7 +51,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Main objects
private Control rendertarget;
private Caps devicecaps;
private Device d3dd;
private Device device;
private Renderer2D renderer2d;
private Renderer3D renderer3d;
@ -60,11 +62,12 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Properties
public Device Device { get { return d3dd; } }
public Device Device { get { return device; } }
public bool IsDisposed { get { return isdisposed; } }
public Renderer2D Renderer2D { get { return renderer2d; } }
public Renderer3D Renderer3D { get { return renderer3d; } }
public Control RenderTarget { get { return rendertarget; } }
#endregion
#region ================== Constructor / Disposer
@ -88,7 +91,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Clean up
renderer2d.Dispose();
renderer3d.Dispose();
d3dd.Dispose();
device.Dispose();
rendertarget = null;
// Done
@ -104,61 +107,61 @@ namespace CodeImp.DoomBuilder.Rendering
private void SetupSettings()
{
// Setup renderstates
d3dd.SetRenderState(RenderStates.AntialiasedLineEnable, true);
d3dd.SetRenderState(RenderStates.Ambient, Color.White.ToArgb());
d3dd.SetRenderState(RenderStates.AmbientMaterialSource, (int)ColorSource.Material);
d3dd.SetRenderState(RenderStates.ColorVertex, false);
d3dd.SetRenderState(RenderStates.DiffuseMaterialSource, (int)ColorSource.Color1);
d3dd.SetRenderState(RenderStates.FillMode, (int)FillMode.Solid);
d3dd.SetRenderState(RenderStates.FogEnable, false);
d3dd.SetRenderState(RenderStates.Lighting, false);
d3dd.SetRenderState(RenderStates.LocalViewer, false);
d3dd.SetRenderState(RenderStates.NormalizeNormals, false);
d3dd.SetRenderState(RenderStates.SpecularEnable, false);
d3dd.SetRenderState(RenderStates.StencilEnable, false);
d3dd.SetRenderState(RenderStates.PointSpriteEnable, false);
d3dd.SetRenderState(RenderStates.DitherEnable, true);
d3dd.SetRenderState(RenderStates.AlphaBlendEnable, false);
d3dd.SetRenderState(RenderStates.ZEnable, false);
d3dd.SetRenderState(RenderStates.ZBufferWriteEnable, false);
d3dd.SetRenderState(RenderStates.Clipping, true);
d3dd.SetRenderState(RenderStates.CullMode, (int)Cull.CounterClockwise);
d3dd.VertexFormat = PTVertex.Format;
device.SetRenderState(RenderStates.AntialiasedLineEnable, false);
device.SetRenderState(RenderStates.Ambient, Color.White.ToArgb());
device.SetRenderState(RenderStates.AmbientMaterialSource, (int)ColorSource.Material);
device.SetRenderState(RenderStates.ColorVertex, false);
device.SetRenderState(RenderStates.DiffuseMaterialSource, (int)ColorSource.Color1);
device.SetRenderState(RenderStates.FillMode, (int)FillMode.Solid);
device.SetRenderState(RenderStates.FogEnable, false);
device.SetRenderState(RenderStates.Lighting, false);
device.SetRenderState(RenderStates.LocalViewer, false);
device.SetRenderState(RenderStates.NormalizeNormals, false);
device.SetRenderState(RenderStates.SpecularEnable, false);
device.SetRenderState(RenderStates.StencilEnable, false);
device.SetRenderState(RenderStates.PointSpriteEnable, false);
device.SetRenderState(RenderStates.DitherEnable, true);
device.SetRenderState(RenderStates.AlphaBlendEnable, false);
device.SetRenderState(RenderStates.ZEnable, false);
device.SetRenderState(RenderStates.ZBufferWriteEnable, false);
device.SetRenderState(RenderStates.Clipping, true);
device.SetRenderState(RenderStates.CullMode, (int)Cull.None);
device.VertexFormat = PTVertex.Format;
// Sampler settings
d3dd.SamplerState[0].MagFilter = TextureFilter.Linear;
d3dd.SamplerState[0].MinFilter = TextureFilter.Linear;
d3dd.SamplerState[0].MipFilter = TextureFilter.Linear;
device.SamplerState[0].MagFilter = TextureFilter.Linear;
device.SamplerState[0].MinFilter = TextureFilter.Linear;
device.SamplerState[0].MipFilter = TextureFilter.Linear;
// Texture addressing
d3dd.SamplerState[0].AddressU = TextureAddress.Wrap;
d3dd.SamplerState[0].AddressV = TextureAddress.Wrap;
d3dd.SamplerState[0].AddressW = TextureAddress.Wrap;
device.SamplerState[0].AddressU = TextureAddress.Wrap;
device.SamplerState[0].AddressV = TextureAddress.Wrap;
device.SamplerState[0].AddressW = TextureAddress.Wrap;
// First texture stage
d3dd.TextureState[0].ColorOperation = TextureOperation.Modulate;
d3dd.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
d3dd.TextureState[0].ColorArgument2 = TextureArgument.TFactor;
d3dd.TextureState[0].ResultArgument = TextureArgument.Current;
d3dd.TextureState[0].TextureCoordinateIndex = 0;
device.TextureState[0].ColorOperation = TextureOperation.Modulate;
device.TextureState[0].ColorArgument1 = TextureArgument.Current;
device.TextureState[0].ColorArgument2 = TextureArgument.TFactor;
device.TextureState[0].ResultArgument = TextureArgument.Current;
device.TextureState[0].TextureCoordinateIndex = 0;
// No more further stages
d3dd.TextureState[1].ColorOperation = TextureOperation.Disable;
device.TextureState[1].ColorOperation = TextureOperation.Disable;
// First alpha stage
d3dd.TextureState[0].AlphaOperation = TextureOperation.Modulate;
d3dd.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
d3dd.TextureState[0].AlphaArgument2 = TextureArgument.TFactor;
device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
device.TextureState[0].AlphaArgument2 = TextureArgument.TFactor;
// No more further stages
d3dd.TextureState[1].AlphaOperation = TextureOperation.Disable;
device.TextureState[1].AlphaOperation = TextureOperation.Disable;
// Setup material
Material material = new Material();
material.Ambient = Color.White;
material.Diffuse = Color.White;
material.Specular = Color.White;
d3dd.Material = material;
device.Material = material;
}
#endregion
@ -168,7 +171,6 @@ namespace CodeImp.DoomBuilder.Rendering
// This initializes the graphics
public bool Initialize()
{
AdapterInformation adapterinfo;
PresentParameters displaypp;
DeviceType devtype;
@ -193,13 +195,13 @@ namespace CodeImp.DoomBuilder.Rendering
if(devicecaps.DeviceCaps.SupportsHardwareTransformAndLight)
{
// Initialize with hardware TnL
d3dd = new Device(adapter, devtype, rendertarget,
device = new Device(adapter, devtype, rendertarget,
CreateFlags.HardwareVertexProcessing, displaypp);
}
else
{
// Initialize with software TnL
d3dd = new Device(adapter, devtype, rendertarget,
device = new Device(adapter, devtype, rendertarget,
CreateFlags.SoftwareVertexProcessing, displaypp);
}
}
@ -211,7 +213,7 @@ namespace CodeImp.DoomBuilder.Rendering
}
// Add event to cancel resize event
d3dd.DeviceResizing += new CancelEventHandler(CancelResize);
device.DeviceResizing += new CancelEventHandler(CancelResize);
// Initialize settings
SetupSettings();
@ -273,7 +275,7 @@ namespace CodeImp.DoomBuilder.Rendering
try
{
// Reset the device
d3dd.Reset(displaypp);
device.Reset(displaypp);
}
catch(Exception)
{
@ -291,5 +293,90 @@ namespace CodeImp.DoomBuilder.Rendering
}
#endregion
#region ================== Rendering
// This begins a drawing session
public bool StartRendering()
{
int coopresult;
// When minimized, do not render anything
if(General.MainWindow.WindowState != FormWindowState.Minimized)
{
// Test the cooperative level
device.CheckCooperativeLevel(out coopresult);
// Check if device must be reset
if(coopresult == (int)ResultCode.DeviceNotReset)
{
// Device is lost and must be reset now
return Reset();
}
// Check if device is lost
else if(coopresult == (int)ResultCode.DeviceLost)
{
// Device is lost and cannot be reset now
return false;
}
// Clear the screen
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, 0, 1f, 0);
// Ready to render
device.BeginScene();
return true;
}
else
{
// Minimized, you cannot see anything
return false;
}
}
// This ends a drawing session
public void FinishRendering()
{
try
{
// Done
device.EndScene();
// Display the scene
device.Present();
}
// Errors are not a problem here
catch(Exception) { }
}
#endregion
#region ================== Tools
// Make a color from ARGB
public static int ARGB(float a, float r, float g, float b)
{
return Color.FromArgb((int)(a * 255f), (int)(r * 255f), (int)(g * 255f), (int)(b * 255f)).ToArgb();
}
// Make a color from RGB
public static int RGB(int r, int g, int b)
{
return Color.FromArgb(255, r, g, b).ToArgb();
}
// This makes a Vector3 from Vector3D
public static Vector3 V3(Vector3D v3d)
{
return new Vector3(v3d.x, v3d.y, v3d.z);
}
// This makes a Vector3D from Vector3
public static Vector3D V3D(Vector3 v3)
{
return new Vector3D(v3.X, v3.Y, v3.Z);
}
#endregion
}
}

View file

@ -36,13 +36,14 @@ namespace CodeImp.DoomBuilder.Rendering
public struct PTVertex
{
// Vertex format
public static readonly VertexFormats Format = VertexFormats.Position | VertexFormats.Texture1;
public static readonly int Stride = 5 * 4;
public static readonly VertexFormats Format = VertexFormats.Position | VertexFormats.Diffuse | VertexFormats.Texture1;
public static readonly int Stride = 6 * 4;
// Members
public float x;
public float y;
public float z;
public int c;
public float u;
public float v;
}

View file

@ -44,10 +44,12 @@ namespace CodeImp.DoomBuilder.Rendering
// Owner
private Graphics graphics;
// Main objects
private Line line;
// View settings (world coordinates)
private float scale;
private float offsetx;
private float offsety;
// Disposing
private bool isdisposed = false;
@ -55,7 +57,9 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Properties
// Disposing
public float OffsetX { get { return offsetx; } }
public float OffsetY { get { return offsety; } }
public float Scale { get { return scale; } }
public bool IsDisposed { get { return isdisposed; } }
#endregion
@ -68,11 +72,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Initialize
this.graphics = graphics;
// Create line object
line = new Line(graphics.Device);
line.Width = 2f;
line.Antialias = true;
// We have no destructor
GC.SuppressFinalize(this);
}
@ -84,7 +83,6 @@ namespace CodeImp.DoomBuilder.Rendering
if(!isdisposed)
{
// Clean up
line.Dispose();
// Done
isdisposed = true;
@ -94,42 +92,43 @@ namespace CodeImp.DoomBuilder.Rendering
#endregion
#region ================== Methods
// This rebuilds matrices according to view settings
private void SetupMatrices()
{
Matrix proj;
float width, height, left, top, right, bottom;
// Build projection matrix
width = (float)graphics.RenderTarget.ClientSize.Width / scale;
height = (float)graphics.RenderTarget.ClientSize.Height / scale;
left = offsetx - width * 0.5f;
top = offsety - height * 0.5f;
right = offsetx + width * 0.5f;
bottom = offsety + height * 0.5f;
proj = Matrix.OrthoOffCenterLH(left, right, top, bottom, -1f, 1f);
// Apply matrices
graphics.Device.Transform.Projection = proj;
graphics.Device.Transform.View = Matrix.Identity;
graphics.Device.Transform.World = Matrix.Identity;
}
// This begins a drawing session
public bool StartRendering()
{
int coopresult;
// When minimized, do not render anything
if(General.MainWindow.WindowState != FormWindowState.Minimized)
// Can we render?
if(graphics.StartRendering())
{
// Test the cooperative level
graphics.Device.CheckCooperativeLevel(out coopresult);
// Setup matrices
SetupMatrices();
// Check if device must be reset
if(coopresult == (int)ResultCode.DeviceNotReset)
{
// TODO: Device is lost and must be reset now
//return Reset();
return false;
}
// Check if device is lost
else if(coopresult == (int)ResultCode.DeviceLost)
{
// Device is lost and cannot be reset now
return false;
}
// Clear the screen
graphics.Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, 0, 1f, 0);
// Ready to render
graphics.Device.BeginScene();
// Success
return true;
}
else
{
// Minimized, you cannot see anything
// Cannot render
return false;
}
}
@ -137,39 +136,50 @@ namespace CodeImp.DoomBuilder.Rendering
// This ends a drawing session
public void FinishRendering()
{
try
{
// Done
graphics.Device.EndScene();
// Display the scene
graphics.Device.Present();
}
// Errors are not a problem here
catch(Exception) { }
// Finish and present our drawing
graphics.FinishRendering();
}
// This renders a set of Linedefs
public void RenderLinedefs(IEnumerable<Linedef> linedefs)
// This changes view position
public void PositionView(float x, float y)
{
Vector2[] vertices = new Vector2[2];
// Change position in world coordinates
offsetx = x;
offsety = y;
}
// This changes zoom
public void ScaleView(float scale)
{
// Change zoom scale
this.scale = scale;
}
line.Begin();
// This renders a set of Linedefs
public void RenderLinedefs(ICollection<Linedef> linedefs)
{
PTVertex[] verts = new PTVertex[linedefs.Count * 4];
int i = 0;
graphics.Device.RenderState.TextureFactor = -1;
// Go for all linedefs
foreach(Linedef l in linedefs)
{
// Make vertices
vertices[0].X = l.Start.Position.x;
vertices[0].Y = l.Start.Position.y;
vertices[1].X = l.End.Position.x;
vertices[1].Y = l.End.Position.y;
// Draw line
line.Draw(vertices, -1);
verts[i++] = l.LineVertices[0];
verts[i++] = l.LineVertices[1];
verts[i++] = l.LineVertices[2];
verts[i++] = l.LineVertices[3];
}
// Draw lines
graphics.Device.DrawUserPrimitives(PrimitiveType.LineList, linedefs.Count * 2, verts);
}
line.End();
// This renders a set of Linedefs
public void RenderVertices(MapSet map, ICollection<Vertex> vertices)
{
}
#endregion