Added support for SRB2's 3D floors and slopes, as well as SRB2's method of storing the Z positions of Things

This commit is contained in:
MascaraSnake 2015-12-31 16:46:40 +01:00
parent 4cf012d92c
commit 29f05db92d
18 changed files with 1168 additions and 711 deletions

View File

@ -30,16 +30,25 @@ namespace CodeImp.DoomBuilder.IO
{
internal class DoomMapSetIO : MapSetIO
{
#region ================== Constants
#region ================== Constants
#endregion
#endregion
#region ================== Constructor / Disposer
#region ================== Variables
protected Dictionary<int, int[]> threeDFloorTypes;
protected Dictionary<int, int[]> slopeTypes;
protected Dictionary<int, int[]> slopeCopyTypes;
#endregion
// Constructor
public DoomMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
#region ================== Constructor / Disposer
// Constructor
public DoomMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
{
}
threeDFloorTypes = new Dictionary<int, int[]>() { { 160, new int[3] { -1, -1, -1 } } };
slopeTypes = new Dictionary<int, int[]>() { { 181, new int[2] { -1, -1 } } };
slopeCopyTypes = new Dictionary<int, int[]>() { { 118, new int[2] { -1, -1 } } };
}
#endregion
@ -66,7 +75,9 @@ namespace CodeImp.DoomBuilder.IO
public override bool HasNumericLinedefFlags { get { return true; } }
public override bool HasNumericThingFlags { get { return true; } }
public override bool HasNumericLinedefActivations { get { return true; } }
public override int MaxTag { get { return ushort.MaxValue; } }
public override bool HasLinedefParameters { get { return true; } }
public override bool HasTranslucent3DFloors { get { return false; } }
public override int MaxTag { get { return ushort.MaxValue; } }
public override int MinTag { get { return ushort.MinValue; } }
public override int MaxAction { get { return ushort.MaxValue; } }
public override int MinAction { get { return ushort.MinValue; } }
@ -78,18 +89,24 @@ namespace CodeImp.DoomBuilder.IO
public override int MinBrightness { get { return short.MinValue; } }
public override int MaxThingType { get { return ushort.MaxValue; } }
public override int MinThingType { get { return ushort.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } }
public override int MaxThingHeight { get { return int.MaxValue; } }
public override int MinThingHeight { get { return int.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } }
public override float MinCoordinate { get { return short.MinValue; } }
public override int MaxThingAngle { get { return short.MaxValue; } }
public override int MinThingAngle { get { return short.MinValue; } }
public override Dictionary<MapElementType, Dictionary<string, UniversalType>> UIFields { get { return uifields; } } //mxd
#endregion
public override Dictionary<int, int[]> ThreeDFloorTypes { get { return threeDFloorTypes; } }
public override Dictionary<int, int[]> SlopeTypes { get { return slopeTypes; } }
public override Dictionary<int, int[]> SlopeCopyTypes { get { return slopeCopyTypes; } }
public override int Custom3DFloorType { get { return 160; } }
#region ================== Reading
#endregion
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
// Find the index where first map lump begins
int firstindex = wad.FindLumpIndex(mapname) + 1;
@ -113,8 +130,8 @@ namespace CodeImp.DoomBuilder.IO
return map;
}
// This reads the THINGS from WAD file
private void ReadThings(MapSet map, int firstindex)
// This reads the THINGS from WAD file
protected virtual void ReadThings(MapSet map, int firstindex)
{
// Get the lump from wad file
Lump lump = wad.FindLump("THINGS", firstindex);
@ -393,8 +410,8 @@ namespace CodeImp.DoomBuilder.IO
WriteThings(map, position, manager.Config.MapLumps);
}
// This writes the THINGS to WAD file
private void WriteThings(MapSet map, int position, Dictionary<string, MapLumpInfo> maplumps)
// This writes the THINGS to WAD file
protected virtual void WriteThings(MapSet map, int position, Dictionary<string, MapLumpInfo> maplumps)
{
// Create memory to write to
MemoryStream mem = new MemoryStream();

View File

@ -30,20 +30,31 @@ namespace CodeImp.DoomBuilder.IO
{
internal class HexenMapSetIO : MapSetIO
{
#region ================== Constants
#region ================== Constants
#endregion
#endregion
#region ================== Constructor / Disposer
#region ================== Variables
protected Dictionary<int, int[]> threeDFloorTypes;
protected Dictionary<int, int[]> slopeTypes;
protected Dictionary<int, int[]> slopeCopyTypes;
#endregion
// Constructor
public HexenMapSetIO(WAD wad, MapManager manager) : base(wad, manager) { }
#region ================== Constructor / Disposer
#endregion
// Constructor
public HexenMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
{
threeDFloorTypes = new Dictionary<int, int[]>() { { 160, new int[3] { -1, -1, -1 } } };
slopeTypes = new Dictionary<int, int[]>() { { 181, new int[2] { -1, -1 } } };
slopeCopyTypes = new Dictionary<int, int[]>() { { 118, new int[2] { -1, -1 } } };
}
#region ================== Properties
#endregion
public override int MaxSidedefs { get { return ushort.MaxValue; } }
#region ================== Properties
public override int MaxSidedefs { get { return ushort.MaxValue; } }
public override int MaxVertices { get { return ushort.MaxValue; } }
public override int MaxLinedefs { get { return ushort.MaxValue; } }
public override int MaxSectors { get { return ushort.MaxValue; } }
@ -64,7 +75,9 @@ namespace CodeImp.DoomBuilder.IO
public override bool HasNumericLinedefFlags { get { return true; } }
public override bool HasNumericThingFlags { get { return true; } }
public override bool HasNumericLinedefActivations { get { return true; } }
public override int MaxTag { get { return ushort.MaxValue; } }
public override bool HasLinedefParameters { get { return true; } }
public override bool HasTranslucent3DFloors { get { return false; } }
public override int MaxTag { get { return ushort.MaxValue; } }
public override int MinTag { get { return ushort.MinValue; } }
public override int MaxAction { get { return byte.MaxValue; } }
public override int MinAction { get { return byte.MinValue; } }
@ -76,18 +89,24 @@ namespace CodeImp.DoomBuilder.IO
public override int MinBrightness { get { return short.MinValue; } }
public override int MaxThingType { get { return ushort.MaxValue; } }
public override int MinThingType { get { return ushort.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } }
public override int MaxThingHeight { get { return int.MaxValue; } }
public override int MinThingHeight { get { return int.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } }
public override float MinCoordinate { get { return short.MinValue; } }
public override int MaxThingAngle { get { return short.MaxValue; } }
public override int MinThingAngle { get { return short.MinValue; } }
public override Dictionary<MapElementType, Dictionary<string, UniversalType>> UIFields { get { return uifields; } } //mxd
#endregion
public override Dictionary<int, int[]> ThreeDFloorTypes { get { return threeDFloorTypes; } }
public override Dictionary<int, int[]> SlopeTypes { get { return slopeTypes; } }
public override Dictionary<int, int[]> SlopeCopyTypes { get { return slopeCopyTypes; } }
public override int Custom3DFloorType { get { return 160; } }
#region ================== Reading
#endregion
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
// Find the index where first map lump begins
int firstindex = wad.FindLumpIndex(mapname) + 1;

View File

@ -47,7 +47,9 @@ namespace CodeImp.DoomBuilder.IO
bool HasNumericLinedefFlags { get; }
bool HasNumericThingFlags { get; }
bool HasNumericLinedefActivations { get; }
int MaxTag { get; }
bool HasLinedefParameters { get; }
bool HasTranslucent3DFloors { get; }
int MaxTag { get; }
int MinTag { get; }
int MaxAction { get; }
int MinAction { get; }
@ -59,12 +61,18 @@ namespace CodeImp.DoomBuilder.IO
int MinBrightness { get; }
int MaxThingType { get; }
int MinThingType { get; }
float MaxCoordinate { get; }
int MaxThingHeight { get; }
int MinThingHeight { get; }
float MaxCoordinate { get; }
float MinCoordinate { get; }
int MaxThingAngle { get; }
int MinThingAngle { get; }
Dictionary<MapElementType, Dictionary<string, UniversalType>> UIFields { get; } //mxd. Element type (like "sector"), list of uifields.
string GetElementName(MapElementType elementtype); //mxd
MapElementType GetElementType(string elementname); //mxd
}
Dictionary<int, int[]> ThreeDFloorTypes { get; }
Dictionary<int,int[]> SlopeTypes { get; }
Dictionary<int, int[]> SlopeCopyTypes { get; }
int Custom3DFloorType { get; }
}
}

