Thing Info panel: thing action is no longer shown in Doom map format.

Sector and Thing Info panels: fixed possible crash when trying to show unknown thing/sector flag.
Hints were not shown properly when multiselection was started while highlighting a map element.
Copy/Paste actions work much faster now.
Classic modes: rendered grid size in now adjusted to current zoom level.
This commit is contained in:
MaxED 2013-12-17 08:19:40 +00:00
parent 1bd58bab4b
commit 9df67e8b22
15 changed files with 754 additions and 151 deletions

View file

@ -789,7 +789,9 @@
<Compile Include="GZBuilder\Windows\TagStatisticsForm.Designer.cs">
<DependentUpon>TagStatisticsForm.cs</DependentUpon>
</Compile>
<Compile Include="IO\ClipboardStreamReader.cs" />
<Compile Include="IO\DoomColormapReader.cs" />
<Compile Include="IO\ClipboardStreamWriter.cs" />
<Compile Include="Map\GroupInfo.cs" />
<Compile Include="Map\SelectionType.cs" />
<Compile Include="Map\MapElementCollection.cs" />

View file

@ -236,7 +236,7 @@ namespace CodeImp.DoomBuilder.Controls
flags.Items.Clear();
foreach(KeyValuePair<string, bool> group in s.Flags) {
if(group.Value) {
ListViewItem item = new ListViewItem(General.Map.Config.SectorFlags[group.Key]);
ListViewItem item = new ListViewItem(General.Map.Config.SectorFlags.ContainsKey(group.Key) ? General.Map.Config.SectorFlags[group.Key] : group.Key);
item.Checked = true;
flags.Items.Add(item);
}

View file

@ -31,8 +31,8 @@ namespace CodeImp.DoomBuilder.Controls
System.Windows.Forms.Label label5;
System.Windows.Forms.Label label4;
System.Windows.Forms.Label label3;
System.Windows.Forms.Label label2;
System.Windows.Forms.Label label1;
this.labelaction = new System.Windows.Forms.Label();
this.infopanel = new System.Windows.Forms.GroupBox();
this.arg5 = new System.Windows.Forms.Label();
this.arglbl5 = new System.Windows.Forms.Label();
@ -57,7 +57,6 @@ namespace CodeImp.DoomBuilder.Controls
label5 = new System.Windows.Forms.Label();
label4 = new System.Windows.Forms.Label();
label3 = new System.Windows.Forms.Label();
label2 = new System.Windows.Forms.Label();
label1 = new System.Windows.Forms.Label();
this.infopanel.SuspendLayout();
this.spritepanel.SuspendLayout();
@ -91,14 +90,14 @@ namespace CodeImp.DoomBuilder.Controls
label3.TabIndex = 3;
label3.Text = "Position:";
//
// label2
// labelaction
//
label2.AutoSize = true;
label2.Location = new System.Drawing.Point(17, 39);
label2.Name = "label2";
label2.Size = new System.Drawing.Size(41, 14);
label2.TabIndex = 2;
label2.Text = "Action:";
this.labelaction.AutoSize = true;
this.labelaction.Location = new System.Drawing.Point(17, 39);
this.labelaction.Name = "labelaction";
this.labelaction.Size = new System.Drawing.Size(41, 14);
this.labelaction.TabIndex = 2;
this.labelaction.Text = "Action:";
//
// label1
//
@ -128,7 +127,7 @@ namespace CodeImp.DoomBuilder.Controls
this.infopanel.Controls.Add(this.action);
this.infopanel.Controls.Add(label4);
this.infopanel.Controls.Add(label3);
this.infopanel.Controls.Add(label2);
this.infopanel.Controls.Add(this.labelaction);
this.infopanel.Controls.Add(this.type);
this.infopanel.Controls.Add(label1);
this.infopanel.Location = new System.Drawing.Point(0, 0);
@ -381,6 +380,7 @@ namespace CodeImp.DoomBuilder.Controls
private System.Windows.Forms.GroupBox infopanel;
private System.Windows.Forms.GroupBox flagsPanel;
private System.Windows.Forms.ListView flags;
private System.Windows.Forms.Label labelaction;
}
}

View file

