UDMF on top!

This commit is contained in:
codeimp 2008-06-01 20:25:46 +00:00
parent 2b9a233579
commit e30b68c9c3
49 changed files with 1814 additions and 722 deletions

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*
@ -96,17 +101,8 @@ Used to guess the game for which a WAD file is made.
gamedetect
{
EXTENDED = 2;
BEHAVIOR = 2;
E1M1 = 2; E1M2 = 2; E1M3 = 2; E1M4 = 2; E1M5 = 2; E1M6 = 2; E1M7 = 2; E1M8 = 2; E1M9 = 2;
E2M1 = 2; E2M2 = 2; E2M3 = 2; E2M4 = 2; E2M5 = 2; E2M6 = 2; E2M7 = 2; E2M8 = 2; E2M9 = 2;
E3M1 = 2; E3M2 = 2; E3M3 = 2; E3M4 = 2; E3M5 = 2; E3M6 = 2; E3M7 = 2; E3M8 = 2; E3M9 = 2;
E4M1 = 2; E4M2 = 2; E4M3 = 2; E4M4 = 2; E4M5 = 2; E4M6 = 2; E4M7 = 2; E4M8 = 2; E4M9 = 2;
MAP01 = 1; MAP02 = 1; MAP03 = 1; MAP04 = 1; MAP05 = 1; MAP06 = 1; MAP07 = 1; MAP08 = 1; MAP09 = 1; MAP10 = 1;
MAP11 = 1; MAP12 = 1; MAP13 = 1; MAP14 = 1; MAP15 = 1; MAP16 = 1; MAP17 = 1; MAP18 = 1; MAP19 = 1; MAP20 = 1;
MAP21 = 1; MAP22 = 1; MAP23 = 1; MAP24 = 1; MAP25 = 1; MAP26 = 1; MAP27 = 1; MAP28 = 1; MAP29 = 1; MAP30 = 1;
MAP31 = 1; MAP32 = 1; MAP33 = 2; MAP34 = 2; MAP35 = 2; MAP36 = 2; MAP37 = 2; MAP38 = 2; MAP39 = 2; MAP40 = 2;
MAP41 = 2;
TEXTMAP = 3;
ENDMAP = 3;
}
@ -137,58 +133,15 @@ maplumpnames
TEXTMAP
{
required = true;
nodebuild = true;
nodebuild = false;
allowempty = true;
}
SEGS
{
required = false;
nodebuild = true;
allowempty = false;
}
SSECTORS
{
required = false;
nodebuild = true;
allowempty = false;
}
NODES
{
required = false;
nodebuild = true;
allowempty = false;
}
SECTORS
{
required = true;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = false;
}
ENDMAP
{
required = true;
nodebuild = false;
allowempty = true;
blindcopy = true;
}
}
@ -196,6 +149,7 @@ maplumpnames
/*
ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
Only add fields here that Doom Builder does not edit with its own user-interface!
The "default" field must match the UDMF specifications!
Field data types:
0 = integer *
@ -218,62 +172,6 @@ Field data types:
*/
universalfields
{
linedefs
{
texture_scale_x
{
type = 1;
default = 1.0f;
}
texture_scale_y
{
type = 1;
default = 1.0f;
}
texture_offset_x
{
type = 1;
default = 0.0f;
}
texture_offset_y
{
type = 1;
default = 0.0f;
}
brightness
{
type = 0;
default = -1;
}
colormap
{
type = 10;
default = 0;
}
normalmap
{
type = 6;
default = "";
}
second_action
{
type = 4;
default = 0;
}
hidden
{
type = 3;
default = false;
}
}
}
@ -378,22 +276,31 @@ gen_sectortypes
// LINEDEF FLAGS
linedefflags
{
1 = "Impassable";
2 = "Block Monster";
4 = "Double Sided";
8 = "Upper Unpegged";
16 = "Lower Unpegged";
32 = "Secret";
64 = "Block Sound";
128 = "Hidden";
256 = "Shown";
512 = "PassThru";
1024 = "3dMidTex";
blocking = "Impassable";
blockmonsters = "Block monster";
twosided = "Doublesided";
dontpegtop = "Upper unpegged";
dontpegbottom = "Lower unpegged";
secret = "Secret";
blocksound = "Block sound";
dontdraw = "Hidden";
mapped = "Shown";
midtex3d = "Walkable middle texture";
}
// LINEDEF ACTIVATIONS
linedefactivations
{
playercross = "When player walks over";
playeruse = "When player presses use";
monstercross = "When monster walks over";
monsteruse = "When monster presses use";
impact = "On projectile impact";
playerpush = "When player bumps";
monsterpush = "When moinsters bumps";
missilecross = "When projectile crosses";
repeatspecial = "Repeatable action";
passuse = "Pass use on";
}
// LINEDEF TYPES
@ -2487,15 +2394,21 @@ gen_linedeftypes
// THING FLAGS
thingflags
{
1 = "Easy";
2 = "Medium";
4 = "Hard";
8 = "Deaf";
16 = "Multiplayer";
32 = "Not In DM";
64 = "Not In Coop";
128 = "Friendly";
512 = "Dormant";
skill1 = "Skill 1";
skill2 = "Skill 2";
skill3 = "Skill 3";
skill4 = "Skill 4";
skill5 = "Skill 5";
ambush = "Deaf";
single = "Singleplayer";
dm = "Deathmatch";
coop = "Cooperative";
friend = "Friendly";
dormant = "Dormant";
standing = "Standing";
strifeally = "Ally";
translucent = "Translucent";
invisible = "Invisible";
}
// THING FLAGS ERROR MASK

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -37,7 +37,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*

View file