View File

@ -70,7 +70,9 @@ namespace CodeImp.DoomBuilder.IO
public abstract bool HasNumericLinedefFlags { get; }
public abstract bool HasNumericThingFlags { get; }
public abstract bool HasNumericLinedefActivations { get; }
public abstract int MaxTag { get; }
public abstract bool HasLinedefParameters { get; }
public abstract bool HasTranslucent3DFloors { get; }
public abstract int MaxTag { get; }
public abstract int MinTag { get; }
public abstract int MaxAction { get; }
public abstract int MinAction { get; }
@ -82,18 +84,24 @@ namespace CodeImp.DoomBuilder.IO
public abstract int MinBrightness { get; }
public abstract int MaxThingType { get; }
public abstract int MinThingType { get; }
public abstract float MaxCoordinate { get; }
public abstract int MaxThingHeight { get; }
public abstract int MinThingHeight { get; }
public abstract float MaxCoordinate { get; }
public abstract float MinCoordinate { get; }
public abstract int MaxThingAngle { get; }
public abstract int MinThingAngle { get; }
public abstract Dictionary<MapElementType, Dictionary<string, UniversalType>> UIFields { get; } //mxd
#endregion
public abstract Dictionary<int, int[]> ThreeDFloorTypes { get; }
public abstract Dictionary<int, int[]> SlopeTypes { get; }
public abstract Dictionary<int, int[]> SlopeCopyTypes { get; }
public abstract int Custom3DFloorType { get; }
#region ================== Constructor / Disposer
#endregion
// Constructor
protected MapSetIO(WAD wad, MapManager manager)
#region ================== Constructor / Disposer
// Constructor
protected MapSetIO(WAD wad, MapManager manager)
{
// Initialize
this.wad = wad;

View File

@ -0,0 +1,220 @@

#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.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Types;
#endregion
namespace CodeImp.DoomBuilder.IO
{
internal class SRB2MapSetIO : DoomMapSetIO
{
#region ================== Constants
#endregion
#region ================== Constructor / Disposer
// Constructor
public SRB2MapSetIO(WAD wad, MapManager manager) : base(wad, manager)
{
threeDFloorTypes = new Dictionary<int, int[]>() {
{ 100, new int[4] { 1, 0, 2, 0} },
{ 101, new int[4] { 1, 1, 2, 1} },
{ 102, new int[4] { 1, 1, 1, 1} },
{ 103, new int[4] { 1, 1, 2, 1} },
{ 104, new int[4] { 1, 1, 2, 0} },
{ 105, new int[4] { 1, 1, 0, 1} },
{ 120, new int[4] { 6, 0, 2, 2} },
{ 121, new int[4] { 6, 0, 1, 2} },
{ 122, new int[4] { 6, 0, 2, 2} },
{ 123, new int[4] { 6, 0, 1, 2} },
{ 124, new int[4] { 6, 0, 1, 2} },
{ 125, new int[4] { 6, 0, 1, 2} },
{ 140, new int[4] { 1, 0, 2, 1} },
{ 141, new int[4] { 1, 0, 1, 1} },
{ 142, new int[4] { 1, 0, 1, 1} },
{ 143, new int[4] { 1, 0, 2, 1} },
{ 144, new int[4] { 1, 0, 1, 1} },
{ 145, new int[4] { 1, 0, 1, 1} },
{ 146, new int[4] { 1, 0, 2, 1} },
{ 150, new int[4] { 1, 0, 2, 0} },
{ 151, new int[4] { 1, 0, 2, 0} },
{ 152, new int[4] { 1, 0, 2, 0} },
{ 160, new int[4] { 1, 0, 2, 0} },
{ 170, new int[4] { 1, 0, 2, 0} },
{ 171, new int[4] { 1, 0, 2, 0} },
{ 172, new int[4] { 1, 0, 2, 1} },
{ 173, new int[4] { 1, 0, 2, 1} },
{ 174, new int[4] { 1, 0, 1, 1} },
{ 175, new int[4] { 1, 0, 1, 1} },
{ 176, new int[4] { 1, 0, 2, 0} },
{ 177, new int[4] { 1, 0, 2, 0} },
{ 178, new int[4] { 1, 0, 2, 0} },
{ 179, new int[4] { 1, 0, 2, 0} },
{ 180, new int[4] { 1, 0, 2, 0} },
{ 190, new int[4] { 1, 0, 2, 0} },
{ 191, new int[4] { 1, 1, 2, 1} },
{ 192, new int[4] { 1, 1, 1, 1} },
{ 193, new int[4] { 1, 1, 0, 1} },
{ 194, new int[4] { 1, 0, 2, 1} },
{ 195, new int[4] { 1, 0, 1, 1} },
{ 200, new int[4] { 3, 1, 0, 1} },
{ 201, new int[4] { 3, 0, 0, 0} },
{ 202, new int[4] { 3, 5, 2, 5} },
{ 220, new int[4] { 3, 0, 2, 0} },
{ 221, new int[4] { 3, 1, 1, 0} },
{ 222, new int[4] { 3, 1, 2, 0} },
{ 223, new int[4] { 3, 1, 0, 1} },
{ 250, new int[4] { 1, 0, 2, 0} },
{ 251, new int[4] { 1, 0, 2, 0} },
{ 252, new int[4] { 1, 0, 2, 0} },
{ 253, new int[4] { 1, 0, 1, 0} },
{ 254, new int[4] { 1, 0, 2, 0} },
{ 255, new int[4] { 1, 0, 2, 0} },
{ 256, new int[4] { 1, 0, 1, 0} },
{ 257, new int[4] { 5, 0, 2, 0} },
{ 258, new int[4] { 1, 1, 2, 0} },
{ 259, new int[4] { 1, 0, 2, 0} }
};
slopeTypes = new Dictionary<int, int[]>() {
{ 700, new int[2] { 1, 0 } },
{ 701, new int[2] { 0, 1 } },
{ 702, new int[2] { 1, 1 } },
{ 703, new int[2] { 1, 2 } },
{ 710, new int[2] { 2, 0 } },
{ 711, new int[2] { 0, 2 } },
{ 712, new int[2] { 2, 2 } },
{ 713, new int[2] { 2, 1 } }
};
slopeCopyTypes = new Dictionary<int, int[]>() {
{ 720, new int[2] { 1, 0 } },
{ 721, new int[2] { 0, 1 } },
{ 722, new int[2] { 1, 1 } },
};
}
#endregion
#region ================== Properties
public override bool HasThingHeight { get { return true; } }
public override bool HasLinedefParameters { get { return false; } }
public override bool HasTranslucent3DFloors { get { return true; } }
public override int Custom3DFloorType { get { return 259; } }
public override int MaxThingHeight { get { return 4095; } }
public override int MinThingHeight { get { return 0; } }
#endregion
#region ================== Reading
// This reads the THINGS from WAD file
protected override void ReadThings(MapSet map, int firstindex)
{
// 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
MemoryStream mem = new MemoryStream(lump.Stream.ReadAllBytes());
int num = (int)lump.Stream.Length / 10;
BinaryReader reader = new BinaryReader(mem);
// Read items from the lump
map.SetCapacity(0, 0, 0, 0, map.Things.Count + num);
for (int i = 0; i < num; i++)
{
// Read properties from stream
int x = reader.ReadInt16();
int y = reader.ReadInt16();
int angle = reader.ReadInt16();
int type = reader.ReadUInt16();
int flags = reader.ReadUInt16();
// Make string flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>(StringComparer.Ordinal);
foreach (KeyValuePair<string, string> f in manager.Config.ThingFlags)
{
int fnum;
if (int.TryParse(f.Key, out fnum)) stringflags[f.Key] = ((flags & fnum) == fnum);
}
// MascaraSnake: SRB2 stores Z position in upper 12 bits of flags. Read Z position and remove it from flags.
int z = flags >> 4;
flags &= 0xF;
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, z, angle, 0, 0, 1.0f, 1.0f, stringflags, 0, 0, new int[Thing.NUM_ARGS]);
}
// Done
mem.Dispose();
}
#endregion
#region ================== Writing
// This writes the THINGS to WAD file
protected override void WriteThings(MapSet map, int position, Dictionary<string, MapLumpInfo> maplumps)
{
// Create memory to write to
MemoryStream mem = new MemoryStream();
BinaryWriter writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all things
foreach (Thing t in map.Things)
{
// Convert flags
int flags = 0;
foreach (KeyValuePair<string, bool> f in t.Flags)
{
int fnum;
if (f.Value && int.TryParse(f.Key, out fnum)) flags |= fnum;
}
// MascaraSnake: SRB2 stores Z position in upper 12 bits of flags. Add Z position to flags.
flags |= (UInt16)t.Position.z << 4;
// Write properties to stream
writer.Write((Int16)t.Position.x);
writer.Write((Int16)t.Position.y);
writer.Write((Int16)t.AngleDoom);
writer.Write((UInt16)t.Type);
writer.Write((UInt16)flags);
}
// Find insert position and remove old lump
int insertpos = MapManager.RemoveSpecificLump(wad, "THINGS", position, MapManager.TEMP_MAP_HEADER, maplumps);
if (insertpos == -1) insertpos = position + 1;
if (insertpos > wad.Lumps.Count) insertpos = wad.Lumps.Count;
// Create the lump from memory
Lump lump = wad.Insert("THINGS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
#endregion
}
}

View File

@ -34,18 +34,27 @@ namespace CodeImp.DoomBuilder.IO
// Name of the UDMF configuration file
private const string UDMF_UI_CONFIG_NAME = "UDMF_UI.cfg";
#endregion
#region ================== Constructor / Disposer
// Constructor
public UniversalMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
#endregion
#region ================== Variables
protected Dictionary<int, int[]> threeDFloorTypes;
protected Dictionary<int, int[]> slopeTypes;
protected Dictionary<int, int[]> slopeCopyTypes;
#endregion
#region ================== Constructor / Disposer
// Constructor
public UniversalMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
{
if((manager != null) && (manager.Config != null))
{
// Make configuration
Configuration config = new Configuration();
threeDFloorTypes = new Dictionary<int, int[]>() { { 160, new int[3] { -1, -1, -1 } } };
slopeTypes = new Dictionary<int, int[]>() { { 181, new int[2] { -1, -1 } } };
slopeCopyTypes = new Dictionary<int, int[]>() { { 118, new int[2] { -1, -1 } } };
// Make configuration
Configuration config = new Configuration();
//mxd. Find a resource named UDMF_UI.cfg
string[] resnames = General.ThisAssembly.GetManifestResourceNames();
@ -116,7 +125,9 @@ namespace CodeImp.DoomBuilder.IO
public override bool HasNumericLinedefFlags { get { return false; } }
public override bool HasNumericThingFlags { get { return false; } }
public override bool HasNumericLinedefActivations { get { return false; } }
public override int MaxTag { get { return int.MaxValue; } }
public override bool HasLinedefParameters { get { return true; } }
public override bool HasTranslucent3DFloors { get { return false; } }
public override int MaxTag { get { return int.MaxValue; } }
public override int MinTag { get { return int.MinValue; } }
public override int MaxAction { get { return int.MaxValue; } }
public override int MinAction { get { return int.MinValue; } }
@ -128,18 +139,24 @@ namespace CodeImp.DoomBuilder.IO
public override int MinBrightness { get { return int.MinValue; } }
public override int MaxThingType { get { return int.MaxValue; } }
public override int MinThingType { get { return int.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } } //mxd. UDMF maps are still bounded to -32768 .. 32767 range
public override int MaxThingHeight { get { return int.MaxValue; } }
public override int MinThingHeight { get { return int.MinValue; } }
public override float MaxCoordinate { get { return short.MaxValue; } } //mxd. UDMF maps are still bounded to -32768 .. 32767 range
public override float MinCoordinate { get { return short.MinValue; } } //mxd
public override int MaxThingAngle { get { return int.MaxValue; } }
public override int MinThingAngle { get { return int.MinValue; } }
public override Dictionary<MapElementType, Dictionary<string, UniversalType>> UIFields { get { return uifields; } } //mxd
#endregion
public override Dictionary<int, int[]> ThreeDFloorTypes { get { return threeDFloorTypes; } }
public override Dictionary<int, int[]> SlopeTypes { get { return slopeTypes; } }
public override Dictionary<int, int[]> SlopeCopyTypes { get { return slopeCopyTypes; } }
public override int Custom3DFloorType { get { return 160; } }
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
#endregion
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
UniversalStreamReader udmfreader = new UniversalStreamReader(uifields); //mxd

View File

@ -22,6 +22,7 @@ using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing;
using System.Text.RegularExpressions;
using CodeImp.DoomBuilder.IO;
#endregion
@ -90,8 +91,10 @@ namespace CodeImp.DoomBuilder.Map
internal Dictionary<string, bool> Flags { get { return flags; } }
public int Action { get { return action; } set { BeforePropsChange(); action = value; UpdateColorPreset(); } }
public int Activate { get { return activate; } set { BeforePropsChange(); activate = value; UpdateColorPreset(); } }
public int Tag { get { return tags[0]; } set { BeforePropsChange(); tags[0] = value; if((value < General.Map.FormatInterface.MinTag) || (value > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } } //mxd
public bool Is3DFloor { get { return General.Map.FormatInterface.ThreeDFloorTypes.ContainsKey(Action); } }
public bool IsSlope { get { return General.Map.FormatInterface.SlopeTypes.ContainsKey(Action); } }
public bool IsSlopeCopy { get { return General.Map.FormatInterface.SlopeCopyTypes.ContainsKey(Action); } }
public int Tag { get { return tags[0]; } set { BeforePropsChange(); tags[0] = value; if((value < General.Map.FormatInterface.MinTag) || (value > General.Map.FormatInterface.MaxTag)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } } //mxd
public List<int> Tags { get { return tags; } set { BeforePropsChange(); tags = value; } } //mxd
public float LengthSq { get { return lengthsq; } }
public float Length { get { return length; } }
@ -751,13 +754,98 @@ namespace CodeImp.DoomBuilder.Map
if(selecteditem.List != null) selecteditem.List.Remove(selecteditem);
selecteditem = null;
}
#endregion
#region ================== Methods
// This checks and returns a flag without creating it
public bool IsFlagSet(string flagname)
#endregion
#region ================== Methods
public void Set3DFloorArgs()
{
Args[0] = Tag;
Args[1] = 1;
Args[2] = 0;
Args[3] = 0;
Args[4] = 0;
if (Action == General.Map.FormatInterface.Custom3DFloorType && Back != null)
{
string tex = Back.HighTexture;
Regex r = new Regex("^[A-F0-9]*$");
if (r.IsMatch(tex))
{
int value = Convert.ToInt32(tex, 16);
bool exists = (value & 0x1) == 0x1;
bool solid = ((value & 0x2) == 0x2) || ((value & 0x4) == 0x4);
bool render = ((value & 0x8) == 0x8) || ((value & 0x10) == 0x10);
bool water = (value & 0x20) == 0x20;
bool noshade = (value & 0x40) == 0x40;
bool translucent = (value & 0x1000) == 0x1000;
bool fog = (value & 0x2000) == 0x2000;
bool inside = ((value & 0x8000) == 0x8000) || ((value & 0x10000) == 0x10000);
if (exists)
{
Args[1] = water ? 2 : (solid ? 1 : 3);
if (inside) Args[1] += 4;
}
Args[2] = noshade ? 1 : 0;
if (inside) Args[2] += 2;
if (fog) Args[2] += 4;
Args[3] = render ? (translucent ? ParseTranslucency(Front.HighTexture) : 255) : 0;
}
}
else
{
int[] settings = General.Map.FormatInterface.ThreeDFloorTypes[Action];
Args[1] = settings[0];
Args[2] = Flags.ContainsKey("64") && Flags["64"] ? settings[3] : settings[1];
switch (settings[2])
{
case 0:
Args[3] = 0;
break;
case 1:
Args[3] = ParseTranslucency(Front.HighTexture);
break;
case 2:
Args[3] = 255;
break;
default:
Args[3] = 0;
break;
}
}
}
private int ParseTranslucency(string tex)
{
int result = 128;
if (tex.StartsWith("#") && tex.Length == 4)
{
int alpha;
if (int.TryParse(tex.Substring(1), out alpha) && alpha >= 0 && alpha <= 255) result = alpha;
}
return result;
}
public void SetSlopeArgs()
{
int[] settings = General.Map.FormatInterface.SlopeTypes[Action];
Args[0] = settings[0];
Args[1] = settings[1];
Args[2] = 0;
}
public void SetSlopeCopyArgs()
{
int[] settings = General.Map.FormatInterface.SlopeCopyTypes[Action];
if (settings[0] == 1) Args[0] = Tag;
if (settings[0] == 2) Args[2] = Tag;
if (settings[1] == 1) Args[1] = Tag;
if (settings[1] == 2) Args[3] = Tag;
Args[4] = 0;
}
// This checks and returns a flag without creating it
public bool IsFlagSet(string flagname)
{
return flags.ContainsKey(flagname) && flags[flagname];
}

View File

@ -670,7 +670,8 @@ namespace CodeImp.DoomBuilder.Map
foreach(Sidedef side in s.sidedefs)
{
// Carbon copy of EffectLineSlope class here...
if(side.Line.Action == 181 && ((side.Line.Args[0] == 1 && side == side.Line.Front) || side.Line.Args[0] == 2) && side.Other != null)
// MascaraSnake: Handle slopes
if(side.Line.IsSlope && ((side.Line.Args[0] == 1 && side == side.Line.Front) || side.Line.Args[0] == 2) && side.Other != null)
{
Linedef l = side.Line;
@ -750,7 +751,8 @@ namespace CodeImp.DoomBuilder.Map
foreach(Sidedef side in s.sidedefs)
{
// Carbon copy of EffectLineSlope class here...
if(side.Line.Action == 181 && ((side.Line.Args[1] == 1 && side == side.Line.Front) || side.Line.Args[1] == 2) && side.Other != null)
// MascaraSnake: Handle slopes
if(side.Line.IsSlope && ((side.Line.Args[1] == 1 && side == side.Line.Front) || side.Line.Args[1] == 2) && side.Other != null)
{
Linedef l = side.Line;

View File

@ -616,9 +616,11 @@ namespace CodeImp.DoomBuilder.Rendering
//find lines with 3d floor action and collect sector tags
foreach(Linedef l in General.Map.Map.Linedefs)
{
if(l.Action == 160)
{
int sectortag = (General.Map.UDMF || (l.Args[1] & 8) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
//MascaraSnake: 3D floor handling
if(l.Is3DFloor)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.Set3DFloorArgs();
int sectortag = (General.Map.UDMF || (l.Args[1] & 8) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
if(sectortag != 0 && !tags.Contains(sectortag)) tags.Add(sectortag);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -138,12 +138,32 @@ namespace CodeImp.DoomBuilder.Windows
thingtype.Setup();
}
#endregion
#endregion
#region ================== Methods
#region ================== Methods
// This sets up the form to edit the given things
public void Setup(ICollection<Thing> things)
private string evaluateFlagsValue()
{
int i = 1;
int value = 0;
foreach (CheckBox box in flags.Checkboxes)
{
if (box.CheckState == CheckState.Indeterminate) return "";
if (box.CheckState == CheckState.Checked) value += i;
i *= 2;
}
float z = General.GetByIndex(things, 0).Position.z;
foreach (Thing t in things)
{
if (t.Position.z != z) return "";
}
return (value + ((int)z << 4)).ToString();
}
// This sets up the form to edit the given things
public void Setup(ICollection<Thing> things)
{
preventchanges = true;
@ -256,8 +276,9 @@ namespace CodeImp.DoomBuilder.Windows
angle_WhenTextChanged(angle, EventArgs.Empty);
flags_OnValueChanged(flags, EventArgs.Empty);
preventmapchange = false;
flagsvalue.Text = evaluateFlagsValue();
argscontrol.UpdateScriptControls(); //mxd
argscontrol.UpdateScriptControls(); //mxd
actionhelp.UpdateAction(action.GetValue()); //mxd
}
@ -526,11 +547,12 @@ namespace CodeImp.DoomBuilder.Windows
float z = posZ.GetResultFloat(thingprops[i++].Z);
if(useabsoluteheight && !posZ.CheckIsRelative() && t.Sector != null)
z -= (float)Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position.x, t.Position.y), General.Map.FormatInterface.VertexDecimals);
t.Move(new Vector3D(t.Position.x, t.Position.y, z));
t.Move(new Vector3D(t.Position.x, t.Position.y, General.Clamp(z, General.Map.FormatInterface.MinThingHeight, General.Map.FormatInterface.MaxThingHeight)));
}
}
General.Map.IsChanged = true;
flagsvalue.Text = evaluateFlagsValue();
General.Map.IsChanged = true;
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
}
@ -613,7 +635,8 @@ namespace CodeImp.DoomBuilder.Windows
//everything is OK
missingflags.Visible = false;
settingsgroup.ForeColor = SystemColors.ControlText;
}
flagsvalue.Text = evaluateFlagsValue();
}
#endregion

View File

@ -59,7 +59,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// set to be sky
if(sd.HighRequired() && sd.HighTexture == "-")
{
if(sd.Line.Action == 181 && sd.Line.Args[1] > 0) continue; //mxd. Ceiling slopes doesn't require upper texture
// MascaraSnake: Slope handling
if(sd.Line.IsSlope && sd.Line.Args[1] > 0) continue; //mxd. Ceiling slopes doesn't require upper texture
if(sd.Other != null && sd.Other.Sector.CeilTexture != General.Map.Config.SkyFlatName)
{
SubmitResult(new ResultMissingTexture(sd, SidedefPart.Upper));
@ -77,7 +78,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// set to be sky
if(sd.LowRequired() && sd.LowTexture == "-")
{
if(sd.Line.Action == 181 && sd.Line.Args[0] > 0) continue; //mxd. Floor slopes doesn't require lower texture
// MascaraSnake: Slope handling
if (sd.Line.IsSlope && sd.Line.Args[0] > 0) continue; //mxd. Floor slopes doesn't require lower texture
if(sd.Other != null && sd.Other.Sector.FloorTexture != General.Map.Config.SkyFlatName)
{
SubmitResult(new ResultMissingTexture(sd, SidedefPart.Lower));

View File

@ -228,9 +228,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. 3D floors may need updating...
foreach(Sidedef s in level.sector.Sidedefs)
{
if(s.Line.Action == 160 && s.Line.Front != null)
// MascaraSnake: 3D floor handling
if(s.Line.Is3DFloor && s.Line.Front != null)
{
int sectortag = ((General.Map.UDMF || (s.Line.Args[1] & 8) != 0) ? s.Line.Args[0] : s.Line.Args[0] + (s.Line.Args[4] << 8));
if (!General.Map.FormatInterface.HasLinedefParameters) s.Line.Set3DFloorArgs();
int sectortag = ((General.Map.UDMF || (s.Line.Args[1] & 8) != 0) ? s.Line.Args[0] : s.Line.Args[0] + (s.Line.Args[4] << 8));
foreach(Sector sector in General.Map.Map.Sectors)
{
if(sector.Tags.Contains(sectortag))

View File

@ -509,9 +509,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
private void OnTextureChanged()
{
//check for 3d floors
if(Sidedef.Line.Action == 160)
// MascaraSnake: 3D floor handling
if(Sidedef.Line.Is3DFloor)
{
int sectortag = ((General.Map.UDMF || (Sidedef.Line.Args[1] & 8) != 0) ? Sidedef.Line.Args[0] : Sidedef.Line.Args[0] + (Sidedef.Line.Args[4] << 8));
if (!General.Map.FormatInterface.HasLinedefParameters) Sidedef.Line.Set3DFloorArgs();
int sectortag = ((General.Map.UDMF || (Sidedef.Line.Args[1] & 8) != 0) ? Sidedef.Line.Args[0] : Sidedef.Line.Args[0] + (Sidedef.Line.Args[4] << 8));
if(sectortag == 0) return;
foreach(Sector sector in General.Map.Map.Sectors)

View File

@ -855,8 +855,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
switch(t.Type)
{
case 1504: slopefloorthings.Add(t); break;
case 1505: slopeceilingthings.Add(t); break;
//case 1504: slopefloorthings.Add(t); break;
//case 1505: slopeceilingthings.Add(t); break;
}
}
}
@ -884,123 +884,133 @@ namespace CodeImp.DoomBuilder.BuilderModes
sd.AddEffectGlowingFlat(s);
}
}
// Find interesting linedefs (such as line slopes)
foreach(Linedef l in General.Map.Map.Linedefs)
{
switch(l.Action)
{
// ========== Plane Align (see http://zdoom.org/wiki/Plane_Align) ==========
case 181:
if(((l.Args[0] == 1) || (l.Args[1] == 1)) && (l.Front != null))
{
SectorData sd = GetSectorData(l.Front.Sector);
sd.AddEffectLineSlope(l);
}
if(((l.Args[0] == 2) || (l.Args[1] == 2)) && (l.Back != null))
{
SectorData sd = GetSectorData(l.Back.Sector);
sd.AddEffectLineSlope(l);
}
break;
// ========== Plane Copy (mxd) (see http://zdoom.org/wiki/Plane_Copy) ==========
case 118:
{
//check the flags...
bool floorCopyToBack = false;
bool floorCopyToFront = false;
bool ceilingCopyToBack = false;
bool ceilingCopyToFront = false;
// Find interesting linedefs (such as line slopes)
foreach (Linedef l in General.Map.Map.Linedefs)
{
// MascaraSnake: Slope handling
// ========== Plane Align (see http://zdoom.org/wiki/Plane_Align) ==========
if (l.IsSlope)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.SetSlopeArgs();
if (((l.Args[0] == 1) || (l.Args[1] == 1)) && (l.Front != null))
{
SectorData sd = GetSectorData(l.Front.Sector);
sd.AddEffectLineSlope(l);
}
if (((l.Args[0] == 2) || (l.Args[1] == 2)) && (l.Back != null))
{
SectorData sd = GetSectorData(l.Back.Sector);
sd.AddEffectLineSlope(l);
}
}
if(l.Args[4] > 0 && l.Args[4] != 3 && l.Args[4] != 12)
{
floorCopyToBack = (l.Args[4] & 1) == 1;
floorCopyToFront = (l.Args[4] & 2) == 2;
ceilingCopyToBack = (l.Args[4] & 4) == 4;
ceilingCopyToFront = (l.Args[4] & 8) == 8;
}
// Copy slope to front sector
if(l.Front != null)
{
if( (l.Args[0] > 0 || l.Args[1] > 0) || (l.Back != null && (floorCopyToFront || ceilingCopyToFront)) )
{
SectorData sd = GetSectorData(l.Front.Sector);
sd.AddEffectPlaneClopySlope(l, true);
}
}
// MascaraSnake: Slope handling
// ========== Plane Copy (mxd) (see http://zdoom.org/wiki/Plane_Copy) ==========
if (l.IsSlopeCopy)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.SetSlopeCopyArgs();
//check the flags...
bool floorCopyToBack = false;
bool floorCopyToFront = false;
bool ceilingCopyToBack = false;
bool ceilingCopyToFront = false;
// Copy slope to back sector
if(l.Back != null)
{
if( (l.Args[2] > 0 || l.Args[3] > 0) || (l.Front != null && (floorCopyToBack || ceilingCopyToBack)) )
{
SectorData sd = GetSectorData(l.Back.Sector);
sd.AddEffectPlaneClopySlope(l, false);
}
}
}
break;
if (l.Args[4] > 0 && l.Args[4] != 3 && l.Args[4] != 12)
{
floorCopyToBack = (l.Args[4] & 1) == 1;
floorCopyToFront = (l.Args[4] & 2) == 2;
ceilingCopyToBack = (l.Args[4] & 4) == 4;
ceilingCopyToFront = (l.Args[4] & 8) == 8;
}
// ========== Sector 3D floor (see http://zdoom.org/wiki/Sector_Set3dFloor) ==========
case 160:
if(l.Front != null)
{
//mxd. Added hi-tag/line ID check
int sectortag = (General.Map.UDMF || (l.Args[1] & (int)Effect3DFloor.FloorTypes.HiTagIsLineID) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
if(sectortags.ContainsKey(sectortag))
{
List<Sector> sectors = sectortags[sectortag];
foreach(Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffect3DFloor(l);
}
}
}
break;
// Copy slope to front sector
if (l.Front != null)
{
if ((l.Args[0] > 0 || l.Args[1] > 0) || (l.Back != null && (floorCopyToFront || ceilingCopyToFront)))
{
SectorData sd = GetSectorData(l.Front.Sector);
sd.AddEffectPlaneClopySlope(l, true);
}
}
// ========== Transfer Brightness (see http://zdoom.org/wiki/ExtraFloor_LightOnly) =========
case 50:
if(l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach(Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectBrightnessLevel(l);
}
}
break;
// Copy slope to back sector
if (l.Back != null)
{
if ((l.Args[2] > 0 || l.Args[3] > 0) || (l.Front != null && (floorCopyToBack || ceilingCopyToBack)))
{
SectorData sd = GetSectorData(l.Back.Sector);
sd.AddEffectPlaneClopySlope(l, false);
}
}
}
// ========== mxd. Transfer Floor Brightness (see http://www.zdoom.org/w/index.php?title=Transfer_FloorLight) =========
case 210:
if(l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach(Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectTransferFloorBrightness(l);
}
}
break;
// MascaraSnake: 3D floor handling
// ========== Sector 3D floor (see http://zdoom.org/wiki/Sector_Set3dFloor) ==========
if (l.Is3DFloor)
{
if (l.Front != null)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.Set3DFloorArgs();
//mxd. Added hi-tag/line ID check
int sectortag = (General.Map.UDMF || (l.Args[1] & (int)Effect3DFloor.FloorTypes.HiTagIsLineID) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
if (sectortags.ContainsKey(sectortag))
{
List<Sector> sectors = sectortags[sectortag];
foreach (Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffect3DFloor(l);
}
}
}
// ========== mxd. Transfer Ceiling Brightness (see http://www.zdoom.org/w/index.php?title=Transfer_CeilingLight) =========
case 211:
if(l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach(Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectTransferCeilingBrightness(l);
}
}
break;
}
}
}
if (General.Map.FormatInterface.HasLinedefParameters)
{
switch (l.Action)
{
// ========== Transfer Brightness (see http://zdoom.org/wiki/ExtraFloor_LightOnly) =========
case 50:
if (l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectBrightnessLevel(l);
}
}
break;
// ========== mxd. Transfer Floor Brightness (see http://www.zdoom.org/w/index.php?title=Transfer_FloorLight) =========
case 210:
if (l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectTransferFloorBrightness(l);
}
}
break;
// ========== mxd. Transfer Ceiling Brightness (see http://www.zdoom.org/w/index.php?title=Transfer_CeilingLight) =========
case 211:
if (l.Front != null && sectortags.ContainsKey(l.Args[0]))
{
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
SectorData sd = GetSectorData(s);
sd.AddEffectTransferCeilingBrightness(l);
}
}
break;
}
}
}
// Find interesting things (such as sector slopes)
foreach(Thing t in General.Map.Map.Things)
@ -3589,12 +3599,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
//assign/remove action
if(vg.GeometryType == VisualGeometryType.WALL_LOWER)
{
if(vg.Sidedef.Line.Action == 0 || (vg.Sidedef.Line.Action == 181 && vg.Sidedef.Line.Args[0] == 0))
// MascaraSnake: Slope handling
if(vg.Sidedef.Line.Action == 0 || (vg.Sidedef.Line.IsSlope && vg.Sidedef.Line.Args[0] == 0))
{
//check if the sector already has floor slopes
foreach(Sidedef side in vg.Sidedef.Sector.Sidedefs)
{
if(side == vg.Sidedef || side.Line.Action != 181) continue;
// MascaraSnake: Slope handling
if(side == vg.Sidedef || !side.Line.IsSlope) continue;
int arg = (side == side.Line.Front ? 1 : 2);
@ -3616,12 +3628,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else if(vg.GeometryType == VisualGeometryType.WALL_UPPER)
{
if(vg.Sidedef.Line.Action == 0 || (vg.Sidedef.Line.Action == 181 && vg.Sidedef.Line.Args[1] == 0))
// MascaraSnake: Slope handling
if (vg.Sidedef.Line.Action == 0 || (vg.Sidedef.Line.IsSlope && vg.Sidedef.Line.Args[1] == 0))
{
//check if the sector already has ceiling slopes
foreach(Sidedef side in vg.Sidedef.Sector.Sidedefs)
{
if(side == vg.Sidedef || side.Line.Action != 181) continue;
// MascaraSnake: Slope handling
if (side == vg.Sidedef || !side.Line.IsSlope) continue;
int arg = (side == side.Line.Front ? 1 : 2);
@ -3646,7 +3660,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
//check if the sector has ceiling slopes
foreach(Sidedef side in vg.Sector.Sector.Sidedefs)
{
if(side.Line.Action != 181) continue;
// MascaraSnake: Slope handling
if (!side.Line.IsSlope) continue;
int arg = (side == side.Line.Front ? 1 : 2);
@ -3667,7 +3682,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
//check if the sector has floor slopes
foreach(Sidedef side in vg.Sector.Sector.Sidedefs)
{
if(side.Line.Action != 181) continue;
// MascaraSnake: Slope handling
if (!side.Line.IsSlope) continue;
int arg = (side == side.Line.Front ? 1 : 2);

View File

@ -164,7 +164,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
ceiling.splitsides = (!clipsides && !ignorebottomheight); // if "ignorebottomheight" flag is set, both ceiling and floor will be at the same level and sidedef clipping with floor level will fail resulting in incorrect light props transfer in some cases
//mxd. Check slopes, cause GZDoom can't handle sloped translucent 3d floors...
sloped3dfloor = ((alpha < 255 || renderadditive) &&
//MascaraSnake: SRB2 can, so only check in Doom
sloped3dfloor = (!General.Map.FormatInterface.HasTranslucent3DFloors && (alpha < 255 || renderadditive) &&
(Angle2D.RadToDeg(ceiling.plane.Normal.GetAngleZ()) != 270 ||
Angle2D.RadToDeg(floor.plane.Normal.GetAngleZ()) != 90));

View File

@ -576,7 +576,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef side in Sector.Sector.Sidedefs)
{
if(side.Line.Action == 181)
// MascaraSnake: Slope handling
if(side.Line.IsSlope)
{
if(side.Line.Args[1] == 1 && side.Line.Front != null && side.Line.Front == side)
{

View File

@ -542,7 +542,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef side in Sector.Sector.Sidedefs)
{
if(side.Line.Action == 181)
// MascaraSnake: Slope handling
if(side.Line.IsSlope)
{
if(side.Line.Args[0] == 1 && side.Line.Front != null && side.Line.Front == side)
{