@ -56,34 +56,23 @@ namespace CodeImp.DoomBuilder.Controls
float zvalue;
// Show/hide stuff depending on format
if(!General.Map.FormatInterface.HasActionArgs)
{
arglbl1.Visible = false;
arglbl2.Visible = false;
arglbl3.Visible = false;
arglbl4.Visible = false;
arglbl5.Visible = false;
arg1.Visible = false;
arg2.Visible = false;
arg3.Visible = false;
arg4.Visible = false;
arg5.Visible = false;
infopanel.Width = doomformatwidth;
}
else
{
arglbl1.Visible = true;
arglbl2.Visible = true;
arglbl3.Visible = true;
arglbl4.Visible = true;
arglbl5.Visible = true;
arg1.Visible = true;
arg2.Visible = true;
arg3.Visible = true;
arg4.Visible = true;
arg5.Visible = true;
infopanel.Width = hexenformatwidth;
}
bool hasArgs = General.Map.FormatInterface.HasActionArgs;
arglbl1.Visible = hasArgs;
arglbl2.Visible = hasArgs;
arglbl3.Visible = hasArgs;
arglbl4.Visible = hasArgs;
arglbl5.Visible = hasArgs;
arg1.Visible = hasArgs;
arg2.Visible = hasArgs;
arg3.Visible = hasArgs;
arg4.Visible = hasArgs;
arg5.Visible = hasArgs;
infopanel.Width = (hasArgs ? hexenformatwidth : doomformatwidth);
//mxd
bool hasAction = General.Map.FormatInterface.HasThingAction;
action.Visible = hasAction;
labelaction.Visible = hasAction;
// Move panel
spritepanel.Left = infopanel.Left + infopanel.Width + infopanel.Margin.Right + spritepanel.Margin.Left;
@ -206,7 +195,7 @@ namespace CodeImp.DoomBuilder.Controls
flags.Items.Clear();
foreach(KeyValuePair<string, bool> group in t.Flags){
if(group.Value) {
ListViewItem item = new ListViewItem(General.Map.Config.ThingFlags[group.Key]);
ListViewItem item = new ListViewItem(General.Map.Config.ThingFlags.ContainsKey(group.Key) ? General.Map.Config.ThingFlags[group.Key] : group.Key);
item.Checked = true;
flags.Items.Add(item);
}

View file

@ -135,12 +135,9 @@
<metadata name="label3.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label2.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<metadata name="labelaction.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View file

@ -35,7 +35,7 @@ namespace CodeImp.DoomBuilder.Editing
{
#region ================== Constants
private const string CLIPBOARD_DATA_FORMAT = "DOOM_BUILDER_GEOMETRY";
private const string CLIPBOARD_DATA_FORMAT = "GZDOOM_BUILDER_GEOMETRY";
#endregion
@ -228,9 +228,8 @@ namespace CodeImp.DoomBuilder.Editing
// Write data to stream
MemoryStream memstream = new MemoryStream();
UniversalStreamWriter writer = new UniversalStreamWriter();
writer.RememberCustomTypes = false;
writer.Write(copyset, memstream, null);
ClipboardStreamWriter writer = new ClipboardStreamWriter(); //mxd
writer.Write(copyset, memstream);
// Set on clipboard
Clipboard.SetData(CLIPBOARD_DATA_FORMAT, memstream);
@ -283,8 +282,7 @@ namespace CodeImp.DoomBuilder.Editing
General.Map.Map.ClearAllMarks(true);
// Read data stream
UniversalStreamReader reader = new UniversalStreamReader(General.Map.FormatInterface.UIFields); //mxd
reader.StrictChecking = false;
ClipboardStreamReader reader = new ClipboardStreamReader(); //mxd
General.Map.Map.BeginAddRemove();
reader.Read(General.Map.Map, memstream);
General.Map.Map.EndAddRemove();

View file

@ -0,0 +1,354 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Types;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal class ClipboardStreamReader
{
#region ================== Variables
private struct SidedefData
{
public int OffsetX;
public int OffsetY;
public int SectorID;
public string HighTexture;
public string MiddleTexture;
public string LowTexture;
public Dictionary<string, UniValue> Fields;
public Dictionary<string, bool> Flags;
}
#endregion
#region ================== Reading
// This reads from a stream
public MapSet Read(MapSet map, Stream stream) {
BinaryReader reader = new BinaryReader(stream);
// Read the map
Dictionary<int, Vertex> vertexlink = ReadVertices(map, reader);
Dictionary<int, Sector> sectorlink = ReadSectors(map, reader);
Dictionary<int, SidedefData> sidedeflink = ReadSidedefs(reader);
ReadLinedefs(map, reader, vertexlink, sectorlink, sidedeflink);
ReadThings(map, reader);
return map;
}
private Dictionary<int, Vertex> ReadVertices(MapSet map, BinaryReader reader) {
int count = reader.ReadInt32();
// Create lookup table
Dictionary<int, Vertex> link = new Dictionary<int, Vertex>(count);
// Go for all collections
map.SetCapacity(map.Vertices.Count + count, 0, 0, 0, 0);
for(int i = 0; i < count; i++) {
float x = reader.ReadSingle();
float y = reader.ReadSingle();
float zc = reader.ReadSingle();
float zf = reader.ReadSingle();
// Create new item
Dictionary<string, UniValue> fields = ReadCustomFields(reader);
Vertex v = map.CreateVertex(new Vector2D(x, y));
if(v != null) {
//zoffsets
v.ZCeiling = zc;
v.ZFloor = zf;
// Add custom fields
v.Fields.BeforeFieldsChange();
foreach (KeyValuePair<string, UniValue> group in fields) {
v.Fields.Add(group.Key, group.Value);
}
// Add it to the lookup table
link.Add(i, v);
}
}
// Return lookup table
return link;
}
private Dictionary<int, Sector> ReadSectors(MapSet map, BinaryReader reader) {
int count = reader.ReadInt32();
// Create lookup table
Dictionary<int, Sector> link = new Dictionary<int, Sector>(count);
// Go for all collections
map.SetCapacity(0, 0, 0, map.Sectors.Count + count, 0);
for (int i = 0; i < count; i++) {
int tag = reader.ReadInt32();
int effect = reader.ReadInt32();
int hfloor = reader.ReadInt32();
int hceil = reader.ReadInt32();
int bright = reader.ReadInt32();
string tfloor = ReadString(reader);
string tceil = ReadString(reader);
//flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
int numFlags = reader.ReadInt32();
for(int f = 0; f < numFlags; f++)
stringflags.Add(ReadString(reader), true);
//add missing flags
foreach (KeyValuePair<string, string> flag in General.Map.Config.SectorFlags) {
if(stringflags.ContainsKey(flag.Key)) continue;
stringflags.Add(flag.Key, false);
}
// Create new item
Dictionary<string, UniValue> fields = ReadCustomFields(reader);
Sector s = map.CreateSector();
if(s != null) {
s.Update(hfloor, hceil, tfloor, tceil, effect, stringflags, tag, bright);
// Add custom fields
s.Fields.BeforeFieldsChange();
foreach(KeyValuePair<string, UniValue> group in fields) {
s.Fields.Add(group.Key, group.Value);
}
// Add it to the lookup table
link.Add(i, s);
}
}
// Return lookup table
return link;
}
// This reads the linedefs and sidedefs
private void ReadLinedefs(MapSet map, BinaryReader reader, Dictionary<int, Vertex> vertexlink, Dictionary<int, Sector> sectorlink, Dictionary<int, SidedefData> sidedeflink) {
int count = reader.ReadInt32();
// Go for all lines
map.SetCapacity(0, map.Linedefs.Count + count, map.Sidedefs.Count + sidedeflink.Count, 0, 0);
for(int i = 0; i < count; i++) {
int[] args = new int[Linedef.NUM_ARGS];
int tag = reader.ReadInt32();
int v1 = reader.ReadInt32();
int v2 = reader.ReadInt32();
int s1 = reader.ReadInt32();
int s2 = reader.ReadInt32();
int special = reader.ReadInt32();
for(int a = 0; a < Linedef.NUM_ARGS; a++) {
args[a] = reader.ReadInt32();
}
//flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
int numFlags = reader.ReadInt32();
for(int f = 0; f < numFlags; f++)
stringflags.Add(ReadString(reader), true);
//add missing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags) {
if(stringflags.ContainsKey(flag.Key)) continue;
stringflags.Add(flag.Key, false);
}
//add missing activations
foreach (LinedefActivateInfo activate in General.Map.Config.LinedefActivates) {
if(stringflags.ContainsKey(activate.Key)) continue;
stringflags.Add(activate.Key, false);
}
// Read custom fields
Dictionary<string, UniValue> fields = ReadCustomFields(reader);
// Check if not zero-length
if (Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f) {
// Create new linedef
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
if (l != null) {
l.Update(stringflags, 0, tag, special, args);
l.UpdateCache();
// Add custom fields
l.Fields.BeforeFieldsChange();
foreach(KeyValuePair<string, UniValue> group in fields) {
l.Fields.Add(group.Key, group.Value);
}
// Connect sidedefs to the line
if(s1 > -1) {
if(s1 < sidedeflink.Count)
AddSidedef(map, sidedeflink[s1], l, true, sectorlink, s1);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
}
if(s2 > -1) {
if(s2 < sidedeflink.Count)
AddSidedef(map, sidedeflink[s2], l, false, sectorlink, s2);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed.");
}
}
} else {
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed.");
}
}
}
private void AddSidedef(MapSet map, SidedefData data, Linedef ld, bool front, Dictionary<int, Sector> sectorlink, int index) {
// Create sidedef
if(sectorlink.ContainsKey(data.SectorID)) {
Sidedef s = map.CreateSidedef(ld, front, sectorlink[data.SectorID]);
if(s != null) {
s.Update(data.OffsetX, data.OffsetY, data.HighTexture, data.MiddleTexture, data.LowTexture, data.Flags);
// Add custom fields
foreach (KeyValuePair<string, UniValue> group in data.Fields) {
s.Fields.Add(group.Key, group.Value);
}
}
} else {
General.ErrorLogger.Add(ErrorType.Warning, "Sidedef references invalid sector " + data.SectorID + ". Sidedef has been removed.");
}
}
private Dictionary<int, SidedefData> ReadSidedefs(BinaryReader reader) {
Dictionary<int, SidedefData> sidedeflink = new Dictionary<int, SidedefData>();
int count = reader.ReadInt32();
for(int i = 0; i < count; i++) {
SidedefData data = new SidedefData();
data.OffsetX = reader.ReadInt32();
data.OffsetY = reader.ReadInt32();
data.SectorID = reader.ReadInt32();
data.HighTexture = ReadString(reader);
data.MiddleTexture = ReadString(reader);
data.LowTexture = ReadString(reader);
//flags
data.Flags = new Dictionary<string, bool>();
int numFlags = reader.ReadInt32();
for(int f = 0; f < numFlags; f++)
data.Flags.Add(ReadString(reader), true);
//add missing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.SidedefFlags) {
if(data.Flags.ContainsKey(flag.Key)) continue;
data.Flags.Add(flag.Key, false);
}
//custom fields
data.Fields = ReadCustomFields(reader);
sidedeflink.Add(i, data);
}
return sidedeflink;
}
private void ReadThings(MapSet map, BinaryReader reader) {
int count = reader.ReadInt32();
// Go for all collections
map.SetCapacity(0, 0, 0, 0, map.Things.Count + count);
for(int i = 0; i < count; i++) {
int[] args = new int[Linedef.NUM_ARGS];
int tag = reader.ReadInt32();
float x = reader.ReadSingle();
float y = reader.ReadSingle();
float height = reader.ReadSingle();
int angledeg = reader.ReadInt32();
int type = reader.ReadInt32();
int special = reader.ReadInt32();
for(int a = 0; a < Linedef.NUM_ARGS; a++) {
args[a] = reader.ReadInt32();
}
//flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
int numFlags = reader.ReadInt32();
for(int f = 0; f < numFlags; f++)
stringflags.Add(ReadString(reader), true);
//add missing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags) {
if(stringflags.ContainsKey(flag.Key)) continue;
stringflags.Add(flag.Key, false);
}
// Create new item
Dictionary<string, UniValue> fields = ReadCustomFields(reader);
Thing t = map.CreateThing();
if(t != null) {
t.Update(type, x, y, height, angledeg, stringflags, tag, special, args);
// Add custom fields
t.Fields.BeforeFieldsChange();
foreach(KeyValuePair<string, UniValue> group in fields) {
t.Fields.Add(group.Key, group.Value);
}
}
}
}
private Dictionary<string, UniValue> ReadCustomFields(BinaryReader reader) {
Dictionary<string, UniValue> fields = new Dictionary<string, UniValue>();
int fieldscount = reader.ReadInt32();
for(int f = 0; f < fieldscount; f++) {
string name = ReadString(reader);
UniversalType type = (UniversalType)reader.ReadInt32();
UniversalType valueType = (UniversalType)reader.ReadInt32();
switch(valueType) {
case UniversalType.Float:
fields.Add(name, new UniValue(type, reader.ReadSingle()));
break;
case UniversalType.Boolean:
fields.Add(name, new UniValue(type, reader.ReadBoolean()));
break;
case UniversalType.Integer:
fields.Add(name, new UniValue(type, reader.ReadInt32()));
break;
case UniversalType.String:
fields.Add(name, new UniValue(type, ReadString(reader)));
break;
default: //WOLOLO! ERRORS!
throw new Exception("Got unknown value type while reading custom fields from clipboard data! Field '" + name + "', type '" + type + "', primitive type '" + valueType + "'");
}
}
return fields;
}
private string ReadString(BinaryReader reader) {
int len = reader.ReadInt32();
if (len == 0) return string.Empty;
char[] chars = new char[len];
for (int i = 0; i < len; ++i) chars[i] = reader.ReadChar(); //sb.Append(reader.ReadChar());
return new string(chars);
}
#endregion
}
}