@ -12,7 +12,7 @@ game = "ZDoom (Doom in UDMF format)";
engine = "zdoom";
// The format interface handles the map data format
formatinterface = "HexenMapSetIO";
formatinterface = "UniversalMapSetIO";
// Default lump name for new map
defaultlumpname = "MAP01";
@ -37,7 +37,27 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
skill1;
skill2;
skill3;
skill4;
skill5;
skill6;
skill7;
skill8;
single;
coop;
class1;
class2;
class3;
class4;
class5;
class6;
class7;
class8;
}
/*
@ -185,8 +205,7 @@ maplumpnames
/*
ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
Only add fields here that Doom Builder does not edit with its own user-interface!
The "default" is the editor's default value. Set "specdefault" to the UDMF specification's
default when "default" differs from the UDMF specification's default!
The "default" field must match the UDMF specifications!
Field data types:
0 = integer *
@ -209,57 +228,233 @@ Field data types:
*/
universalfields
{
linedefs
linedef
{
texture_scale_x
comment
{
type = 2;
default = "";
}
alpha
{
type = 1;
default = 1.0f;
}
texture_scale_y
renderstyle
{
type = 1;
default = 1.0f;
type = 16;
default = "translucent";
enum
{
translucent = "Translucent";
add = "Additive";
}
}
}
sidedef
{
comment
{
type = 2;
default = "";
}
texture_offset_x
{
type = 1;
default = 0.0f;
}
texture_offset_y
{
type = 1;
default = 0.0f;
}
brightness
light
{
type = 0;
default = -1;
default = 0;
}
colormap
lightabsolute
{
type = 3;
default = false;
}
nofakecontrast
{
type = 3;
default = false;
}
offsetx_top
{
type = 1;
default = 0.0f;
}
offsety_top
{
type = 1;
default = 0.0f;
}
offsetx_mid
{
type = 1;
default = 0.0f;
}
offsety_mid
{
type = 1;
default = 0.0f;
}
offsetx_bottom
{
type = 1;
default = 0.0f;
}
offsety_bottom
{
type = 1;
default = 0.0f;
}
}
thing
{
comment
{
type = 2;
default = "";
}
}
sector
{
comment
{
type = 2;
default = "";
}
xpanningfloor
{
type = 1;
default = 0.0f;
}
ypanningfloor
{
type = 1;
default = 0.0f;
}
xpanningceiling
{
type = 1;
default = 0.0f;
}
ypanningceiling
{
type = 1;
default = 0.0f;
}
xscalefloor
{
type = 1;
default = 1.0f;
}
yscalefloor
{
type = 1;
default = 1.0f;
}
xscaleceiling
{
type = 1;
default = 1.0f;
}
yscaleceiling
{
type = 1;
default = 1.0f;
}
rotationfloor
{
type = 8;
default = 0.0f;
}
rotationceiling
{
type = 8;
default = 0.0f;
}
lightfloor
{
type = 1;
default = 0.0f;
}
lightceiling
{
type = 1;
default = 0.0f;
}
lightfloorabsolute
{
type = 3;
default = false;
}
lightceilingabsolute
{
type = 3;
default = false;
}
gravity
{
type = 1;
default = 1.0f;
}
lightcolor
{
type = 10;
default = 16777215;
}
fadecolor
{
type = 10;
default = 0;
}
normalmap
desaturation
{
type = 6;
default = "";
type = 1;
default = 0.0f;
}
second_action
silent
{
type = 4;
default = 0;
type = 3;
default = false;
}
hidden
nofallingdamage
{
type = 3;
default = false;
}
dropactors
{
type = 3;
default = false;
@ -515,36 +710,42 @@ gen_sectortypes
// LINEDEF FLAGS
linedefflags
{
1 = "Impassable";
2 = "Block Monster";
4 = "Double Sided";
8 = "Upper Unpegged";
16 = "Lower Unpegged";
32 = "Secret";
64 = "Block Sound";
128 = "Hidden";
256 = "Shown";
512 = "Repeatable Action";
8192 = "Monster Activates";
32768 = "Block Everything";
blocking = "Impassable";
blockmonsters = "Block monster";
twosided = "Doublesided";
dontpegtop = "Upper unpegged";
dontpegbottom = "Lower unpegged";
secret = "Secret";
blocksound = "Block sound";
dontdraw = "Hidden";
mapped = "Shown";
monsteractivate = "Monster activates";
blockeverything = "Block everything";
blockplayers = "Block players";
blockfloaters = "Block floating";
translucent = "Translucent";
jumpover = "Jump over";
zoneboundary = "Sound zone boundary";
clipmidtex = "Clip middle texture";
wrapmidtex = "Wrap middle texture";
midtex3d = "Walkable middle texture";
}
// Activations filter for Hexen type activations
// This filters the activation bits from the flags
linedefactivationsfilter = 7168;
// LINEDEF ACTIVATIONS
// Make sure these are in order from lowest value to highest value
linedefactivations
{
0 = "Player walks over";
1024 = "Player presses Use";
2048 = "Monster walks over";
3072 = "Projectile hits";
4096 = "Player bumps";
5120 = "Projectile flies over";
6144 = "Player presses Use (PassThru)";
7168 = "Projectile hits or crosses";
playercross = "When player walks over";
playeruse = "When player presses use";
monstercross = "When monster walks over";
monsteruse = "When monster presses use";
impact = "On projectile impact";
playerpush = "When player bumps";
monsterpush = "When moinsters bumps";
missilecross = "When projectile crosses";
repeatspecial = "Repeatable action";
passuse = "Pass use on";
firstsideonly = "Front side only";
checkswitchrange = "Switch height check";
}
// LINEDEF TYPES
@ -4784,21 +4985,33 @@ linedeftypes
// THING FLAGS
thingflags
{
1 = "Easy";
2 = "Medium";
4 = "Hard";
8 = "Deaf";
16 = "Dormant";
32 = "Fighter class";
64 = "Cleric class";
128 = "Mage class";
256 = "Singleplayer";
512 = "Cooperative";
1024 = "Deathmatch";
2048 = "Translucent (25%)";
4096 = "Invisible";
8192 = "Friendly";
16384 = "Frozen while inactive";
skill1 = "Skill 1";
skill2 = "Skill 2";
skill3 = "Skill 3";
skill4 = "Skill 4";
skill5 = "Skill 5";
skill6 = "Skill 6";
skill7 = "Skill 7";
skill8 = "Skill 8";
ambush = "Deaf";
single = "Singleplayer";
dm = "Deathmatch";
coop = "Cooperative";
friend = "Friendly";
class1 = "Class 1";
class2 = "Class 2";
class3 = "Class 3";
class4 = "Class 4";
class5 = "Class 5";
class6 = "Class 6";
class7 = "Class 7";
class8 = "Class 8";
dormant = "Dormant";
standing = "Standing";
strifeally = "Ally";
translucent = "Translucent";
invisible = "Invisible";
}
// THING FLAGS ERROR MASK

View file

@ -36,7 +36,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*

View file

@ -36,7 +36,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*

View file

@ -36,7 +36,17 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 999;
defaulthingflags
{
1;
2;
4;
32;
64;
128;
256;
512;
}
/*
@ -4757,6 +4767,7 @@ thingflags
16384 = "Frozen while inactive";
}
// THING FLAGS ERROR MASK
// Mask for the thing flags which indicates the options
// that make the same thing appear in the same modes

View file

@ -36,7 +36,12 @@ defaultflatscale = 1.0f;
start3dmode = 32000;
// Default flags for first new thing
defaulthingflags = 7; //1 + 2 + 4
defaulthingflags
{
1;
2;
4;
}
/*

View file

@ -1,11 +1,17 @@
- Make UDMF implementation
- All fields in sectors, linedefs and things must internally use UDMF fields
- Also enummed field values support
- Finish the custom fields editor
- Fix the browse button
- Enums should drop down in list
- Doubleclick to rename?
- Remember sort order
- Booleans should be enumerable (dropdown true/false)
- Strings should have a mutliline edit window on browse button
- Complete Things filter with UDMF fields
- Controls to increase/decrease grid size
- "Insert Thing" control
- Make "Make Sector" mode
- On mousemove (?) already show the sector outline it will create
- On click make the sector

View file

@ -123,6 +123,8 @@
<Compile Include="Data\DataLocationList.cs" />
<Compile Include="Data\DataManager.cs" />
<Compile Include="Data\WADReader.cs" />
<Compile Include="IO\UniversalCollection.cs" />
<Compile Include="IO\UniversalEntry.cs" />
<Compile Include="IO\UniversalParser.cs" />
<Compile Include="Map\MapElement.cs" />
<Compile Include="Map\UniFields.cs" />
@ -142,6 +144,7 @@
<Compile Include="Types\TypeHandler.cs" />
<Compile Include="Types\TypeHandlerAttribute.cs" />
<Compile Include="Types\TypesManager.cs" />
<Compile Include="Types\UniversalType.cs" />
<Compile Include="Windows\AboutForm.cs">
<SubType>Form</SubType>
</Compile>
@ -199,6 +202,12 @@
<Compile Include="Windows\ConfigForm.Designer.cs">
<DependentUpon>ConfigForm.cs</DependentUpon>
</Compile>
<Compile Include="Windows\CustomFieldsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Windows\CustomFieldsForm.Designer.cs">
<DependentUpon>CustomFieldsForm.cs</DependentUpon>
</Compile>
<Compile Include="Windows\EffectBrowserForm.cs">
<SubType>Form</SubType>
</Compile>
@ -592,6 +601,10 @@
<SubType>Designer</SubType>
<DependentUpon>BitFlagsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Windows\CustomFieldsForm.resx">
<SubType>Designer</SubType>
<DependentUpon>CustomFieldsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Windows\ThingEditForm.resx">
<SubType>Designer</SubType>
<DependentUpon>ThingEditForm.cs</DependentUpon>

View file

@ -292,6 +292,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Move selected geometry to final position
MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptonearest);
// Snap to map format accuracy
General.Map.Map.SnapAllToAccuracy();
// Update cached values
General.Map.Map.Update(false, false);

View file

@ -43,6 +43,7 @@ namespace CodeImp.DoomBuilder.Config
private Configuration cfg;
// General settings
private string enginename;
private float defaulttexturescale;
private float defaultflatscale;
private string formatinterface;
@ -84,6 +85,9 @@ namespace CodeImp.DoomBuilder.Config
// Universal fields
private List<UniversalFieldInfo> linedeffields;
private List<UniversalFieldInfo> sectorfields;
private List<UniversalFieldInfo> sidedeffields;
private List<UniversalFieldInfo> thingfields;
private List<UniversalFieldInfo> vertexfields;
// Enums
private Dictionary<string, EnumList> enums;
@ -93,6 +97,7 @@ namespace CodeImp.DoomBuilder.Config
#region ================== Properties
// General settings
public string EngineName { get { return enginename; } }
public float DefaultTextureScale { get { return defaulttexturescale; } }
public float DefaultFlatScale { get { return defaultflatscale; } }
public string FormatInterface { get { return formatinterface; } }
@ -134,6 +139,9 @@ namespace CodeImp.DoomBuilder.Config
// Universal fields
public List<UniversalFieldInfo> LinedefFields { get { return linedeffields; } }
public List<UniversalFieldInfo> SectorFields { get { return sectorfields; } }
public List<UniversalFieldInfo> SidedefFields { get { return sidedeffields; } }
public List<UniversalFieldInfo> ThingFields { get { return thingfields; } }
public List<UniversalFieldInfo> VertexFields { get { return vertexfields; } }
// Enums
public IDictionary<string, EnumList> Enums { get { return enums; } }
@ -164,6 +172,7 @@ namespace CodeImp.DoomBuilder.Config
this.enums = new Dictionary<string, EnumList>();
// Read general settings
enginename = cfg.ReadSetting("engine", "");
defaulttexturescale = cfg.ReadSetting("defaulttexturescale", 1f);
defaultflatscale = cfg.ReadSetting("defaultflatscale", 1f);
formatinterface = cfg.ReadSetting("formatinterface", "");
@ -209,8 +218,11 @@ namespace CodeImp.DoomBuilder.Config
LoadSectorGeneralizedEffects();
// Universal fields
linedeffields = LoadUniversalFields("linedefs");
sectorfields = LoadUniversalFields("sectors");
linedeffields = LoadUniversalFields("linedef");
sectorfields = LoadUniversalFields("sector");
sidedeffields = LoadUniversalFields("sidedef");
thingfields = LoadUniversalFields("thing");
vertexfields = LoadUniversalFields("vertex");
}
// Destructor

View file

@ -343,6 +343,11 @@ namespace CodeImp.DoomBuilder.Config
defaultceiltexture = General.Map.Data.FlatNames[1];
}
}
// Texture names may not be null
if((defaulttexture == null) || (defaulttexture == "")) defaulttexture = "-";
if((defaultfloortexture == null) || (defaultfloortexture == "")) defaultfloortexture = "-";
if((defaultceiltexture == null) || (defaultceiltexture == "")) defaultceiltexture = "-";
}
#endregion

View file

@ -44,7 +44,6 @@ namespace CodeImp.DoomBuilder.Config
private string name;
private int type;
private object defaultvalue;
private object specdefault;
#endregion
@ -53,7 +52,6 @@ namespace CodeImp.DoomBuilder.Config
public string Name { get { return name; } }
public int Type { get { return type; } }
public object Default { get { return defaultvalue; } }
public object SpecDefault { get { return specdefault; } }
#endregion
@ -70,7 +68,6 @@ namespace CodeImp.DoomBuilder.Config
// Read type
this.type = cfg.ReadSetting(setting + ".type", 0);
this.defaultvalue = cfg.ReadSettingObject(setting + ".default", null);
this.specdefault = cfg.ReadSettingObject(setting + ".specdefault", this.defaultvalue);
// We have no destructor
GC.SuppressFinalize(this);

View file

@ -58,7 +58,7 @@ namespace CodeImp.DoomBuilder.Controls
TypeHandler th;
string actioninfo = "";
string zinfo;
int zvalue;
float zvalue;
// Show/hide stuff depending on format
if(General.Map.FormatInterface.GetType() == typeof(DoomMapSetIO))
@ -114,25 +114,25 @@ namespace CodeImp.DoomBuilder.Controls
// Hangs from ceiling?
if(ti.Hangs)
{
zvalue = t.Sector.CeilHeight + t.ZOffset;
zvalue = (float)t.Sector.CeilHeight + t.Position.z;
zinfo = zvalue.ToString();
}
else
{
zvalue = t.Sector.FloorHeight + t.ZOffset;
zvalue = (float)t.Sector.FloorHeight + t.Position.z;
zinfo = zvalue.ToString();
}
}
else
{
zvalue = t.ZOffset;
if(zvalue >= 0) zinfo = "+" + zvalue.ToString(); else zinfo = zvalue.ToString();
zvalue = t.Position.z;
if(zvalue >= 0.0f) zinfo = "+" + zvalue.ToString(); else zinfo = zvalue.ToString();
}
// Thing info
type.Text = t.Type + " - " + ti.Title;
action.Text = actioninfo;
position.Text = t.X.ToString() + ", " + t.Y.ToString() + ", " + zinfo;
position.Text = t.Position.x.ToString() + ", " + t.Position.y.ToString() + ", " + zinfo;
tag.Text = t.Tag.ToString();
angle.Text = t.AngleDeg.ToString() + "\u00B0";
spritename.Text = ti.Sprite;

View file

@ -474,18 +474,7 @@ namespace CodeImp.DoomBuilder
{
// Open or create the map settings
settingsfile = newfilepathname.Substring(0, newfilepathname.Length - 4) + ".dbs";
if(File.Exists(settingsfile))
mapsettings = new Configuration(settingsfile, true);
else
mapsettings = new Configuration(true);
// Write settings
mapsettings.WriteSetting("type", "Doom Builder Map Settings Configuration");
mapsettings.WriteSetting("gameconfig", options.ConfigFile);
options.Resources.WriteToConfig(mapsettings, "maps." + options.CurrentName + ".resources");
// Save settings
mapsettings.SaveConfiguration(settingsfile);
options.WriteConfiguration(settingsfile);
}
catch(Exception e)
{

View file

@ -106,15 +106,26 @@ namespace CodeImp.DoomBuilder.IO
{
// Check if this exceeds limits
if((this.position + count) > (this.length + 1))
throw new ArgumentException("Attempted to read outside the range of the stream.");
// Seek if needed
if(basestream.Position != (this.offset + this.position))
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position += count;
return basestream.Read(buffer, offset, count);
{
// Read only within limits
count = this.length - (int)this.position;
}
// Anything to read?
if(count > 0)
{
// Seek if needed
if(basestream.Position != (this.offset + this.position))
basestream.Seek(this.offset + this.position, SeekOrigin.Begin);
// Read from base stream
position += count;
return basestream.Read(buffer, offset, count);
}
else
{
return 0;
}
}
// This writes to the stream

View file

@ -383,6 +383,7 @@ namespace CodeImp.DoomBuilder.IO
lump = wad.Insert("THINGS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
// This writes the VERTEXES to WAD file
@ -414,6 +415,7 @@ namespace CodeImp.DoomBuilder.IO
lump = wad.Insert("VERTEXES", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
// This writes the LINEDEFS to WAD file
@ -468,6 +470,7 @@ namespace CodeImp.DoomBuilder.IO
lump = wad.Insert("LINEDEFS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
// This writes the SIDEDEFS to WAD file
@ -503,6 +506,7 @@ namespace CodeImp.DoomBuilder.IO
lump = wad.Insert("SIDEDEFS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
// This writes the SECTORS to WAD file
@ -539,6 +543,7 @@ namespace CodeImp.DoomBuilder.IO
lump = wad.Insert("SECTORS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
mem.Flush();
}
#endregion

View file

@ -386,7 +386,7 @@ namespace CodeImp.DoomBuilder.IO
writer.Write((UInt16)t.Tag);
writer.Write((Int16)t.Position.x);
writer.Write((Int16)t.Position.y);
writer.Write((Int16)t.ZOffset);
writer.Write((Int16)t.Position.z);
writer.Write((Int16)((t.Angle * Angle2D.PIDEG) - 90));
writer.Write((UInt16)t.Type);
writer.Write((UInt16)flags);

View file

@ -0,0 +1,39 @@
#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.IO;
using System.Text;
using System.Globalization;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
#endregion
namespace CodeImp.DoomBuilder.IO
{
public sealed class UniversalCollection : List<UniversalEntry>
{
// Overload
public void Add(string key, object value)
{
base.Add(new UniversalEntry(key, value));
}
}
}

View file

@ -0,0 +1,73 @@
#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.IO;
using System.Text;
using System.Globalization;
using System.Collections;
using System.Collections.Specialized;
#endregion
namespace CodeImp.DoomBuilder.IO
{
public sealed class UniversalEntry
{
#region ================== Constants
#endregion
#region ================== Variables
private string key;
private object value;
#endregion
#region ================== Properties
public string Key { get { return key; } }
public object Value { get { return value; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public UniversalEntry(string key, object value)
{
// Initialize
this.key = key;
this.value = value;
}
#endregion
#region ================== Methods
// This checks if the value is of the given type
// Will throw and exception when it is not
public void ValidateType(Type t)
{
if(value.GetType() != t) throw new Exception("The value of entry '" + key + "' is of incompatible type (expected " + t.Name + ")");
}
#endregion
}
}

View file

@ -25,6 +25,8 @@ using System.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Types;
#endregion
@ -67,6 +69,22 @@ namespace CodeImp.DoomBuilder.IO
// 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);
// 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();
@ -86,12 +104,14 @@ namespace CodeImp.DoomBuilder.IO
#endregion
#region ================== Reading
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
UniversalParser textmap = new UniversalParser();
StreamReader lumpreader = null;
Dictionary<int, Vertex> vertexlink;
Dictionary<int, Sector> sectorlink;
// Find the index where first map lump begins
int firstindex = wad.FindLumpIndex(mapname) + 1;
@ -103,7 +123,8 @@ namespace CodeImp.DoomBuilder.IO
try
{
// Parse the UDMF data
lumpreader = new StreamReader(lump.Stream);
lumpreader = new StreamReader(lump.Stream, Encoding.ASCII);
lump.Stream.Seek(0, SeekOrigin.Begin);
textmap.InputConfiguration(lumpreader.ReadToEnd());
// Check for errors
@ -114,7 +135,11 @@ namespace CodeImp.DoomBuilder.IO
}
else
{
// Read the map
vertexlink = ReadVertices(map, textmap);
sectorlink = ReadSectors(map, textmap);
ReadLinedefs(map, textmap, vertexlink, sectorlink);
ReadThings(map, textmap);
}
}
catch(Exception e)
@ -130,6 +155,279 @@ namespace CodeImp.DoomBuilder.IO
return map;
}
// This reads the things
private void ReadThings(MapSet map, UniversalParser textmap)
{
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "thing");
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
int[] args = new int[Linedef.NUM_ARGS];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f);
float y = GetCollectionEntry<float>(c, "y", true, 0.0f);
float height = GetCollectionEntry<float>(c, "height", false, 0.0f);
int tag = GetCollectionEntry<int>(c, "id", false, 0);
int angledeg = GetCollectionEntry<int>(c, "angle", false, 0);
int type = GetCollectionEntry<int>(c, "type", true, 0);
int special = GetCollectionEntry<int>(c, "special", false, 0);
args[0] = GetCollectionEntry<int>(c, "arg0", false, 0);
args[1] = GetCollectionEntry<int>(c, "arg1", false, 0);
args[2] = GetCollectionEntry<int>(c, "arg2", false, 0);
args[3] = GetCollectionEntry<int>(c, "arg3", false, 0);
args[4] = GetCollectionEntry<int>(c, "arg4", false, 0);
// Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.ThingFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(c, flag.Key, false, false);
// Create new item
Thing t = map.CreateThing();
t.Update(type, x, y, height, Angle2D.DegToRad(angledeg), stringflags, tag, special, args);
//t.DetermineSector();
t.UpdateConfiguration();
// Custom fields
ReadCustomFields(c, t, "thing");
}
}
// This reads the linedefs and sidedefs
private void ReadLinedefs(MapSet map, UniversalParser textmap,
Dictionary<int, Vertex> vertexlink, Dictionary<int, Sector> sectorlink)
{
// Get list of entries
List<UniversalCollection> linescolls = GetNamedCollections(textmap.Root, "linedef");
List<UniversalCollection> sidescolls = GetNamedCollections(textmap.Root, "sidedef");
// Go for all lines
for(int i = 0; i < linescolls.Count; i++)
{
// Read fields
UniversalCollection lc = linescolls[i];
int[] args = new int[Linedef.NUM_ARGS];
int tag = GetCollectionEntry<int>(lc, "id", false, 0);
int v1 = GetCollectionEntry<int>(lc, "v1", true, 0);
int v2 = GetCollectionEntry<int>(lc, "v2", true, 0);
int special = GetCollectionEntry<int>(lc, "special", false, 0);
args[0] = GetCollectionEntry<int>(lc, "arg0", false, 0);
args[1] = GetCollectionEntry<int>(lc, "arg1", false, 0);
args[2] = GetCollectionEntry<int>(lc, "arg2", false, 0);
args[3] = GetCollectionEntry<int>(lc, "arg3", false, 0);
args[4] = GetCollectionEntry<int>(lc, "arg4", false, 0);
int s1 = GetCollectionEntry<int>(lc, "sidefront", true, -1);
int s2 = GetCollectionEntry<int>(lc, "sideback", false, -1);
// Flags
Dictionary<string, bool> stringflags = new Dictionary<string, bool>();
foreach(KeyValuePair<string, string> flag in General.Map.Config.LinedefFlags)
stringflags[flag.Key] = GetCollectionEntry<bool>(lc, flag.Key, false, false);
// Activations
foreach(LinedefActivateInfo activate in General.Map.Config.LinedefActivates)
stringflags[activate.Key] = GetCollectionEntry<bool>(lc, activate.Key, false, false);
// Create new item
Linedef l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
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) ReadSidedef(map, sidescolls[s1], l, true, sectorlink);
if(s2 > -1) ReadSidedef(map, sidescolls[s2], l, false, sectorlink);
}
}
// This reads a single sidedef and connects it to the given linedef
private void ReadSidedef(MapSet map, UniversalCollection sc, Linedef ld,
bool front, Dictionary<int, Sector> sectorlink)
{
// Read fields
int offsetx = GetCollectionEntry<int>(sc, "offsetx", false, 0);
int offsety = GetCollectionEntry<int>(sc, "offsety", false, 0);
string thigh = GetCollectionEntry<string>(sc, "texturetop", false, "-");
string tlow = GetCollectionEntry<string>(sc, "texturebottom", false, "-");
string tmid = GetCollectionEntry<string>(sc, "texturemiddle", false, "-");
int sector = GetCollectionEntry<int>(sc, "sector", true, 0);
// Create sidedef
Sidedef s = map.CreateSidedef(ld, front, sectorlink[sector]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
// Custom fields
ReadCustomFields(sc, s, "sidedef");
}
// This reads the sectors
private Dictionary<int, Sector> ReadSectors(MapSet map, UniversalParser textmap)
{
Dictionary<int, Sector> link;
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "sector");
// Create lookup table
link = new Dictionary<int, Sector>(collections.Count);
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
int hfloor = GetCollectionEntry<int>(c, "heightfloor", false, 0);
int hceil = GetCollectionEntry<int>(c, "heightceiling", false, 0);
string tfloor = GetCollectionEntry<string>(c, "texturefloor", true, "-");
string tceil = GetCollectionEntry<string>(c, "textureceiling", true, "-");
int bright = GetCollectionEntry<int>(c, "lightlevel", false, 160);
int special = GetCollectionEntry<int>(c, "special", false, 0);
int tag = GetCollectionEntry<int>(c, "id", false, 0);
// Create new item
Sector s = map.CreateSector();
s.Update(hfloor, hceil, tfloor, tceil, special, tag, bright);
// Custom fields
ReadCustomFields(c, s, "sector");
// Add it to the lookup table
link.Add(i, s);
}
// Return lookup table
return link;
}
// This reads the vertices
private Dictionary<int, Vertex> ReadVertices(MapSet map, UniversalParser textmap)
{
Dictionary<int, Vertex> link;
// Get list of entries
List<UniversalCollection> collections = GetNamedCollections(textmap.Root, "vertex");
// Create lookup table
link = new Dictionary<int, Vertex>(collections.Count);
// Go for all collections
for(int i = 0; i < collections.Count; i++)
{
// Read fields
UniversalCollection c = collections[i];
float x = GetCollectionEntry<float>(c, "x", true, 0.0f);
float y = GetCollectionEntry<float>(c, "y", true, 0.0f);
// Create new item
Vertex v = map.CreateVertex(new Vector2D(x, y));
// Custom fields
ReadCustomFields(c, v, "vertex");
// Add it to the lookup table
link.Add(i, v);
}
// Return lookup table
return link;
}
// This reads custom fields from a collection and adds them to a map element
private void ReadCustomFields(UniversalCollection collection, MapElement element, string elementname)
{
// Go for all the elements in the collection
foreach(UniversalEntry e in collection)
{
// Check if not a managed field
if(!config.SettingExists("managedfields." + elementname + "." + e.Key))
{
int type = (int)UniversalType.Integer;
// Determine default type
if(e.Value.GetType() == typeof(int)) type = (int)UniversalType.Integer;
else if(e.Value.GetType() == typeof(float)) type = (int)UniversalType.Float;
else if(e.Value.GetType() == typeof(bool)) type = (int)UniversalType.Boolean;
else if(e.Value.GetType() == typeof(string)) type = (int)UniversalType.String;
// Try to find the type from configuration
type = manager.Options.GetUniversalFieldType(elementname, e.Key, type);
// Make custom field
element.Fields.Add(e.Key, new UniValue(type, e.Value));
}
}
}
// This validates and returns an entry
private T GetCollectionEntry<T>(UniversalCollection c, string entryname, bool required, T defaultvalue)
{
T result = default(T);
bool found = false;
// Find the entry
foreach(UniversalEntry e in c)
{
// Check if matches
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)))
{
// Make it a float
result = (T)e.Value;
}
else
{
// Verify type
e.ValidateType(typeof(T));
// Found it!
result = (T)e.Value;
}
// Done
found = true;
}
}
// Not found?
if(!found)
{
// Entry is required?
if(required)
{
// Error, cannot find required entry!
throw new Exception("Error while reading UDMF map data: Missing required field '" + entryname + "'.");
}
else
{
// Make default entry
result = defaultvalue;
}
}
// Return result
return result;
}
// This makes a list of all collections with the given name
private List<UniversalCollection> GetNamedCollections(UniversalCollection collection, string entryname)
{
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);
return list;
}
#endregion
#region ================== Writing
@ -137,9 +435,197 @@ namespace CodeImp.DoomBuilder.IO
// This writes a MapSet to the file
public override void Write(MapSet map, string mapname, int position)
{
UniversalParser textmap = new UniversalParser();
// Begin with fields that must be at the top
textmap.Root.Add("namespace", manager.Config.EngineName);
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 map.Vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in map.Sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in map.Sectors) sectorids.Add(s, sectorids.Count);
// We will write the custom field types again, so forget
// all previous field types (this gets rid of unused field types)
manager.Options.ForgetUniversalFieldTypes();
// Write the data structures to textmap
WriteVertices(map, textmap);
WriteLinedefs(map, textmap, sidedefids, vertexids);
WriteSidedefs(map, textmap, sectorids);
WriteSectors(map, textmap);
WriteThings(map, textmap);
// Get the textmap as string
string textmapstr = textmap.OutputConfiguration();
// Find insert position and remove old lump
int insertpos = MapManager.RemoveSpecificLump(wad, "TEXTMAP", position, "", manager.Config.MapLumpNames);
if(insertpos == -1) insertpos = position + 1;
if(insertpos > wad.Lumps.Count) insertpos = wad.Lumps.Count;
// Create the lump from memory
Lump lump = wad.Insert("TEXTMAP", insertpos, textmapstr.Length);
StreamWriter lumpwriter = new StreamWriter(lump.Stream);
lump.Stream.Seek(0, SeekOrigin.Begin);
lumpwriter.Write(textmapstr);
lumpwriter.Flush();
}
// This writes the vertices
private void WriteVertices(MapSet map, UniversalParser textmap)
{
// Go for all vertices
foreach(Vertex v in map.Vertices)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("x", v.Position.x);
coll.Add("y", v.Position.y);
// Add custom fields
AddCustomFields(v, "vertex", coll);
// Store
textmap.Root.Add("vertex", coll);
}
}
// This writes the linedefs
private void WriteLinedefs(MapSet map, UniversalParser textmap, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids)
{
// Go for all linedefs
foreach(Linedef l in map.Linedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(l.Tag != 0) coll.Add("id", l.Tag);
coll.Add("v1", vertexids[l.Start]);
coll.Add("v2", vertexids[l.End]);
if(l.Front != null) coll.Add("sidefront", sidedefids[l.Front]); else coll.Add("sidefront", -1);
if(l.Back != null) coll.Add("sideback", sidedefids[l.Back]); else coll.Add("sideback", -1);
if(l.Action != 0) coll.Add("special", l.Action);
if(l.Args[0] != 0) coll.Add("arg0", l.Args[0]);
if(l.Args[1] != 0) coll.Add("arg1", l.Args[1]);
if(l.Args[2] != 0) coll.Add("arg2", l.Args[2]);
if(l.Args[3] != 0) coll.Add("arg3", l.Args[3]);
if(l.Args[4] != 0) coll.Add("arg4", l.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in l.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(l, "linedef", coll);
// Store
textmap.Root.Add("linedef", coll);
}
}
// This writes the sidedefs
private void WriteSidedefs(MapSet map, UniversalParser textmap, IDictionary<Sector, int> sectorids)
{
// Go for all sidedefs
foreach(Sidedef s in map.Sidedefs)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
if(s.OffsetX != 0) coll.Add("offsetx", s.OffsetX);
if(s.OffsetY != 0) coll.Add("offsety", s.OffsetY);
if(s.LongHighTexture != map.EmptyLongName) coll.Add("texturetop", s.HighTexture);
if(s.LongLowTexture != map.EmptyLongName) coll.Add("texturebottom", s.LowTexture);
if(s.LongMiddleTexture != map.EmptyLongName) coll.Add("texturemiddle", s.MiddleTexture);
coll.Add("sector", sectorids[s.Sector]);
// Add custom fields
AddCustomFields(s, "sidedef", coll);
// Store
textmap.Root.Add("sidedef", coll);
}
}
// This writes the sectors
private void WriteSectors(MapSet map, UniversalParser textmap)
{
// Go for all sectors
foreach(Sector s in map.Sectors)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
coll.Add("heightfloor", s.FloorHeight);
coll.Add("heightceiling", s.CeilHeight);
coll.Add("texturefloor", s.FloorTexture);
coll.Add("textureceiling", s.CeilTexture);
coll.Add("lightlevel", s.Brightness);
if(s.Effect != 0) coll.Add("special", s.Effect);
if(s.Tag != 0) coll.Add("id", s.Tag);
// Add custom fields
AddCustomFields(s, "sector", coll);
// Store
textmap.Root.Add("sector", coll);
}
}
// This writes the things
private void WriteThings(MapSet map, UniversalParser textmap)
{
// Go for all things
foreach(Thing t in map.Things)
{
// Make collection
UniversalCollection coll = new UniversalCollection();
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);
coll.Add("angle", t.AngleDeg);
coll.Add("type", t.Type);
if(t.Action != 0) coll.Add("special", t.Action);
if(t.Args[0] != 0) coll.Add("arg0", t.Args[0]);
if(t.Args[1] != 0) coll.Add("arg1", t.Args[1]);
if(t.Args[2] != 0) coll.Add("arg2", t.Args[2]);
if(t.Args[3] != 0) coll.Add("arg3", t.Args[3]);
if(t.Args[4] != 0) coll.Add("arg4", t.Args[4]);
// Flags
foreach(KeyValuePair<string, bool> flag in t.Flags)
if(flag.Value) coll.Add(flag.Key, flag.Value);
// Add custom fields
AddCustomFields(t, "thing", coll);
// Store
textmap.Root.Add("thing", coll);
}
}
// This adds custom fields from a map element to a collection
private void AddCustomFields(MapElement element, string elementname, UniversalCollection collection)
{
// Add custom fields
foreach(KeyValuePair<string, UniValue> f in element.Fields)
{
// Not a managed field?
if(!config.SettingExists("managedfields." + elementname + "." + f.Key))
{
// Add type information to DBS file for map
manager.Options.SetUniversalFieldType(elementname, f.Key, f.Value.Type);
// Store field
collection.Add(f.Key, f.Value.Value);
}
}
}
#endregion
}
}

View file

@ -22,6 +22,7 @@ using System.Text;
using System.Globalization;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
#endregion
@ -34,6 +35,9 @@ namespace CodeImp.DoomBuilder.IO
// Path seperator
public const string DEFAULT_SEPERATOR = ".";
// Allowed characters in a key
public const string KEY_CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789_";
// Parse mode constants
private const int PM_NOTHING = 0;
private const int PM_ASSIGNMENT = 1;
@ -43,11 +47,11 @@ namespace CodeImp.DoomBuilder.IO
// Error strings
private const string ERROR_KEYMISSING = "Missing key name in assignment or scope.";
private const string ERROR_KEYSPACES = "Spaces not allowed in key names.";
private const string ERROR_KEYCHARACTERS = "Invalid characters in key name.";
private const string ERROR_ASSIGNINVALID = "Invalid assignment. Missing a previous terminator symbol?";
private const string ERROR_VALUEINVALID = "Invalid value in assignment. Missing a previous terminator symbol?";
private const string ERROR_VALUETOOBIG = "Value too big.";
private const string ERROR_KEYNOTUNQIUE = "Key is not unique within scope.";
private const string ERROR_KEYWITHOUTVALUE = "Key has no value assigned.";
private const string ERROR_KEYWORDUNKNOWN = "Unknown keyword in assignment. Missing a previous terminator symbol?";
#endregion
@ -60,7 +64,7 @@ namespace CodeImp.DoomBuilder.IO
private int cpErrorLine = 0;
// Configuration root
private ListDictionary root = null;
private UniversalCollection root = null;
#endregion
@ -70,7 +74,7 @@ namespace CodeImp.DoomBuilder.IO
public int ErrorResult { get { return cpErrorResult; } }
public string ErrorDescription { get { return cpErrorDescription; } }
public int ErrorLine { get { return cpErrorLine; } }
public ListDictionary Root { get { return root; } set { root = value; } }
public UniversalCollection Root { get { return root; } }
#endregion
@ -100,114 +104,6 @@ namespace CodeImp.DoomBuilder.IO
#region ================== Private Methods
// This is called by all the ReadSetting overloads to perform the read
private bool CheckSetting(string setting, string pathseperator)
{
ListDictionary cs = null;
// Split the path in an array
string[] keys = setting.Split(pathseperator.ToCharArray());
// Get the root item
object item = root;
// Go for each item
for(int i = 0; i < keys.Length; i++)
{
// Check if the current item is of ConfigStruct type
if(item is ListDictionary)
{
// Check if the key is valid
if(ValidateKey(null, keys[i].Trim(), -1) == true)
{
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Check if the requested item exists
if(cs.Contains(keys[i]) == true)
{
// Set the item to the next item
item = cs[keys[i]];
}
else
{
// Key not found
return false;
}
}
else
{
// Invalid key in path
return false;
}
}
else
{
// Unable to go any further
return false;
}
}
// Return result
return true;
}
// This is called by all the ReadSetting overloads to perform the read
private object ReadAnySetting(string setting, object defaultsetting, string pathseperator)
{
ListDictionary cs = null;
// Split the path in an array
string[] keys = setting.Split(pathseperator.ToCharArray());
// Get the root item
object item = root;
// Go for each item
for(int i = 0; i < keys.Length; i++)
{
// Check if the current item is of ConfigStruct type
if(item is ListDictionary)
{
// Check if the key is valid
if(ValidateKey(null, keys[i].Trim(), -1) == true)
{
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Check if the requested item exists
if(cs.Contains(keys[i]) == true)
{
// Set the item to the next item
item = cs[keys[i]];
}
else
{
// Key not found
// return default setting
return defaultsetting;
}
}
else
{
// Invalid key in path
// return default setting
return defaultsetting;
}
}
else
{
// Unable to go any further
// return default setting
return defaultsetting;
}
}
// Return the item
return item;
}
// This returns a string added with escape characters
private string EscapedString(string str)
{
@ -235,12 +131,12 @@ namespace CodeImp.DoomBuilder.IO
// This validates a given key and sets
// error properties if key is invalid and errorline > -1
private bool ValidateKey(ListDictionary container, string key, int errorline)
private bool ValidateKey(string key, int errorline)
{
bool validateresult;
bool validateresult = true;
// Check if key is an empty string
if(key == "")
if(key.Length == 0)
{
// ERROR: Missing key name in statement
if(errorline > -1) RaiseError(errorline, ERROR_KEYMISSING);
@ -248,70 +144,16 @@ namespace CodeImp.DoomBuilder.IO
}
else
{
// Check if there are spaces in the key
if(key.IndexOfAny(" ".ToCharArray()) > -1)
// Check if all characters are valid
foreach(char c in key)
{
// ERROR: Spaces not allowed in key names
if(errorline > -1) RaiseError(errorline, ERROR_KEYSPACES);
validateresult = false;
}
else
{
// Check if we can test existance
if(container != null)
if(KEY_CHARACTERS.IndexOf(c) == -1)
{
// Test if the key exists in this container
if(container.Contains(key) == true)
{
// ERROR: Key is not unique within struct
if(errorline > -1) RaiseError(errorline, ERROR_KEYNOTUNQIUE);
validateresult = false;
}
else
{
// Key OK
validateresult = true;
}
// ERROR: Invalid characters in key name
if(errorline > -1) RaiseError(errorline, ERROR_KEYCHARACTERS);
validateresult = false;
break;
}
else
{
// Key OK
validateresult = true;
}
}
}
// Return result
return validateresult;
}
// This validates a given keyword and sets
// error properties if keyword is invalid and errorline > -1
private bool ValidateKeyword(string keyword, int errorline)
{
bool validateresult;
// Check if key is an empty string
if(keyword == "")
{
// ERROR: Missing key name in statement
if(errorline > -1) RaiseError(errorline, ERROR_ASSIGNINVALID);
validateresult = false;
}
else
{
// Check if there are spaces in the key
if(keyword.IndexOfAny(" ".ToCharArray()) > -1)
{
// ERROR: Spaces not allowed in key names
if(errorline > -1) RaiseError(errorline, ERROR_ASSIGNINVALID);
validateresult = false;
}
else
{
// Key OK
validateresult = true;
}
}
@ -322,14 +164,14 @@ namespace CodeImp.DoomBuilder.IO
// This parses a structure in the given data starting
// from the given pos and line and updates pos and line.
private ListDictionary InputStructure(ref string data, ref int pos, ref int line)
private UniversalCollection InputStructure(ref string data, ref int pos, ref int line)
{
char c = '\0'; // current data character
int pm = PM_NOTHING; // current parse mode
string key = "", val = ""; // current key and value beign built
bool escape = false; // escape sequence?
bool endofstruct = false; // true as soon as this level struct ends
ListDictionary cs = new ListDictionary();
UniversalCollection cs = new UniversalCollection();
// Go through all of the data until
// the end or until the struct closes
@ -348,13 +190,13 @@ namespace CodeImp.DoomBuilder.IO
case '{': // Begin of new struct
// Validate key
if(ValidateKey(cs, key.Trim(), line))
if(ValidateKey(key.Trim(), line))
{
// Next character
pos++;
// Parse this struct and add it
cs.Add(key.Trim(), InputStructure(ref data, ref pos, ref line));
cs.Add(new UniversalEntry(key.Trim(), InputStructure(ref data, ref pos, ref line)));
// Check the last character
pos--;
@ -377,7 +219,7 @@ namespace CodeImp.DoomBuilder.IO
case '=': // Assignment
// Validate key
if(ValidateKey(cs, key.Trim(), line))
if(ValidateKey(key.Trim(), line))
{
// Now parsing assignment
pm = PM_ASSIGNMENT;
@ -389,14 +231,10 @@ namespace CodeImp.DoomBuilder.IO
case ';': // Terminator
// Validate key
if(ValidateKey(cs, key.Trim(), line))
if(ValidateKey(key.Trim(), line))
{
// Add the key with null as value
cs.Add(key.Trim(), null);
// Reset key and value
key = "";
val = "";
// Error: No value
RaiseError(line, ERROR_KEYWITHOUTVALUE);
}
// Leave switch
@ -470,7 +308,7 @@ namespace CodeImp.DoomBuilder.IO
default: // Everything else
// Add character to key
key += c.ToString(CultureInfo.InvariantCulture);
key += c.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
// Leave switch
break;
@ -542,7 +380,7 @@ namespace CodeImp.DoomBuilder.IO
}
// Add it to struct
cs.Add(key.Trim(), fval);
cs.Add(new UniversalEntry(key.Trim(), fval));
}
else
{
@ -556,7 +394,7 @@ namespace CodeImp.DoomBuilder.IO
ival = System.Convert.ToInt32(val.Trim(), CultureInfo.InvariantCulture);
// Add it to struct
cs.Add(key.Trim(), ival);
cs.Add(new UniversalEntry(key.Trim(), ival));
}
catch(System.OverflowException)
{
@ -567,7 +405,7 @@ namespace CodeImp.DoomBuilder.IO
lval = System.Convert.ToInt64(val.Trim(), CultureInfo.InvariantCulture);
// Add it to struct
cs.Add(key.Trim(), lval);
cs.Add(new UniversalEntry(key.Trim(), lval));
}
catch(System.OverflowException)
{
@ -673,7 +511,7 @@ namespace CodeImp.DoomBuilder.IO
else if(c == '\"')
{
// Add string to struct
cs.Add(key.Trim(), val);
cs.Add(new UniversalEntry(key.Trim(), val));
// End of assignment
pm = PM_ASSIGNMENT;
@ -702,38 +540,34 @@ namespace CodeImp.DoomBuilder.IO
// Check if keyword ends
if(c == ';')
{
// Validate the keyword
if(ValidateKeyword(val.Trim(), line))
// Add to the struct depending on the keyword
switch(val.Trim().ToLowerInvariant())
{
// Add to the struct depending on the keyword
switch(val.Trim().ToLowerInvariant())
{
case "true":
// Add boolean true
cs.Add(key.Trim(), true);
break;
case "false":
// Add boolean false
cs.Add(key.Trim(), false);
break;
default:
// Unknown keyword
RaiseError(line, ERROR_KEYWORDUNKNOWN);
break;
}
// End of assignment
pm = PM_NOTHING;
// Reset key and value
key = "";
val = "";
case "true":
// Add boolean true
cs.Add(new UniversalEntry(key.Trim(), true));
break;
case "false":
// Add boolean false
cs.Add(new UniversalEntry(key.Trim(), false));
break;
default:
// Unknown keyword
RaiseError(line, ERROR_KEYWORDUNKNOWN);
break;
}
// End of assignment
pm = PM_NOTHING;
// Reset key and value
key = "";
val = "";
}
// Check for new line
else if(c == '\n')
@ -759,7 +593,7 @@ namespace CodeImp.DoomBuilder.IO
// This will create a data structure from the given object
private string OutputStructure(ListDictionary cs, int level, string newline, bool whitespace)
private string OutputStructure(UniversalCollection cs, int level, string newline, bool whitespace)
{
string leveltabs = "";
string spacing = "";
@ -776,7 +610,7 @@ namespace CodeImp.DoomBuilder.IO
}
// Get enumerator
IDictionaryEnumerator de = cs.GetEnumerator();
IEnumerator<UniversalEntry> de = cs.GetEnumerator();
// Go for each item
for(int i = 0; i < cs.Count; i++)
@ -784,53 +618,54 @@ namespace CodeImp.DoomBuilder.IO
// Go to next item
de.MoveNext();
// Check if the value if of ConfigStruct type
if(de.Value is ListDictionary)
// Check if the value if of collection type
if(de.Current.Value is UniversalCollection)
{
// Output recursive structure
if(whitespace) { db.Append(leveltabs); db.Append(newline); }
db.Append(leveltabs); db.Append(de.Key); db.Append(newline);
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(newline);
db.Append(leveltabs); db.Append("{"); db.Append(newline);
db.Append(OutputStructure((ListDictionary)de.Value, level + 1, newline, whitespace));
db.Append(OutputStructure((UniversalCollection)de.Current.Value, level + 1, newline, whitespace));
db.Append(leveltabs); db.Append("}"); db.Append(newline);
if(whitespace) { db.Append(leveltabs); db.Append(newline); }
}
// Check if the value is of boolean type
else if(de.Value is bool)
else if(de.Current.Value is bool)
{
// Check value
if((bool)de.Value == true)
if((bool)de.Current.Value == true)
{
// Output the keyword "true"
db.Append(leveltabs); db.Append(de.Key.ToString()); db.Append(spacing);
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.Key.ToString()); db.Append(spacing);
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing);
db.Append("="); db.Append(spacing); db.Append("false;"); db.Append(newline);
}
}
// Check if value is of float type
else if(de.Value is float)
else if(de.Current.Value is float)
{
// Output the value with a postfixed f
db.Append(leveltabs); db.Append(de.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append(String.Format(CultureInfo.InvariantCulture, "{0}", de.Value)); db.Append("f;"); db.Append(newline);
// Output the value as float (3 decimals)
float f = (float)de.Current.Value;
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append(f.ToString("0.000", CultureInfo.InvariantCulture)); db.Append(";"); db.Append(newline);
}
// Check if value is of other numeric type
else if(de.Value.GetType().IsPrimitive)
else if(de.Current.Value.GetType().IsPrimitive)
{
// Output the value unquoted
db.Append(leveltabs); db.Append(de.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append(String.Format(CultureInfo.InvariantCulture, "{0}", de.Value)); db.Append(";"); db.Append(newline);
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append(String.Format(CultureInfo.InvariantCulture, "{0}", de.Current.Value)); db.Append(";"); db.Append(newline);
}
else
{
// Output the value with quotes and escape characters
db.Append(leveltabs); db.Append(de.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append("\""); db.Append(EscapedString(de.Value.ToString())); db.Append("\";"); db.Append(newline);
db.Append(leveltabs); db.Append(de.Current.Key); db.Append(spacing); db.Append("=");
db.Append(spacing); db.Append("\""); db.Append(EscapedString(de.Current.Value.ToString())); db.Append("\";"); db.Append(newline);
}
}
}
@ -857,186 +692,7 @@ namespace CodeImp.DoomBuilder.IO
public void NewConfiguration()
{
// Create new configuration
root = new ListDictionary();
}
// This checks if a given setting exists (disregards type)
public bool SettingExists(string setting) { return CheckSetting(setting, DEFAULT_SEPERATOR); }
public bool SettingExists(string setting, string pathseperator) { return CheckSetting(setting, pathseperator); }
// This can give a value of a key specified in a path form
// also, this does not error when the setting does not exist,
// but instead returns the given default value.
public string ReadSetting(string setting, string defaultsetting) { object r = ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR); if(r != null) return r.ToString(); else return null; }
public string ReadSetting(string setting, string defaultsetting, string pathseperator) { object r = ReadAnySetting(setting, defaultsetting, pathseperator); if(r != null) return r.ToString(); else return null; }
public int ReadSetting(string setting, int defaultsetting) { return Convert.ToInt32(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public int ReadSetting(string setting, int defaultsetting, string pathseperator) { return Convert.ToInt32(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public float ReadSetting(string setting, float defaultsetting) { return Convert.ToSingle(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public float ReadSetting(string setting, float defaultsetting, string pathseperator) { return Convert.ToSingle(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public short ReadSetting(string setting, short defaultsetting) { return Convert.ToInt16(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public short ReadSetting(string setting, short defaultsetting, string pathseperator) { return Convert.ToInt16(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public long ReadSetting(string setting, long defaultsetting) { return Convert.ToInt64(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public long ReadSetting(string setting, long defaultsetting, string pathseperator) { return Convert.ToInt64(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public bool ReadSetting(string setting, bool defaultsetting) { return Convert.ToBoolean(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public bool ReadSetting(string setting, bool defaultsetting, string pathseperator) { return Convert.ToBoolean(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public byte ReadSetting(string setting, byte defaultsetting) { return Convert.ToByte(ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR), CultureInfo.InvariantCulture); }
public byte ReadSetting(string setting, byte defaultsetting, string pathseperator) { return Convert.ToByte(ReadAnySetting(setting, defaultsetting, pathseperator), CultureInfo.InvariantCulture); }
public ListDictionary ReadSetting(string setting, ListDictionary defaultsetting) { return (ListDictionary)ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR); }
public ListDictionary ReadSetting(string setting, ListDictionary defaultsetting, string pathseperator) { return (ListDictionary)ReadAnySetting(setting, defaultsetting, pathseperator); }
public object ReadSettingObject(string setting, object defaultsetting) { return ReadAnySetting(setting, defaultsetting, DEFAULT_SEPERATOR); }
// This writes a given setting to the configuration.
// Wont change existing structs, but will add them as needed.
// Returns true when written, false when failed.
public bool WriteSetting(string setting, object settingvalue) { return WriteSetting(setting, settingvalue, DEFAULT_SEPERATOR); }
public bool WriteSetting(string setting, object settingvalue, string pathseperator)
{
ListDictionary cs = null;
// Split the path in an array
string[] keys = setting.Split(pathseperator.ToCharArray());
string finalkey = keys[keys.Length - 1];
// Get the root item
object item = root;
// Go for each path item
for(int i = 0; i < (keys.Length - 1); i++)
{
// Check if the key is valid
if(ValidateKey(null, keys[i].Trim(), -1) == true)
{
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Check if the requested item exists
if(cs.Contains(keys[i]) == true)
{
// Check if the requested item is a ConfigStruct
if(cs[keys[i]] is ListDictionary)
{
// Set the item to the next item
item = cs[keys[i]];
}
else
{
// Cant proceed with path
return false;
}
}
else
{
// Key not found
// Create it now
ListDictionary ncs = new ListDictionary();
cs.Add(keys[i], ncs);
// Set the item to the next item
item = cs[keys[i]];
}
}
else
{
// Invalid key in path
return false;
}
}
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Check if the key already exists
if(cs.Contains(finalkey) == true)
{
// Update the value
cs[finalkey] = settingvalue;
}
else
{
// Create the key/value pair
cs.Add(finalkey, settingvalue);
}
// Return success
return true;
}
// This removes a given setting from the configuration.
public bool DeleteSetting(string setting) { return DeleteSetting(setting, DEFAULT_SEPERATOR); }
public bool DeleteSetting(string setting, string pathseperator)
{
ListDictionary cs = null;
// Split the path in an array
string[] keys = setting.Split(pathseperator.ToCharArray());
string finalkey = keys[keys.Length - 1];
// Get the root item
object item = root;
// Go for each path item
for(int i = 0; i < (keys.Length - 1); i++)
{
// Check if the key is valid
if(ValidateKey(null, keys[i].Trim(), -1) == true)
{
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Check if the requested item exists
if(cs.Contains(keys[i]) == true)
{
// Check if the requested item is a ConfigStruct
if(cs[keys[i]] is ListDictionary)
{
// Set the item to the next item
item = cs[keys[i]];
}
else
{
// Cant proceed with path
return false;
}
}
else
{
// Key not found
// Create it now
ListDictionary ncs = new ListDictionary();
cs.Add(keys[i], ncs);
// Set the item to the next item
item = cs[keys[i]];
}
}
else
{
// Invalid key in path
return false;
}
}
// Cast to ConfigStruct
cs = (ListDictionary)item;
// Arrived at our destination
// Delete the key if the key exists
if(cs.Contains(finalkey) == true)
{
// Key exists, delete it
cs.Remove(finalkey);
// Return success
return true;
}
else
{
// Key not found, return fail
return false;
}
root = new UniversalCollection();
}

View file

@ -24,6 +24,7 @@ using System.Text;
using CodeImp.DoomBuilder.IO;
using System.IO;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Config;
#endregion
@ -37,6 +38,9 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Variables
// Map configuration
private Configuration mapconfig;
// Game configuration
private string configfile;
@ -77,6 +81,7 @@ namespace CodeImp.DoomBuilder.Map
internal MapOptions()
{
// Initialize
this.mapconfig = new Configuration(true);
this.previousname = "";
this.currentname = "";
this.configfile = "";
@ -94,10 +99,10 @@ namespace CodeImp.DoomBuilder.Map
this.currentname = mapname;
this.configfile = cfg.ReadSetting("config", "");
this.resources = new DataLocationList();
// Go for all items in the map info
mapinfo = cfg.ReadSetting(mapname, new Hashtable());
foreach(DictionaryEntry mp in mapinfo)
this.mapconfig.Root = cfg.ReadSetting(mapname, new Hashtable());
foreach(DictionaryEntry mp in this.mapconfig.Root)
{
// Item is a structure?
if(mp.Value is IDictionary)
@ -128,6 +133,30 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Methods
// This stores the map options in a configuration
public void WriteConfiguration(string settingsfile)
{
Configuration wadcfg;
// Write settings to config
resources.WriteToConfig(mapconfig, "resources");
// Load the file or make a new file
if(File.Exists(settingsfile))
wadcfg = new Configuration(settingsfile, true);
else
wadcfg = new Configuration(true);
// Write configuration type information
wadcfg.WriteSetting("type", "Doom Builder Map Settings Configuration");
// Update the settings file with this map configuration
wadcfg.WriteSetting("maps." + currentname, mapconfig.Root);
// Save file
wadcfg.SaveConfiguration(settingsfile);
}
// This adds a resource location and returns the index where the item was added
public int AddResource(DataLocation res)
{
@ -179,6 +208,39 @@ namespace CodeImp.DoomBuilder.Map
return currentname;
}
// This returns the UDMF field type
public int GetUniversalFieldType(string elementname, string fieldname, int defaulttype)
{
int type;
// Check if the field type is set in the game configuration
type = General.Map.Config.ReadSetting("universalfields." + elementname + "." + fieldname + ".type", -1);
if(type == -1)
{
// Read from map configuration
type = mapconfig.ReadSetting("fieldtypes." + elementname + "-" + fieldname, defaulttype);
}
return type;
}
// This stores the UDMF field type
public void SetUniversalFieldType(string elementname, string fieldname, int type)
{
// Check if the type of this field is not set in the game configuration
if(General.Map.Config.ReadSetting("universalfields." + elementname + "." + fieldname + ".type", -1) == -1)
{
// Write type to map configuration
mapconfig.WriteSetting("fieldtypes." + elementname + "-" + fieldname, type);
}
}
// This removes all UDMF field types
public void ForgetUniversalFieldTypes()
{
mapconfig.DeleteSetting("fieldtypes");
}
#endregion
}
}

View file

@ -1216,6 +1216,7 @@ namespace CodeImp.DoomBuilder.Map
public void SnapAllToAccuracy()
{
foreach(Vertex v in vertices) v.SnapToAccuracy();
foreach(Thing t in things) t.SnapToAccuracy();
}
// This returns the next unused tag number

View file

@ -87,9 +87,6 @@ namespace CodeImp.DoomBuilder.Map
public float Size { get { return size; } }
public float IconOffset { get { return iconoffset; } }
public PixelColor Color { get { return color; } }
public int X { get { return x; } }
public int Y { get { return y; } }
public int ZOffset { get { return zoffset; } set { zoffset = value; } }
public int Tag { get { return tag; } set { tag = value; if((tag < 0) || (tag > MapSet.HIGHEST_TAG)) throw new ArgumentOutOfRangeException("Tag", "Invalid tag number"); } }
public Sector Sector { get { return sector; } }
@ -149,9 +146,6 @@ namespace CodeImp.DoomBuilder.Map
t.flags = new Dictionary<string,bool>(flags);
t.tag = tag;
t.action = action;
t.x = x;
t.y = y;
t.zoffset = zoffset;
t.args = EMPTY_ARGS;
t.size = size;
t.color = color;
@ -206,24 +200,27 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Changes
// This moves the thing
// NOTE: This does not update sector! (call DetermineSector)
public void Move(Vector3D newpos)
{
// Change position
this.pos = newpos;
}
// This moves the thing
// NOTE: This does not update sector! (call DetermineSector)
public void Move(Vector2D newpos)
{
// Change position
this.x = (int)newpos.x;
this.y = (int)newpos.y;
this.pos = new Vector3D(newpos.x, newpos.y, zoffset);
}
// This moves the thing
// NOTE: This does not update sector! (call DetermineSector)
public void Move(int x, int y, int zoffset)
public void Move(float x, float y, float zoffset)
{
// Change position
this.x = x;
this.y = y;
this.zoffset = zoffset;
this.pos = new Vector3D(x, y, zoffset);
}
@ -236,7 +233,7 @@ namespace CodeImp.DoomBuilder.Map
// This updates all properties
// NOTE: This does not update sector! (call DetermineSector)
public void Update(int type, int x, int y, int zoffset, float angle,
public void Update(int type, float x, float y, float zoffset, float angle,
Dictionary<string, bool> flags, int tag, int action, int[] args)
{
// Apply changes
@ -288,6 +285,16 @@ namespace CodeImp.DoomBuilder.Map
this.Move(General.Map.Grid.SnappedToGrid((Vector2D)pos));
}
// This snaps the vertex to the map format accuracy
public void SnapToAccuracy()
{
// Round the coordinates
Vector3D newpos = new Vector3D((float)Math.Round(pos.x, General.Map.FormatInterface.VertexDecimals),
(float)Math.Round(pos.y, General.Map.FormatInterface.VertexDecimals),
(float)Math.Round(pos.z, General.Map.FormatInterface.VertexDecimals));
this.Move(newpos);
}
// This returns the distance from given coordinates
public float DistanceToSq(Vector2D p)
{

View file

@ -0,0 +1,50 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO;
#endregion
namespace CodeImp.DoomBuilder.Types
{
internal enum UniversalType : int
{
Integer = 0,
Float = 1,
String = 2,
Boolean = 3,
LinedefType = 4,
SectorEffect = 5,
Texture = 6,
Flat = 7,
AngleDegrees = 8,
AngleRadians = 9,
Color = 10,
EnumOption = 11,
EnumBits = 12,
SectorTag = 13,
ThingTag = 14,
LinedefTag = 15,
EnumStrings = 16
}
}

View file

@ -167,11 +167,12 @@ namespace CodeImp.DoomBuilder.Windows
// Returns the flags or the same flags when cancelled
public static int ShowDialog(IWin32Window owner, EnumList flags, int value)
{
int result = value;
BitFlagsForm f = new BitFlagsForm();
f.Setup(flags, value);
if(f.ShowDialog(owner) == DialogResult.OK) return value = f.Value;
if(f.ShowDialog(owner) == DialogResult.OK) result = f.Value;
f.Dispose();
return value;
return result;
}
#endregion

View file

@ -0,0 +1,102 @@
namespace CodeImp.DoomBuilder.Windows
{
partial class CustomFieldsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.fieldslist = new CodeImp.DoomBuilder.Controls.FieldsEditorControl();
this.cancel = new System.Windows.Forms.Button();
this.apply = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// fieldslist
//
this.fieldslist.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.fieldslist.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.fieldslist.Location = new System.Drawing.Point(10, 10);
this.fieldslist.Margin = new System.Windows.Forms.Padding(1);
this.fieldslist.Name = "fieldslist";
this.fieldslist.Size = new System.Drawing.Size(506, 310);
this.fieldslist.TabIndex = 0;
//
// cancel
//
this.cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancel.Location = new System.Drawing.Point(404, 336);
this.cancel.Margin = new System.Windows.Forms.Padding(1);
this.cancel.Name = "cancel";
this.cancel.Size = new System.Drawing.Size(112, 25);
this.cancel.TabIndex = 19;
this.cancel.Text = "Cancel";
this.cancel.UseVisualStyleBackColor = true;
this.cancel.Click += new System.EventHandler(this.cancel_Click);
//
// apply
//
this.apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.apply.Location = new System.Drawing.Point(285, 336);
this.apply.Margin = new System.Windows.Forms.Padding(1);
this.apply.Name = "apply";
this.apply.Size = new System.Drawing.Size(112, 25);
this.apply.TabIndex = 18;
this.apply.Text = "OK";
this.apply.UseVisualStyleBackColor = true;
this.apply.Click += new System.EventHandler(this.apply_Click);
//
// CustomFieldsForm
//
this.AcceptButton = this.apply;
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.CancelButton = this.cancel;
this.ClientSize = new System.Drawing.Size(526, 371);
this.Controls.Add(this.cancel);
this.Controls.Add(this.apply);
this.Controls.Add(this.fieldslist);
this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CustomFieldsForm";
this.Opacity = 0;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CustomFieldsForm";
this.ResumeLayout(false);
}
#endregion
private CodeImp.DoomBuilder.Controls.FieldsEditorControl fieldslist;
private System.Windows.Forms.Button cancel;
private System.Windows.Forms.Button apply;
}
}

View file

@ -0,0 +1,102 @@
#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.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Diagnostics;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Config;
using System.IO;
using CodeImp.DoomBuilder.Controls;
using CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.Windows
{
public partial class CustomFieldsForm : DelayedForm
{
// Keep a list of elements
private ICollection<MapElement> elements;
// Constructor
public CustomFieldsForm()
{
// Initialize
InitializeComponent();
}
// This shows the dialog, returns false when cancelled
public static bool ShowDialog(IWin32Window owner, string title, ICollection<MapElement> elements, List<UniversalFieldInfo> fixedfields)
{
bool result;
CustomFieldsForm f = new CustomFieldsForm();
f.Setup(title, elements, fixedfields);
result = (f.ShowDialog(owner) == DialogResult.OK);
f.Dispose();
return result;
}
// This sets up the dialog
public void Setup(string title, ICollection<MapElement> elements, List<UniversalFieldInfo> fixedfields)
{
// Keep list
this.elements = elements;
// Fill universal fields list
fieldslist.ListFixedFields(fixedfields);
// Initialize custom fields editor
fieldslist.Setup();
// Setup from first element
MapElement fe = General.GetByIndex<MapElement>(elements, 0);
fieldslist.SetValues(fe.Fields, true);
// Setup from all elements
foreach(MapElement e in elements)
fieldslist.SetValues(e.Fields, false);
}
// OK clicked
private void apply_Click(object sender, EventArgs e)
{
// Apply fields to all elements
foreach(MapElement el in elements) fieldslist.Apply(el.Fields);
// Done
General.Map.IsChanged = true;
this.DialogResult = DialogResult.OK;
this.Close();
}
// Cancel clicked
private void cancel_Click(object sender, EventArgs e)
{
// Be gone
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}
}

View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="fieldslist.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="cancel.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="apply.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View file

@ -73,6 +73,7 @@ namespace CodeImp.DoomBuilder.Windows
this.splitter = new System.Windows.Forms.SplitContainer();
this.frontside = new System.Windows.Forms.CheckBox();
this.frontgroup = new System.Windows.Forms.GroupBox();
this.customfrontbutton = new System.Windows.Forms.Button();
this.frontsector = new CodeImp.DoomBuilder.Controls.NumericTextbox();
this.frontlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
this.frontmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
@ -81,6 +82,7 @@ namespace CodeImp.DoomBuilder.Windows
this.frontoffsetx = new CodeImp.DoomBuilder.Controls.NumericTextbox();
this.backside = new System.Windows.Forms.CheckBox();
this.backgroup = new System.Windows.Forms.GroupBox();
this.custombackbutton = new System.Windows.Forms.Button();
this.backsector = new CodeImp.DoomBuilder.Controls.NumericTextbox();
this.backlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
this.backmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
@ -269,9 +271,9 @@ namespace CodeImp.DoomBuilder.Windows
this.actiongroup.Controls.Add(this.browseaction);
this.actiongroup.Controls.Add(this.udmfpanel);
this.actiongroup.Controls.Add(this.argspanel);
this.actiongroup.Location = new System.Drawing.Point(8, 166);
this.actiongroup.Location = new System.Drawing.Point(8, 177);
this.actiongroup.Name = "actiongroup";
this.actiongroup.Size = new System.Drawing.Size(517, 253);
this.actiongroup.Size = new System.Drawing.Size(517, 242);
this.actiongroup.TabIndex = 18;
this.actiongroup.TabStop = false;
this.actiongroup.Text = " Action ";
@ -326,7 +328,7 @@ namespace CodeImp.DoomBuilder.Windows
this.udmfpanel.Controls.Add(this.udmfactivates);
this.udmfpanel.Location = new System.Drawing.Point(6, 143);
this.udmfpanel.Name = "udmfpanel";
this.udmfpanel.Size = new System.Drawing.Size(505, 104);
this.udmfpanel.Size = new System.Drawing.Size(505, 92);
this.udmfpanel.TabIndex = 12;
this.udmfpanel.Visible = false;
//
@ -339,7 +341,7 @@ namespace CodeImp.DoomBuilder.Windows
this.udmfactivates.Columns = 2;
this.udmfactivates.Location = new System.Drawing.Point(56, 5);
this.udmfactivates.Name = "udmfactivates";
this.udmfactivates.Size = new System.Drawing.Size(401, 95);
this.udmfactivates.Size = new System.Drawing.Size(401, 83);
this.udmfactivates.TabIndex = 1;
//
// argspanel
@ -477,7 +479,7 @@ namespace CodeImp.DoomBuilder.Windows
this.settingsgroup.Controls.Add(this.flags);
this.settingsgroup.Location = new System.Drawing.Point(8, 8);
this.settingsgroup.Name = "settingsgroup";
this.settingsgroup.Size = new System.Drawing.Size(517, 152);
this.settingsgroup.Size = new System.Drawing.Size(517, 163);
this.settingsgroup.TabIndex = 19;
this.settingsgroup.TabStop = false;
this.settingsgroup.Text = " Settings ";
@ -491,7 +493,7 @@ namespace CodeImp.DoomBuilder.Windows
this.flags.Columns = 3;
this.flags.Location = new System.Drawing.Point(18, 26);
this.flags.Name = "flags";
this.flags.Size = new System.Drawing.Size(493, 119);
this.flags.Size = new System.Drawing.Size(493, 125);
this.flags.TabIndex = 0;
//
// checkBox1
@ -596,6 +598,7 @@ namespace CodeImp.DoomBuilder.Windows
this.frontgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.frontgroup.Controls.Add(this.customfrontbutton);
this.frontgroup.Controls.Add(this.frontsector);
this.frontgroup.Controls.Add(label11);
this.frontgroup.Controls.Add(this.frontlow);
@ -615,6 +618,17 @@ namespace CodeImp.DoomBuilder.Windows
this.frontgroup.TabStop = false;
this.frontgroup.Text = " ";
//
// customfrontbutton
//
this.customfrontbutton.Location = new System.Drawing.Point(82, 124);
this.customfrontbutton.Name = "customfrontbutton";
this.customfrontbutton.Size = new System.Drawing.Size(115, 25);
this.customfrontbutton.TabIndex = 15;
this.customfrontbutton.Text = "Custom fields...";
this.customfrontbutton.UseVisualStyleBackColor = true;
this.customfrontbutton.Visible = false;
this.customfrontbutton.Click += new System.EventHandler(this.customfrontbutton_Click);
//
// frontsector
//
this.frontsector.AllowNegative = false;
@ -691,6 +705,7 @@ namespace CodeImp.DoomBuilder.Windows
this.backgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.backgroup.Controls.Add(this.custombackbutton);
this.backgroup.Controls.Add(this.backsector);
this.backgroup.Controls.Add(label12);
this.backgroup.Controls.Add(this.backlow);
@ -710,6 +725,17 @@ namespace CodeImp.DoomBuilder.Windows
this.backgroup.TabStop = false;
this.backgroup.Text = " ";
//
// custombackbutton
//
this.custombackbutton.Location = new System.Drawing.Point(82, 124);
this.custombackbutton.Name = "custombackbutton";
this.custombackbutton.Size = new System.Drawing.Size(115, 25);
this.custombackbutton.TabIndex = 18;
this.custombackbutton.Text = "Custom fields...";
this.custombackbutton.UseVisualStyleBackColor = true;
this.custombackbutton.Visible = false;
this.custombackbutton.Click += new System.EventHandler(this.custombackbutton_Click);
//
// backsector
//
this.backsector.AllowNegative = false;
@ -889,5 +915,7 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.Label arg2label;
private System.Windows.Forms.Label arg4label;
private System.Windows.Forms.SplitContainer splitter;
private System.Windows.Forms.Button customfrontbutton;
private System.Windows.Forms.Button custombackbutton;
}
}

View file

@ -127,7 +127,7 @@ namespace CodeImp.DoomBuilder.Windows
// Flags
foreach(CheckBox c in flags.Checkboxes)
c.Checked = fl.Flags[c.Tag.ToString()];
if(fl.Flags.ContainsKey(c.Tag.ToString())) c.Checked = fl.Flags[c.Tag.ToString()];
// Activations
foreach(LinedefActivateInfo ai in activation.Items)
@ -137,7 +137,7 @@ namespace CodeImp.DoomBuilder.Windows
foreach(CheckBox c in udmfactivates.Checkboxes)
{
LinedefActivateInfo ai = (c.Tag as LinedefActivateInfo);
c.Checked = fl.Flags[ai.Key];
if(fl.Flags.ContainsKey(ai.Key)) c.Checked = fl.Flags[ai.Key];
}
// Action/tags
@ -188,10 +188,13 @@ namespace CodeImp.DoomBuilder.Windows
// Flags
foreach(CheckBox c in flags.Checkboxes)
{
if(l.Flags[c.Tag.ToString()] != c.Checked)
if(l.Flags.ContainsKey(c.Tag.ToString()))
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
if(l.Flags[c.Tag.ToString()] != c.Checked)
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
}
}
}
@ -208,10 +211,13 @@ namespace CodeImp.DoomBuilder.Windows
foreach(CheckBox c in udmfactivates.Checkboxes)
{
LinedefActivateInfo ai = (c.Tag as LinedefActivateInfo);
if(c.Checked != fl.Flags[ai.Key])
if(l.Flags.ContainsKey(ai.Key))
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
if(c.Checked != l.Flags[ai.Key])
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
}
}
}
@ -249,6 +255,7 @@ namespace CodeImp.DoomBuilder.Windows
if(frontsector.Text != l.Front.Sector.Index.ToString()) frontsector.Text = "";
if(frontoffsetx.Text != l.Front.OffsetX.ToString()) frontoffsetx.Text = "";
if(frontoffsety.Text != l.Front.OffsetY.ToString()) frontoffsety.Text = "";
if(General.Map.IsType(typeof(UniversalMapSetIO))) customfrontbutton.Visible = true;
}
// Back settings
@ -260,6 +267,7 @@ namespace CodeImp.DoomBuilder.Windows
if(backsector.Text != l.Back.Sector.Index.ToString()) backsector.Text = "";
if(backoffsetx.Text != l.Back.OffsetX.ToString()) backoffsetx.Text = "";
if(backoffsety.Text != l.Back.OffsetY.ToString()) backoffsety.Text = "";
if(General.Map.IsType(typeof(UniversalMapSetIO))) custombackbutton.Visible = true;
}
// Custom fields
@ -445,5 +453,27 @@ namespace CodeImp.DoomBuilder.Windows
{
action.Value = ActionBrowserForm.BrowseAction(this, action.Value);
}
// Custom fields on front sides
private void customfrontbutton_Click(object sender, EventArgs e)
{
// Make collection of front sides
List<MapElement> sides = new List<MapElement>(lines.Count);
foreach(Linedef l in lines) if(l.Front != null) sides.Add(l.Front);
// Edit these
CustomFieldsForm.ShowDialog(this, "Front side custom fields", sides, General.Map.Config.SidedefFields);
}
// Custom fields on back sides
private void custombackbutton_Click(object sender, EventArgs e)
{
// Make collection of back sides
List<MapElement> sides = new List<MapElement>(lines.Count);
foreach(Linedef l in lines) if(l.Back != null) sides.Add(l.Back);
// Edit these
CustomFieldsForm.ShowDialog(this, "Back side custom fields", sides, General.Map.Config.SidedefFields);
}
}
}

View file

@ -291,6 +291,9 @@
<metadata name="frontgroup.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="customfrontbutton.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="frontsector.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@ -315,6 +318,9 @@
<metadata name="backgroup.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="custombackbutton.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="backsector.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View file

@ -87,6 +87,9 @@ namespace CodeImp.DoomBuilder.Windows
// Action
tag.Text = sc.Tag.ToString();
// Custom fields
fieldslist.SetValues(sc.Fields, true);
////////////////////////////////////////////////////////////////////////
// Now go for all sectors and change the options when a setting is different
@ -107,6 +110,9 @@ namespace CodeImp.DoomBuilder.Windows
// Action
if(s.Tag.ToString() != tag.Text) tag.Text = "";
// Custom fields
fieldslist.SetValues(s.Fields, false);
}
}
@ -134,6 +140,9 @@ namespace CodeImp.DoomBuilder.Windows
// Action
s.Tag = tag.GetResult(s.Tag);
// Custom fields
fieldslist.Apply(s.Fields);
}
// Done

View file

@ -64,6 +64,9 @@ namespace CodeImp.DoomBuilder.Windows
action.GeneralizedCategories = General.Map.Config.GenActionCategories;
action.AddInfo(General.Map.Config.SortedLinedefActions.ToArray());
// Fill universal fields list
fieldslist.ListFixedFields(General.Map.Config.ThingFields);
// Initialize custom fields editor
fieldslist.Setup();
@ -123,14 +126,14 @@ namespace CodeImp.DoomBuilder.Windows
// Flags
foreach(CheckBox c in flags.Checkboxes)
c.Checked = ft.Flags[c.Tag.ToString()];
if(ft.Flags.ContainsKey(c.Tag.ToString())) c.Checked = ft.Flags[c.Tag.ToString()];
// Coordination
angledeg = ft.AngleDeg - 90;
if(angledeg < 0) angledeg += 360;
if(angledeg >= 360) angledeg -= 360;
angle.Text = angledeg.ToString();
height.Text = ft.ZOffset.ToString();
height.Text = ((int)ft.Position.z).ToString();
// Action/tags
action.Value = ft.Action;
@ -141,6 +144,9 @@ namespace CodeImp.DoomBuilder.Windows
arg3.SetValue(ft.Args[3]);
arg4.SetValue(ft.Args[4]);
// Custom fields
fieldslist.SetValues(ft.Fields, true);
////////////////////////////////////////////////////////////////////////
// Now go for all lines and change the options when a setting is different
////////////////////////////////////////////////////////////////////////
@ -159,10 +165,13 @@ namespace CodeImp.DoomBuilder.Windows
// Flags
foreach(CheckBox c in flags.Checkboxes)
{
if(t.Flags[c.Tag.ToString()] != c.Checked)
if(t.Flags.ContainsKey(c.Tag.ToString()))
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
if(t.Flags[c.Tag.ToString()] != c.Checked)
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
}
}
}
@ -171,7 +180,7 @@ namespace CodeImp.DoomBuilder.Windows
if(angledeg < 0) angledeg += 360;
if(angledeg >= 360) angledeg -= 360;
if(angledeg.ToString() != angle.Text) angle.Text = "";
if(t.ZOffset.ToString() != height.Text) height.Text = "";
if(((int)t.Position.z).ToString() != height.Text) height.Text = "";
// Action/tags
if(t.Action != action.Value) action.Empty = true;
@ -181,6 +190,9 @@ namespace CodeImp.DoomBuilder.Windows
if(t.Args[2] != arg2.GetResult(-1)) arg2.ClearValue();
if(t.Args[3] != arg3.GetResult(-1)) arg3.ClearValue();
if(t.Args[4] != arg4.GetResult(-1)) arg4.ClearValue();
// Custom fields
fieldslist.SetValues(t.Fields, false);
}
}
@ -323,7 +335,7 @@ namespace CodeImp.DoomBuilder.Windows
// Coordination
t.Rotate(Angle2D.DegToRad((float)(angle.GetResult(t.AngleDeg - 90) + 90)));
t.ZOffset = height.GetResult(t.ZOffset);
t.Move(t.Position.x, t.Position.y, (float)height.GetResult((int)t.Position.z));
// Apply all flags
foreach(CheckBox c in flags.Checkboxes)
@ -341,6 +353,9 @@ namespace CodeImp.DoomBuilder.Windows
t.Args[3] = arg3.GetResult(t.Args[3]);
t.Args[4] = arg4.GetResult(t.Args[4]);
// Custom fields
fieldslist.Apply(t.Fields);
// Update settings
t.UpdateConfiguration();
}