View file

@ -0,0 +1,271 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CodeImp.DoomBuilder.Map;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Types;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal class ClipboardStreamWriter
{
#region ================== Constants
private const string UDMF_CONFIG_NAME = "UDMF.cfg";
#endregion
#region ================== Variables
private Configuration config;
#endregion
#region ================== Constructor / Disposer
public ClipboardStreamWriter() {
// Make configurations
config = new Configuration();
// Find a resource named UDMF.cfg
string[] resnames = General.ThisAssembly.GetManifestResourceNames();
foreach(string rn in resnames) {
// Found it?
if(rn.EndsWith(UDMF_CONFIG_NAME, StringComparison.InvariantCultureIgnoreCase)) {
// Get a stream from the resource
Stream udmfcfg = General.ThisAssembly.GetManifestResourceStream(rn);
StreamReader udmfcfgreader = new StreamReader(udmfcfg, Encoding.ASCII);
// Load configuration from stream
config.InputConfiguration(udmfcfgreader.ReadToEnd());
// Now we add the linedef flags, activations and thing flags
// to this list, so that these don't show up in the custom
// fields list either. We use true as dummy value (it has no meaning)
// Add linedef flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
config.WriteSetting("managedfields.linedef." + flag.Key, true);
// Add linedef activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
config.WriteSetting("managedfields.linedef." + activate.Key, true);
//mxd. Add sidedef flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.SidedefFlags)
config.WriteSetting("managedfields.sidedef." + flag.Key, true);
//mxd. Add sector flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.SectorFlags)
config.WriteSetting("managedfields.sector." + flag.Key, true);
// Add thing flags
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
config.WriteSetting("managedfields.thing." + flag.Key, true);
// Done
udmfcfgreader.Dispose();
udmfcfg.Dispose();
break;
}
}
}
#endregion
#region ================== Writing
public void Write(MapSet map, Stream stream) {
Write(map.Vertices, map.Linedefs, map.Sidedefs, map.Sectors, map.Things, stream);
}
public void Write(ICollection<Vertex> vertices, ICollection<Linedef> linedefs, ICollection<Sidedef> sidedefs,
ICollection<Sector> sectors, ICollection<Thing> things, Stream stream) {
// Create collections
Dictionary<Vertex, int> vertexids = new Dictionary<Vertex, int>();
Dictionary<Sidedef, int> sidedefids = new Dictionary<Sidedef, int>();
Dictionary<Sector, int> sectorids = new Dictionary<Sector, int>();
// Index the elements in the data structures
foreach(Vertex v in vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in sectors) sectorids.Add(s, sectorids.Count);
BinaryWriter writer = new BinaryWriter(stream);
// Write the data structures to stream
WriteVertices(vertices, writer);
WriteSectors(sectors, writer);
WriteSidedefs(sidedefs, writer, sectorids);
WriteLinedefs(linedefs, writer, sidedefids, vertexids);
WriteThings(things, writer);
writer.Flush();
}
private void WriteVertices(ICollection<Vertex> vertices, BinaryWriter writer) {
writer.Write(vertices.Count);
foreach(Vertex v in vertices) {
//write "static" properties
writer.Write(v.Position.x);
writer.Write(v.Position.y);
writer.Write(v.ZCeiling);
writer.Write(v.ZFloor);
// Write custom fields
AddCustomFields(v.Fields, "vertex", writer);
}
}
// This adds linedefs
private void WriteLinedefs(ICollection<Linedef> linedefs, BinaryWriter writer, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids) {
writer.Write(linedefs.Count);
// Go for all linedefs
foreach(Linedef l in linedefs) {
//write "static" properties
writer.Write(l.Tag);
writer.Write(vertexids[l.Start]);
writer.Write(vertexids[l.End]);
//sidedefs
writer.Write((l.Front != null && sidedefids.ContainsKey(l.Front)) ? sidedefids[l.Front] : -1);
writer.Write((l.Back != null && sidedefids.ContainsKey(l.Back)) ? sidedefids[l.Back] : -1);
//action and args
writer.Write(l.Action);
for(int i = 0; i < l.Args.Length; i++) writer.Write(l.Args[i]);
AddFlags(l.Flags, writer);
AddCustomFields(l.Fields, "linedef", writer);
}
}
// This adds sidedefs
private void WriteSidedefs(ICollection<Sidedef> sidedefs, BinaryWriter writer, IDictionary<Sector, int> sectorids) {
writer.Write(sidedefs.Count);
// Go for all sidedefs
foreach(Sidedef s in sidedefs) {
//write "static" properties
writer.Write(s.OffsetX);
writer.Write(s.OffsetY);
writer.Write(sectorids[s.Sector]);
//textures
writer.Write(s.HighTexture.Length);
writer.Write(s.HighTexture.ToCharArray());
writer.Write(s.MiddleTexture.Length);
writer.Write(s.MiddleTexture.ToCharArray());
writer.Write(s.LowTexture.Length);
writer.Write(s.LowTexture.ToCharArray());
AddFlags(s.Flags, writer);
AddCustomFields(s.Fields, "sidedef", writer);
}
}
// This adds sectors
private void WriteSectors(ICollection<Sector> sectors, BinaryWriter writer) {
writer.Write(sectors.Count);
// Go for all sectors
foreach(Sector s in sectors) {
//write "static" properties
writer.Write(s.Tag);
writer.Write(s.Effect);
writer.Write(s.FloorHeight);
writer.Write(s.CeilHeight);
writer.Write(s.Brightness);
//textures
writer.Write(s.FloorTexture.Length);
writer.Write(s.FloorTexture.ToCharArray());
writer.Write(s.CeilTexture.Length);
writer.Write(s.CeilTexture.ToCharArray());
AddFlags(s.Flags, writer);
AddCustomFields(s.Fields, "sector", writer);
}
}
// This adds things
private void WriteThings(ICollection<Thing> things, BinaryWriter writer) {
writer.Write(things.Count);
// Go for all things
foreach(Thing t in things) {
//write "static" properties
writer.Write(t.Tag);
writer.Write(t.Position.x);
writer.Write(t.Position.y);
writer.Write(t.Position.z);
writer.Write(t.AngleDoom);
writer.Write(t.Type);
writer.Write(t.Action);
for(int i = 0; i < t.Args.Length; i++) writer.Write(t.Args[i]);
AddFlags(t.Flags, writer);
AddCustomFields(t.Fields, "thing", writer);
}
}
private void AddCustomFields(UniFields elementFields, string elementname, BinaryWriter writer) {
Dictionary<string, UniValue> fields = new Dictionary<string, UniValue>();
foreach(KeyValuePair<string, UniValue> f in elementFields) {
if(config.SettingExists("managedfields." + elementname + "." + f.Key)) continue;
fields.Add(f.Key, f.Value);
}
writer.Write(fields.Count);
foreach(KeyValuePair<string, UniValue> f in fields) {
writer.Write(f.Key.Length);
writer.Write(f.Key.ToCharArray());
writer.Write(f.Value.Type);
if(f.Value.Value is bool) {
writer.Write((int)UniversalType.Boolean);
writer.Write((bool)f.Value.Value);
} else if(f.Value.Value is float) {
writer.Write((int)UniversalType.Float);
writer.Write((float)f.Value.Value);
} else if(f.Value.Value.GetType().IsPrimitive) {
writer.Write((int)UniversalType.Integer);
writer.Write((int)f.Value.Value);
} else if(f.Value.Value is string) {
writer.Write((int)UniversalType.String);
string s = (string)f.Value.Value;
writer.Write(s.Length);
writer.Write(s.ToCharArray());
} else { //WOLOLO! ERRORS!
General.ErrorLogger.Add(ErrorType.Error, "Unable to copy Universal Field '" + f.Key + "' to clipboard: unknown value type '" + f.Value.Type + "'!");
}
}
}
private void AddFlags(Dictionary<string, bool> elementFlags, BinaryWriter writer) {
List<string> flags = new List<string>();
foreach(KeyValuePair<string, bool> f in elementFlags) {
if(!f.Value) continue;
flags.Add(f.Key);
}
writer.Write(flags.Count);
foreach(string s in flags) {
writer.Write(s.Length);
writer.Write(s.ToCharArray());
}
}
#endregion
}
}

View file

@ -172,6 +172,7 @@ namespace CodeImp.DoomBuilder.IO
private int cpErrorLine = 0;
private string cpErrorFile = "";
private char[] space = new[]{ ' ' }; //mxd
private char[] newline = new[] { '\n' }; //mxd
// Configuration root
private IDictionary root = null;
@ -1091,7 +1092,7 @@ namespace CodeImp.DoomBuilder.IO
{
// Count the lines in the block comment
string blockdata = data.Substring(pos, np - pos + 2);
line += (blockdata.Split("\n".ToCharArray()).Length - 1);
line += (blockdata.Split(newline).Length - 1);
// Skip everything in this block
pos = np + 2;

View file

@ -61,6 +61,7 @@ namespace CodeImp.DoomBuilder.IO
private int cpErrorResult = 0;
private string cpErrorDescription = "";
private int cpErrorLine = 0;
private char[] newline = new[]{'\n'}; //mxd
// Configuration root
private UniversalCollection root = null;
@ -296,7 +297,7 @@ namespace CodeImp.DoomBuilder.IO
{
// Count the lines in the block comment
string blockdata = data.Substring(pos, np - pos + 2);
line += (blockdata.Split("\n".ToCharArray()).Length - 1);
line += (blockdata.Split(newline).Length - 1);
// Skip everything in this block
pos = np + 1;
@ -690,19 +691,8 @@ namespace CodeImp.DoomBuilder.IO
// Check if the value is of boolean type
else if(de.Current.Value is bool)
{
// Check value
if((bool)de.Current.Value == true)
{
// Output the keyword "true"
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing);
db.Append("="); db.Append(spacing); db.Append("true;"); db.Append(newline);
}
else
{
// Output the keyword "false"
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing);
db.Append("="); db.Append(spacing); db.Append("false;"); db.Append(newline);
}
db.Append(leveltabs).Append(de.Current.Key).Append(spacing).Append("=").Append(spacing);
db.Append((bool)de.Current.Value ? "true;" : "false;").Append(newline);
}
// Check if value is of float type
else if(de.Current.Value is float)

View file

@ -231,9 +231,15 @@ namespace CodeImp.DoomBuilder.IO
UniversalCollection lc = linescolls[i];
int[] args = new int[Linedef.NUM_ARGS];
string where = "linedef " + i;
int tag = GetCollectionEntry<int>(lc, "id", false, 0, where);
int v1 = GetCollectionEntry<int>(lc, "v1", true, 0, where);
int v2 = GetCollectionEntry<int>(lc, "v2", true, 0, where);
if (!vertexlink.ContainsKey(v1) || !vertexlink.ContainsKey(v2)) { //mxd
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed.");
continue;
}
int tag = GetCollectionEntry<int>(lc, "id", false, 0, where);
int special = GetCollectionEntry<int>(lc, "special", false, 0, where);
args[0] = GetCollectionEntry<int>(lc, "arg0", false, 0, where);
args[1] = GetCollectionEntry<int>(lc, "arg1", false, 0, where);
@ -256,48 +262,41 @@ namespace CodeImp.DoomBuilder.IO
// Activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false, where);
// Create new linedef
if(vertexlink.ContainsKey(v1) && vertexlink.ContainsKey(v2))
// Check if not zero-length
if(Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f)
{
// Check if not zero-length
if(Vector2D.ManhattanDistance(vertexlink[v1].Position, vertexlink[v2].Position) > 0.0001f)
// Create new linedef
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
if(l != null)
{
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
if(l != null)
l.Update(stringflags, 0, tag, special, args);
l.UpdateCache();
// Custom fields
ReadCustomFields(lc, l, "linedef");
// Read sidedefs and connect them to the line
if(s1 > -1)
{
l.Update(stringflags, 0, tag, special, args);
l.UpdateCache();
if(s1 < sidescolls.Count)
ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
}
// Custom fields
ReadCustomFields(lc, l, "linedef");
// Read sidedefs and connect them to the line
if(s1 > -1)
{
if(s1 < sidescolls.Count)
ReadSidedef(map, sidescolls[s1], l, true, sectorlink, s1);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid front sidedef " + s1 + ". Sidedef has been removed.");
}
if(s2 > -1)
{
if(s2 < sidescolls.Count)
ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed.");
}
if(s2 > -1)
{
if(s2 < sidescolls.Count)
ReadSidedef(map, sidescolls[s2], l, false, sectorlink, s2);
else
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references invalid back sidedef " + s1 + ". Sidedef has been removed.");
}
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed.");
}
}
else
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " references one or more invalid vertices. Linedef has been removed.");
General.ErrorLogger.Add(ErrorType.Warning, "Linedef " + i + " is zero-length. Linedef has been removed.");
}
}
}
@ -505,8 +504,7 @@ namespace CodeImp.DoomBuilder.IO
if(e.Key == entryname)
{
// Let's be kind and cast any int to a float if needed
if((typeof(T) == typeof(float)) &&
(e.Value.GetType() == typeof(int)))
if((typeof(T) == typeof(float)) && (e.Value is int))
{
// Make it a float
object fvalue = (float)(int)e.Value;
@ -547,8 +545,10 @@ namespace CodeImp.DoomBuilder.IO
List<UniversalCollection> list = new List<UniversalCollection>();
// Make list
foreach(UniversalEntry e in collection)
if((e.Value is UniversalCollection) && (e.Key == entryname)) list.Add(e.Value as UniversalCollection);
foreach (UniversalEntry e in collection) {
if (!(e.Value is UniversalCollection) || (e.Key != entryname)) continue; //mxd
list.Add(e.Value as UniversalCollection);
}
return list;
}

View file

@ -290,7 +290,7 @@ namespace CodeImp.DoomBuilder.IO
if(t.Tag != 0) coll.Add("id", t.Tag);
coll.Add("x", t.Position.x);
coll.Add("y", t.Position.y);
if(t.Position.z != 0.0f) coll.Add("height", (float)t.Position.z);
if(t.Position.z != 0.0f) coll.Add("height", t.Position.z);
coll.Add("angle", t.AngleDoom);
coll.Add("type", t.Type);
if(t.Action != 0) coll.Add("special", t.Action);

View file

@ -135,6 +135,7 @@ namespace CodeImp.DoomBuilder.Map
case UniversalType.SectorEffect:
case UniversalType.SectorTag:
case UniversalType.ThingTag:
case UniversalType.ThingType:
{
int v = 0;
//mxd. Seems to work faster this way
@ -160,6 +161,7 @@ namespace CodeImp.DoomBuilder.Map
case UniversalType.String:
case UniversalType.Texture:
case UniversalType.EnumStrings:
case UniversalType.ThingClass:
{
string v = (string)value;
s.rwString(ref v);

View file

@ -872,64 +872,62 @@ namespace CodeImp.DoomBuilder.Rendering
Vector2D ltpos, rbpos;
Vector2D tlb, rbb;
Vector2D pos = new Vector2D();
float sizeinv = 1f / size;
float ystart, yend;
float xstart, xend;
float from, to;
// Only render grid when not screen-filling
if((size * scale) > 6f)
//mxd. Increase rendered grid size if needed
if(size * scale <= 6f) do { size *= 2; } while(size * scale <= 6f);
float sizeinv = 1f / size;
// Determine map coordinates for view window
ltpos = DisplayToMap(new Vector2D(0, 0));
rbpos = DisplayToMap(new Vector2D(windowsize.Width, windowsize.Height));
// Clip to nearest grid
ltpos = GridSetup.SnappedToGrid(ltpos, size, sizeinv);
rbpos = GridSetup.SnappedToGrid(rbpos, size, sizeinv);
// Translate top left boundary and right bottom boundary of map to screen coords
tlb = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary).GetTransformed(translatex, translatey, scale, -scale);
rbb = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary).GetTransformed(translatex, translatey, scale, -scale);
// Draw all horizontal grid lines
ystart = rbpos.y > General.Map.Config.BottomBoundary ? rbpos.y : General.Map.Config.BottomBoundary;
yend = ltpos.y < General.Map.Config.TopBoundary ? ltpos.y : General.Map.Config.TopBoundary;
for(float y = ystart; y < yend + size; y += size)
{
// Determine map coordinates for view window
ltpos = DisplayToMap(new Vector2D(0, 0));
rbpos = DisplayToMap(new Vector2D(windowsize.Width, windowsize.Height));
if(y > General.Map.Config.TopBoundary) y = General.Map.Config.TopBoundary;
else if(y < General.Map.Config.BottomBoundary) y = General.Map.Config.BottomBoundary;
// Clip to nearest grid
ltpos = GridSetup.SnappedToGrid(ltpos, size, sizeinv);
rbpos = GridSetup.SnappedToGrid(rbpos, size, sizeinv);
from = tlb.x < 0 ? 0 : tlb.x;
to = rbb.x > windowsize.Width ? windowsize.Width : rbb.x;
// Translate top left boundary and right bottom boundary of map
// to screen coords
tlb = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary).GetTransformed(translatex, translatey, scale, -scale);
rbb = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary).GetTransformed(translatex, translatey, scale, -scale);
pos.y = y;
pos = pos.GetTransformed(translatex, translatey, scale, -scale);
// Draw all horizontal grid lines
ystart = rbpos.y > General.Map.Config.BottomBoundary ? rbpos.y : General.Map.Config.BottomBoundary;
yend = ltpos.y < General.Map.Config.TopBoundary ? ltpos.y : General.Map.Config.TopBoundary;
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter.DrawGridLineH((int)pos.y, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c);
}
for (float y = ystart; y < yend + size; y += size)
{
if (y > General.Map.Config.TopBoundary) y = General.Map.Config.TopBoundary;
else if (y < General.Map.Config.BottomBoundary) y = General.Map.Config.BottomBoundary;
// Draw all vertical grid lines
xstart = ltpos.x > General.Map.Config.LeftBoundary ? ltpos.x : General.Map.Config.LeftBoundary;
xend = rbpos.x < General.Map.Config.RightBoundary ? rbpos.x : General.Map.Config.RightBoundary;
from = tlb.x < 0 ? 0 : tlb.x;
to = rbb.x > windowsize.Width ? windowsize.Width : rbb.x;
for(float x = xstart; x < xend + size; x += size)
{
if(x > General.Map.Config.RightBoundary) x = General.Map.Config.RightBoundary;
else if(x < General.Map.Config.LeftBoundary) x = General.Map.Config.LeftBoundary;
pos.y = y;
pos = pos.GetTransformed(translatex, translatey, scale, -scale);
from = tlb.y < 0 ? 0 : tlb.y;
to = rbb.y > windowsize.Height ? windowsize.Height : rbb.y;
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter.DrawGridLineH((int)pos.y, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c);
}
pos.x = x;
pos = pos.GetTransformed(translatex, translatey, scale, -scale);
// Draw all vertical grid lines
xstart = ltpos.x > General.Map.Config.LeftBoundary ? ltpos.x : General.Map.Config.LeftBoundary;
xend = rbpos.x < General.Map.Config.RightBoundary ? rbpos.x : General.Map.Config.RightBoundary;
for (float x = xstart; x < xend + size; x += size)
{
if (x > General.Map.Config.RightBoundary) x = General.Map.Config.RightBoundary;
else if (x < General.Map.Config.LeftBoundary) x = General.Map.Config.LeftBoundary;
from = tlb.y < 0 ? 0 : tlb.y;
to = rbb.y > windowsize.Height ? windowsize.Height : rbb.y;
pos.x = x;
pos = pos.GetTransformed(translatex, translatey, scale, -scale);
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter.DrawGridLineV((int)pos.x, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c);
}
// Note: I'm not using Math.Ceiling in this case, because that doesn't work right.
gridplotter.DrawGridLineV((int)pos.x, (int)Math.Round(from + 0.49999f), (int)Math.Round(to + 0.49999f), ref c);
}
}

View file

@ -182,6 +182,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
protected override void StartMultiSelection() {
General.Interface.HideInfo();
General.Interface.ShowEditModeHints(multiselectionHints);
base.StartMultiSelection();
}