Added, Sector Edit window, UDMF: added UI for sector damage-realted properties.

Added, DECORATE parser: damage types are now parsed.
Added: the editor now reports duplicate textures/flats/patches/sprites/colormaps/voxels in the loaded wads.
Added, all text parsers: added #region/#endregion support.
Added TERRAIN parser.
Added, Script Editor: added special handling for DECORATE special comments.
Added, Sector Edit window, UDMF: Soundsequence value was setup incorrectly when showing the window for multiple sectors with mixed Soundsequence value. 
Fixed, Map Options window: "Strictly load patches between P_START and P_END" was not applied when applying the changes.
Fixed, MAPINFO parser: MapInfo should be treated as defined when a map MAPINFO block corresponding to current map is encountered even if it doesn't define any properties recognized by the editor.
Fixed, all text parsers: in some cases error line was calculated incorrectly when reporting an error detected by a text parser.
Cosmetic: changed ' to " in the rest of Error and Warning messages.
Internal: added text resource tracking.
Updated ZDoom_DECORATE.cfg.
Updated documentation ("Game Configuration - Basic Settings" page).
This commit is contained in:
MaxED 2016-02-22 12:33:19 +00:00
parent 324a7461c7
commit 0f7aa9f827
46 changed files with 2285 additions and 1036 deletions

View file

@ -80,6 +80,8 @@ sectorflags
waterzone = "Sector is under water and swimmable";
norespawn = "Players can't respawn in this sector";
dropactors = "Actors drop with instantly moving floors";
damageterraineffect = "Spawn terrain splashes on damage";
damagehazard = "Strife damage model";
}
linedefflags

View file

@ -76,6 +76,9 @@ common
{
include("ZDoom_generalized.cfg", "gen_sectortypes");
}
//mxd. Built-in Damage types
damagetypes = "BFGSplash Drowning Slime Fire Crush Telefrag Falling Suicide Exit Melee Railgun Ice Disintegrate Poison PoisonCloud Electric Massacre DrainLife Extreme InstantDeath";
}
// ***********************************************************

View file

@ -17,13 +17,55 @@ arrayopen = "[";
arrayclose = "]";
argumentdelimiter = ",";
terminator = ";";
extrawordchars = "#."; // Extra characters to be treated as a part of a word by the Script Editor
extrawordchars = "#.$"; // Extra characters to be treated as a part of a word by the Script Editor
keywordhelp = "http://www.zdoom.org/wiki/index.php?title=%K";
scripttype = 3; //0 = unknown script, 1 = acc, 2 = modeldef, 3 = decorate
keywords
{
//Editor special comments
//These are handled in a different fascion: key is replaced with the value and the caret is placed at [EP] position
$Angled = "$Angled";
$NotAngled = "$NotAngled";
$Category = "//$Category \"[EP]\"";
$Sprite = "//$Sprite \"[EP]\"";
$Title = "//$Title \"[EP]\"";
$Arg0 = "//$Arg0 \"[EP]\"";
$Arg1 = "//$Arg1 \"[EP]\"";
$Arg2 = "//$Arg2 \"[EP]\"";
$Arg3 = "//$Arg3 \"[EP]\"";
$Arg4 = "//$Arg4 \"[EP]\"";
$Arg0Default = "//$Arg0Default ";
$Arg1Default = "//$Arg1Default ";
$Arg2Default = "//$Arg2Default ";
$Arg3Default = "//$Arg3Default ";
$Arg4Default = "//$Arg4Default ";
$Arg0Tooltip = "//$Arg0Tooltip \"[EP]\"";
$Arg1Tooltip = "//$Arg1Tooltip \"[EP]\"";
$Arg2Tooltip = "//$Arg2Tooltip \"[EP]\"";
$Arg3Tooltip = "//$Arg3Tooltip \"[EP]\"";
$Arg4Tooltip = "//$Arg4Tooltip \"[EP]\"";
$Arg0Type = "//$Arg0Type ";
$Arg1Type = "//$Arg1Type ";
$Arg2Type = "//$Arg2Type ";
$Arg3Type = "//$Arg3Type ";
$Arg4Type = "//$Arg4Type ";
$Arg0Enum = "//$Arg0Enum ";
$Arg1Enum = "//$Arg1Enum ";
$Arg2Enum = "//$Arg2Enum ";
$Arg3Enum = "//$Arg3Enum ";
$Arg4Enum = "//$Arg4Enum ";
$Color = "//$Color ";
$Obsolete = "//$Obsolete \"[EP]\"";
$GZDB_SKIP = "//$GZDB_SKIP";
//Preprocessor directives
#Include = "#Include";
#region = "#region";
#endregion = "#endregion";
//WFDS
A_Bool = "return A_Bool(bool result);";
A_Int = "return A_Int(int result);";
A_State = "return A_State(int offset OR str state);";
//Monster AI
A_AlertMonsters = "A_AlertMonsters[(float maxrange = 0.0[, int flags = 0])]";
A_Burst = "A_Burst(str chunktype)";
@ -339,25 +381,30 @@ keywords
A_ShootGun = "A_ShootGun";
A_SPosAttackUseAtkSound = "A_SPosAttackUseAtkSound";
//Mathematical functions
abs = "abs(x)\nReturns the absolute value of x.";
sin = "sin(x)\nTrigonometry function, x must be in degrees.";
cos = "cos(x)\nTrigonometry function, x must be in degrees.";
sqrt = "sqrt(x)\nReturns the square root of x.";
random = "random[identifier](min, max)\nReturns a random integer value between min and max.";
random2 = "random2[identifier](mask)\nReturns a random integer value between -mask and +mask.";
frandom = "frandom[identifier](min, max)\nReturns a random floating point value between min and max.";
randompick = "randompick[identifier](int, ...)\nPicks a number from the numbers placed in it.\nThis can take an unlimited amount of parameters.";
frandompick = "frandompick[identifier](int, ...)\nSimilar to randompick but for float-point values.";
abs = "float abs(x)\nReturns the absolute value of x.";
sin = "float sin(x)\nTrigonometry function, x must be in degrees.";
cos = "float cos(x)\nTrigonometry function, x must be in degrees.";
sqrt = "float sqrt(x)\nReturns the square root of x.";
random = "int random[identifier](min, max)\nReturns a random integer value between min and max.";
random2 = "int random2[identifier](mask)\nReturns a random integer value between -mask and +mask.";
frandom = "float frandom[identifier](min, max)\nReturns a random floating point value between min and max.";
randompick = "int randompick[identifier](int, ...)\nPicks a number from the numbers placed in it.\nThis can take an unlimited amount of parameters.";
frandompick = "float frandompick[identifier](int, ...)\nSimilar to randompick but for float-point values.";
//State functions
Light = "Light(str lightname)";
Offset = "Offset(int x, int y)";
//Special functions
CheckClass = "bool CheckClass(str classname[, int ptr_select = AAPTR_DEFAULT[, bool match_superclass = false]])";
IsPointerEqual = "bool IsPointerEqual(int ptr_select1, int ptr_select2)";
IsPointerEqual = "bool IsPointerEqual(int ptr1, int ptr2)";
CountInv = "int CountInv(str itemclassname[, int ptr_select = AAPTR_DEFAULT])";
GetDistance = "float GetDistance(bool checkz[, int ptr_select = AAPTR_TARGET])";
}
properties
{
action;
native;
replaces;
Actor;
enum;
const;

View file

@ -1,46 +1,40 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Game Configuration - Basic Settings</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<link rel="stylesheet" type="text/css" href="default.css" media="screen" title="Default" />
<title>Game Configuration - Basic Settings</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<link rel="stylesheet" type="text/css" href="default.css" media="screen" title="Default" />
</head>
<body>
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
<param name="keyword" value="Configurations">
<param name="keyword" value="Game Configurations">
</object>
<div id="title"><h1>Game Configuration - Basic Settings</h1></div>
<div id="contents">
<p>
<b class="fat">type</b> (string)<br />
</object>
<div id="title">
<h1>Game Configuration - Basic Settings</h1>
</div>
<div id="contents">
<p> <b class="fat">type</b> (string)<br />
This indicates the type of configuration to prevent accedential use of a different configuration. Must always be the string "Doom Builder 2 Game Configuration".<br />
<br />
<b class="fat">game</b> (string)<br />
<b class="fat">game</b> (string)<br />
The name that is displayed in Doom Buider for your Game Configuration.<br />
Default value is <b>"&lt;unnamed game&gt;"</b>.<br />
Default value is <b>"&lt;unnamed game&gt;"</b>.<br />
<br />
<b class="fat">enabledbydefault</b> (boolean) - <span class="red">GZDB only</span>.<br />
This game configuration is available by default. You can enable and disable game configurations using <a href="w_gameconfigurations.html">Game Configurations window</a>.<br />
Default value is <b>false</b>.<br />
Default value is <b>false</b>.<br />
<br />
<b class="fat">actionspecialhelp</b> (string) - <span class="red">GZDB only</span>.<br />
<b class="fat">actionspecialhelp</b> (string) - <span class="red">GZDB only</span>.<br />
The URL used to display action special help. &quot;<strong>%K</strong>&quot; wildcard is replaced by <strong>id</strong> property defined in <a href="gc_linedefsettings.html#actionid">action definition</a>.<br />
<br />
<b class="fat">thingclasshelp</b> (string) - <span class="red">GZDB only</span>.<br />
The URL to open when thing class name is clicked in the Thing Edit form. &quot;<strong>%K</strong>&quot; wildcard is replaced by <strong>classname</strong> property defined in thing definition or by DECORATE actor name.<br />
<b class="fat">thingclasshelp</b> (string) - <span class="red">GZDB only</span>.<br />
The URL to open when thing class name is clicked in the Thing Edit form. &quot;<strong>%K</strong>&quot; wildcard is replaced by <strong>classname</strong> property defined in thing definition or by DECORATE actor name.<br />
<br />
<b class="fat">basegame</b> (integer) [0 .. 4] - <span class="red">GZDB only</span>.<br />
Indicates which game the current configuration is based on. Used to load game-specific GLDEFS lumps (DOOMDEFS, HTICDEFS, HEXNDEFS or STRFDEFS).
<br /><b>Possible values:</b> 1 (DOOM), 2 (HERETIC), 3 (HEXEN) or 4 (STRIFE).<br />
Default value is <b>0</b> (don't load game-specific lumps).<br />
<b class="fat">basegame</b> (integer) [0 .. 4] - <span class="red">GZDB only</span>.<br />
Indicates which game the current configuration is based on. Used to load game-specific GLDEFS lumps (DOOMDEFS, HTICDEFS, HEXNDEFS or STRFDEFS). <br />
<b>Possible values:</b> 1 (DOOM), 2 (HERETIC), 3 (HEXEN) or 4 (STRIFE).<br />
Default value is <b>0</b> (don't load game-specific lumps).<br />
<br />
<b class="fat">engine</b> (string)<br />
Game engine/sourceport name. This is used as the UDMF namespace for UDMF map format interface. It currently has no other function.<br />
@ -56,19 +50,19 @@
Default value is <b>false</b>.<br />
<br />
<b class="fat">defaultsavecompiler</b> (string)<br />
Name of the <a href="scriptingconfigs.html">Nodebuilder Compiler Configuration structure</a> to use as the default settings for the compiler that is used when saving the map. The user can still change this in the <a href="w_gameconfigurations.html">Game Configurations window</a>.<br />
Name of the <a href="scriptingconfigs.html">Nodebuilder Compiler Configuration structure</a> to use as the default settings for the compiler that is used when saving the map. The user can still change this in the <a href="w_gameconfigurations.html">Game Configurations window</a>.<br />
<br />
<b class="fat">defaulttestcompiler</b> (string)<br />
Name of the <a href="scriptingconfigs.html">Nodebuilder Compiler Configuration structure</a> to use as the default settings for the compiler that is used when testing the map. The user can still change this in the <a href="w_gameconfigurations.html">Game Configurations window</a>.<br />
Name of the <a href="scriptingconfigs.html">Nodebuilder Compiler Configuration structure</a> to use as the default settings for the compiler that is used when testing the map. The user can still change this in the <a href="w_gameconfigurations.html">Game Configurations window</a>.<br />
<br />
<b class="fat">defaultscriptcompiler</b> (string) - <span class="red">GZDB only</span>.<br />
Name of the <a href="scriptingconfigs.html">Script Compiler Configuration file</a> to use as the default settings for the script compiler that is used when compiling map scripts. The user can still change this in the <a href="w_mapoptions.html">Map Options window</a>.<br />
<b class="fat">defaultscriptcompiler</b> (string) - <span class="red">GZDB only</span>.<br />
Name of the <a href="scriptingconfigs.html">Script Compiler Configuration file</a> to use as the default settings for the script compiler that is used when compiling map scripts. The user can still change this in the <a href="w_mapoptions.html">Map Options window</a>.<br />
<br />
<b class="fat">skills</b> (structure)<br />
This defines the skill options the user has available with this game engine/project. The settings in this structure are expected to be numbers with string values (the descriptive name for the skill level).<br />
<br />
<strong>Example:</strong>
<pre>
<pre>
skills
{
1 = "I'm too young to die";
@ -78,66 +72,74 @@ skills
5 = "Nightmare!";
}
</pre>
<br />
<b class="fat">linetagindicatesectors</b> (boolean)<br />
When <b>true</b>, Doom Builder will highlight sectors associated with the same tag number when a line is highlighted. This is only really useful for Doom format maps, because Hexen format and UDMF format has no single tag on linedefs (in those formats, the arguments of the linedef's action can be tags, which also works to highlight sectors).<br />
Default value is <b>false</b>.<br />
<br />
<b class="fat">singlesidedflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line with only one side. Doom Builder will set this flag value on a linedef when it changes a line to become single sided and removes the flag from a linedef when it becomes double sided. Plugins can also use this information to perform operations on linedefs. For map formats that use numeric flags (Doom and Hexen) this must be an integer flag value. For map formats that use named flags (UDMF), this must be a string indicating the name of the flag.<br />
<br />
<b class="fat">doublesidedflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line with two sides. Doom Builder will set this flag value on a linedef when it changes a line to become double sided and removes the flag from a linedef when it becomes single sided. Plugins can also use this information to perform operations on linedefs. For map formats that use numeric flags (Doom and Hexen) this must be an integer flag value. For map formats that use named flags (UDMF), this must be a string indicating the name of the flag.<br />
<br />
<b class="fat">impassableflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line which blocks players and monsters. Doom Builder uses this to give the line a special color and plugins can use this information to perform operations related to blocking sound lines. For map formats that use numeric flags (Doom and Hexen) this must be an integer specifying the flag value of the Impassable flag. For map formats that use named flags (UDMF), this must be a string indicating the name of the Impassable flag.<br />
<br />
<b class="fat">defaultwalltexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use on sidedefs when creating a new sector.<br />
<b>"STARTAN"</b>.<br />
<br />
<b class="fat">defaultfloortexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a flat to use on the floor when creating a new sector.<br />
Default value is <b>"FLOOR0_1"</b>.<br />
<br />
<b class="fat">defaultceilingtexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a flat to use on the ceiling when creating a new sector.<br />
Default value is <b>"CEIL1_1"</b>.<br />
<br />
<b class="fat">makedoortrack</b> (string)<br />
Name of a texture to use on the walls when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedoordoor</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use as the door texture when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedoorceil</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use as the door's ceiling texture when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedooraction</b> (integer)<br />
Linedef action number to put on the lines when making a door.<br />
<br />
<b class="fat">makedoorarg#</b> (0 .. 4) (integer)<br />
Arguments for the linedef action number to put on the lines when making a door.<br />
<br />
<b class="fat">doomlightlevels</b> (boolean)<br />
Set this to <b>false</b> to use linear lighting in Doom Builder. Normally Doom Builder uses a simulation of Doom's light levels.
<br />Default value is <b>true</b>.<br />
<br />
<b class="fat">start3dmode</b> (integer)<br />
Thing type number that Doom Builder will use to keep your Visual Mode camera position stored in the map. Doom Builder will place a single thing of this type in your map and move it along as you move in Visual Mode.<br />
<br />
<b class="fat">skyflatname</b> (string)<br />
Name of the flat that is interpreted as sky (meaning there is no ceiling). Doom Builder and plugins can use this information for various purposes.
<br />Default value is <b>"F_SKY1"</b>.<br />
<br />
<b class="fat">defaultskytextures</b> (structure) - <span class="red">GZDB only</span>.<br />
Defines the relationship between map names and sky texture names used by vanilla maps.<br />
<br />
<strong>Example:</strong>
<pre>
<br />
<b class="fat">damagetypes</b> (string) - <span class="red">GZDB only</span>.<br />
Space-separated list of built-in damage types. This list is combined with DamageTypes parsed from DECORATE.<br />
<br />
<strong>Example:</strong>
<pre>
damagetypes = "None BFGSplash Drowning Slime";
</pre>
<br />
<b class="fat">linetagindicatesectors</b> (boolean)<br />
When <b>true</b>, Doom Builder will highlight sectors associated with the same tag number when a line is highlighted. This is only really useful for Doom format maps, because Hexen format and UDMF format has no single tag on linedefs (in those formats, the arguments of the linedef's action can be tags, which also works to highlight sectors).<br />
Default value is <b>false</b>.<br />
<br />
<b class="fat">singlesidedflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line with only one side. Doom Builder will set this flag value on a linedef when it changes a line to become single sided and removes the flag from a linedef when it becomes double sided. Plugins can also use this information to perform operations on linedefs. For map formats that use numeric flags (Doom and Hexen) this must be an integer flag value. For map formats that use named flags (UDMF), this must be a string indicating the name of the flag.<br />
<br />
<b class="fat">doublesidedflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line with two sides. Doom Builder will set this flag value on a linedef when it changes a line to become double sided and removes the flag from a linedef when it becomes single sided. Plugins can also use this information to perform operations on linedefs. For map formats that use numeric flags (Doom and Hexen) this must be an integer flag value. For map formats that use named flags (UDMF), this must be a string indicating the name of the flag.<br />
<br />
<b class="fat">impassableflag</b> (integer or string)<br />
This lets Doom Builder know the <a href="gc_linedefflags.html">linedef flag</a> that indicates a line which blocks players and monsters. Doom Builder uses this to give the line a special color and plugins can use this information to perform operations related to blocking sound lines. For map formats that use numeric flags (Doom and Hexen) this must be an integer specifying the flag value of the Impassable flag. For map formats that use named flags (UDMF), this must be a string indicating the name of the Impassable flag.<br />
<br />
<b class="fat">defaultwalltexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use on sidedefs when creating a new sector.<br />
Default value is <b>"STARTAN"</b>.<br />
<br />
<b class="fat">defaultfloortexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a flat to use on the floor when creating a new sector.<br />
Default value is <b>"FLOOR0_1"</b>.<br />
<br />
<b class="fat">defaultceilingtexture</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a flat to use on the ceiling when creating a new sector.<br />
Default value is <b>"CEIL1_1"</b>.<br />
<br />
<b class="fat">makedoortrack</b> (string)<br />
Name of a texture to use on the walls when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedoordoor</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use as the door texture when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedoorceil</b> (string) - <span class="red">GZDB only</span>.<br />
Name of a texture to use as the door's ceiling texture when making a door.<br />
Default value is <b>"-"</b> (no texture).<br />
<br />
<b class="fat">makedooraction</b> (integer)<br />
Linedef action number to put on the lines when making a door.<br />
<br />
<b class="fat">makedoorarg#</b> (0 .. 4) (integer)<br />
Arguments for the linedef action number to put on the lines when making a door.<br />
<br />
<b class="fat">doomlightlevels</b> (boolean)<br />
Set this to <b>false</b> to use linear lighting in Doom Builder. Normally Doom Builder uses a simulation of Doom's light levels. <br />
Default value is <b>true</b>.<br />
<br />
<b class="fat">start3dmode</b> (integer)<br />
Thing type number that Doom Builder will use to keep your Visual Mode camera position stored in the map. Doom Builder will place a single thing of this type in your map and move it along as you move in Visual Mode.<br />
<br />
<b class="fat">skyflatname</b> (string)<br />
Name of the flat that is interpreted as sky (meaning there is no ceiling). Doom Builder and plugins can use this information for various purposes. <br />
Default value is <b>"F_SKY1"</b>.<br />
<br />
<b class="fat">defaultskytextures</b> (structure) - <span class="red">GZDB only</span>.<br />
Defines the relationship between map names and sky texture names used by vanilla maps.<br />
<br />
<strong>Example:</strong>
<pre>
defaultskytextures
{
SKY1 = "MAP01,MAP02,MAP03,MAP04,MAP05";
@ -145,10 +147,11 @@ defaultskytextures
SKY3 = "MAP21,MAP22,MAP23,MAP24,MAP25";
}
</pre>
<br />
<b class="fat">longtexturenames</b> (boolean) - <span class="red">GZDB only</span>.<br />
Enables support for long (> 8 chars) texture names. This is used by GZDoom Builder to limit the input fields in the user interface and to check the validity of texture names in resources. This setting should only be enabled for UDMF game configurations. Enabling this setting will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3 This does NOT determine the actual limitation on the texture names in the map file format.<br />Default value is <b>false</b>.<br />
<br />
<br />
<b class="fat">longtexturenames</b> (boolean) - <span class="red">GZDB only</span>.<br />
Enables support for long (> 8 chars) texture names. This is used by GZDoom Builder to limit the input fields in the user interface and to check the validity of texture names in resources. This setting should only be enabled for UDMF game configurations. Enabling this setting will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3 This does NOT determine the actual limitation on the texture names in the map file format.<br />
Default value is <b>false</b>.<br />
<br />
</p>
</div>
</div>
</body>

View file

@ -1016,6 +1016,7 @@
<Compile Include="ZDoom\ReverbsParser.cs" />
<Compile Include="ZDoom\SndSeqParser.cs" />
<Compile Include="ZDoom\StateGoto.cs" />
<Compile Include="ZDoom\TerrainParser.cs" />
<Compile Include="ZDoom\TexturesParser.cs" />
<Compile Include="ZDoom\TextureStructure.cs" />
<Compile Include="ZDoom\VoxeldefParser.cs" />

View file

@ -78,9 +78,9 @@ namespace CodeImp.DoomBuilder.Compilers
foreach(string include in includes)
{
// Grab the script text from the resources
Stream s = General.Map.Data.LoadFile(include);
TextResourceData data = General.Map.Data.LoadFile(include);
if(s != null)
if(data.Stream != null)
{
// Pull the pk3 or directory sub folder out if applicable
FileInfo fi = new FileInfo(Path.Combine(this.tempdir.FullName, include));
@ -94,8 +94,8 @@ namespace CodeImp.DoomBuilder.Compilers
if(!string.IsNullOrEmpty(fi.DirectoryName)) Directory.CreateDirectory(fi.DirectoryName);
// Dump the script into the target file
BinaryReader reader = new BinaryReader(s);
File.WriteAllBytes(fi.FullName, reader.ReadBytes((int)s.Length));
BinaryReader reader = new BinaryReader(data.Stream);
File.WriteAllBytes(fi.FullName, reader.ReadBytes((int)data.Stream.Length));
}
}
}
@ -174,10 +174,14 @@ namespace CodeImp.DoomBuilder.Compilers
// Everything before the match is the filename
err.filename = linestr.Substring(0, match.Index).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
//mxd. Get rid of temp directory path
if(err.filename.StartsWith(this.tempdir.Name)) err.filename = err.filename.Replace(this.tempdir.Name, string.Empty);
if(!Path.IsPathRooted(err.filename))
{
//mxd. If the error is in an include file, try to find it in loaded resources
if(includes.Contains(err.filename.ToLowerInvariant()))
if(includes.Contains(err.filename))
{
foreach(DataReader dr in General.Map.Data.Containers)
{

View file

@ -54,7 +54,7 @@ namespace CodeImp.DoomBuilder.Config
private readonly string defaultsavecompiler;
private readonly string defaulttestcompiler;
private readonly string formatinterface;
private readonly string defaultLinedefActivation; //mxd
private readonly string defaultlinedefactivation; //mxd
private readonly string singlesidedflag;
private readonly string doublesidedflag;
private readonly string impassableflag;
@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.Config
private readonly bool linetagindicatesectors;
private readonly string decorategames;
private string skyflatname;
private Dictionary<string, string> defaultskytextures; //mxd <map name, sky texture name>
private readonly Dictionary<string, string> defaultskytextures; //mxd <map name, sky texture name>
private readonly int maxtexturenamelength;
private readonly bool longtexturenames; //mxd
private readonly int leftboundary;
@ -147,13 +147,16 @@ namespace CodeImp.DoomBuilder.Config
// Enums
private readonly Dictionary<string, EnumList> enums;
//mxd. DamageTypes
private HashSet<string> damagetypes;
// Defaults
private readonly List<DefinedTextureSet> texturesets;
private readonly List<ThingsFilter> thingfilters;
//mxd. Holds base game type (doom, heretic, hexen or strife)
private readonly GameType gameType;
private readonly GameType gametype;
#endregion
@ -171,7 +174,7 @@ namespace CodeImp.DoomBuilder.Config
public string DefaultCeilingTexture { get { return defaultceilingtexture; } } //mxd
public bool ScaledTextureOffsets { get { return scaledtextureoffsets; } }
public string FormatInterface { get { return formatinterface; } }
public string DefaultLinedefActivationFlag { get { return defaultLinedefActivation; } } //mxd
public string DefaultLinedefActivationFlag { get { return defaultlinedefactivation; } } //mxd
public string SingleSidedFlag { get { return singlesidedflag; } }
public string DoubleSidedFlag { get { return doublesidedflag; } }
public string ImpassableFlag { get { return impassableflag; } }
@ -263,12 +266,15 @@ namespace CodeImp.DoomBuilder.Config
// Enums
public IDictionary<string, EnumList> Enums { get { return enums; } }
//mxd. DamageTypes
internal IEnumerable<string> DamageTypes { get { return damagetypes; } }
// Defaults
internal List<DefinedTextureSet> TextureSets { get { return texturesets; } }
public List<ThingsFilter> ThingsFilters { get { return thingfilters; } }
//mxd
public GameType GameType { get { return gameType; } }
public GameType GameType { get { return gametype; } }
#endregion
@ -316,7 +322,7 @@ namespace CodeImp.DoomBuilder.Config
//mxd
int gt = (cfg.ReadSetting("basegame", (int)GameType.UNKNOWN));
gameType = ( (gt > -1 && gt < Gldefs.GLDEFS_LUMPS_PER_GAME.Length) ? (GameType)gt : GameType.UNKNOWN);
gametype = ( (gt > -1 && gt < Gldefs.GLDEFS_LUMPS_PER_GAME.Length) ? (GameType)gt : GameType.UNKNOWN);
enginename = cfg.ReadSetting("engine", "");
defaultsavecompiler = cfg.ReadSetting("defaultsavecompiler", "");
@ -350,7 +356,7 @@ namespace CodeImp.DoomBuilder.Config
doomlightlevels = cfg.ReadSetting("doomlightlevels", true);
actionspecialhelp = cfg.ReadSetting("actionspecialhelp", string.Empty); //mxd
thingclasshelp = cfg.ReadSetting("thingclasshelp", string.Empty); //mxd
defaultLinedefActivation = cfg.ReadSetting("defaultlinedefactivation", ""); //mxd
defaultlinedefactivation = cfg.ReadSetting("defaultlinedefactivation", ""); //mxd
for(int i = 0; i < Linedef.NUM_ARGS; i++) makedoorargs[i] = cfg.ReadSetting("makedoorarg" + i.ToString(CultureInfo.InvariantCulture), 0);
//mxd. Update map format flags
@ -391,6 +397,9 @@ namespace CodeImp.DoomBuilder.Config
// Enums
LoadEnums();
//mxd. Damage types
LoadDamageTypes();
// Things
LoadThingFlags();
@ -471,6 +480,25 @@ namespace CodeImp.DoomBuilder.Config
enums.Add(de.Key.ToString(), list);
}
}
//mxd. This loads built-in DamageTypes
private void LoadDamageTypes()
{
string dtypes = cfg.ReadSetting("damagetypes", "None");
string[] dtypesarr = dtypes.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
damagetypes = new HashSet<string>();
foreach(string dtype in dtypesarr)
{
if(damagetypes.Contains(dtype))
{
General.ErrorLogger.Add(ErrorType.Warning, "DamageType \"" + dtype + "\" is double defined in the \"" + this.Name + "\" game configuration");
continue;
}
damagetypes.Add(dtype);
}
}
// This loads a universal fields list
private List<UniversalFieldInfo> LoadUniversalFields(string elementname)
@ -489,7 +517,7 @@ namespace CodeImp.DoomBuilder.Config
}
catch(Exception)
{
General.ErrorLogger.Add(ErrorType.Warning, "Unable to read universal field definition 'universalfields." + elementname + "." + de.Key + "' from game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Unable to read universal field definition \"universalfields." + elementname + "." + de.Key + "\" from game configuration \"" + this.Name + "\"");
}
}
@ -532,8 +560,8 @@ namespace CodeImp.DoomBuilder.Config
{
if(!things.ContainsKey(t.Index))
things.Add(t.Index, t);
else
General.ErrorLogger.Add(ErrorType.Warning, "Thing number " + t.Index + " is defined more than once (as '" + things[t.Index].Title + "' and '" + t.Title + "') in the '" + this.Name + "' game configuration");
else
General.ErrorLogger.Add(ErrorType.Warning, "Thing number " + t.Index + " is defined more than once (as \"" + things[t.Index].Title + "\" and \"" + t.Title + "\") in the \"" + this.Name + "\" game configuration");
}
// Recursively add things from child categories
@ -624,7 +652,7 @@ namespace CodeImp.DoomBuilder.Config
{
// Failure
if(de.Value != null)
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'linedeftypes' contains invalid types in game configuration '" + this.Name + "'. All types must be expanded structures.");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"linedeftypes\" contains invalid types in the \"" + this.Name + "\" game configuration. All types must be expanded structures.");
}
}
}
@ -676,7 +704,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'gen_linedeftypes' contains invalid entries in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"gen_linedeftypes\" contains invalid entries in the \"" + this.Name + "\" game configuration");
}
}
}
@ -703,7 +731,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'sectortypes' contains invalid keys in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"sectortypes\" contains invalid keys in the \"" + this.Name + "\" game configuration");
}
}
@ -728,7 +756,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'sectorbrightness' contains invalid keys in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"sectorbrightness\" contains invalid keys in the \"" + this.Name + "\" game configuration");
}
}
@ -751,7 +779,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'gen_sectortypes' contains invalid entries in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"gen_sectortypes\" contains invalid entries in the \"" + this.Name + "\" game configuration");
}
}
}
@ -777,7 +805,7 @@ namespace CodeImp.DoomBuilder.Config
foreach(string s in thingflagscompare[group].Flags.Keys)
{
if(flagscache.Contains(s))
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag '" + s + "' is double-defined in '" + group + "' group!");
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag \"" + s + "\" is double defined in the \"" + group + "\" group of the \"" + this.Name + "\" game configuration");
else
flagscache.Add(s);
}
@ -793,7 +821,7 @@ namespace CodeImp.DoomBuilder.Config
{
if(!thingflagscompare.ContainsKey(s))
{
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare group '" + s + "', required by flag '" + flag.Flag + "' does not exist!");
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare group \"" + s + "\" required by flag \"" + flag.Flag + "\" does not exist in the \"" + this.Name + "\" game configuration");
flag.RequiredGroups.Remove(s);
}
}
@ -803,15 +831,15 @@ namespace CodeImp.DoomBuilder.Config
{
if(!thingflagscompare.ContainsKey(s))
{
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare group '" + s + "', ignored by flag '" + flag.Flag + "' does not exist!");
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare group \"" + s + "\", ignored by flag \"" + flag.Flag + "\" does not exist in the \"" + this.Name + "\" game configuration");
flag.IgnoredGroups.Remove(s);
}
}
// Required flag is missing?
if(!string.IsNullOrEmpty(flag.RequiredFlag) && !flagscache.Contains(flag.RequiredFlag) /*!group.Value.Flags.ContainsKey(flag.RequiredFlag)*/)
if(!string.IsNullOrEmpty(flag.RequiredFlag) && !flagscache.Contains(flag.RequiredFlag))
{
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag '" + flag.RequiredFlag + "', required by flag '" + flag.Flag + "' does not exist!");
General.ErrorLogger.Add(ErrorType.Warning, "ThingFlagsCompare flag \"" + flag.RequiredFlag + "\", required by flag \"" + flag.Flag + "\" does not exist in the \"" + this.Name + "\" game configuration");
flag.RequiredFlag = string.Empty;
}
}
@ -835,7 +863,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'defaultthingflags' contains unknown thing flags in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"defaultthingflags\" contains unknown thing flags in the \"" + this.Name + "\" game configuration");
}
}
}
@ -854,7 +882,7 @@ namespace CodeImp.DoomBuilder.Config
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Structure 'skills' contains invalid skill numbers in game configuration '" + this.Name + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Structure \"skills\" contains invalid skill numbers in the \"" + this.Name + "\" game configuration");
}
}
}
@ -911,14 +939,14 @@ namespace CodeImp.DoomBuilder.Config
string skytex = de.Key.ToString();
if(defaultskytextures.ContainsKey(skytex))
{
General.ErrorLogger.Add(ErrorType.Warning, "Sky texture \"" + skytex + "\" is double-defined in the current game configuration!");
General.ErrorLogger.Add(ErrorType.Warning, "Sky texture \"" + skytex + "\" is double defined in the \"" + this.Name + "\" game configuration");
continue;
}
string[] maps = de.Value.ToString().Split(separator, StringSplitOptions.RemoveEmptyEntries);
if(maps.Length == 0)
{
General.ErrorLogger.Add(ErrorType.Warning, "Sky texture \"" + skytex + "\" has no map names defined in the current game configuration!");
General.ErrorLogger.Add(ErrorType.Warning, "Sky texture \"" + skytex + "\" has no map names defined in the \"" + this.Name + "\" game configuration");
continue;
}
@ -926,7 +954,7 @@ namespace CodeImp.DoomBuilder.Config
{
if(defaultskytextures.ContainsKey(map))
{
General.ErrorLogger.Add(ErrorType.Warning, "Map \"" + map + "\" is double-defined in the \"DefaultSkyTextures\" block of current game configuration!");
General.ErrorLogger.Add(ErrorType.Warning, "Map \"" + map + "\" is double defined in the \"DefaultSkyTextures\" block of \"" + this.Name + "\" game configuration");
continue;
}

View file

@ -65,7 +65,8 @@ namespace CodeImp.DoomBuilder.Config
// Add a texture
internal void AddTexture(ImageData image)
{
if(textures.ContainsKey(image.LongName) && !image.HasPatchWithSameName)
//mxd. Wad duplicates are checked by WadReader
if(location.type != DataLocation.RESOURCE_WAD && textures.ContainsKey(image.LongName) && !image.HasPatchWithSameName)
General.ErrorLogger.Add(ErrorType.Warning, "Texture \"" + image.Name + "\" is double defined in resource \"" + this.Location.location + "\".");
textures[image.LongName] = image;
}
@ -73,7 +74,8 @@ namespace CodeImp.DoomBuilder.Config
// Add a flat
internal void AddFlat(ImageData image)
{
if(flats.ContainsKey(image.LongName) && (!General.Map.Config.MixTexturesFlats || !image.HasPatchWithSameName))
//mxd. Wad duplicates are checked by WadReader
if(location.type != DataLocation.RESOURCE_WAD && flats.ContainsKey(image.LongName) && (!General.Map.Config.MixTexturesFlats || !image.HasPatchWithSameName))
General.ErrorLogger.Add(ErrorType.Warning, "Flat \"" + image.Name + "\" is double defined in resource \"" + this.Location.location + "\".");
flats[image.LongName] = image;
}

View file

@ -17,10 +17,12 @@
#region ================== Namespaces
using System;
using System.Globalization;
using System.IO;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Compilers;
@ -114,7 +116,6 @@ namespace CodeImp.DoomBuilder.Controls
//mxd. Bind functionbar events
editor.FunctionBar.DropDown += functionbar_DropDown;
editor.FunctionBar.SelectedIndexChanged += functionbar_SelectedIndexChanged;
}
// Disposer
@ -202,7 +203,8 @@ namespace CodeImp.DoomBuilder.Controls
// This changes the script configurations
public virtual void ChangeScriptConfig(ScriptConfiguration newconfig)
{
UpdateNavigator(); //mxd
List<CompilerError> errors = UpdateNavigator(); //mxd
if(panel.ActiveTab == this) panel.ShowErrors(errors); //mxd
}
// Call this to set the tab title
@ -273,23 +275,25 @@ namespace CodeImp.DoomBuilder.Controls
}
//mxd
protected void UpdateNavigator()
//TODO: rewrite this using reflection, move UpdateNavigator[Type] to appropriate parsers
internal List<CompilerError> UpdateNavigator()
{
// Store currently selected item name
string prevtext = editor.FunctionBar.Text;
List<CompilerError> result = new List<CompilerError>();
switch(config.ScriptType)
{
case ScriptType.ACS:
UpdateNavigatorAcs(new MemoryStream(editor.GetText()));
result = UpdateNavigatorAcs(new MemoryStream(editor.GetText()));
break;
case ScriptType.DECORATE:
UpdateNavigatorDecorate(new MemoryStream(editor.GetText()));
result = UpdateNavigatorDecorate(new MemoryStream(editor.GetText()));
break;
case ScriptType.MODELDEF:
UpdateNavigatorModeldef(new MemoryStream(editor.GetText()));
result = UpdateNavigatorModeldef(new MemoryStream(editor.GetText()));
break;
default: // Unsupported script type. Just clear the items
@ -322,52 +326,59 @@ namespace CodeImp.DoomBuilder.Controls
preventchanges = false;
}
return result;
}
//mxd
private void UpdateNavigatorDecorate(MemoryStream stream)
private List<CompilerError> UpdateNavigatorDecorate(MemoryStream stream)
{
if(stream == null) return;
List<CompilerError> result = new List<CompilerError>();
if(stream == null) return result;
editor.FunctionBar.Items.Clear();
DecorateParserSE parser = new DecorateParserSE();
if(parser.Parse(stream, "DECORATE", false))
{
TextResourceData data = new TextResourceData(stream, new DataLocation(), "DECORATE", false);
if(parser.Parse(data, false))
editor.FunctionBar.Items.AddRange(parser.Actors.ToArray());
}
if(parser.HasError)
{
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
}
result.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
return result;
}
//mxd
private void UpdateNavigatorModeldef(MemoryStream stream)
private List<CompilerError> UpdateNavigatorModeldef(MemoryStream stream)
{
if(stream == null) return;
List<CompilerError> result = new List<CompilerError>();
if(stream == null) return result;
editor.FunctionBar.Items.Clear();
ModeldefParserSE parser = new ModeldefParserSE();
if(parser.Parse(stream, "MODELDEF", false))
{
TextResourceData data = new TextResourceData(stream, new DataLocation(), "MODELDEF", false);
if(parser.Parse(data, false))
editor.FunctionBar.Items.AddRange(parser.Models.ToArray());
}
if(parser.HasError)
{
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
}
result.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
return result;
}
//mxd
private void UpdateNavigatorAcs(MemoryStream stream)
private List<CompilerError> UpdateNavigatorAcs(MemoryStream stream)
{
if(stream == null) return;
List<CompilerError> result = new List<CompilerError>();
if(stream == null) return result;
editor.FunctionBar.Items.Clear();
AcsParserSE parser = new AcsParserSE { AddArgumentsToScriptNames = true, IsMapScriptsLump = this is ScriptLumpDocumentTab };
if(parser.Parse(stream, "SCRIPTS", false))
AcsParserSE parser = new AcsParserSE { AddArgumentsToScriptNames = true, IsMapScriptsLump = this is ScriptLumpDocumentTab, IgnoreErrors = true };
TextResourceData data = new TextResourceData(stream, new DataLocation(), (parser.IsMapScriptsLump ? "?SCRIPTS" : Filename), false);
if(parser.Parse(data, false))
{
editor.FunctionBar.Items.AddRange(parser.NamedScripts.ToArray());
editor.FunctionBar.Items.AddRange(parser.NumberedScripts.ToArray());
@ -375,25 +386,25 @@ namespace CodeImp.DoomBuilder.Controls
}
if(parser.HasError)
{
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
}
result.Add(new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine));
return result;
}
//mxd
internal ScriptType VerifyScriptType()
{
ScriptTypeParserSE parser = new ScriptTypeParserSE();
if(parser.Parse(new MemoryStream(editor.GetText()), config.Description, false))
TextResourceData data = new TextResourceData(new MemoryStream(editor.GetText()), new DataLocation(), config.Description, false);
if(parser.Parse(data, false))
{
if(parser.ScriptType != ScriptType.UNKNOWN && config.ScriptType != parser.ScriptType)
return parser.ScriptType;
}
if(parser.HasError)
{
panel.ShowErrors(new List<CompilerError> { new CompilerError(parser.ErrorDescription, parser.ErrorSource, parser.ErrorLine) });
}
return ScriptType.UNKNOWN;
}
@ -416,30 +427,68 @@ namespace CodeImp.DoomBuilder.Controls
{
// Text must be exactly the same
long hash = MurmurHash2.Hash(Text);
if(hash != settings.Hash) return;
// Restore fold levels
if(settings.FoldLevels != null && General.Settings.ScriptShowFolding && (Scintilla.Lexer == Lexer.Cpp || Scintilla.Lexer == Lexer.CppNoCase))
bool applyfolding = General.Settings.ScriptShowFolding && (Scintilla.Lexer == Lexer.Cpp || Scintilla.Lexer == Lexer.CppNoCase);
if(hash == settings.Hash)
{
// We'll want to fold deeper levels first...
int[] fl = new int[settings.FoldLevels.Keys.Count];
settings.FoldLevels.Keys.CopyTo(fl, 0);
// Restore fold levels
if(applyfolding) ApplyFolding(settings.FoldLevels ?? GetFoldLevels());
List<int> foldlevels = new List<int>(fl);
foldlevels.Sort((a, b) => -1 * a.CompareTo(b)); // Sort in descending order
// Restore scroll
Scintilla.FirstVisibleLine = settings.FirstVisibleLine;
foreach(int level in foldlevels)
// Restore caret position
Scintilla.SetEmptySelection(settings.CaretPosition);
}
// Do what Visual Studio does: fold all #regions
else if(applyfolding)
{
ApplyFolding(GetFoldLevels());
}
}
internal void SetDefaultViewSettings()
{
if(General.Settings.ScriptShowFolding && (Scintilla.Lexer == Lexer.Cpp || Scintilla.Lexer == Lexer.CppNoCase))
ApplyFolding(GetFoldLevels());
}
private void ApplyFolding(Dictionary<int, HashSet<int>> foldlevelsarr)
{
// We'll want to fold deeper levels first...
int[] fl = new int[foldlevelsarr.Keys.Count];
foldlevelsarr.Keys.CopyTo(fl, 0);
List<int> foldlevels = new List<int>(fl);
foldlevels.Sort((a, b) => -1 * a.CompareTo(b)); // Sort in descending order
foreach(int level in foldlevels)
{
foreach(int line in foldlevelsarr[level])
Scintilla.Lines[line].FoldLine(FoldAction.Contract);
}
}
private Dictionary<int, HashSet<int>> GetFoldLevels()
{
Dictionary<int, HashSet<int>> foldlevels = new Dictionary<int, HashSet<int>>();
int foldlevel = NativeMethods.SC_FOLDLEVELBASE;
for(int i = 0; i < Scintilla.Lines.Count; i++)
{
string line = Scintilla.Lines[i].Text.TrimStart();
if(line.StartsWith("#region", true, CultureInfo.InvariantCulture))
{
foreach(int line in settings.FoldLevels[level])
Scintilla.Lines[line].FoldLine(FoldAction.Contract);
foldlevel++;
if(!foldlevels.ContainsKey(foldlevel)) foldlevels.Add(foldlevel, new HashSet<int>());
foldlevels[foldlevel].Add(i);
}
else if(line.StartsWith("#endregion", true, CultureInfo.InvariantCulture) && foldlevel > NativeMethods.SC_FOLDLEVELBASE)
{
foldlevel--;
}
}
// Restore scroll
Scintilla.FirstVisibleLine = settings.FirstVisibleLine;
// Restore caret position
Scintilla.SetEmptySelection(settings.CaretPosition);
return foldlevels;
}
//mxd
@ -511,7 +560,7 @@ namespace CodeImp.DoomBuilder.Controls
//mxd
private void functionbar_DropDown(object sender, EventArgs e)
{
if(!preventchanges && editor.IsChanged) UpdateNavigator();
if(!preventchanges && editor.IsChanged) panel.ShowErrors(UpdateNavigator());
}
//mxd

View file

@ -69,6 +69,7 @@ namespace CodeImp.DoomBuilder.Controls
private const string LEXERS_RESOURCE = "Lexers.cfg";
private const int MAX_BACKTRACK_LENGTH = 200;
private const int HIGHLIGHT_INDICATOR = 8; //mxd. Indicators 0-7 could be in use by a lexer so we'll use indicator 8 to highlight words.
private const string ENTRY_POSITION_MARKER = "[EP]"; //mxd
#endregion
@ -237,11 +238,14 @@ namespace CodeImp.DoomBuilder.Controls
{
scriptedit.Lines[linenumber].Goto();
EnsureLineVisible(linenumber);
scriptedit.SetEmptySelection(scriptedit.Lines[linenumber].Position);
}
// This makes sure a line is visible
public void EnsureLineVisible(int linenumber)
{
int caretpos = scriptedit.CurrentPosition;
// Determine target lines range
int startline = Math.Max(0, linenumber - 4);
int endline = Math.Min(scriptedit.Lines.Count, Math.Max(linenumber, linenumber + scriptedit.LinesOnScreen - 6));
@ -255,6 +259,9 @@ namespace CodeImp.DoomBuilder.Controls
scriptedit.Lines[startline].Goto();
else if(scriptedit.FirstVisibleLine + scriptedit.LinesOnScreen <= endline)
scriptedit.Lines[endline].Goto();
// We don't want to change caret position
scriptedit.CurrentPosition = caretpos;
}
//mxd
@ -513,7 +520,12 @@ namespace CodeImp.DoomBuilder.Controls
// Autocomplete doesn't mind '.' or ':'
// Skip adding the keyword if we have a snippet with the same name
if(!scriptconfig.Snippets.Contains(p))
autocompletedict.Add(p, p + "?" + imageindex);
{
if(autocompletedict.ContainsKey(p))
General.ErrorLogger.Add(ErrorType.Warning, "Property \"" + p + "\" is double defined in \"" + scriptconfig.Description + "\" script configuration.");
else
autocompletedict.Add(p, p + "?" + imageindex);
}
}
string words = propertieslist.ToString();
scriptedit.SetKeywords(propertiesindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant()));
@ -695,7 +707,7 @@ namespace CodeImp.DoomBuilder.Controls
// Check if we have the [EP] marker
if(entrypos == -1)
{
int pos = processedlines[i].IndexOf("[EP]", StringComparison.Ordinal);
int pos = processedlines[i].IndexOf(ENTRY_POSITION_MARKER, StringComparison.OrdinalIgnoreCase);
if(pos != -1)
{
processedlines[i] = processedlines[i].Remove(pos, 4);
@ -1307,7 +1319,31 @@ namespace CodeImp.DoomBuilder.Controls
{
// Expand snippet?
string[] lines = scriptconfig.GetSnippet(e.Text);
if(lines != null) InsertSnippet(lines);
if(lines != null)
{
InsertSnippet(lines);
}
// Format editor comment?
else if(e.Text.StartsWith("$"))
{
string definition = scriptconfig.GetFunctionDefinition(e.Text);
if(!string.IsNullOrEmpty(definition))
{
int entrypos = definition.IndexOf(ENTRY_POSITION_MARKER, StringComparison.OrdinalIgnoreCase);
// Remove the marker
if(entrypos != -1) definition = definition.Remove(entrypos, 4);
// Replace insterted text with expanded comment
int startpos = scriptedit.WordStartPosition(scriptedit.CurrentPosition, true);
scriptedit.SelectionStart = startpos;
scriptedit.SelectionEnd = scriptedit.WordEndPosition(scriptedit.CurrentPosition, true);
scriptedit.ReplaceSelection(definition);
// Update caret position
if(entrypos != -1) scriptedit.SetEmptySelection(startpos + entrypos);
}
}
}
// Key pressed down

View file

@ -129,6 +129,10 @@ namespace CodeImp.DoomBuilder.Controls
if(General.Map.Options.ScriptLumpSettings[maplumpinfo.Name].IsActiveTab)
activetab = t;
}
else
{
t.SetDefaultViewSettings();
}
t.OnTextChanged += tabpage_OnLumpTextChanged; //mxd
t.Scintilla.UpdateUI += scintilla_OnUpdateUI; //mxd
@ -146,6 +150,10 @@ namespace CodeImp.DoomBuilder.Controls
if(General.Map.Options.ScriptLumpSettings[maplumpinfo.Name].IsActiveTab)
activetab = t;
}
else
{
t.SetDefaultViewSettings();
}
t.OnTextChanged += tabpage_OnLumpTextChanged; //mxd
t.Scintilla.UpdateUI += scintilla_OnUpdateUI; //mxd
@ -176,6 +184,7 @@ namespace CodeImp.DoomBuilder.Controls
{
int scriptsindex = GetTabPageIndex("SCRIPTS");
tabs.SelectedIndex = (scriptsindex == -1 ? 0 : scriptsindex);
activetab = tabs.TabPages[tabs.SelectedIndex] as ScriptDocumentTab;
}
//mxd. Apply quick search settings
@ -183,8 +192,12 @@ namespace CodeImp.DoomBuilder.Controls
searchwholeword.Checked = matchwholeword;
searchbox_TextChanged(this, EventArgs.Empty);
// If the map has remembered any compile errors, then show them
ShowErrors(General.Map.Errors);
//mxd. If the map or script navigator has any compile errors, show them
if(activetab != null)
{
List<CompilerError> errors = activetab.UpdateNavigator();
ShowErrors(General.Map.Errors.Count > 0 ? General.Map.Errors : errors);
}
// Done
UpdateToolbar(true);
@ -839,7 +852,27 @@ namespace CodeImp.DoomBuilder.Controls
//mxd. Add new tabs
foreach(string name in openfile.FileNames)
{
if(!openedfiles.Contains(name)) OpenFile(name);
if(!openedfiles.Contains(name))
{
ScriptFileDocumentTab t = OpenFile(name);
// Apply document settings
bool settingsfound = false;
foreach(ScriptDocumentSettings settings in General.Map.Options.ScriptFileSettings.Values)
{
// Does this file exist?
if(settings.Filename == t.Filename)
{
// Apply stored settings
t.SetViewSettings(settings);
settingsfound = true;
break;
}
}
// Apply default settings
if(!settingsfound) t.SetDefaultViewSettings();
}
}
// Select the last new item
@ -909,6 +942,10 @@ namespace CodeImp.DoomBuilder.Controls
// A tab is selected
private void tabs_Selecting(object sender, TabControlCancelEventArgs e)
{
//mxd. Update script navigator
ScriptDocumentTab tab = e.TabPage as ScriptDocumentTab;
if(tab != null) ShowErrors(tab.UpdateNavigator());
UpdateToolbar(true);
}

View file

@ -22,6 +22,7 @@ using System.IO;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.GZDoom;
#endregion
@ -127,7 +128,7 @@ namespace CodeImp.DoomBuilder.Controls
compiler.Dispose();
//mxd. Update script navigator
UpdateNavigator();
errors.AddRange(UpdateNavigator());
// Feed errors to panel
panel.ShowErrors(errors);
@ -172,10 +173,27 @@ namespace CodeImp.DoomBuilder.Controls
}
// Preprocess the file
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path, includetype) => se.Parse(General.Map.Data.LoadFile(path), path, true, includetype, false) };
AcsParserSE parser = new AcsParserSE
{
OnInclude = delegate(AcsParserSE se, string includefile, AcsParserSE.IncludeType includetype)
{
TextResourceData data = General.Map.Data.LoadFile(includefile);
if(data == null)
{
// Fial
errors.Add(new CompilerError("Unable to find include file \"" + includefile + "\""));
panel.ShowErrors(errors);
}
else
{
se.Parse(data, true, includetype, false);
}
}
};
using(FileStream stream = File.OpenRead(filepathname))
{
if(!parser.Parse(stream, filepathname, scriptconfig.Compiler.Files, true, AcsParserSE.IncludeType.NONE, false))
TextResourceData data = new TextResourceData(stream, new DataLocation(), filepathname, false);
if(!parser.Parse(data, scriptconfig.Compiler.Files, true, AcsParserSE.IncludeType.NONE, false))
{
// Check for errors
if(parser.HasError)
@ -258,7 +276,7 @@ namespace CodeImp.DoomBuilder.Controls
compiler.Dispose();
// Update script navigator
UpdateNavigator();
errors.AddRange(UpdateNavigator());
// Feed errors to panel
panel.ShowErrors(errors);
@ -333,7 +351,7 @@ namespace CodeImp.DoomBuilder.Controls
this.filepathname = filepathname;
editor.ClearUndoRedo();
SetTitle(Path.GetFileName(filepathname));
UpdateNavigator(); //mxd
panel.ShowErrors(UpdateNavigator()); //mxd
return true;
}

View file

@ -74,7 +74,6 @@ namespace CodeImp.DoomBuilder.Controls
{
editor.SetText(stream.ToArray()); //mxd
editor.ClearUndoRedo();
UpdateNavigator(); //mxd
}
// Set title
@ -103,10 +102,10 @@ namespace CodeImp.DoomBuilder.Controls
General.Map.CompileLump((ismapheader ? MapManager.CONFIG_MAP_HEADER : lumpname), true);
//mxd. Update script navigator
UpdateNavigator();
errors = UpdateNavigator();
// Feed errors to panel
panel.ShowErrors(General.Map.Errors);
panel.ShowErrors(General.Map.Errors.Count > 0 ? General.Map.Errors : errors);
}
// Implicit save

View file

@ -42,6 +42,19 @@ using Matrix = SlimDX.Matrix;
namespace CodeImp.DoomBuilder.Data
{
public struct TextResource //mxd
{
public string Filename; // Path to text file inside of Resource
public int LumpIndex; // Text lump index if Resource is wad
internal DataReader Resource;
public HashSet<string> Entries; // Actors/models/sounds etc.
public override string ToString()
{
return Filename + (LumpIndex != -1 ? ":" + LumpIndex : "") + " (" + Entries.Count + " entries)";
}
}
public sealed class DataManager
{
#region ================== Constants
@ -74,12 +87,17 @@ namespace CodeImp.DoomBuilder.Data
//mxd
private Dictionary<int, ModelData> modeldefentries; //Thing.Type, Model entry
private readonly Dictionary<int, DynamicLightData> gldefsentries; //Thing.Type, Light entry
private Dictionary<int, DynamicLightData> gldefsentries; //Thing.Type, Light entry
private MapInfo mapinfo;
private Dictionary<string, KeyValuePair<int, int>> reverbs; //<name, <arg1, arg2>
private Dictionary<long, GlowingFlatData> glowingflats; // Texture name hash, Glowing Flat Data
private Dictionary<string, SkyboxInfo> skyboxes;
private List<string> soundsequences;
private string[] soundsequences;
private string[] terrainnames;
private string[] damagetypes;
//mxd. Text resources
private Dictionary<ScriptType, HashSet<TextResource>> textresources;
// Background loading
private Queue<ImageData> imageque;
@ -108,8 +126,8 @@ namespace CodeImp.DoomBuilder.Data
private ImageData[] commenttextures;
// Used images
private Dictionary<long, long> usedtextures; //mxd
private Dictionary<long, long> usedflats; //mxd. Used only when MixTextursFlats is disabled
private Dictionary<long, bool> usedtextures; //mxd
private Dictionary<long, bool> usedflats; //mxd. Used only when MixTextursFlats is disabled
// Things combined with things created from Decorate
private DecorateParser decorate;
@ -133,8 +151,13 @@ namespace CodeImp.DoomBuilder.Data
public MapInfo MapInfo { get { return mapinfo; } }
public Dictionary<string, KeyValuePair<int, int>> Reverbs { get { return reverbs; } }
public Dictionary<long, GlowingFlatData> GlowingFlats { get { return glowingflats; } }
public List<string> SoundSequences { get { return soundsequences; } }
internal List<DataReader> Containers { get { return containers; } } //mxd
public string[] SoundSequences { get { return soundsequences; } }
public string[] TerrainNames { get { return terrainnames; } }
public string[] DamageTypes { get { return damagetypes; } }
internal Dictionary<ScriptType, HashSet<TextResource>> TextResources { get { return textresources; } }
//mxd
internal IEnumerable<DataReader> Containers { get { return containers; } }
public Playpal Palette { get { return palette; } }
public PreviewManager Previews { get { return previews; } }
@ -179,15 +202,6 @@ namespace CodeImp.DoomBuilder.Data
// We have no destructor
GC.SuppressFinalize(this);
//mxd.
modeldefentries = new Dictionary<int, ModelData>();
gldefsentries = new Dictionary<int, DynamicLightData>();
reverbs = new Dictionary<string, KeyValuePair<int, int>>(StringComparer.Ordinal);
glowingflats = new Dictionary<long, GlowingFlatData>();
skyboxes = new Dictionary<string, SkyboxInfo>(StringComparer.Ordinal);
soundsequences = new List<string>();
// Load special images (mxd: the rest is loaded in LoadInternalTextures())
whitetexture = new ResourceImage("CodeImp.DoomBuilder.Resources.White.png") { UseColorCorrection = false };
whitetexture.LoadImage();
@ -294,11 +308,22 @@ namespace CodeImp.DoomBuilder.Data
imageque = new Queue<ImageData>();
previews = new PreviewManager();
texturesets = new List<MatchingTextureSet>();
usedtextures = new Dictionary<long, long>(); //mxd
usedflats = new Dictionary<long, long>(); //mxd
usedtextures = new Dictionary<long, bool>(); //mxd
usedflats = new Dictionary<long, bool>(); //mxd
internalsprites = new Dictionary<string, ImageData>(StringComparer.Ordinal);
thingcategories = General.Map.Config.GetThingCategories();
thingtypes = General.Map.Config.GetThingTypes();
//mxd. Create even more collections!
modeldefentries = new Dictionary<int, ModelData>();
gldefsentries = new Dictionary<int, DynamicLightData>();
reverbs = new Dictionary<string, KeyValuePair<int, int>>(StringComparer.Ordinal);
glowingflats = new Dictionary<long, GlowingFlatData>();
skyboxes = new Dictionary<string, SkyboxInfo>(StringComparer.Ordinal);
soundsequences = new string[0];
terrainnames = new string[0];
textresources = new Dictionary<ScriptType, HashSet<TextResource>>();
damagetypes = new string[0];
// Load texture sets
foreach(DefinedTextureSet ts in General.Map.ConfigSettings.TextureSets)
@ -360,10 +385,12 @@ namespace CodeImp.DoomBuilder.Data
// Load stuff
LoadPalette();
int texcount = LoadTextures(texturesonly, texturenamesshorttofull);
int flatcount = LoadFlats(flatsonly, flatnamesshorttofull);
Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd
int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers);
int flatcount = LoadFlats(flatsonly, flatnamesshorttofull, cachedparsers);
int colormapcount = LoadColormaps(colormapsonly);
LoadSprites();
LoadSprites(cachedparsers);
cachedparsers = null; //mxd
//mxd. Load MAPINFO. Should happen before parisng DECORATE
Dictionary<int, string> spawnnums, doomednums;
@ -465,6 +492,9 @@ namespace CodeImp.DoomBuilder.Data
//mxd. Create camera textures. Should be done after loading textures.
LoadAnimdefs();
//mxd
LoadTerrain();
// Sort names
texturenames.Sort();
@ -547,6 +577,14 @@ namespace CodeImp.DoomBuilder.Data
flats = null;
sprites = null;
modeldefentries = null; //mxd
gldefsentries = null; //mxd
reverbs = null; //mxd
glowingflats = null; //mxd
skyboxes = null; //mxd
soundsequences = null; //mxd
terrainnames = null; //mxd
textresources = null; //mxd
damagetypes = null; //mxd
texturenames = null;
flatnames = null;
imageque = null;
@ -568,7 +606,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader d in containers)
{
// Suspend
General.WriteLogLine("Suspended data resource '" + d.Location.location + "'");
General.WriteLogLine("Suspended data resource \"" + d.Location.location + "\"");
d.Suspend();
}
}
@ -582,7 +620,7 @@ namespace CodeImp.DoomBuilder.Data
try
{
// Resume
General.WriteLogLine("Resumed data resource '" + d.Location.location + "'");
General.WriteLogLine("Resumed data resource \"" + d.Location.location + "\"");
d.Resume();
}
catch(Exception e)
@ -820,9 +858,6 @@ namespace CodeImp.DoomBuilder.Data
i.Value.SetUsedInMap(usedtextures.ContainsKey(i.Key));
if(i.Value.IsImageLoaded != i.Value.IsReferenced) ProcessImage(i.Value);
}
// Done
updatedusedtextures = false;
}
}
//mxd. Use separate collections
@ -847,10 +882,10 @@ namespace CodeImp.DoomBuilder.Data
if(i.Value.IsImageLoaded != i.Value.IsReferenced) ProcessImage(i.Value);
}
}
// Done
updatedusedtextures = false;
}
// Done
updatedusedtextures = false;
}
#endregion
@ -930,7 +965,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Textures
// This loads the textures
private int LoadTextures(Dictionary<long, ImageData> list, Dictionary<long, long> nametranslation)
private int LoadTextures(Dictionary<long, ImageData> list, Dictionary<long, long> nametranslation, Dictionary<string, TexturesParser> cachedparsers)
{
PatchNames pnames = new PatchNames();
int counter = 0;
@ -946,7 +981,7 @@ namespace CodeImp.DoomBuilder.Data
if(newpnames != null) pnames = newpnames;
// Load textures
ICollection<ImageData> images = dr.LoadTextures(pnames);
IEnumerable<ImageData> images = dr.LoadTextures(pnames, cachedparsers);
if(images != null)
{
// Go for all textures
@ -1144,7 +1179,7 @@ namespace CodeImp.DoomBuilder.Data
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Unable to load editor texture '" + name + "'. Using built-in one instead.");
General.ErrorLogger.Add(ErrorType.Warning, "Unable to load editor texture \"" + name + "\". Using built-in one instead.");
result = new ResourceImage("CodeImp.DoomBuilder.Resources." + name);
}
@ -1157,7 +1192,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Flats
// This loads the flats
private int LoadFlats(Dictionary<long, ImageData> list, Dictionary<long, long> nametranslation)
private int LoadFlats(Dictionary<long, ImageData> list, Dictionary<long, long> nametranslation, Dictionary<string, TexturesParser> cachedparsers)
{
int counter = 0;
@ -1165,7 +1200,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
// Load flats
ICollection<ImageData> images = dr.LoadFlats();
IEnumerable<ImageData> images = dr.LoadFlats(cachedparsers);
if(images != null)
{
// Go for all flats
@ -1279,7 +1314,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Sprites
// This loads the hard defined sprites (not all the lumps, we do that on a need-to-know basis, see LoadThingSprites)
private int LoadSprites()
private int LoadSprites(Dictionary<string, TexturesParser> cachedparsers)
{
int counter = 0;
@ -1288,7 +1323,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
// Load sprites
ICollection<ImageData> images = dr.LoadSprites();
IEnumerable<ImageData> images = dr.LoadSprites(cachedparsers);
if(images != null)
{
// Add or replace in sprites list
@ -1330,7 +1365,7 @@ namespace CodeImp.DoomBuilder.Data
}
else //mxd
{
General.ErrorLogger.Add(ErrorType.Error, "Missing sprite lump '" + ti.Sprite + "'. Forgot to include required resources?");
General.ErrorLogger.Add(ErrorType.Error, "Missing sprite lump \"" + ti.Sprite + "\". Forgot to include required resources?");
}
}
else
@ -1494,7 +1529,7 @@ namespace CodeImp.DoomBuilder.Data
private int LoadDecorateThings(Dictionary<int, string> spawnnumsoverride, Dictionary<int, string> doomednumsoverride)
{
int counter = 0;
char[] catsplitter = new[] {Path.AltDirectorySeparatorChar}; //mxd
char[] catsplitter = { Path.AltDirectorySeparatorChar }; //mxd
// Create new parser
decorate = new DecorateParser { OnInclude = LoadDecorateFromLocation };
@ -1508,26 +1543,43 @@ namespace CodeImp.DoomBuilder.Data
// Load Decorate info cumulatively (the last Decorate is added to the previous)
// I'm not sure if this is the right thing to do though.
currentreader = dr;
Dictionary<string, Stream> decostreams = dr.GetDecorateData("DECORATE");
foreach(KeyValuePair<string, Stream> group in decostreams)
IEnumerable<TextResourceData> decostreams = dr.GetDecorateData("DECORATE");
foreach(TextResourceData data in decostreams)
{
// Parse the data
group.Value.Seek(0, SeekOrigin.Begin);
decorate.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true);
data.Stream.Seek(0, SeekOrigin.Begin);
decorate.Parse(data, true);
//mxd. DECORATE lumps are interdepandable. Can't carry on...
if(decorate.HasError)
{
decorate.LogError(); //mxd
decorate.LogError();
currentreader = null;
return counter;
}
}
}
//mxd. Add to text resources collection
textresources[decorate.ScriptType] = new HashSet<TextResource>(decorate.TextResources.Values);
currentreader = null;
if(!decorate.HasError)
{
//mxd. Create DamageTypes list
// Combine damage types from config and decorate
HashSet<string> dtset = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
dtset.UnionWith(General.Map.Config.DamageTypes);
dtset.UnionWith(decorate.DamageTypes);
// Sort values
List<string> dtypes = new List<string>(dtset);
dtypes.Sort();
// Apply to collection
damagetypes = new string[dtypes.Count];
dtypes.CopyTo(damagetypes);
// Step 1. Go for all actors in the decorate to make things or update things
foreach(ActorStructure actor in decorate.Actors)
{
@ -1632,7 +1684,7 @@ namespace CodeImp.DoomBuilder.Data
// Loudly give up...
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Failed to apply MAPINFO DoomEdNum override '" + group.Key + " = " + group.Value + ": failed to find corresponding actor class...");
General.ErrorLogger.Add(ErrorType.Warning, "Failed to apply MAPINFO DoomEdNum override \"" + group.Key + " = " + group.Value + "\": failed to find corresponding actor class...");
}
}
@ -1658,16 +1710,13 @@ namespace CodeImp.DoomBuilder.Data
}
bool spawnidschanged = false;
if(!decorate.HasError)
foreach(ActorStructure actor in decorate.Actors)
{
foreach(ActorStructure actor in decorate.Actors)
int spawnid = actor.GetPropertyValueInt("spawnid", 0);
if(spawnid != 0)
{
int spawnid = actor.GetPropertyValueInt("spawnid", 0);
if(spawnid != 0)
{
configspawnnums[spawnid] = new EnumItem(spawnid.ToString(), (actor.HasPropertyWithValue("$title") ? actor.GetPropertyAllValues("$title") : actor.ClassName));
spawnidschanged = true;
}
configspawnnums[spawnid] = new EnumItem(spawnid.ToString(), (actor.HasPropertyWithValue("$title") ? actor.GetPropertyAllValues("$title") : actor.ClassName));
spawnidschanged = true;
}
}
@ -1676,9 +1725,7 @@ namespace CodeImp.DoomBuilder.Data
{
// Modify by MAPINFO data
foreach(KeyValuePair<int, string> group in spawnnumsoverride)
{
configspawnnums[group.Key] = new EnumItem(group.Key.ToString(), (thingtypes.ContainsKey(group.Key) ? thingtypes[group.Key].Title : group.Value));
}
spawnidschanged = true;
}
@ -1761,11 +1808,11 @@ namespace CodeImp.DoomBuilder.Data
private void LoadDecorateFromLocation(DecorateParser parser, string location)
{
//General.WriteLogLine("Including DECORATE resource '" + location + "'...");
Dictionary<string, Stream> decostreams = currentreader.GetDecorateData(location);
foreach(KeyValuePair<string, Stream> group in decostreams)
IEnumerable<TextResourceData> decostreams = currentreader.GetDecorateData(location);
foreach(TextResourceData data in decostreams)
{
// Parse this data
parser.Parse(group.Value, group.Key, false);
parser.Parse(data, false);
//mxd. DECORATE lumps are interdepandable. Can't carry on...
if(parser.HasError)
@ -1821,13 +1868,13 @@ namespace CodeImp.DoomBuilder.Data
if(!string.IsNullOrEmpty(ti.Value.ClassName))
{
if(actors.ContainsKey(ti.Value.ClassName) && actors[ti.Value.ClassName] != ti.Key)
General.ErrorLogger.Add(ErrorType.Warning, "actor '" + ti.Value.ClassName + "' has several editor numbers! Only the last one (" + ti.Key + ") will be used.");
General.ErrorLogger.Add(ErrorType.Warning, "Actor \"" + ti.Value.ClassName + "\" has several editor numbers! Only the last one (" + ti.Key + ") will be used.");
actors[ti.Value.ClassName] = ti.Key;
}
}
if(actors.Count == 0)
General.ErrorLogger.Add(ErrorType.Warning, "unable to find any DECORATE actor definitions!");
General.ErrorLogger.Add(ErrorType.Warning, "Unable to find any DECORATE actor definitions!");
return actors;
}
@ -1836,10 +1883,7 @@ namespace CodeImp.DoomBuilder.Data
public void ReloadModeldef()
{
if(modeldefentries != null)
{
foreach(KeyValuePair<int, ModelData> group in modeldefentries)
group.Value.Dispose();
}
foreach(KeyValuePair<int, ModelData> group in modeldefentries) group.Value.Dispose();
// Bail out when not supported by current game configuration
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
@ -1852,7 +1896,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(Thing t in General.Map.Map.Things) t.UpdateCache();
//rebuild geometry if in Visual mode
// Rebuild geometry if in Visual mode
if(General.Editing.Mode != null && General.Editing.Mode.GetType().Name == "BaseVisualMode")
{
General.Editing.Mode.OnReloadResources();
@ -1905,16 +1949,16 @@ namespace CodeImp.DoomBuilder.Data
{
currentreader = dr;
Dictionary<string, Stream> streams = dr.GetModeldefData();
foreach(KeyValuePair<string, Stream> group in streams)
IEnumerable<TextResourceData> streams = dr.GetModeldefData();
foreach(TextResourceData data in streams)
{
// Parse the data
if(parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true))
if(parser.Parse(data, true))
{
foreach(KeyValuePair<string, ModelData> g in parser.Entries)
{
if(modeldefentriesbyname.ContainsKey(g.Key))
General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor '" + g.Key + "' is double-defined in '" + group.Key + "'");
if(modeldefentriesbyname.ContainsKey(g.Key))
General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor \"" + g.Key + "\" is double defined in \"" + Path.Combine(data.Source.Location.GetShortName(), data.Filename) + "\"");
modeldefentriesbyname[g.Key] = g.Value;
}
@ -1925,6 +1969,8 @@ namespace CodeImp.DoomBuilder.Data
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
foreach(KeyValuePair<string, ModelData> e in modeldefentriesbyname)
@ -1932,7 +1978,7 @@ namespace CodeImp.DoomBuilder.Data
if(actorsbyclass.ContainsKey(e.Key))
modeldefentries[actorsbyclass[e.Key]] = modeldefentriesbyname[e.Key];
else if(!decorate.ActorsByClass.ContainsKey(e.Key))
General.ErrorLogger.Add(ErrorType.Warning, "Got MODELDEF override for class '" + e.Key + "', but haven't found such class in Decorate");
General.ErrorLogger.Add(ErrorType.Warning, "MODELDEF model \"" + e.Key + "\" doesn't match any Decorate actor class");
}
}
@ -1942,8 +1988,8 @@ namespace CodeImp.DoomBuilder.Data
// Bail out when not supported by current game configuration
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
//Get names of all voxel models, which can be used "as is"
Dictionary<string, bool> voxelNames = new Dictionary<string, bool>(StringComparer.Ordinal);
// Get names of all voxel models, which can be used "as is"
HashSet<string> voxelnames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach(DataReader dr in containers)
{
@ -1954,7 +2000,7 @@ namespace CodeImp.DoomBuilder.Data
foreach(string s in result)
{
if(!voxelNames.ContainsKey(s)) voxelNames.Add(s, false);
if(!voxelnames.Contains(s)) voxelnames.Add(s);
}
}
@ -1969,7 +2015,7 @@ namespace CodeImp.DoomBuilder.Data
if(ti.Sprite.Length == 0 || ti.Sprite.Length > CLASIC_IMAGE_NAME_LENGTH)
{
if(ti.Actor == null) continue;
sprite = ti.Actor.FindSuitableVoxel(voxelNames);
sprite = ti.Actor.FindSuitableVoxel(voxelnames);
}
else
{
@ -1982,17 +2028,17 @@ namespace CodeImp.DoomBuilder.Data
}
VoxeldefParser parser = new VoxeldefParser();
Dictionary<string, bool> processed = new Dictionary<string, bool>(StringComparer.Ordinal);
HashSet<string> processed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
//parse VOXLEDEF
// Parse VOXLEDEF
foreach(DataReader dr in containers)
{
currentreader = dr;
KeyValuePair<string, Stream> group = dr.GetVoxeldefData();
if(group.Value != null)
IEnumerable<TextResourceData> streams = dr.GetVoxeldefData();
foreach(TextResourceData data in streams)
{
if(parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true))
if(parser.Parse(data, true))
{
foreach(KeyValuePair<string, ModelData> entry in parser.Entries)
{
@ -2000,8 +2046,9 @@ namespace CodeImp.DoomBuilder.Data
{
if(sc.Key.Contains(entry.Key))
{
foreach(int id in sc.Value) modeldefentries[id] = entry.Value;
processed.Add(entry.Key, false);
foreach(int id in sc.Value)
modeldefentries[id] = entry.Value;
processed.Add(entry.Key);
}
}
}
@ -2012,19 +2059,21 @@ namespace CodeImp.DoomBuilder.Data
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
//get voxel models
foreach(KeyValuePair<string, bool> group in voxelNames)
// Get voxel models
foreach(string voxelname in voxelnames)
{
if(processed.ContainsKey(group.Key)) continue;
if(processed.Contains(voxelname)) continue;
foreach(KeyValuePair<string, List<int>> sc in sprites)
{
if(sc.Key.Contains(group.Key))
if(sc.Key.Contains(voxelname))
{
//it's a model without a definition, and it corresponds to a sprite we can display, so let's add it
// It's a model without a definition, and it corresponds to a sprite we can display, so let's add it
ModelData data = new ModelData { IsVoxel = true };
data.ModelNames.Add(group.Key);
data.ModelNames.Add(voxelname);
foreach(int id in sprites[sc.Key]) modeldefentries[id] = data;
}
@ -2045,21 +2094,26 @@ namespace CodeImp.DoomBuilder.Data
{
currentreader = dr;
parser.ClearIncludesList();
Dictionary<string, Stream> streams = dr.GetGldefsData(General.Map.Config.GameType);
IEnumerable<TextResourceData> streams = dr.GetGldefsData(General.Map.Config.GameType);
foreach(KeyValuePair<string, Stream> group in streams)
foreach(TextResourceData data in streams)
{
parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), false);
parser.Parse(data, false);
// Gldefs can be interdependable. Can't carry on
if(parser.HasError)
{
parser.LogError();
currentreader = null;
return;
}
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
// Create Gldefs Entries dictionary
foreach(KeyValuePair<string, string> e in parser.Objects) //<ClassName, Light name>
{
@ -2067,7 +2121,7 @@ namespace CodeImp.DoomBuilder.Data
if(actorsbyclass.ContainsKey(e.Key) && parser.LightsByName.ContainsKey(e.Value))
gldefsentries[actorsbyclass[e.Key]] = parser.LightsByName[e.Value];
else if(!decorate.AllActorsByClass.ContainsKey(e.Key))
General.ErrorLogger.Add(ErrorType.Warning, "Got GLDEFS light for class '" + e.Key + "', but haven't found such class in DECORATE");
General.ErrorLogger.Add(ErrorType.Warning, "GLDEFS object \"" + e.Key + "\" doesn't match any DECORATE actor class");
}
// Grab them glowy flats!
@ -2093,12 +2147,12 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
currentreader = dr;
IEnumerable<TextResourceData> streams = dr.GetMapinfoData();
Dictionary<string, Stream> streams = dr.GetMapinfoData();
foreach(KeyValuePair<string, Stream> group in streams)
foreach(TextResourceData data in streams)
{
// Parse the data
parser.Parse(group.Value, Path.Combine(dr.Location.location, group.Key), General.Map.Options.LevelName, false);
parser.Parse(data, General.Map.Options.LevelName, false);
//MAPINFO lumps are interdependable. Can't carry on...
if(parser.HasError)
@ -2123,14 +2177,16 @@ namespace CodeImp.DoomBuilder.Data
doomednums = new Dictionary<int, string>();
mapinfo = new MapInfo();
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
}
private void ParseFromLocation(ZDTextParser parser, string location, bool clearerrors)
{
if(currentreader.IsSuspended) throw new Exception("Data reader is suspended");
parser.Parse(currentreader.LoadFile(location), location, clearerrors);
parser.Parse(new TextResourceData(currentreader, currentreader.LoadFile(location), location, true), clearerrors);
}
//mxd. This loads REVERBS
@ -2145,17 +2201,19 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
currentreader = dr;
Dictionary<string, Stream> streams = dr.GetReverbsData();
foreach(KeyValuePair<string, Stream> group in streams)
IEnumerable<TextResourceData> streams = dr.GetReverbsData();
foreach(TextResourceData data in streams)
{
// Parse the data
parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true);
parser.Parse(data, true);
// Report errors?
if(parser.HasError) parser.LogError();
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
reverbs = parser.GetReverbs();
}
@ -2163,8 +2221,6 @@ namespace CodeImp.DoomBuilder.Data
//mxd. This loads SNDSEQ
private void LoadSndSeq()
{
soundsequences.Clear();
// Bail out when not supported by current game configuration
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
@ -2172,18 +2228,20 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
currentreader = dr;
Dictionary<string, Stream> streams = dr.GetSndSeqData();
IEnumerable<TextResourceData> streams = dr.GetSndSeqData();
// Parse the data
foreach(KeyValuePair<string, Stream> group in streams)
foreach(TextResourceData data in streams)
{
parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true);
parser.Parse(data, true);
// Report errors?
if(parser.HasError) parser.LogError();
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
soundsequences = parser.GetSoundSequences();
}
@ -2198,12 +2256,12 @@ namespace CodeImp.DoomBuilder.Data
foreach(DataReader dr in containers)
{
currentreader = dr;
Dictionary<string, Stream> streams = dr.GetAnimdefsData();
IEnumerable<TextResourceData> streams = dr.GetAnimdefsData();
// Parse the data
foreach(KeyValuePair<string, Stream> group in streams)
foreach(TextResourceData data in streams)
{
parser.Parse(group.Value, Path.Combine(currentreader.Location.GetShortName(), group.Key), true);
parser.Parse(data, true);
// Report errors?
if(parser.HasError) parser.LogError();
@ -2212,27 +2270,27 @@ namespace CodeImp.DoomBuilder.Data
foreach(var g in parser.CameraTextures)
{
// Grab a local copy
CameraTextureData data = g.Value;
CameraTextureData camtexdata = g.Value;
// Apply texture size override?
if(!data.FitTexture)
if(!camtexdata.FitTexture)
{
long longname = Lump.MakeLongName(data.Name);
long longname = Lump.MakeLongName(camtexdata.Name);
if(textures.ContainsKey(longname))
{
data.ScaleX = (float)textures[longname].Width / data.Width;
data.ScaleY = (float)textures[longname].Height / data.Height;
camtexdata.ScaleX = (float)textures[longname].Width / camtexdata.Width;
camtexdata.ScaleY = (float)textures[longname].Height / camtexdata.Height;
}
else if(flats.ContainsKey(longname))
{
data.ScaleX = (float)flats[longname].Width / data.Width;
data.ScaleY = (float)flats[longname].Height / data.Height;
camtexdata.ScaleX = (float)flats[longname].Width / camtexdata.Width;
camtexdata.ScaleY = (float)flats[longname].Height / camtexdata.Height;
}
}
// Create texture
CameraTextureImage camteximage = new CameraTextureImage(data);
CameraTextureImage camteximage = new CameraTextureImage(camtexdata);
// Add to flats and textures
texturenames.Add(camteximage.Name);
@ -2252,18 +2310,66 @@ namespace CodeImp.DoomBuilder.Data
}
}
//mxd. Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
}
//mxd. This loads TERRAIN
private void LoadTerrain()
{
// Bail out when not supported by current game configuration
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
TerrainParser parser = new TerrainParser();
foreach(DataReader dr in containers)
{
currentreader = dr;
IEnumerable<TextResourceData> streams = dr.GetTerrainData();
// Parse the data
foreach(TextResourceData data in streams)
{
parser.Parse(data, true);
// Report errors?
if(parser.HasError) parser.LogError();
}
}
// Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null;
// Sort
List<string> names = new List<string>(parser.TerrainNames);
names.Sort();
// Set as collection
terrainnames = names.ToArray();
}
//mxd
internal Stream LoadFile(string name)
internal TextResourceData LoadFile(string name)
{
// Filesystem path?
if(Path.IsPathRooted(name))
return (File.Exists(name) ? File.OpenRead(name) : null);
{
if(File.Exists(name))
{
DataLocation location = new DataLocation{ location = name, type = DataLocation.RESOURCE_DIRECTORY };
return new TextResourceData(File.OpenRead(name), location, name, false);
}
foreach(DataReader dr in containers)
if(dr.FileExists(name)) return dr.LoadFile(name);
return null;
}
// Search in resources
for(int i = containers.Count - 1; i >= 0; i--)
{
if(containers[i].FileExists(name))
return new TextResourceData(containers[i], containers[i].LoadFile(name), name, false);
}
return null;
}
@ -2312,21 +2418,18 @@ namespace CodeImp.DoomBuilder.Data
foreach(Sidedef sd in General.Map.Map.Sidedefs)
{
// Add used textures to dictionary
if(sd.LongHighTexture != MapSet.EmptyLongName) usedtextures[sd.LongHighTexture] = 0;
if(sd.LongMiddleTexture != MapSet.EmptyLongName) usedtextures[sd.LongMiddleTexture] = 0;
if(sd.LongLowTexture != MapSet.EmptyLongName) usedtextures[sd.LongLowTexture] = 0;
if(sd.LongHighTexture != MapSet.EmptyLongName) usedtextures[sd.LongHighTexture] = true;
if(sd.LongMiddleTexture != MapSet.EmptyLongName) usedtextures[sd.LongMiddleTexture] = true;
if(sd.LongLowTexture != MapSet.EmptyLongName) usedtextures[sd.LongLowTexture] = true;
}
// Go through the map to find the used flats
foreach(Sector s in General.Map.Map.Sectors)
{
// Add used flats to dictionary
usedtextures[s.LongFloorTexture] = 0;
usedtextures[s.LongCeilTexture] = 0;
usedtextures[s.LongFloorTexture] = false;
usedtextures[s.LongCeilTexture] = false;
}
// Notify the background thread that it needs to update the images
updatedusedtextures = true;
}
}
//mxd. Use separate collections
@ -2340,9 +2443,9 @@ namespace CodeImp.DoomBuilder.Data
foreach(Sidedef sd in General.Map.Map.Sidedefs)
{
// Add used textures to dictionary
if(sd.LongHighTexture != MapSet.EmptyLongName) usedtextures[sd.LongHighTexture] = 0;
if(sd.LongMiddleTexture != MapSet.EmptyLongName) usedtextures[sd.LongMiddleTexture] = 0;
if(sd.LongLowTexture != MapSet.EmptyLongName) usedtextures[sd.LongLowTexture] = 0;
if(sd.LongHighTexture != MapSet.EmptyLongName) usedtextures[sd.LongHighTexture] = true;
if(sd.LongMiddleTexture != MapSet.EmptyLongName) usedtextures[sd.LongMiddleTexture] = true;
if(sd.LongLowTexture != MapSet.EmptyLongName) usedtextures[sd.LongLowTexture] = true;
}
}
@ -2354,14 +2457,14 @@ namespace CodeImp.DoomBuilder.Data
foreach(Sector s in General.Map.Map.Sectors)
{
// Add used flats to dictionary
usedflats[s.LongFloorTexture] = 0;
usedflats[s.LongCeilTexture] = 0;
usedflats[s.LongFloorTexture] = false;
usedflats[s.LongCeilTexture] = false;
}
}
// Notify the background thread that it needs to update the images
updatedusedtextures = true;
}
// Notify the background thread that it needs to update the images
updatedusedtextures = true;
}
#endregion

View file

@ -20,11 +20,66 @@ using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
#endregion
namespace CodeImp.DoomBuilder.Data
{
//mxd
public class TextResourceData
{
private Stream stream;
private DataReader source;
private DataLocation sourcelocation;
private string filename;
private int lumpindex;
private bool trackable;
internal Stream Stream { get { return stream; } }
internal DataReader Source { get { return source; } }
internal DataLocation SourceLocation { get { return sourcelocation; } }
internal string Filename { get { return filename; } } // Lump name/Filename
internal int LumpIndex { get { return lumpindex; } } // Lump index in a WAD
internal bool Trackable { get { return trackable; } set { trackable = value; } } // When false, wont be added to DataManager.TextResources
internal TextResourceData(DataReader Source, Stream Stream, string Filename, bool Trackable)
{
source = Source;
sourcelocation = Source.Location;
stream = Stream;
filename = Filename;
trackable = Trackable;
WADReader reader = source as WADReader;
if(reader != null)
lumpindex = reader.WadFile.FindLumpIndex(filename);
else
lumpindex = -1;
}
internal TextResourceData(DataReader Source, Stream Stream, string Filename, int LumpIndex, bool Trackable)
{
source = Source;
sourcelocation = Source.Location;
stream = Stream;
filename = Filename;
lumpindex = LumpIndex;
trackable = Trackable;
}
internal TextResourceData(Stream Stream, DataLocation Location, string Filename, bool Trackable)
{
source = null;
sourcelocation = Location;
stream = Stream;
filename = Filename;
lumpindex = -1;
trackable = Trackable;
}
}
internal abstract class DataReader
{
#region ================== Constants
@ -114,77 +169,80 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Textures
// When implemented, this should read the patch names
public virtual PatchNames LoadPatchNames() { return null; }
public abstract PatchNames LoadPatchNames();
// When implemented, this returns the patch lump
public virtual Stream GetPatchData(string pname, bool longname) { return null; }
public abstract Stream GetPatchData(string pname, bool longname);
// When implemented, this returns the texture lump
public virtual Stream GetTextureData(string pname, bool longname) { return null; }
public abstract Stream GetTextureData(string pname, bool longname);
// When implemented, this loads the textures
public virtual ICollection<ImageData> LoadTextures(PatchNames pnames) { return null; }
public abstract IEnumerable<ImageData> LoadTextures(PatchNames pnames, Dictionary<string, TexturesParser> cachedparsers);
#endregion
#region ================== Flats
// When implemented, this loads the flats
public virtual ICollection<ImageData> LoadFlats() { return null; }
public abstract IEnumerable<ImageData> LoadFlats(Dictionary<string, TexturesParser> cachedparsers);
// When implemented, this returns the flat lump
public virtual Stream GetFlatData(string pname, bool longname) { return null; }
public abstract Stream GetFlatData(string pname, bool longname);
#endregion
#region ================== Sprites
// When implemented, this loads the sprites
public virtual ICollection<ImageData> LoadSprites() { return null; }
public abstract IEnumerable<ImageData> LoadSprites(Dictionary<string, TexturesParser> cachedparsers);
// When implemented, this returns the sprite lump
public virtual Stream GetSpriteData(string pname) { return null; }
public abstract Stream GetSpriteData(string pname);
// When implemented, this checks if the given sprite lump exists
public virtual bool GetSpriteExists(string pname) { return false; }
public abstract bool GetSpriteExists(string pname);
#endregion
#region ================== Decorate, Modeldef, Mapinfo, Gldefs, etc...
// When implemented, this returns the DECORATE lump
public abstract Dictionary<string, Stream> GetDecorateData(string pname); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetDecorateData(string pname);
//mxd. When implemented, this returns the MODELDEF lump
public abstract Dictionary<string, Stream> GetModeldefData(); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetModeldefData();
//mxd. When implemented, this returns the MAPINFO lump
public abstract Dictionary<string, Stream> GetMapinfoData(); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetMapinfoData();
//mxd. When implemented, this returns the GLDEFS lump
public abstract Dictionary<string, Stream> GetGldefsData(GameType gametype); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetGldefsData(GameType gametype);
//mxd. When implemented, this returns the REVERBS lump
public abstract Dictionary<string, Stream> GetReverbsData(); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetReverbsData();
//mxd. When implemented, this returns the VOXELDEF lump
public abstract KeyValuePair<string, Stream> GetVoxeldefData(); // { return new KeyValuePair<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetVoxeldefData();
//mxd. When implemented, this returns the SNDSEQ lump
public abstract Dictionary<string, Stream> GetSndSeqData(); // { return new Dictionary<string, Stream>(); }
public abstract IEnumerable<TextResourceData> GetSndSeqData();
//mxd. When implemented, this returns the ANIMDEFS lump
public abstract Dictionary<string, Stream> GetAnimdefsData();
public abstract IEnumerable<TextResourceData> GetAnimdefsData();
//mxd. When implemented, this returns the TERRAIN lump
public abstract IEnumerable<TextResourceData> GetTerrainData();
//mxd. When implemented, this returns the list of voxel model names
public abstract IEnumerable<string> GetVoxelNames(); // { return null; }
public abstract IEnumerable<string> GetVoxelNames();
//mxd. When implemented, this returns the voxel lump
public abstract Stream GetVoxelData(string name); // { return null; }
public abstract Stream GetVoxelData(string name);
//mxd
internal abstract MemoryStream LoadFile(string name);// { return null; }
internal abstract bool FileExists(string filename);// { return false; }
internal abstract MemoryStream LoadFile(string name);
internal abstract bool FileExists(string filename);
#endregion
}

View file

@ -17,6 +17,7 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.IO;
@ -37,7 +38,7 @@ namespace CodeImp.DoomBuilder.Data
// Constructor
public DirectoryReader(DataLocation dl) : base(dl)
{
General.WriteLogLine("Opening directory resource '" + location.location + "'");
General.WriteLogLine("Opening directory resource \"" + location.location + "\"");
// Initialize
files = new DirectoryFilesList(dl.location, true);
@ -46,14 +47,27 @@ namespace CodeImp.DoomBuilder.Data
// We have no destructor
GC.SuppressFinalize(this);
}
//mxd. Don't move directory wads anywhere
protected override void Initialize()
{
// Load all WAD files in the root as WAD resources
string[] wadfiles = GetFilesWithExt("", "wad", false);
wads = new List<WADReader>(wadfiles.Length);
foreach(string wadfile in wadfiles)
{
DataLocation wdl = new DataLocation(DataLocation.RESOURCE_WAD, Path.Combine(location.location, wadfile), false, false, true);
wads.Add(new WADReader(wdl));
}
}
// Disposer
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
{
General.WriteLogLine("Closing directory resource '" + location.location + "'");
General.WriteLogLine("Closing directory resource \"" + location.location + "\"");
// Done
base.Dispose();
@ -113,7 +127,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading patch '" + pname + "' from directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading patch \"" + pname + "\" from directory: " + e.Message);
}
// Nothing found
@ -156,7 +170,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading texture '" + pname + "' from directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading texture \"" + pname + "\" from directory: " + e.Message);
}
// Nothing found
@ -189,7 +203,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading colormap '" + pname + "' from directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading colormap \"" + pname + "\" from directory: " + e.Message);
}
// Nothing found
@ -225,7 +239,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading sprite '" + pname + "' from directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading sprite \"" + pname + "\" from directory: " + e.Message);
}
// Nothing found
@ -256,7 +270,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while checking sprite '" + pname + "' existance in directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while checking sprite \"" + pname + "\" existance in directory: " + e.Message);
}
// Nothing found
@ -292,7 +306,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading voxel '" + name + "' from directory: " + e.Message);
General.ErrorLogger.Add(ErrorType.Error, e.GetType().Name + " while loading voxel \"" + name + "\" from directory: " + e.Message);
}
// Nothing found
@ -347,9 +361,9 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd. This returns all files in a given directory which title starts with given title
protected override string[] GetAllFilesWhichTitleStartsWith(string path, string title)
protected override string[] GetAllFilesWhichTitleStartsWith(string path, string title, bool subfolders)
{
return files.GetAllFilesWhichTitleStartsWith(path, title).ToArray();
return files.GetAllFilesWhichTitleStartsWith(path, title, subfolders).ToArray();
}
// This returns all files in a given directory that match the given extension
@ -394,7 +408,7 @@ namespace CodeImp.DoomBuilder.Data
}
catch(Exception e)
{
General.ErrorLogger.Add(ErrorType.Error, "Unable to load file: "+e.Message);
General.ErrorLogger.Add(ErrorType.Error, "Unable to load file: " + e.Message);
}
return s;
}

View file

@ -51,7 +51,7 @@ namespace CodeImp.DoomBuilder.Data
// Constructor
public PK3Reader(DataLocation dl) : base(dl)
{
General.WriteLogLine("Opening " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource '" + location.location + "'");
General.WriteLogLine("Opening " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource \"" + location.location + "\"");
if(!File.Exists(location.location))
throw new FileNotFoundException("Could not find the file \"" + location.location + "\"", location.location);
@ -108,8 +108,15 @@ namespace CodeImp.DoomBuilder.Data
// Not already disposed?
if(!isdisposed)
{
General.WriteLogLine("Closing " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource '" + location.location + "'");
General.WriteLogLine("Closing " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource \"" + location.location + "\"");
//mxd. Remove temp files
foreach(WADReader wr in wads)
{
try { File.Delete(wr.Location.location); }
catch(Exception) { }
}
//mxd
if(archive != null)
{
@ -375,9 +382,9 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd. This returns all files in a given directory which title starts with given title
protected override string[] GetAllFilesWhichTitleStartsWith(string path, string title)
protected override string[] GetAllFilesWhichTitleStartsWith(string path, string title, bool subfolders)
{
return files.GetAllFilesWhichTitleStartsWith(path, title).ToArray();
return files.GetAllFilesWhichTitleStartsWith(path, title, subfolders).ToArray();
}
// This returns all files in a given directory that match the given extension
@ -447,7 +454,7 @@ namespace CodeImp.DoomBuilder.Data
if(filedata == null)
{
//mxd
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file '" + filename + "' in archive '" + location.location + "'.");
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file \"" + filename + "\" in archive \"" + location.location + "\".");
return null;
}

View file

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
#endregion
@ -44,8 +45,8 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Variables
// Source
protected bool roottextures;
protected bool rootflats;
protected readonly bool roottextures;
protected readonly bool rootflats;
// WAD files that must be loaded as well
protected List<WADReader> wads;
@ -91,13 +92,6 @@ namespace CodeImp.DoomBuilder.Data
// Clean up
foreach(WADReader wr in wads) wr.Dispose();
// Remove temp files
foreach(WADReader wr in wads)
{
try { File.Delete(wr.Location.location); }
catch(Exception) { }
}
// Done
base.Dispose();
}
@ -148,7 +142,7 @@ namespace CodeImp.DoomBuilder.Data
if(stream.Length > 767) //mxd
palette = new Playpal(stream);
else
General.ErrorLogger.Add(ErrorType.Warning, "Warning: invalid palette '"+foundfile+"'");
General.ErrorLogger.Add(ErrorType.Warning, "Warning: invalid palette \"" + foundfile + "\"");
stream.Dispose();
}
@ -161,19 +155,19 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Textures
// This loads the textures
public override ICollection<ImageData> LoadTextures(PatchNames pnames)
public override IEnumerable<ImageData> LoadTextures(PatchNames pnames, Dictionary<string, TexturesParser> cachedparsers)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<long, ImageData> images = new Dictionary<long, ImageData>();
ICollection<ImageData> collection;
IEnumerable<ImageData> collection;
// Load from wad files (NOTE: backward order, because the last wad's images have priority)
for(int i = wads.Count - 1; i >= 0; i--)
{
PatchNames wadpnames = wads[i].LoadPatchNames(); //mxd
collection = wads[i].LoadTextures((wadpnames != null && wadpnames.Length > 0) ? wadpnames : pnames); //mxd
collection = wads[i].LoadTextures((wadpnames != null && wadpnames.Length > 0) ? wadpnames : pnames, cachedparsers); //mxd
AddImagesToList(images, collection);
}
@ -208,12 +202,24 @@ namespace CodeImp.DoomBuilder.Data
// Load TEXTURES lump files
imgset.Clear();
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES", false); //mxd
foreach(string texturesfile in alltexturefiles)
{
MemoryStream filedata = LoadFile(texturesfile);
WADReader.LoadHighresTextures(filedata, texturesfile, ref imgset, images, null);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, texturesfile);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Textures)
imgset.Add(t.MakeImage());
}
else
{
MemoryStream filedata = LoadFile(texturesfile);
TextResourceData data = new TextResourceData(this, filedata, texturesfile, true); //mxd
cachedparsers.Add(fullpath, WADReader.LoadHighresTextures(data, ref imgset)); //mxd
filedata.Dispose();
}
}
// Add images from TEXTURES lump file
@ -224,8 +230,7 @@ namespace CodeImp.DoomBuilder.Data
AddImagesToList(images, collection);
// Add images to the container-specific texture set
foreach(ImageData img in images.Values)
textureset.AddTexture(img);
foreach(ImageData img in images.Values) textureset.AddTexture(img);
return new List<ImageData>(images.Values);
}
@ -265,10 +270,10 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Flats
// This loads the textures
public override ICollection<ImageData> LoadFlats()
public override IEnumerable<ImageData> LoadFlats(Dictionary<string, TexturesParser> cachedparsers)
{
Dictionary<long, ImageData> images = new Dictionary<long, ImageData>();
ICollection<ImageData> collection;
IEnumerable<ImageData> collection;
List<ImageData> imgset = new List<ImageData>();
// Error when suspended
@ -278,7 +283,7 @@ namespace CodeImp.DoomBuilder.Data
// Note the backward order, because the last wad's images have priority
for(int i = wads.Count - 1; i >= 0; i--)
{
collection = wads[i].LoadFlats();
collection = wads[i].LoadFlats(cachedparsers);
AddImagesToList(images, collection);
}
@ -294,12 +299,24 @@ namespace CodeImp.DoomBuilder.Data
AddImagesToList(images, collection);
// Load TEXTURES lump file
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES", false); //mxd
foreach(string texturesfile in alltexturefiles)
{
MemoryStream filedata = LoadFile(texturesfile);
WADReader.LoadHighresFlats(filedata, texturesfile, ref imgset, null, images);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, texturesfile);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Flats)
imgset.Add(t.MakeImage());
}
else
{
MemoryStream filedata = LoadFile(texturesfile);
TextResourceData data = new TextResourceData(this, filedata, texturesfile, true); //mxd
cachedparsers.Add(fullpath, WADReader.LoadHighresFlats(data, ref imgset)); //mxd
filedata.Dispose();
}
}
// Add images from TEXTURES lump file
@ -308,9 +325,6 @@ namespace CodeImp.DoomBuilder.Data
// Add images to the container-specific texture set
foreach(ImageData img in images.Values)
textureset.AddFlat(img);
// Add images from TEXTURES lump file
AddImagesToList(images, imgset);
return new List<ImageData>(images.Values);
}
@ -341,7 +355,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Sprites
// This loads the textures
public override ICollection<ImageData> LoadSprites()
public override IEnumerable<ImageData> LoadSprites(Dictionary<string, TexturesParser> cachedparsers)
{
Dictionary<long, ImageData> images = new Dictionary<long, ImageData>();
List<ImageData> imgset = new List<ImageData>();
@ -353,18 +367,30 @@ namespace CodeImp.DoomBuilder.Data
// Note the backward order, because the last wad's images have priority
for(int i = wads.Count - 1; i >= 0; i--)
{
ICollection<ImageData> collection = wads[i].LoadSprites();
IEnumerable<ImageData> collection = wads[i].LoadSprites(cachedparsers);
AddImagesToList(images, collection);
}
// Load TEXTURES lump file
imgset.Clear();
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES"); //mxd
string[] alltexturefiles = GetAllFilesWhichTitleStartsWith("", "TEXTURES", false); //mxd
foreach(string texturesfile in alltexturefiles)
{
MemoryStream filedata = LoadFile(texturesfile);
WADReader.LoadHighresSprites(filedata, texturesfile, ref imgset, null, null);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, texturesfile);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Sprites)
imgset.Add(t.MakeImage());
}
else
{
MemoryStream filedata = LoadFile(texturesfile);
TextResourceData data = new TextResourceData(this, filedata, texturesfile, true); //mxd
cachedparsers.Add(fullpath, WADReader.LoadHighresSprites(data, ref imgset)); //mxd
filedata.Dispose();
}
}
// Add images from TEXTURES lump file
@ -409,14 +435,14 @@ namespace CodeImp.DoomBuilder.Data
#region ================== DECORATE
// This finds and returns a sprite stream
public override Dictionary<string, Stream> GetDecorateData(string pname)
// This finds and returns DECORATE streams
public override IEnumerable<TextResourceData> GetDecorateData(string pname)
{
Dictionary<string, Stream> result = new Dictionary<string, Stream>();
string[] allfilenames;
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
List<TextResourceData> result = new List<TextResourceData>();
string[] allfilenames;
// Find in root directory
string filename = Path.GetFileName(pname);
@ -424,8 +450,8 @@ namespace CodeImp.DoomBuilder.Data
if(filename.IndexOf('.') > -1)
{
string fullName = Path.Combine(pathname, filename);
if(FileExists(fullName))
string fullname = Path.Combine(pathname, filename);
if(FileExists(fullname))
{
allfilenames = new string[1];
allfilenames[0] = Path.Combine(pathname, filename);
@ -433,26 +459,18 @@ namespace CodeImp.DoomBuilder.Data
else
{
allfilenames = new string[0];
General.ErrorLogger.Add(ErrorType.Warning, "Unable to load DECORATE file '" + fullName + "'");
General.ErrorLogger.Add(ErrorType.Warning, "Unable to load DECORATE file \"" + fullname + "\"");
}
}
else
allfilenames = GetAllFilesWithTitle(pathname, filename, false);
foreach(string foundfile in allfilenames)
{
result.Add(foundfile, LoadFile(foundfile));
}
result.Add(new TextResourceData(this, LoadFile(foundfile), foundfile, true));
// Find in any of the wad files
for(int i = wads.Count - 1; i >= 0; i--)
{
Dictionary<string, Stream> wadresult = wads[i].GetDecorateData(pname);
foreach(KeyValuePair<string, Stream> group in wadresult)
{
result.Add(group.Key, group.Value);
}
}
result.AddRange(wads[i].GetDecorateData(pname));
return result;
}
@ -462,22 +480,25 @@ namespace CodeImp.DoomBuilder.Data
#region ================== MODELDEF (mxd)
//mxd
public override Dictionary<string, Stream> GetModeldefData()
public override IEnumerable<TextResourceData> GetModeldefData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Modedef should be in root folder
string[] files = GetAllFiles("", false);
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
List<TextResourceData> result = new List<TextResourceData>();
foreach(string s in files)
{
if(Path.GetFileNameWithoutExtension(s).ToUpperInvariant().StartsWith("MODELDEF"))
streams.Add(s, LoadFile(s));
if(Path.GetFileNameWithoutExtension(s).ToUpperInvariant().StartsWith("MODELDEF"))
result.Add(new TextResourceData(this, LoadFile(s), s, true));
}
return streams;
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetModeldefData());
return result;
}
#endregion
@ -504,21 +525,22 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd
public override KeyValuePair<string, Stream> GetVoxeldefData()
public override IEnumerable<TextResourceData> GetVoxeldefData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
//voxeldef should be in root folder
string[] files = GetAllFiles("", false);
// VOXELDEF should be in root folder
string[] files = GetAllFilesWithTitle("", "VOXELDEF", false);
List<TextResourceData> result = new List<TextResourceData>();
foreach(string s in files)
{
if(Path.GetFileNameWithoutExtension(s).ToUpperInvariant() == "VOXELDEF")
return new KeyValuePair<string,Stream>(s, LoadFile(s));
}
result.Add(new TextResourceData(this, LoadFile(s), s, true));
return new KeyValuePair<string,Stream>();
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetVoxeldefData());
return result;
}
#endregion
@ -526,24 +548,28 @@ namespace CodeImp.DoomBuilder.Data
#region ================== (Z)MAPINFO (mxd)
//mxd
public override Dictionary<string, Stream> GetMapinfoData()
public override IEnumerable<TextResourceData> GetMapinfoData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Mapinfo should be in root folder
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
List<TextResourceData> result = new List<TextResourceData>();
// Try to find (z)mapinfo
string[] files = GetAllFiles("", false);
foreach(string s in files)
string[] files = GetAllFilesWithTitle("", "ZMAPINFO", false);
if(files.Length == 0) files = GetAllFilesWithTitle("", "MAPINFO", false);
if(files.Length > 0)
{
string filename = Path.GetFileNameWithoutExtension(s.ToLowerInvariant());
if(filename == "zmapinfo" || filename == "mapinfo")
streams[s] = LoadFile(s);
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
}
return streams;
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetMapinfoData());
return result;
}
#endregion
@ -551,123 +577,123 @@ namespace CodeImp.DoomBuilder.Data
#region ================== GLDEFS (mxd)
//mxd
public override Dictionary<string, Stream> GetGldefsData(GameType gametype)
public override IEnumerable<TextResourceData> GetGldefsData(GameType gametype)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
List<TextResourceData> result = new List<TextResourceData>();
//at least one of gldefs should be in root folder
string[] files = GetAllFiles("", false);
// At least one of gldefs should be in the root folder
List<string> files = new List<string>();
//try to load game specific GLDEFS first
// Try to load game specific GLDEFS first
if(gametype != GameType.UNKNOWN)
{
string lumpname = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gametype];
foreach(string s in files)
{
if(Path.GetFileNameWithoutExtension(s).ToUpperInvariant() == lumpname)
streams.Add(s, LoadFile(s));
}
files.AddRange(GetAllFilesWhichTitleStartsWith("", lumpname, false));
}
// Can be several entries
foreach(string s in files)
{
if(Path.GetFileNameWithoutExtension(s).ToUpperInvariant().StartsWith("GLDEFS"))
streams.Add(s, LoadFile(s));
}
files.AddRange(GetAllFilesWhichTitleStartsWith("", "GLDEFS", false));
return streams;
// Add to collection
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetGldefsData(gametype));
return result;
}
#endregion
#region ================== REVERBS (mxd)
public override Dictionary<string, Stream> GetReverbsData()
public override IEnumerable<TextResourceData> GetReverbsData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>();
List<TextResourceData> result = new List<TextResourceData>();
string[] files = GetAllFilesWithTitle("", "REVERBS", false);
// Get from wads first
//TODO: is this the correct order?..
foreach(WADReader wr in wads)
{
Dictionary<string, Stream> wadstreams = wr.GetReverbsData();
foreach(KeyValuePair<string, Stream> pair in wadstreams) streams.Add(pair.Key, pair.Value);
}
// Add to collection
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
// Then from our own files
string foundfile = FindFirstFile("reverbs", false);
if((foundfile != null) && FileExists(foundfile))
{
streams.Add(foundfile, LoadFile(foundfile));
}
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetReverbsData());
return streams;
return result;
}
#endregion
#region ================== SNDSEQ (mxd)
public override Dictionary<string, Stream> GetSndSeqData()
public override IEnumerable<TextResourceData> GetSndSeqData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>();
List<TextResourceData> result = new List<TextResourceData>();
string[] files = GetAllFilesWithTitle("", "SNDSEQ", false);
// Get from wads first
//TODO: is this the correct order?..
foreach(WADReader wr in wads)
{
Dictionary<string, Stream> wadstreams = wr.GetSndSeqData();
foreach(KeyValuePair<string, Stream> pair in wadstreams) streams.Add(pair.Key, pair.Value);
}
// Add to collection
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
// Then from our own files
string foundfile = FindFirstFile("sndseq", false);
if(!string.IsNullOrEmpty(foundfile) && FileExists(foundfile))
{
streams.Add(foundfile, LoadFile(foundfile));
}
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetSndSeqData());
return streams;
return result;
}
#endregion
#region ================== ANIMDEFS (mxd)
public override Dictionary<string, Stream> GetAnimdefsData()
public override IEnumerable<TextResourceData> GetAnimdefsData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>();
List<TextResourceData> result = new List<TextResourceData>();
string[] files = GetAllFilesWithTitle("", "ANIMDEFS", false);
// Get from wads first
//TODO: is this the correct order?..
foreach(WADReader wr in wads)
{
Dictionary<string, Stream> wadstreams = wr.GetAnimdefsData();
foreach(KeyValuePair<string, Stream> pair in wadstreams)
streams.Add(pair.Key, pair.Value);
}
// Add to collection
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
// Then from our own files
string foundfile = FindFirstFile("animdefs", false);
if(!string.IsNullOrEmpty(foundfile) && FileExists(foundfile))
{
streams.Add(foundfile, LoadFile(foundfile));
}
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetAnimdefsData());
return streams;
return result;
}
#endregion
#region ================== TERRAIN (mxd)
//mxd
public override IEnumerable<TextResourceData> GetTerrainData()
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
List<TextResourceData> result = new List<TextResourceData>();
string[] files = GetAllFilesWithTitle("", "TERRAIN", false);
// Add to collection
foreach(string s in files)
result.Add(new TextResourceData(this, LoadFile(s), s, true));
// Find in any of the wad files
foreach(WADReader wr in wads) result.AddRange(wr.GetTerrainData());
return result;
}
#endregion
@ -700,7 +726,7 @@ namespace CodeImp.DoomBuilder.Data
}
// This copies images from a collection unless they already exist in the list
private static void AddImagesToList(Dictionary<long, ImageData> targetlist, ICollection<ImageData> sourcelist)
private static void AddImagesToList(Dictionary<long, ImageData> targetlist, IEnumerable<ImageData> sourcelist)
{
// Go for all source images
foreach(ImageData src in sourcelist)
@ -721,7 +747,7 @@ namespace CodeImp.DoomBuilder.Data
protected abstract string[] GetAllFilesWithTitle(string path, string title, bool subfolders);
//mxd. This must return all files in a given directory which title starts with given title
protected abstract string[] GetAllFilesWhichTitleStartsWith(string path, string title);
protected abstract string[] GetAllFilesWhichTitleStartsWith(string path, string title, bool subfolders);
// This must return all files in a given directory that match the given extension
protected abstract string[] GetFilesWithExt(string path, string extension, bool subfolders);

View file

@ -50,22 +50,23 @@ namespace CodeImp.DoomBuilder.Data
// Source
private WAD file;
private bool is_iwad;
private bool strictpatches;
private readonly bool strictpatches;
// Lump ranges
private List<LumpRange> flatranges;
private List<LumpRange> invertedflatranges; //mxd
private List<LumpRange> patchranges;
private List<LumpRange> spriteranges;
private List<LumpRange> textureranges;
private List<LumpRange> colormapranges;
private List<LumpRange> voxelranges; //mxd
private readonly List<LumpRange> flatranges;
private readonly List<LumpRange> invertedflatranges; //mxd
private readonly List<LumpRange> patchranges;
private readonly List<LumpRange> spriteranges;
private readonly List<LumpRange> textureranges;
private readonly List<LumpRange> colormapranges;
private readonly List<LumpRange> voxelranges; //mxd
#endregion
#region ================== Properties
public bool IsIWAD { get { return is_iwad; } }
internal WAD WadFile { get { return file; } } //mxd
#endregion
@ -74,7 +75,7 @@ namespace CodeImp.DoomBuilder.Data
// Constructor
public WADReader(DataLocation dl) : base(dl)
{
General.WriteLogLine("Opening WAD resource '" + location.location + "'");
General.WriteLogLine("Opening WAD resource \"" + location.location + "\"");
if(!File.Exists(location.location))
throw new FileNotFoundException("Could not find the file \"" + location.location + "\"", location.location);
@ -91,12 +92,12 @@ namespace CodeImp.DoomBuilder.Data
voxelranges = new List<LumpRange>(); //mxd
// Find ranges
FindRanges(patchranges, General.Map.Config.PatchRanges, "patches");
FindRanges(spriteranges, General.Map.Config.SpriteRanges, "sprites");
FindRanges(flatranges, General.Map.Config.FlatRanges, "flats");
FindRanges(textureranges, General.Map.Config.TextureRanges, "textures");
FindRanges(colormapranges, General.Map.Config.ColormapRanges, "colormaps");
FindRanges(voxelranges, General.Map.Config.VoxelRanges, "voxels");
FindRanges(patchranges, General.Map.Config.PatchRanges, "patches", "Patch");
FindRanges(spriteranges, General.Map.Config.SpriteRanges, "sprites", "Sprite");
FindRanges(flatranges, General.Map.Config.FlatRanges, "flats", "Flat");
FindRanges(textureranges, General.Map.Config.TextureRanges, "textures", "Texture");
FindRanges(colormapranges, General.Map.Config.ColormapRanges, "colormaps", "Colormap");
FindRanges(voxelranges, General.Map.Config.VoxelRanges, "voxels", "Voxel");
//mxd
invertedflatranges = new List<LumpRange>();
@ -140,7 +141,7 @@ namespace CodeImp.DoomBuilder.Data
// Not already disposed?
if(!isdisposed)
{
General.WriteLogLine("Closing WAD resource '" + location.location + "'");
General.WriteLogLine("Closing WAD resource \"" + location.location + "\"");
// Clean up
file.Dispose();
@ -176,7 +177,7 @@ namespace CodeImp.DoomBuilder.Data
}
// This fills a ranges list
private void FindRanges(List<LumpRange> ranges, IDictionary rangeinfos, string rangename)
private void FindRanges(List<LumpRange> ranges, IDictionary rangeinfos, string rangename, string elementname)
{
Dictionary<LumpRange, KeyValuePair<string, string>> failedranges = new Dictionary<LumpRange, KeyValuePair<string, string>>(); //mxd
Dictionary<int, bool> successfulrangestarts = new Dictionary<int, bool>(); //mxd
@ -193,9 +194,7 @@ namespace CodeImp.DoomBuilder.Data
int startindex = file.FindLumpIndex(rangestart);
while(startindex > -1)
{
LumpRange range = new LumpRange();
range.start = startindex;
range.end = file.FindLumpIndex(rangeend, startindex);
LumpRange range = new LumpRange { start = startindex, end = file.FindLumpIndex(rangeend, startindex) };
if(range.end > -1)
{
if(!successfulrangestarts.ContainsKey(startindex)) successfulrangestarts.Add(startindex, false); //mxd
@ -221,7 +220,20 @@ namespace CodeImp.DoomBuilder.Data
foreach(KeyValuePair<LumpRange, KeyValuePair<string, string>> group in failedranges)
{
if(successfulrangestarts.ContainsKey(group.Key.start)) continue;
General.ErrorLogger.Add(ErrorType.Warning, "'" + group.Value.Key + "' range at index " + group.Key.start + " is not closed in '" + location.location + "' ('" + group.Value.Value + "' marker is missing)!");
General.ErrorLogger.Add(ErrorType.Warning, "\"" + group.Value.Key + "\" range at index " + group.Key.start + " is not closed in resource \"" + location.location + "\" (\"" + group.Value.Value + "\" marker is missing).");
}
//mxd. Check duplicates
foreach(LumpRange range in ranges)
{
HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
for(int i = range.start + 1; i < range.end; i++)
{
if(names.Contains(file.Lumps[i].Name))
General.ErrorLogger.Add(ErrorType.Warning, elementname + " \"" + file.Lumps[i].Name + "\", index " + i + " is double defined in resource \"" + location.location + "\".");
else
names.Add(file.Lumps[i].Name);
}
}
}
@ -335,7 +347,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Textures
// This loads the textures
public override ICollection<ImageData> LoadTextures(PatchNames pnames)
public override IEnumerable<ImageData> LoadTextures(PatchNames pnames, Dictionary<string, TexturesParser> cachedparsers)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
@ -371,7 +383,7 @@ namespace CodeImp.DoomBuilder.Data
else
{
// Can't load image without size
General.ErrorLogger.Add(ErrorType.Error, "Can't load texture '" + file.Lumps[i].Name + "' because it doesn't contain any data.");
General.ErrorLogger.Add(ErrorType.Error, "Can't load texture \"" + file.Lumps[i].Name + "\" because it doesn't contain any data.");
}
}
}
@ -380,10 +392,21 @@ namespace CodeImp.DoomBuilder.Data
int lumpindex = file.FindLumpIndex("TEXTURES");
while(lumpindex > -1)
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
WADReader.LoadHighresTextures(filedata, Path.Combine(Path.GetFileName(file.Filename), "TEXTURES#" + lumpindex), ref images, null, null);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, "TEXTURES#" + lumpindex);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Textures)
images.Add(t.MakeImage());
}
else
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
cachedparsers.Add(fullpath, LoadHighresTextures(new TextResourceData(this, filedata, "TEXTURES", lumpindex, true), ref images)); //mxd
filedata.Dispose();
}
// Find next
lumpindex = file.FindLumpIndex("TEXTURES", lumpindex + 1);
}
@ -396,11 +419,11 @@ namespace CodeImp.DoomBuilder.Data
}
// This loads the texture definitions from a TEXTURES lump
public static void LoadHighresTextures(Stream stream, string filename, ref List<ImageData> images, Dictionary<long, ImageData> textures, Dictionary<long, ImageData> flats)
public static TexturesParser LoadHighresTextures(TextResourceData data, ref List<ImageData> images)
{
// Parse the data
TexturesParser parser = new TexturesParser();
parser.Parse(stream, filename, false);
parser.Parse(data, false);
if(parser.HasError) parser.LogError(); //mxd
// Make the textures
@ -410,6 +433,15 @@ namespace CodeImp.DoomBuilder.Data
ImageData img = t.MakeImage();
images.Add(img);
}
//mxd. Add to text resources collection
if(!General.Map.Data.TextResources.ContainsKey(parser.ScriptType))
General.Map.Data.TextResources[parser.ScriptType] = new HashSet<TextResource>();
foreach(KeyValuePair<string, TextResource> group in parser.TextResources)
General.Map.Data.TextResources[parser.ScriptType].Add(group.Value);
return parser; //mxd
}
// This loads a set of textures
@ -582,7 +614,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Flats
//mxd. This loads the flats
public override ICollection<ImageData> LoadFlats()
public override IEnumerable<ImageData> LoadFlats(Dictionary<string, TexturesParser> cachedparsers)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
@ -610,9 +642,20 @@ namespace CodeImp.DoomBuilder.Data
int lumpindex = file.FindLumpIndex("TEXTURES");
while(lumpindex > -1)
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
WADReader.LoadHighresFlats(filedata, Path.Combine(Path.GetFileName(file.Filename), "TEXTURES#" + lumpindex), ref images, null, null);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, "TEXTURES#" + lumpindex);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Flats)
images.Add(t.MakeImage());
}
else
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
cachedparsers.Add(fullpath, LoadHighresFlats(new TextResourceData(this, filedata, "TEXTURES", lumpindex, true), ref images)); //mxd
filedata.Dispose();
}
// Find next
lumpindex = file.FindLumpIndex("TEXTURES", lumpindex + 1);
@ -626,11 +669,11 @@ namespace CodeImp.DoomBuilder.Data
}
// This loads the flat definitions from a TEXTURES lump
public static void LoadHighresFlats(Stream stream, string filename, ref List<ImageData> images, Dictionary<long, ImageData> textures, Dictionary<long, ImageData> flats)
public static TexturesParser LoadHighresFlats(TextResourceData data, ref List<ImageData> images)
{
// Parse the data
TexturesParser parser = new TexturesParser();
parser.Parse(stream, filename, false);
parser.Parse(data, false);
if(parser.HasError) parser.LogError(); //mxd
// Make the textures
@ -640,6 +683,15 @@ namespace CodeImp.DoomBuilder.Data
ImageData img = t.MakeImage();
images.Add(img);
}
//mxd. Add to text resources collection
if(!General.Map.Data.TextResources.ContainsKey(parser.ScriptType))
General.Map.Data.TextResources[parser.ScriptType] = new HashSet<TextResource>();
foreach(KeyValuePair<string, TextResource> group in parser.TextResources)
General.Map.Data.TextResources[parser.ScriptType].Add(group.Value);
return parser; //mxd
}
// This finds and returns a patch stream
@ -664,7 +716,7 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Sprite
// This loads the textures
public override ICollection<ImageData> LoadSprites()
public override IEnumerable<ImageData> LoadSprites(Dictionary<string, TexturesParser> cachedparsers)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
@ -675,10 +727,21 @@ namespace CodeImp.DoomBuilder.Data
int lumpindex = file.FindLumpIndex("TEXTURES");
while(lumpindex > -1)
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
WADReader.LoadHighresSprites(filedata, Path.Combine(Path.GetFileName(file.Filename), "TEXTURES#" + lumpindex), ref images, null, null);
filedata.Dispose();
//mxd. Added TexturesParser caching
string fullpath = Path.Combine(this.location.location, "TEXTURES#" + lumpindex);
if(cachedparsers.ContainsKey(fullpath))
{
// Make the textures
foreach(TextureStructure t in cachedparsers[fullpath].Sprites)
images.Add(t.MakeImage());
}
else
{
MemoryStream filedata = new MemoryStream(file.Lumps[lumpindex].Stream.ReadAllBytes());
cachedparsers.Add(fullpath, LoadHighresSprites(new TextResourceData(this, filedata, "TEXTURES", lumpindex, true), ref images)); //mxd
filedata.Dispose();
}
// Find next
lumpindex = file.FindLumpIndex("TEXTURES", lumpindex + 1);
}
@ -688,11 +751,11 @@ namespace CodeImp.DoomBuilder.Data
}
// This loads the sprites definitions from a TEXTURES lump
public static void LoadHighresSprites(Stream stream, string filename, ref List<ImageData> images, Dictionary<long, ImageData> textures, Dictionary<long, ImageData> flats)
public static TexturesParser LoadHighresSprites(TextResourceData data, ref List<ImageData> images)
{
// Parse the data
TexturesParser parser = new TexturesParser();
parser.Parse(stream, filename, false);
parser.Parse(data, false);
if(parser.HasError) parser.LogError(); //mxd
// Make the textures
@ -702,6 +765,15 @@ namespace CodeImp.DoomBuilder.Data
ImageData img = t.MakeImage();
images.Add(img);
}
//mxd. Add to text resources collection
if(!General.Map.Data.TextResources.ContainsKey(parser.ScriptType))
General.Map.Data.TextResources[parser.ScriptType] = new HashSet<TextResource>();
foreach(KeyValuePair<string, TextResource> group in parser.TextResources)
General.Map.Data.TextResources[parser.ScriptType].Add(group.Value);
return parser; //mxd
}
// This finds and returns a sprite stream
@ -763,11 +835,10 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd
public override KeyValuePair<string, Stream> GetVoxeldefData()
public override IEnumerable<TextResourceData> GetVoxeldefData()
{
Lump lump = file.FindLump("VOXELDEF");
if(lump != null) return new KeyValuePair<string, Stream>("VOXELDEF", lump.Stream);
return new KeyValuePair<string, Stream>();
if(issuspended) throw new Exception("Data reader is suspended");
return GetFirstLump("VOXELDEF");
}
//mxd. This finds and returns a voxel stream or null if no voxel was found
@ -791,117 +862,107 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Decorate, Gldefs, Mapinfo, etc...
// This finds and returns a sprite stream
public override Dictionary<string, Stream> GetDecorateData(string pname)
public override IEnumerable<TextResourceData> GetDecorateData(string pname)
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetAllLumps("DECORATE");
}
//mxd. Should be only one entry per wad
public override IEnumerable<TextResourceData> GetMapinfoData()
{
if(issuspended) throw new Exception("Data reader is suspended");
// First look for ZMAPINFO
List<TextResourceData> result = new List<TextResourceData>();
result.AddRange(GetFirstLump("ZMAPINFO"));
// Then for MAPINFO
if(result.Count == 0) result.AddRange(GetFirstLump("MAPINFO"));
return result;
}
//mxd
public override IEnumerable<TextResourceData> GetGldefsData(GameType gametype)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> result = new Dictionary<string, Stream>();
List<TextResourceData> result = new List<TextResourceData>();
// Find all lumps named 'DECORATE'
int lumpindex = file.FindLumpIndex(pname);
// Try to load game specific GLDEFS first
if(gametype != GameType.UNKNOWN)
{
string lumpname = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gametype];
result.AddRange(GetFirstLump(lumpname));
}
// Should be only one entry per wad
result.AddRange(GetFirstLump("GLDEFS"));
return result;
}
//mxd
public override IEnumerable<TextResourceData> GetModeldefData()
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetFirstLump("MODELDEF");
}
//mxd
public override IEnumerable<TextResourceData> GetReverbsData()
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetFirstLump("REVERBS");
}
//mxd
public override IEnumerable<TextResourceData> GetSndSeqData()
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetFirstLump("SNDSEQ");
}
//mxd
public override IEnumerable<TextResourceData> GetAnimdefsData()
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetAllLumps("ANIMDEFS");
}
//mxd
public override IEnumerable<TextResourceData> GetTerrainData()
{
if(issuspended) throw new Exception("Data reader is suspended");
return GetAllLumps("TERRAIN");
}
//mxd
private IEnumerable<TextResourceData> GetFirstLump(string name)
{
List<TextResourceData> result = new List<TextResourceData>();
int lumpindex = file.FindLumpIndex(name);
if(lumpindex != -1)
result.Add(new TextResourceData(this, file.Lumps[lumpindex].Stream, name, lumpindex, true));
return result;
}
//mxd
private IEnumerable<TextResourceData> GetAllLumps(string name)
{
List<TextResourceData> result = new List<TextResourceData>();
// Find all lumps with given name
int lumpindex = file.FindLumpIndex(name);
while(lumpindex > -1)
{
//mxd. Since we are using Dictionary, all names should be unique
result.Add(Path.Combine(file.Filename, pname + "#" + lumpindex), file.Lumps[lumpindex].Stream);
// Find next
lumpindex = file.FindLumpIndex(pname, lumpindex + 1);
}
return result;
}
// Add to collection
result.Add(new TextResourceData(this, file.Lumps[lumpindex].Stream, name, lumpindex, true));
//mxd
public override Dictionary<string, Stream> GetMapinfoData()
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
string src = "ZMAPINFO";
//should be only one entry per wad
//first look for ZMAPINFO
int lumpindex = file.FindLumpIndex(src);
//then for MAPINFO
if(lumpindex == -1)
{
src = "MAPINFO";
lumpindex = file.FindLumpIndex(src);
// Find next entry
lumpindex = file.FindLumpIndex(name, lumpindex + 1);
}
if(lumpindex != -1) streams.Add(src, file.Lumps[lumpindex].Stream);
return streams;
}
//mxd
public override Dictionary<string, Stream> GetGldefsData(GameType gameType)
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
int lumpindex;
//try to load game specific GLDEFS first
if(gameType != GameType.UNKNOWN)
{
string lumpName = Gldefs.GLDEFS_LUMPS_PER_GAME[(int)gameType];
lumpindex = file.FindLumpIndex(lumpName);
if(lumpindex != -1)
streams.Add(lumpName, file.Lumps[lumpindex].Stream);
}
//should be only one entry per wad
lumpindex = file.FindLumpIndex("GLDEFS");
if(lumpindex != -1) streams.Add("GLDEFS", file.Lumps[lumpindex].Stream);
return streams;
}
//mxd
public override Dictionary<string, Stream> GetModeldefData()
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> streams = new Dictionary<string, Stream>(StringComparer.Ordinal);
int lumpindex = file.FindLumpIndex("MODELDEF");
if(lumpindex != -1) streams.Add("MODELDEF", file.Lumps[lumpindex].Stream);
return streams;
}
//mxd
public override Dictionary<string, Stream> GetReverbsData()
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> result = new Dictionary<string, Stream>();
Lump lump = file.FindLump("REVERBS");
if(lump != null) result.Add(Path.Combine(location.location, "REVERBS"), lump.Stream);
return result;
}
//mxd
public override Dictionary<string, Stream> GetSndSeqData()
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> result = new Dictionary<string, Stream>();
Lump lump = file.FindLump("SNDSEQ");
if(lump != null) result.Add(Path.Combine(location.location, "SNDSEQ"), lump.Stream);
return result;
}
//mxd
public override Dictionary<string, Stream> GetAnimdefsData()
{
if(issuspended) throw new Exception("Data reader is suspended");
Dictionary<string, Stream> result = new Dictionary<string, Stream>();
Lump lump = file.FindLump("ANIMDEFS");
if(lump != null) result.Add(Path.Combine(location.location, "ANIMDEFS"), lump.Stream);
return result;
}

View file

@ -120,6 +120,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
UpdateTagPicker(tags[0]);
UpdateTagsList();
removetag.Enabled = (tags.Count > 1);
clear.Enabled = (tagpicker.Text.Trim() != "0");
}
public void SetValue(List<int> newtags, bool first)
@ -278,8 +279,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
private void clear_Click(object sender, EventArgs e)
{
tagpicker.SelectedIndex = -1;
tagpicker.Focus();
tagpicker.Text = "0";
tagpicker.SelectAll();
}
private void addtag_Click(object sender, EventArgs e)
@ -365,6 +367,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Controls
}
string text = tagpicker.Text.Trim();
clear.Enabled = (text != "0");
if(string.IsNullOrEmpty(text))
{
tags[curtagindex] = int.MinValue;

View file

@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
#region ================== Properties
public bool IsDefined { get { return isdefined; } }
public bool IsDefined { get { return isdefined; } internal set { isdefined = value; } }
public string Title { get { return title; } internal set { title = value; isdefined = true; } }
public string Sky1 { get { return sky1; } internal set { sky1 = value; isdefined = true; } }

View file

@ -2,6 +2,8 @@
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
@ -10,6 +12,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
internal sealed class AcsParserSE : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.ACS; } }
internal delegate void IncludeDelegate(AcsParserSE parser, string includefile, IncludeType includetype);
internal IncludeDelegate OnInclude;
@ -31,6 +35,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
internal bool AddArgumentsToScriptNames;
internal bool IsMapScriptsLump;
internal bool IgnoreErrors;
internal enum IncludeType
{
@ -50,37 +55,47 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
specialtokens += "(,)";
}
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
return Parse(stream, sourcefilename, new HashSet<string>(), false, IncludeType.NONE, clearerrors);
return Parse(data, new HashSet<string>(), false, IncludeType.NONE, clearerrors);
}
public bool Parse(Stream stream, string sourcefilename, bool processincludes, IncludeType includetype, bool clearerrors)
public bool Parse(TextResourceData data, bool processincludes, IncludeType includetype, bool clearerrors)
{
return Parse(stream, sourcefilename, includestoskip, processincludes, includetype, clearerrors);
return Parse(data, includestoskip, processincludes, includetype, clearerrors);
}
public bool Parse(Stream stream, string sourcefilename, HashSet<string> configincludes, bool processincludes, IncludeType includetype, bool clearerrors)
public bool Parse(TextResourceData data, HashSet<string> configincludes, bool processincludes, IncludeType includetype, bool clearerrors)
{
string source = sourcefilename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
string source = data.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
// Duplicate checks
if(parsedlumps.Contains(source))
{
ReportError("Already parsed '" + source + "'. Check your #include directives");
return false;
ReportError("Already parsed \"" + source + "\". Check your #include directives");
return IgnoreErrors;
}
parsedlumps.Add(source);
includestoskip = configincludes;
int bracelevel = 0;
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Keep local data
Stream localstream = datastream;
string localsourcename = sourcename;
int localsourcelumpindex = sourcelumpindex;
BinaryReader localreader = datareader;
DataLocation locallocation = datalocation; //mxd
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -98,7 +113,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
case "script":
{
SkipWhitespace(true);
int startpos = (int)stream.Position;
int startpos = (int)datastream.Position;
token = ReadToken();
//is it named script?
@ -139,7 +154,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!string.IsNullOrEmpty(token))
{
int commentstart = token.IndexOf("//", System.StringComparison.Ordinal);
int commentstart = token.IndexOf("//", StringComparison.Ordinal);
if(commentstart != -1) //found comment
{
commentstart += 2;
@ -168,7 +183,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
SkipWhitespace(true);
string funcname = ReadToken(); //read return type
SkipWhitespace(true);
int startpos = (int)stream.Position;
int startpos = (int)datastream.Position;
funcname += " " + ReadToken(); //read function name
// Try to parse argument names
@ -188,7 +203,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(IsMapScriptsLump)
{
ReportError("SCRIPTS lump can not be compiled as a library");
return false;
if(!IgnoreErrors) return false;
}
SkipWhitespace(true);
@ -197,7 +212,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!libname.StartsWith("\"") || !libname.EndsWith("\""))
{
ReportError("#library name should be quoted");
return false;
return IgnoreErrors;
}
libname = StripTokenQuotes(libname);
@ -205,7 +220,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(string.IsNullOrEmpty(libname))
{
ReportError("Expected library name");
return false;
return IgnoreErrors;
}
// Store only when the script compiling was executed for is library
@ -231,7 +246,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!includelump.StartsWith("\"") || !includelump.EndsWith("\""))
{
ReportError(token + " filename should be quoted");
return false;
return IgnoreErrors;
}
includelump = StripTokenQuotes(includelump);
@ -239,7 +254,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(string.IsNullOrEmpty(includelump))
{
ReportError("Expected file name to " + token);
return false;
return IgnoreErrors;
}
includelump = includelump.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
@ -251,7 +266,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
string includelumppath = GetRootedPath(source, includelump);
// Rooting succeeded?
if(HasError || string.IsNullOrEmpty(includelumppath)) return false;
if((HasError && !IgnoreErrors) || string.IsNullOrEmpty(includelumppath))
return IgnoreErrors;
// Already parsed?
if(includes.Contains(includelumppath))
@ -260,8 +276,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
//and must be included/imported separately
if(!islibrary)
{
ReportError("Already parsed '" + includelump + "'. Check your " + token + " directives");
return false;
ReportError("Already parsed \"" + includelump + "\". Check your " + token + " directives");
return IgnoreErrors;
}
}
else
@ -272,16 +288,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// Callback to parse this file
if(OnInclude != null)
{
IsMapScriptsLump = false;
OnInclude(this, includelumppath, islibrary ? IncludeType.LIBRARY : IncludeType.INCLUDE);
}
// Bail out on error
if(this.HasError) return false;
if(this.HasError && !IgnoreErrors) return false;
// Set our buffers back to continue parsing
datastream = localstream;
datareader = localreader;
sourcename = localsourcename;
sourcelumpindex = localsourcelumpindex; //mxd
datalocation = locallocation; //mxd
}
}
break;
@ -340,9 +359,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
return "(void)";
}
protected override string GetLanguageType()
{
return "ACS";
}
}
}

View file

@ -1,5 +1,6 @@
using System.IO;
using System.Collections.Generic;
using System.Collections.Generic;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
@ -9,6 +10,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
internal sealed class DecorateParserSE : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.DECORATE; } }
private readonly List<ScriptItem> actors;
public List<ScriptItem> Actors { get { return actors; } }
@ -17,9 +20,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
actors = new List<ScriptItem>();
}
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -28,7 +39,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "ACTOR") continue;
SkipWhitespace(true);
int startpos = (int)stream.Position;
int startpos = (int)datastream.Position;
List<string> definition = new List<string>();
@ -47,10 +58,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
actors.Sort(ScriptItem.SortByName);
return true;
}
protected override string GetLanguageType()
{
return "DECORATE";
}
}
}

View file

@ -5,6 +5,8 @@ using System.Drawing;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.Rendering;
@ -56,6 +58,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
#region ================== Properties
internal override ScriptType ScriptType { get { return ScriptType.GLDEFS; } }
internal Dictionary<string, DynamicLightData> LightsByName { get { return lightsbyname; } }
internal Dictionary<string, string> Objects { get { return objects; } }
internal Dictionary<long, GlowingFlatData> GlowingFlats { get { return glowingflats; } }
@ -82,14 +86,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
#region ================== Parsing
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Keep local data
Stream localstream = datastream;
string localsourcename = sourcename;
int localsourcelumpindex = sourcelumpindex;
BinaryReader localreader = datareader;
DataLocation locallocation = datalocation;
string localtextresourcepath = textresourcepath;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -123,6 +138,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
datastream = localstream;
datareader = localreader;
sourcename = localsourcename;
sourcelumpindex = localsourcelumpindex;
datalocation = locallocation;
textresourcepath = localtextresourcepath;
break;
case "$gzdb_skip": return !this.HasError;
@ -173,7 +191,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Red))
{
// Not numeric!
ReportError("Expected Red color value, but got '" + token + "'");
ReportError("Expected Red color value, but got \"" + token + "\"");
return false;
}
@ -182,7 +200,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Green))
{
// Not numeric!
ReportError("Expected Green color value, but got '" + token + "'");
ReportError("Expected Green color value, but got \"" + token + "\"");
return false;
}
@ -191,7 +209,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out light.Color.Blue))
{
// Not numeric!
ReportError("Expected Blue color value, but got '" + token + "'");
ReportError("Expected Blue color value, but got \"" + token + "\"");
return false;
}
break;
@ -205,7 +223,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.PrimaryRadius))
{
// Not numeric!
ReportError("Expected Size value, but got '" + token + "'");
ReportError("Expected Size value, but got \"" + token + "\"");
return false;
}
light.PrimaryRadius *= 2;
@ -213,7 +231,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("'" + token + "' is not valid property for " + lighttype);
ReportError("\"" + token + "\" is not valid property for " + lighttype);
return false;
}
break;
@ -224,7 +242,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!ReadSignedFloat(token, ref light.Offset.X))
{
// Not numeric!
ReportError("Expected Offset X value, but got '" + token + "'");
ReportError("Expected Offset X value, but got \"" + token + "\"");
return false;
}
@ -233,7 +251,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!ReadSignedFloat(token, ref light.Offset.Z))
{
// Not numeric!
ReportError("Expected Offset Y value, but got '" + token + "'");
ReportError("Expected Offset Y value, but got \"" + token + "\"");
return false;
}
@ -242,7 +260,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!ReadSignedFloat(token, ref light.Offset.Y))
{
// Not numeric!
ReportError("Expected Offset Z value, but got '" + token + "'");
ReportError("Expected Offset Z value, but got \"" + token + "\"");
return false;
}
break;
@ -256,7 +274,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
{
// Not numeric!
ReportError("expected Subtractive value, but got '" + token + "'");
ReportError("expected Subtractive value, but got \"" + token + "\"");
return false;
}
@ -273,7 +291,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
{
// Not numeric!
ReportError("Expected DontLightSelf value, but got '" + token + "'");
ReportError("Expected DontLightSelf value, but got \"" + token + "\"");
return false;
}
@ -291,7 +309,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out interval))
{
// Not numeric!
ReportError("Expected Interval value, but got '" + token + "'");
ReportError("Expected Interval value, but got \"" + token + "\"");
return false;
}
@ -309,7 +327,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("'" + token + "' is not valid property for " + lighttype);
ReportError("\"" + token + "\" is not valid property for " + lighttype);
return false;
}
break;
@ -323,7 +341,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out light.SecondaryRadius))
{
// Not numeric!
ReportError("Expected SecondarySize value, but got '" + token + "'");
ReportError("Expected SecondarySize value, but got \"" + token + "\"");
return false;
}
@ -331,7 +349,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("'" + token + "' is not valid property for " + lighttype);
ReportError("\"" + token + "\" is not valid property for " + lighttype);
return false;
}
break;
@ -346,7 +364,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out chance))
{
// Not numeric!
ReportError("Expected Chance value, but got '" + token + "'");
ReportError("Expected Chance value, but got \"" + token + "\"");
return false;
}
@ -355,7 +373,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("'" + token + "' is not valid property for " + lighttype);
ReportError("\"" + token + "\" is not valid property for " + lighttype);
return false;
}
break;
@ -370,7 +388,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!float.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out scale))
{
// Not numeric!
ReportError("Expected Scale value, but got '" + token + "'");
ReportError("Expected Scale value, but got \"" + token + "\"");
return false;
}
@ -386,7 +404,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("'" + token + "' is not valid property for " + lighttype);
ReportError("\"" + token + "\" is not valid property for " + lighttype);
return false;
}
break;
@ -398,14 +416,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// General checks
if(light.Color.Red == 0.0f && light.Color.Green == 0.0f && light.Color.Blue == 0.0f)
{
LogWarning("'" + lightname + "' light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom");
LogWarning("\"" + lightname + "\" light Color is " + light.Color.Red + "," + light.Color.Green + "," + light.Color.Blue + ". It won't be shown in GZDoom");
skip = true;
}
// Light-type specific checks
if(light.Type == DynamicLightType.NORMAL && light.PrimaryRadius == 0)
{
LogWarning("'" + lightname + "' light Size is 0. It won't be shown in GZDoom");
LogWarning("\"" + lightname + "\" light Size is 0. It won't be shown in GZDoom");
skip = true;
}
@ -413,7 +431,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
if(light.PrimaryRadius == 0 && light.SecondaryRadius == 0)
{
LogWarning("'" + lightname + "' light Size and SecondarySize are 0. This light won't be shown in GZDoom");
LogWarning("\"" + lightname + "\" light Size and SecondarySize are 0. This light won't be shown in GZDoom");
skip = true;
}
}
@ -484,7 +502,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
LogWarning("Light declaration not found for light '" + token + "'");
LogWarning("Light declaration not found for light \"" + token + "\"");
}
}
}
@ -605,7 +623,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else
{
ReportError("expected glow color value, but got '" + token + "'");
ReportError("expected glow color value, but got \"" + token + "\"");
return false;
}
}
@ -662,8 +680,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!fullblack && !fullbright)
{
string expectedflags = (subtractivetexture ? "'fullbright'" : "'fullbright' or 'fullblack'");
ReportError("expected " + expectedflags + " flag, but got '" + token + "'");
string expectedflags = (subtractivetexture ? "\"fullbright\"" : "\"fullbright\" or \"fullblack\"");
ReportError("expected " + expectedflags + " flag, but got \"" + token + "\"");
return false;
}
@ -697,7 +715,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
return false;
}
if(skyboxes.ContainsKey(name)) LogWarning("Skybox \"" + name + "\" is double-defined");
if(skyboxes.ContainsKey(name)) LogWarning("Skybox \"" + name + "\" is double defined");
SkyboxInfo info = new SkyboxInfo(name.ToUpperInvariant());
@ -782,7 +800,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// Already parsed?
if(parsedlumps.Contains(includelump))
{
ReportError("Already parsed '" + includelump + "'. Check your #include directives");
ReportError("Already parsed \"" + includelump + "\". Check your #include directives");
return false;
}
@ -805,11 +823,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
parsedlumps.Clear();
}
protected override string GetLanguageType()
{
return "GLDEFS";
}
#endregion
}
}

View file

@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using SlimDX;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
@ -34,6 +36,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
#region ================== Properties
internal override ScriptType ScriptType { get { return ScriptType.MAPINFO; } }
public MapInfo MapInfo { get { return mapinfo; } }
public Dictionary<int, string> SpawnNums { get { return spawnnums; } }
public Dictionary<int, string> DoomEdNums { get { return doomednums; } }
@ -59,21 +63,33 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
#region ================== Parsing
override public bool Parse(Stream stream, string sourcefilename, bool clearerrors)
override public bool Parse(TextResourceData data, bool clearerrors)
{
if(string.IsNullOrEmpty(mapname)) throw new NotSupportedException("Map name required!");
return Parse(stream, sourcefilename, mapname, clearerrors);
return Parse(data, mapname, clearerrors);
}
public bool Parse(Stream stream, string sourcefilename, string mapname, bool clearerrors)
public bool Parse(TextResourceData data, string mapname, bool clearerrors)
{
this.mapname = mapname.ToLowerInvariant();
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Keep local data
Stream localstream = datastream;
string localsourcename = sourcename;
int localsourcelumpindex = sourcelumpindex;
BinaryReader localreader = datareader;
DataLocation locallocation = datalocation;
string localtextresourcepath = textresourcepath;
// Classic format skip stoppers...
HashSet<string> breakat = new HashSet<string> { "map", "defaultmap", "adddefaultmap" };
@ -135,6 +151,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// Parse properties
if(!ParseMapBlock()) return false;
// There is a map entry for current map, which makes it defined
mapinfo.IsDefined = true;
break;
case "include":
@ -144,6 +163,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
datastream = localstream;
datareader = localreader;
sourcename = localsourcename;
sourcelumpindex = localsourcelumpindex;
datalocation = locallocation;
textresourcepath = localtextresourcepath;
break;
case "gameinfo":
@ -211,7 +233,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// Already parsed?
if(parsedlumps.Contains(includelump))
{
ReportError("Already parsed '" + includelump + "'. Check your include directives");
ReportError("Already parsed \"" + includelump + "\". Check your include directives");
return false;
}
@ -259,7 +281,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
string skyflatname = StripTokenQuotes(ReadToken());
if(string.IsNullOrEmpty(skyflatname))
{
ReportError("Unable to get SkyFlatName value");
ReportError("Expected SkyFlatName value");
return false; // Finished with this file
}
@ -291,7 +313,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
{
// Not numeric!
ReportError("Expected DoomEdNums entry number, but got '" + token + "'");
ReportError("Expected DoomEdNums entry number, but got \"" + token + "\"");
return false; // Finished with this file
}
@ -303,7 +325,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
string classname = StripTokenQuotes(ReadToken());
if(string.IsNullOrEmpty(classname))
{
ReportError("Unable to get DoomEdNums entry class definition");
ReportError("Expected DoomEdNums class definition");
return false; // Finished with this file
}
@ -344,7 +366,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out id))
{
// Not numeric!
ReportError("Expected SpawnNums number, but got '" + token + "'");
ReportError("Expected SpawnNums number, but got \"" + token + "\"");
return false; // Finished with this file
}
@ -495,7 +517,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!ReadSignedFloat(token, ref scrollspeed))
{
// Not numeric!
ReportError("Expected " + skytype + " scroll speed value, but got '" + token + "'");
ReportError("Expected " + skytype + " scroll speed value, but got \"" + token + "\"");
return false;
}
@ -579,7 +601,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
else //...or not
{
ReportError("Failed to parse " + fadetype + " value from string '" + colorval + "'");
ReportError("Failed to parse " + fadetype + " value from string \"" + colorval + "\"");
return false;
}
@ -603,7 +625,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!ReadSignedInt(token, ref val))
{
// Not numeric!
ReportError("Expected " + shadetype + " value, but got '" + token + "'");
ReportError("Expected " + shadetype + " value, but got \"" + token + "\"");
return false;
}
@ -632,7 +654,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
{
// Not numeric!
ReportError("Expected " + densitytype + " value, but got '" + token + "'");
ReportError("Expected " + densitytype + " value, but got \"" + token + "\"");
return false;
}
@ -670,11 +692,6 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
return false;
}
protected override string GetLanguageType()
{
return "MAPINFO";
}
#endregion
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
using CodeImp.DoomBuilder.GZBuilder.Data;
@ -8,6 +9,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
internal class ModeldefParser : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.MODELDEF; } }
private readonly Dictionary<string, int> actorsbyclass;
internal Dictionary<string, int> ActorsByClass { get { return actorsbyclass; } }
@ -21,10 +24,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
//should be called after all decorate actors are parsed
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -35,21 +47,15 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
token = StripTokenQuotes(token).ToLowerInvariant();
if(token == "model") //model structure start
{
//find classname
// Find classname
SkipWhitespace(true);
string displayclassname = StripTokenQuotes(ReadToken(ActorStructure.ACTOR_CLASS_SPECIAL_TOKENS));
string classname = displayclassname.ToLowerInvariant();
if(!string.IsNullOrEmpty(classname) && !entries.ContainsKey(classname))
{
//now find opening brace
SkipWhitespace(true);
token = ReadToken();
if(token != "{")
{
General.ErrorLogger.Add(ErrorType.Error, "Unexpected token found in '" + sourcefilename + "' at line " + GetCurrentLineNumber() + ": expected '{', but got '" + token + "'");
continue; //something wrong with modeldef declaration, continue to next one
}
// Now find opening brace
if(!NextTokenIs("{")) return false;
ModeldefStructure mds = new ModeldefStructure();
if(mds.Parse(this, displayclassname) && mds.ModelData != null)
@ -103,10 +109,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
}
while(scopelevel > 0);
}
protected override string GetLanguageType()
{
return "MODELDEF";
}
}
}

View file

@ -1,7 +1,9 @@
#region ================== Namespaces
using CodeImp.DoomBuilder.Data;
#region ================== Namespaces
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
@ -13,6 +15,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
internal sealed class ModeldefParserSE : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.MODELDEF; } }
private readonly List<ScriptItem> models;
internal List<ScriptItem> Models { get { return models; } }
@ -21,9 +25,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
models = new List<ScriptItem>();
}
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -32,7 +44,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(string.IsNullOrEmpty(token) || token.ToUpperInvariant() != "MODEL") continue;
SkipWhitespace(true);
int startpos = (int)stream.Position;
int startpos = (int)datastream.Position;
string modelname = ReadToken();
SkipWhitespace(true);
@ -55,10 +67,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
models.Sort(ScriptItem.SortByName);
return true;
}
protected override string GetLanguageType()
{
return "MODELDEF";
}
}
}

View file

@ -60,7 +60,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
path = parser.StripTokenQuotes(parser.ReadToken(false)).Replace("/", "\\"); // Don't skip newline
if(string.IsNullOrEmpty(path))
{
parser.ReportError("Expected model path, but got '" + token + "'");
parser.ReportError("Expected model path");
return false;
}
break;
@ -78,7 +78,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out index))
{
// Not numeric!
parser.ReportError("Expected model index, but got '" + token + "'");
parser.ReportError("Expected model index, but got \"" + token + "\"");
return false;
}
@ -105,13 +105,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
string modelext = Path.GetExtension(token);
if(string.IsNullOrEmpty(modelext))
{
parser.ReportError("Model '" + token + "' won't be loaded. Models without extension are not supported by GZDoom");
parser.ReportError("Model \"" + token + "\" won't be loaded. Models without extension are not supported by GZDoom");
return false;
}
if(modelext != ".md3" && modelext != ".md2")
{
parser.ReportError("Model '" + token + "' won't be loaded. Only MD2 and MD3 models are supported");
parser.ReportError("Model \"" + token + "\" won't be loaded. Only MD2 and MD3 models are supported");
return false;
}
@ -132,7 +132,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out skinIndex))
{
// Not numeric!
parser.ReportError("Expected skin index, but got '" + token + "'");
parser.ReportError("Expected skin index, but got \"" + token + "\"");
return false;
}
@ -148,7 +148,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
token = parser.StripTokenQuotes(parser.ReadToken(false)).ToLowerInvariant(); // Don't skip newline
if(string.IsNullOrEmpty(token))
{
parser.ReportError("Skin path required");
parser.ReportError("Expected skin path");
return false;
}
@ -159,7 +159,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
string texext = Path.GetExtension(token);
if(Array.IndexOf(ModelData.SUPPORTED_TEXTURE_EXTENSIONS, texext) == -1)
{
parser.ReportError("Image format '" + texext + "' is not supported");
parser.ReportError("Image format \"" + texext + "\" is not supported");
return false;
}
@ -177,7 +177,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref scale.Y))
{
// Not numeric!
parser.ReportError("Expected Scale X value, but got '" + token + "'");
parser.ReportError("Expected Scale X value, but got \"" + token + "\"");
return false;
}
@ -186,7 +186,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref scale.X))
{
// Not numeric!
parser.ReportError("Expected Scale Y value, but got '" + token + "'");
parser.ReportError("Expected Scale Y value, but got \"" + token + "\"");
return false;
}
@ -195,7 +195,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref scale.Z))
{
// Not numeric!
parser.ReportError("Expected Scale Z value, but got '" + token + "'");
parser.ReportError("Expected Scale Z value, but got \"" + token + "\"");
return false;
}
break;
@ -210,7 +210,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref offset.X))
{
// Not numeric!
parser.ReportError("Expected Offset X value, but got '" + token + "'");
parser.ReportError("Expected Offset X value, but got \"" + token + "\"");
return false;
}
@ -219,7 +219,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref offset.Y))
{
// Not numeric!
parser.ReportError("Expected Offset Y value, but got '" + token + "'");
parser.ReportError("Expected Offset Y value, but got \"" + token + "\"");
return false;
}
@ -228,7 +228,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref offset.Z))
{
// Not numeric!
parser.ReportError("Expected Offset Z value, but got '" + token + "'");
parser.ReportError("Expected Offset Z value, but got \"" + token + "\"");
return false;
}
break;
@ -243,7 +243,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref offset.Z))
{
// Not numeric!
parser.ReportError("Expected ZOffset value, but got '" + token + "'");
parser.ReportError("Expected ZOffset value, but got \"" + token + "\"");
return false;
}
break;
@ -258,7 +258,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref angleOffset))
{
// Not numeric!
parser.ReportError("Expected AngleOffset value, but got '" + token + "'");
parser.ReportError("Expected AngleOffset value, but got \"" + token + "\"");
return false;
}
break;
@ -273,7 +273,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref pitchOffset))
{
// Not numeric!
parser.ReportError("Expected PitchOffset value, but got '" + token + "'");
parser.ReportError("Expected PitchOffset value, but got \"" + token + "\"");
return false;
}
break;
@ -288,7 +288,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedFloat(token, ref rollOffset))
{
// Not numeric!
parser.ReportError("Expected RollOffset value, but got '" + token + "'");
parser.ReportError("Expected RollOffset value, but got \"" + token + "\"");
return false;
}
break;
@ -382,7 +382,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out modelIndex))
{
// Not numeric!
parser.ReportError("Expected model index, but got '" + token + "'");
parser.ReportError("Expected model index, but got \"" + token + "\"");
return false;
}
@ -410,7 +410,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(!parser.ReadSignedInt(token, ref frame))
{
// Not numeric!
parser.ReportError("Expected model frame index, but got '" + token + "'");
parser.ReportError("Expected model frame index, but got \"" + token + "\"");
return false;
}
@ -457,14 +457,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
// Bail out when got errors or no models are used
if(Array.IndexOf(modelsUsed, true) == -1)
{
parser.ReportError("No models are used by '" + classname + "'");
parser.ReportError("No models are used by \"" + classname + "\"");
return false;
}
// Classname is set in ModeldefParser
ModelData = new ModelData();
ModelData.InheritActorPitch = inheritactorpitch;
ModelData.InheritActorRoll = inheritactorroll;
ModelData = new ModelData { InheritActorPitch = inheritactorpitch, InheritActorRoll = inheritactorroll };
Matrix moffset = Matrix.Translation(offset.Y, -offset.X, offset.Z); // Things are complicated in GZDoom...
Matrix mrotation = Matrix.RotationY(-Angle2D.DegToRad(rollOffset)) * Matrix.RotationX(-Angle2D.DegToRad(pitchOffset)) * Matrix.RotationZ(Angle2D.DegToRad(angleOffset));
ModelData.SetTransform(mrotation, moffset, scale);
@ -482,7 +480,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(ModelData.ModelNames.Count == 0)
{
parser.ReportError("'" + classname + "' has no models");
parser.ReportError("\"" + classname + "\" has no models");
return false;
}

View file

@ -1,7 +1,8 @@
#region ================== Namespaces

#region ================== Namespaces
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.ZDoom;
#endregion
@ -11,17 +12,25 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
{
internal sealed class ScriptTypeParserSE :ZDTextParser
{
private ScriptType scriptType;
internal ScriptType ScriptType { get { return scriptType; } }
internal override ScriptType ScriptType { get { return scripttype; } }
private ScriptType scripttype;
internal ScriptTypeParserSE()
{
scriptType = ScriptType.UNKNOWN;
scripttype = ScriptType.UNKNOWN;
}
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -41,7 +50,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(token == "{")
{
scriptType = ScriptType.MODELDEF;
scripttype = ScriptType.MODELDEF;
return true;
}
@ -57,7 +66,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(token == "{")
{
scriptType = ScriptType.ACS;
scripttype = ScriptType.ACS;
return true;
}
@ -72,7 +81,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(token == ":" || token == "{" || token == "REPLACES")
{
scriptType = ScriptType.DECORATE;
scripttype = ScriptType.DECORATE;
return true;
}
@ -81,7 +90,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
if(token == "{")
{
scriptType = ScriptType.DECORATE;
scripttype = ScriptType.DECORATE;
return true;
}
}
@ -90,10 +99,5 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
return false;
}
protected override string GetLanguageType()
{
return "SCRIPT TYPE CHECKER";
}
}
}

View file

@ -22,6 +22,7 @@ using CodeImp.DoomBuilder.Data;
using System.Diagnostics;
using CodeImp.DoomBuilder.Actions;
using System.Windows.Forms;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Editing;
@ -346,12 +347,13 @@ namespace CodeImp.DoomBuilder
General.MainWindow.DisplayStatus(StatusType.Warning, "Unable to test the map due to script errors.");
}
}
General.Plugins.OnMapSaveEnd(SavePurpose.Testing);
}
//mxd
private void TestingFinished()
{
//Done
// Done
TimeSpan deltatime = TimeSpan.FromTicks(process.ExitTime.Ticks - process.StartTime.Ticks);
process = null;
General.WriteLogLine("Test program has finished.");
@ -361,9 +363,22 @@ namespace CodeImp.DoomBuilder
// Clean up temp file
CleanTempFile(General.Map);
General.Plugins.OnMapSaveEnd(SavePurpose.Testing);
if(General.Map != null)
{
// Device reset may be needed...
if(General.Editing.Mode is ClassicMode)
{
General.Map.Graphics.Reset();
General.MainWindow.RedrawDisplay();
}
else if(General.Editing.Mode is VisualMode)
{
//General.MainWindow.StopExclusiveMouseInput();
//General.MainWindow.StartExclusiveMouseInput();
}
}
General.MainWindow.FocusDisplay();
if(General.Editing.Mode is ClassicMode) General.MainWindow.RedrawDisplay();
}
//mxd

View file

@ -130,7 +130,6 @@ namespace CodeImp.DoomBuilder
//mxd. Scripts
internal Dictionary<string, ScriptItem> NamedScripts { get { return namedscripts; } }
internal Dictionary<int, ScriptItem> NumberedScripts { get { return numberedscripts; } }
internal HashSet<string> ScriptIncludes { get { return scriptincludes; } }
public ViewMode ViewMode { get { return renderer2d.ViewMode; } }
@ -159,8 +158,8 @@ namespace CodeImp.DoomBuilder
//mxd
numberedscripts = new Dictionary<int, ScriptItem>();
namedscripts = new Dictionary<string, ScriptItem>();
scriptincludes = new HashSet<string>();
namedscripts = new Dictionary<string, ScriptItem>(StringComparer.OrdinalIgnoreCase);
scriptincludes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
// Disposer
@ -255,7 +254,7 @@ namespace CodeImp.DoomBuilder
this.changed = false;
this.options = options;
General.WriteLogLine("Creating new map '" + options.CurrentName + "' with configuration '" + options.ConfigFile + "'");
General.WriteLogLine("Creating new map \"" + options.CurrentName + "\" with configuration \"" + options.ConfigFile + "\"");
// Initiate graphics
General.WriteLogLine("Initializing graphics device...");
@ -350,7 +349,7 @@ namespace CodeImp.DoomBuilder
this.maploading = true; //mxd
this.options = options;
General.WriteLogLine("Opening map '" + options.CurrentName + "' with configuration '" + options.ConfigFile + "'");
General.WriteLogLine("Opening map \"" + options.CurrentName + "\" with configuration \"" + options.ConfigFile + "\"");
// Initiate graphics
General.WriteLogLine("Initializing graphics device...");
@ -572,7 +571,7 @@ namespace CodeImp.DoomBuilder
{
General.WriteLogLine("Initializing map format interface " + config.FormatInterface + "...");
io = MapSetIO.Create(config.FormatInterface, tempwad, this);
General.WriteLogLine("Restoring map from '" + backuppath + "'...");
General.WriteLogLine("Restoring map from \"" + backuppath + "\"...");
#if DEBUG
// Restore map
@ -838,7 +837,7 @@ namespace CodeImp.DoomBuilder
int mapindex = wad.FindLumpIndex(origmapname);
wad.Dispose();
if(mapindex != -1 && MessageBox.Show(General.MainWindow, "Target file already contains map '" + origmapname + "'\nDo you want to replace it?", "Map already exists!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
if(mapindex != -1 && MessageBox.Show(General.MainWindow, "Target file already contains map \"" + origmapname + "\"\nDo you want to replace it?", "Map already exists!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
{
data.Resume();
General.WriteLogLine("Map saving cancelled...");
@ -934,7 +933,7 @@ namespace CodeImp.DoomBuilder
{
if(purpose != SavePurpose.IntoFile)
{
General.WriteLogLine("Changing map name from '" + options.PreviousName + "' to '" + options.CurrentName + "'");
General.WriteLogLine("Changing map name from \"" + options.PreviousName + "\" to \"" + options.CurrentName + "\"");
// Find the map header in target
int index = targetwad.FindLumpIndex(options.PreviousName);
@ -1048,7 +1047,7 @@ namespace CodeImp.DoomBuilder
File.WriteAllBytes(backuppath, SharpCompressHelper.CompressStream(ms).ToArray());
// Log it
General.WriteLogLine("Map backup saved to '" + backuppath + "'");
General.WriteLogLine("Map backup saved to \"" + backuppath + "\"");
}
else
{
@ -1915,7 +1914,7 @@ namespace CodeImp.DoomBuilder
//mxd. Boilerplate
if(!config.MapLumps.ContainsKey(lumpname))
{
General.ShowErrorMessage("Unable to compile lump '" + lumpname + "'. This lump is not defined in the current game configuration.", MessageBoxButtons.OK);
General.ShowErrorMessage("Unable to compile lump \"" + lumpname + "\". This lump is not defined in the current game configuration.", MessageBoxButtons.OK);
return false;
}
@ -1930,7 +1929,7 @@ namespace CodeImp.DoomBuilder
//mxd. More boilderplate
if(!General.CompiledScriptConfigs.ContainsKey(General.Map.Options.ScriptCompiler))
{
General.ShowErrorMessage("Unable to compile lump '" + lumpname + "'. Unable to find required script compiler configuration ('" + General.Map.Options.ScriptCompiler + "').", MessageBoxButtons.OK);
General.ShowErrorMessage("Unable to compile lump \"" + lumpname + "\". Unable to find required script compiler configuration (\"" + General.Map.Options.ScriptCompiler + "\").", MessageBoxButtons.OK);
return false;
}
@ -1945,7 +1944,7 @@ namespace CodeImp.DoomBuilder
// Find the lump
if(lumpname == CONFIG_MAP_HEADER) reallumpname = TEMP_MAP_HEADER;
Lump lump = tempwad.FindLump(reallumpname);
if(lump == null) throw new Exception("No such lump in temporary wad file '" + reallumpname + "'.");
if(lump == null) throw new Exception("No such lump in temporary wad file \"" + reallumpname + "\".");
// Determine source file
string sourcefile = (filepathname.Length > 0 ? filepathname : tempwad.Filename);
@ -1995,7 +1994,7 @@ namespace CodeImp.DoomBuilder
//mxd
if(scriptconfig.ScriptType == ScriptType.ACS)
{
compiler.Includes = General.Map.ScriptIncludes;
compiler.Includes = scriptincludes;
compiler.CopyIncludesToWorkingDirectory = true;
}
@ -2074,8 +2073,8 @@ namespace CodeImp.DoomBuilder
//INFO: also, error.linenumber is zero-based
foreach(CompilerError error in compilererrors)
{
General.ErrorLogger.Add(ErrorType.Error, "ACS error in '" + (error.filename.StartsWith("?") ? error.filename.Replace("?", string.Empty) : error.filename)
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "', line " + (error.linenumber + 1) : "'")
General.ErrorLogger.Add(ErrorType.Error, "ACS error in \"" + (error.filename.StartsWith("?") ? error.filename.Substring(1) : error.filename)
+ (error.linenumber != CompilerError.NO_LINE_NUMBER ? "\", line " + (error.linenumber + 1) : "\"")
+ ". " + error.description + ".");
}
}
@ -2090,6 +2089,7 @@ namespace CodeImp.DoomBuilder
List<ScriptItem> numberedscriptslist = new List<ScriptItem>();
List<string> scripincludeslist = new List<string>();
List<CompilerError> compilererrors = new List<CompilerError>();
General.Map.Data.TextResources[ScriptType.ACS] = new HashSet<TextResource>();
// Load the script lumps
foreach(MapLumpInfo maplumpinfo in config.MapLumps.Values)
@ -2103,7 +2103,7 @@ namespace CodeImp.DoomBuilder
//mxd. More boilderplate
if(!General.CompiledScriptConfigs.ContainsKey(General.Map.Options.ScriptCompiler))
{
compilererrors.Add(new CompilerError("Unable to compile lump '" + maplumpinfo.Name + "'. Unable to find required script compiler configuration ('" + General.Map.Options.ScriptCompiler + "')."));
compilererrors.Add(new CompilerError("Unable to compile lump \"" + maplumpinfo.Name + "\". Unable to find required script compiler configuration (\"" + General.Map.Options.ScriptCompiler + "\")."));
return compilererrors;
}
@ -2119,15 +2119,37 @@ namespace CodeImp.DoomBuilder
if(stream != null && stream.Length > 0 && scriptconfig != null && scriptconfig.Compiler != null)
{
// Get script names
AcsParserSE parser = new AcsParserSE { OnInclude = (se, path, includetype) => se.Parse(General.Map.Data.LoadFile(path), path, true, includetype, false) };
AcsParserSE parser = new AcsParserSE
{
IsMapScriptsLump = true,
IgnoreErrors = true,
OnInclude = delegate(AcsParserSE se, string includefile, AcsParserSE.IncludeType includetype)
{
TextResourceData includedata = General.Map.Data.LoadFile(includefile);
if(includedata != null)
{
includedata.Trackable = true;
se.Parse(includedata, true, includetype, false);
}
else
{
General.ErrorLogger.Add(ErrorType.Error, "Unable to find include file \"" + includefile + "\"");
}
}
};
//INFO: CompileLump() prepends lumpname with "?" to distinguish between temporary files and files compiled in place
if(parser.Parse(stream, "?SCRIPTS", scriptconfig.Compiler.Files, true, AcsParserSE.IncludeType.NONE, false))
DataLocation location = new DataLocation { location = tempwad.Filename, type = DataLocation.RESOURCE_WAD };
TextResourceData data = new TextResourceData(stream, location, "?SCRIPTS", false);
if(parser.Parse(data, scriptconfig.Compiler.Files, true, AcsParserSE.IncludeType.NONE, false))
{
// Add them to arrays
namedscriptslist.AddRange(parser.NamedScripts);
numberedscriptslist.AddRange(parser.NumberedScripts);
scripincludeslist.AddRange(parser.Includes);
// Add to text resource list
General.Map.Data.TextResources[parser.ScriptType].UnionWith(parser.TextResources.Values);
}
// Check for errors
@ -2297,7 +2319,7 @@ namespace CodeImp.DoomBuilder
data = new DataManager();
if(!string.IsNullOrEmpty(filepathname))
{
DataLocation maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, false, false, false);
DataLocation maplocation = new DataLocation(DataLocation.RESOURCE_WAD, filepathname, options.StrictPatches, false, false);
data.Load(configinfo.Resources, options.Resources, maplocation);
}
else
@ -2346,7 +2368,7 @@ namespace CodeImp.DoomBuilder
this.options = optionsform.Options;
// Load new game configuration
General.WriteLogLine("Loading game configuration '" + options.ConfigFile + "'...");
General.WriteLogLine("Loading game configuration \"" + options.ConfigFile + "\"...");
configinfo = General.GetConfigurationInfo(options.ConfigFile);
Type oldiotype = io.GetType(); //mxd

View file

@ -166,19 +166,34 @@ namespace CodeImp.DoomBuilder.IO
}
//mxd. This returns a list of all files that are in the given path and which names starts with title
public List<string> GetAllFilesWhichTitleStartsWith(string path, string title)
public List<string> GetAllFilesWhichTitleStartsWith(string path, string title)
{
path = CorrectPath(path).ToLowerInvariant();
title = title.ToLowerInvariant();
List<string> files = new List<string>(entries.Length);
for(int i = 0; i < entries.Length; i++)
{
if((entries[i].path == path) && (entries[i].filetitle.StartsWith(title)))
if((entries[i].path.StartsWith(path)) && (entries[i].filetitle.StartsWith(title)))
files.Add(entries[i].filepathname);
}
return files;
}
//mxd. This returns a list of all files that are in the given path and which names starts with title
public List<string> GetAllFilesWhichTitleStartsWith(string path, string title, bool subdirectories)
{
if(subdirectories)
return GetAllFilesWhichTitleStartsWith(path, title);
else
{
path = CorrectPath(path).ToLowerInvariant();
title = title.ToLowerInvariant();
List<string> files = new List<string>(entries.Length);
for(int i = 0; i < entries.Length; i++)
if((entries[i].path == path) && (entries[i].filetitle.StartsWith(title)))
files.Add(entries[i].filepathname);
return files;
}
}
// This returns a list of all files that are in the given path and subdirectories and have the given extension
public List<string> GetAllFiles(string path, string extension)
{

View file

@ -58,6 +58,12 @@ uifields
desaturation = 1;
soundsequence = 2;
comment = 2;
damageamount = 0;
damagetype = 2;
damageinterval = 0;
leakiness = 0;
floorterrain = 2;
ceilingterrain = 2;
}
thing

View file

@ -123,7 +123,6 @@ namespace CodeImp.DoomBuilder.Windows
private bool shift, ctrl, alt;
private MouseButtons mousebuttons;
private MouseInput mouseinput;
private Rectangle originalclip;
private bool mouseexclusive;
private int mouseexclusivebreaklevel;
@ -1246,7 +1245,7 @@ namespace CodeImp.DoomBuilder.Windows
mouseinput = new MouseInput(this);
// Lock and hide the mouse in window
originalclip = Cursor.Clip;
Cursor.Position = display.PointToScreen(new Point(display.ClientSize.Width / 2, display.ClientSize.Height / 2)); //mxd
Cursor.Clip = display.RectangleToScreen(display.ClientRectangle);
Cursor.Hide();
}
@ -1263,7 +1262,7 @@ namespace CodeImp.DoomBuilder.Windows
mouseinput = null;
// Release and show the mouse
Cursor.Clip = originalclip;
Cursor.Clip = Rectangle.Empty;
Cursor.Position = display.PointToScreen(new Point(display.ClientSize.Width / 2, display.ClientSize.Height / 2));
Cursor.Show();
}

View file

@ -40,6 +40,10 @@
System.Windows.Forms.Label label15;
System.Windows.Forms.Label label6;
System.Windows.Forms.Label label5;
System.Windows.Forms.Label label17;
System.Windows.Forms.Label label16;
System.Windows.Forms.Label label18;
System.Windows.Forms.Label label19;
this.tagsselector = new CodeImp.DoomBuilder.GZBuilder.Controls.TagsSelector();
this.soundsequence = new System.Windows.Forms.ComboBox();
this.resetsoundsequence = new System.Windows.Forms.Button();
@ -57,10 +61,19 @@
this.floorheight = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
this.tabs = new System.Windows.Forms.TabControl();
this.tabproperties = new System.Windows.Forms.TabPage();
this.groupdamage = new System.Windows.Forms.GroupBox();
this.leakiness = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
this.damageinterval = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
this.resetdamagetype = new System.Windows.Forms.Button();
this.damageamount = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
this.damagetype = new System.Windows.Forms.ComboBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.flags = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
this.tabSurfaces = new System.Windows.Forms.TabPage();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.resetfloorterrain = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.floorterrain = new System.Windows.Forms.ComboBox();
this.resetfloorlight = new System.Windows.Forms.Button();
this.labelFloorOffsets = new System.Windows.Forms.Label();
this.labelFloorScale = new System.Windows.Forms.Label();
@ -79,6 +92,9 @@
this.floorOffsets = new CodeImp.DoomBuilder.GZBuilder.Controls.PairedFieldsControl();
this.floortex = new CodeImp.DoomBuilder.Controls.FlatSelectorControl();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.resetceilterrain = new System.Windows.Forms.Button();
this.label7 = new System.Windows.Forms.Label();
this.ceilterrain = new System.Windows.Forms.ComboBox();
this.resetceillight = new System.Windows.Forms.Button();
this.labelCeilOffsets = new System.Windows.Forms.Label();
this.labelCeilScale = new System.Windows.Forms.Label();
@ -119,11 +135,16 @@
label15 = new System.Windows.Forms.Label();
label6 = new System.Windows.Forms.Label();
label5 = new System.Windows.Forms.Label();
label17 = new System.Windows.Forms.Label();
label16 = new System.Windows.Forms.Label();
label18 = new System.Windows.Forms.Label();
label19 = new System.Windows.Forms.Label();
groupaction.SuspendLayout();
groupeffect.SuspendLayout();
groupfloorceiling.SuspendLayout();
this.tabs.SuspendLayout();
this.tabproperties.SuspendLayout();
this.groupdamage.SuspendLayout();
this.groupBox3.SuspendLayout();
this.tabSurfaces.SuspendLayout();
this.groupBox2.SuspendLayout();
@ -140,16 +161,16 @@
groupaction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
groupaction.Controls.Add(this.tagsselector);
groupaction.Location = new System.Drawing.Point(7, 327);
groupaction.Location = new System.Drawing.Point(7, 394);
groupaction.Name = "groupaction";
groupaction.Size = new System.Drawing.Size(490, 85);
groupaction.Size = new System.Drawing.Size(490, 80);
groupaction.TabIndex = 2;
groupaction.TabStop = false;
groupaction.Text = " Identification ";
//
// tagsselector
//
this.tagsselector.Location = new System.Drawing.Point(6, 21);
this.tagsselector.Location = new System.Drawing.Point(6, 15);
this.tagsselector.Name = "tagsselector";
this.tagsselector.Size = new System.Drawing.Size(478, 60);
this.tagsselector.TabIndex = 0;
@ -172,9 +193,9 @@
groupeffect.Controls.Add(this.browseeffect);
groupeffect.Controls.Add(this.effect);
groupeffect.Controls.Add(label8);
groupeffect.Location = new System.Drawing.Point(7, 160);
groupeffect.Location = new System.Drawing.Point(7, 256);
groupeffect.Name = "groupeffect";
groupeffect.Size = new System.Drawing.Size(490, 161);
groupeffect.Size = new System.Drawing.Size(490, 132);
groupeffect.TabIndex = 1;
groupeffect.TabStop = false;
groupeffect.Text = " Effects ";
@ -182,9 +203,9 @@
// soundsequence
//
this.soundsequence.FormattingEnabled = true;
this.soundsequence.Location = new System.Drawing.Point(125, 54);
this.soundsequence.Location = new System.Drawing.Point(283, 48);
this.soundsequence.Name = "soundsequence";
this.soundsequence.Size = new System.Drawing.Size(325, 21);
this.soundsequence.Size = new System.Drawing.Size(167, 21);
this.soundsequence.TabIndex = 32;
this.soundsequence.MouseDown += new System.Windows.Forms.MouseEventHandler(this.soundsequence_MouseDown);
this.soundsequence.TextChanged += new System.EventHandler(this.soundsequence_TextChanged);
@ -192,7 +213,7 @@
// resetsoundsequence
//
this.resetsoundsequence.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetsoundsequence.Location = new System.Drawing.Point(456, 52);
this.resetsoundsequence.Location = new System.Drawing.Point(456, 46);
this.resetsoundsequence.Name = "resetsoundsequence";
this.resetsoundsequence.Size = new System.Drawing.Size(28, 25);
this.resetsoundsequence.TabIndex = 31;
@ -205,7 +226,7 @@
this.fadeColor.DefaultValue = 0;
this.fadeColor.Field = "fadecolor";
this.fadeColor.Label = "Fade:";
this.fadeColor.Location = new System.Drawing.Point(241, 104);
this.fadeColor.Location = new System.Drawing.Point(236, 99);
this.fadeColor.Name = "fadeColor";
this.fadeColor.Size = new System.Drawing.Size(207, 31);
this.fadeColor.TabIndex = 30;
@ -216,7 +237,7 @@
this.lightColor.DefaultValue = 16777215;
this.lightColor.Field = "lightcolor";
this.lightColor.Label = "Light:";
this.lightColor.Location = new System.Drawing.Point(241, 77);
this.lightColor.Location = new System.Drawing.Point(236, 71);
this.lightColor.Name = "lightColor";
this.lightColor.Size = new System.Drawing.Size(207, 29);
this.lightColor.TabIndex = 29;
@ -233,7 +254,7 @@
this.brightness.ButtonStepSmall = 1F;
this.brightness.ButtonStepsUseModifierKeys = true;
this.brightness.ButtonStepsWrapAround = false;
this.brightness.Location = new System.Drawing.Point(125, 79);
this.brightness.Location = new System.Drawing.Point(89, 46);
this.brightness.Name = "brightness";
this.brightness.Size = new System.Drawing.Size(81, 24);
this.brightness.StepValues = null;
@ -251,7 +272,7 @@
this.desaturation.ButtonStepSmall = 0.01F;
this.desaturation.ButtonStepsUseModifierKeys = true;
this.desaturation.ButtonStepsWrapAround = false;
this.desaturation.Location = new System.Drawing.Point(125, 131);
this.desaturation.Location = new System.Drawing.Point(89, 102);
this.desaturation.Name = "desaturation";
this.desaturation.Size = new System.Drawing.Size(81, 24);
this.desaturation.StepValues = null;
@ -260,7 +281,7 @@
// label14
//
label14.AutoSize = true;
label14.Location = new System.Drawing.Point(27, 58);
label14.Location = new System.Drawing.Point(186, 52);
label14.Name = "label14";
label14.Size = new System.Drawing.Size(91, 13);
label14.TabIndex = 3;
@ -269,7 +290,7 @@
// label9
//
label9.AutoSize = true;
label9.Location = new System.Drawing.Point(57, 84);
label9.Location = new System.Drawing.Point(21, 51);
label9.Name = "label9";
label9.Size = new System.Drawing.Size(59, 13);
label9.TabIndex = 2;
@ -277,7 +298,7 @@
//
// label13
//
label13.Location = new System.Drawing.Point(45, 136);
label13.Location = new System.Drawing.Point(9, 107);
label13.Name = "label13";
label13.Size = new System.Drawing.Size(74, 14);
label13.TabIndex = 27;
@ -295,7 +316,7 @@
this.gravity.ButtonStepSmall = 0.01F;
this.gravity.ButtonStepsUseModifierKeys = true;
this.gravity.ButtonStepsWrapAround = false;
this.gravity.Location = new System.Drawing.Point(125, 105);
this.gravity.Location = new System.Drawing.Point(89, 74);
this.gravity.Name = "gravity";
this.gravity.Size = new System.Drawing.Size(81, 24);
this.gravity.StepValues = null;
@ -303,7 +324,7 @@
//
// label2
//
label2.Location = new System.Drawing.Point(45, 110);
label2.Location = new System.Drawing.Point(9, 79);
label2.Name = "label2";
label2.Size = new System.Drawing.Size(74, 14);
label2.TabIndex = 23;
@ -313,7 +334,7 @@
// browseeffect
//
this.browseeffect.Image = global::CodeImp.DoomBuilder.Properties.Resources.List;
this.browseeffect.Location = new System.Drawing.Point(456, 26);
this.browseeffect.Location = new System.Drawing.Point(456, 16);
this.browseeffect.Name = "browseeffect";
this.browseeffect.Size = new System.Drawing.Size(28, 25);
this.browseeffect.TabIndex = 1;
@ -328,16 +349,16 @@
this.effect.Empty = false;
this.effect.GeneralizedCategories = null;
this.effect.GeneralizedOptions = null;
this.effect.Location = new System.Drawing.Point(68, 28);
this.effect.Location = new System.Drawing.Point(89, 18);
this.effect.Name = "effect";
this.effect.Size = new System.Drawing.Size(382, 21);
this.effect.Size = new System.Drawing.Size(361, 21);
this.effect.TabIndex = 0;
this.effect.Value = 402;
//
// label8
//
label8.AutoSize = true;
label8.Location = new System.Drawing.Point(17, 31);
label8.Location = new System.Drawing.Point(35, 22);
label8.Name = "label8";
label8.Size = new System.Drawing.Size(45, 13);
label8.TabIndex = 0;
@ -355,9 +376,9 @@
groupfloorceiling.Controls.Add(this.sectorheightlabel);
groupfloorceiling.Controls.Add(this.sectorheight);
groupfloorceiling.Controls.Add(this.floorheight);
groupfloorceiling.Location = new System.Drawing.Point(7, 6);
groupfloorceiling.Location = new System.Drawing.Point(7, 112);
groupfloorceiling.Name = "groupfloorceiling";
groupfloorceiling.Size = new System.Drawing.Size(188, 148);
groupfloorceiling.Size = new System.Drawing.Size(187, 138);
groupfloorceiling.TabIndex = 0;
groupfloorceiling.TabStop = false;
groupfloorceiling.Text = " Heights ";
@ -366,7 +387,7 @@
//
label15.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label15.ForeColor = System.Drawing.SystemColors.HotTrack;
label15.Location = new System.Drawing.Point(9, 84);
label15.Location = new System.Drawing.Point(9, 83);
label15.Name = "label15";
label15.Size = new System.Drawing.Size(74, 14);
label15.TabIndex = 27;
@ -377,7 +398,7 @@
//
// label6
//
label6.Location = new System.Drawing.Point(9, 24);
label6.Location = new System.Drawing.Point(9, 23);
label6.Name = "label6";
label6.Size = new System.Drawing.Size(74, 14);
label6.TabIndex = 19;
@ -386,7 +407,7 @@
//
// label5
//
label5.Location = new System.Drawing.Point(9, 54);
label5.Location = new System.Drawing.Point(9, 53);
label5.Name = "label5";
label5.Size = new System.Drawing.Size(74, 14);
label5.TabIndex = 17;
@ -404,9 +425,9 @@
this.heightoffset.ButtonStepSmall = 1F;
this.heightoffset.ButtonStepsUseModifierKeys = true;
this.heightoffset.ButtonStepsWrapAround = false;
this.heightoffset.Location = new System.Drawing.Point(89, 79);
this.heightoffset.Location = new System.Drawing.Point(89, 78);
this.heightoffset.Name = "heightoffset";
this.heightoffset.Size = new System.Drawing.Size(88, 24);
this.heightoffset.Size = new System.Drawing.Size(81, 24);
this.heightoffset.StepValues = null;
this.heightoffset.TabIndex = 28;
this.heightoffset.WhenTextChanged += new System.EventHandler(this.heightoffset_WhenTextChanged);
@ -422,16 +443,16 @@
this.ceilingheight.ButtonStepSmall = 1F;
this.ceilingheight.ButtonStepsUseModifierKeys = true;
this.ceilingheight.ButtonStepsWrapAround = false;
this.ceilingheight.Location = new System.Drawing.Point(89, 19);
this.ceilingheight.Location = new System.Drawing.Point(89, 18);
this.ceilingheight.Name = "ceilingheight";
this.ceilingheight.Size = new System.Drawing.Size(88, 24);
this.ceilingheight.Size = new System.Drawing.Size(81, 24);
this.ceilingheight.StepValues = null;
this.ceilingheight.TabIndex = 22;
this.ceilingheight.WhenTextChanged += new System.EventHandler(this.ceilingheight_WhenTextChanged);
//
// sectorheightlabel
//
this.sectorheightlabel.Location = new System.Drawing.Point(9, 114);
this.sectorheightlabel.Location = new System.Drawing.Point(9, 113);
this.sectorheightlabel.Name = "sectorheightlabel";
this.sectorheightlabel.Size = new System.Drawing.Size(74, 14);
this.sectorheightlabel.TabIndex = 20;
@ -441,7 +462,7 @@
// sectorheight
//
this.sectorheight.AutoSize = true;
this.sectorheight.Location = new System.Drawing.Point(90, 114);
this.sectorheight.Location = new System.Drawing.Point(89, 114);
this.sectorheight.Name = "sectorheight";
this.sectorheight.Size = new System.Drawing.Size(13, 13);
this.sectorheight.TabIndex = 21;
@ -458,13 +479,60 @@
this.floorheight.ButtonStepSmall = 1F;
this.floorheight.ButtonStepsUseModifierKeys = true;
this.floorheight.ButtonStepsWrapAround = false;
this.floorheight.Location = new System.Drawing.Point(89, 49);
this.floorheight.Location = new System.Drawing.Point(89, 48);
this.floorheight.Name = "floorheight";
this.floorheight.Size = new System.Drawing.Size(88, 24);
this.floorheight.Size = new System.Drawing.Size(81, 24);
this.floorheight.StepValues = null;
this.floorheight.TabIndex = 23;
this.floorheight.WhenTextChanged += new System.EventHandler(this.floorheight_WhenTextChanged);
//
// label17
//
label17.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label17.ForeColor = System.Drawing.SystemColors.HotTrack;
label17.Location = new System.Drawing.Point(10, 51);
label17.Name = "label17";
label17.Size = new System.Drawing.Size(74, 14);
label17.TabIndex = 29;
label17.Text = "Ammount:";
label17.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label17, "Amount of damage inflicted by this sector.\r\nIf this is 0, all other damage proper" +
"ties will be ignored.\r\nSetting this to a negative value will create a healing se" +
"ctor.");
//
// label16
//
label16.Location = new System.Drawing.Point(10, 23);
label16.Name = "label16";
label16.Size = new System.Drawing.Size(74, 14);
label16.TabIndex = 36;
label16.Text = "Type:";
label16.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// label18
//
label18.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label18.ForeColor = System.Drawing.SystemColors.HotTrack;
label18.Location = new System.Drawing.Point(10, 81);
label18.Name = "label18";
label18.Size = new System.Drawing.Size(74, 14);
label18.TabIndex = 37;
label18.Text = "Interval:";
label18.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label18, "Interval in tics between damage application.");
//
// label19
//
label19.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label19.ForeColor = System.Drawing.SystemColors.HotTrack;
label19.Location = new System.Drawing.Point(10, 111);
label19.Name = "label19";
label19.Size = new System.Drawing.Size(74, 14);
label19.TabIndex = 39;
label19.Text = "Leakiness:";
label19.TextAlign = System.Drawing.ContentAlignment.TopRight;
this.tooltip.SetToolTip(label19, "Probability of leaking through radiation suit\r\n(0 = never, 256 = always)");
//
// tabs
//
this.tabs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -481,11 +549,12 @@
this.tabs.Name = "tabs";
this.tabs.Padding = new System.Drawing.Point(24, 3);
this.tabs.SelectedIndex = 0;
this.tabs.Size = new System.Drawing.Size(511, 445);
this.tabs.Size = new System.Drawing.Size(511, 504);
this.tabs.TabIndex = 1;
//
// tabproperties
//
this.tabproperties.Controls.Add(this.groupdamage);
this.tabproperties.Controls.Add(this.groupBox3);
this.tabproperties.Controls.Add(groupaction);
this.tabproperties.Controls.Add(groupeffect);
@ -494,30 +563,123 @@
this.tabproperties.Location = new System.Drawing.Point(4, 22);
this.tabproperties.Name = "tabproperties";
this.tabproperties.Padding = new System.Windows.Forms.Padding(3);
this.tabproperties.Size = new System.Drawing.Size(503, 419);
this.tabproperties.Size = new System.Drawing.Size(503, 478);
this.tabproperties.TabIndex = 0;
this.tabproperties.Text = "Properties";
this.tabproperties.UseVisualStyleBackColor = true;
//
// groupdamage
//
this.groupdamage.Controls.Add(label19);
this.groupdamage.Controls.Add(this.leakiness);
this.groupdamage.Controls.Add(label18);
this.groupdamage.Controls.Add(this.damageinterval);
this.groupdamage.Controls.Add(label16);
this.groupdamage.Controls.Add(label17);
this.groupdamage.Controls.Add(this.resetdamagetype);
this.groupdamage.Controls.Add(this.damageamount);
this.groupdamage.Controls.Add(this.damagetype);
this.groupdamage.Location = new System.Drawing.Point(200, 112);
this.groupdamage.Name = "groupdamage";
this.groupdamage.Size = new System.Drawing.Size(297, 136);
this.groupdamage.TabIndex = 4;
this.groupdamage.TabStop = false;
this.groupdamage.Text = " Sector damage ";
//
// leakiness
//
this.leakiness.AllowDecimal = false;
this.leakiness.AllowNegative = false;
this.leakiness.AllowRelative = true;
this.leakiness.ButtonStep = 8;
this.leakiness.ButtonStepBig = 16F;
this.leakiness.ButtonStepFloat = 1F;
this.leakiness.ButtonStepSmall = 1F;
this.leakiness.ButtonStepsUseModifierKeys = true;
this.leakiness.ButtonStepsWrapAround = false;
this.leakiness.Location = new System.Drawing.Point(90, 106);
this.leakiness.Name = "leakiness";
this.leakiness.Size = new System.Drawing.Size(81, 24);
this.leakiness.StepValues = null;
this.leakiness.TabIndex = 40;
//
// damageinterval
//
this.damageinterval.AllowDecimal = false;
this.damageinterval.AllowNegative = false;
this.damageinterval.AllowRelative = true;
this.damageinterval.ButtonStep = 8;
this.damageinterval.ButtonStepBig = 16F;
this.damageinterval.ButtonStepFloat = 1F;
this.damageinterval.ButtonStepSmall = 1F;
this.damageinterval.ButtonStepsUseModifierKeys = true;
this.damageinterval.ButtonStepsWrapAround = false;
this.damageinterval.Location = new System.Drawing.Point(90, 76);
this.damageinterval.Name = "damageinterval";
this.damageinterval.Size = new System.Drawing.Size(81, 24);
this.damageinterval.StepValues = null;
this.damageinterval.TabIndex = 38;
//
// resetdamagetype
//
this.resetdamagetype.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetdamagetype.Location = new System.Drawing.Point(263, 17);
this.resetdamagetype.Name = "resetdamagetype";
this.resetdamagetype.Size = new System.Drawing.Size(28, 25);
this.resetdamagetype.TabIndex = 35;
this.resetdamagetype.Text = " ";
this.resetdamagetype.UseVisualStyleBackColor = true;
this.resetdamagetype.Click += new System.EventHandler(this.resetdamagetype_Click);
//
// damageamount
//
this.damageamount.AllowDecimal = false;
this.damageamount.AllowNegative = true;
this.damageamount.AllowRelative = true;
this.damageamount.ButtonStep = 8;
this.damageamount.ButtonStepBig = 16F;
this.damageamount.ButtonStepFloat = 1F;
this.damageamount.ButtonStepSmall = 1F;
this.damageamount.ButtonStepsUseModifierKeys = true;
this.damageamount.ButtonStepsWrapAround = false;
this.damageamount.Location = new System.Drawing.Point(90, 46);
this.damageamount.Name = "damageamount";
this.damageamount.Size = new System.Drawing.Size(81, 24);
this.damageamount.StepValues = null;
this.damageamount.TabIndex = 30;
//
// damagetype
//
this.damagetype.FormattingEnabled = true;
this.damagetype.Location = new System.Drawing.Point(90, 19);
this.damagetype.Name = "damagetype";
this.damagetype.Size = new System.Drawing.Size(167, 21);
this.damagetype.TabIndex = 34;
this.damagetype.MouseDown += new System.Windows.Forms.MouseEventHandler(this.damagetype_MouseDown);
this.damagetype.TextChanged += new System.EventHandler(this.damagetype_TextChanged);
//
// groupBox3
//
this.groupBox3.Controls.Add(this.flags);
this.groupBox3.Location = new System.Drawing.Point(201, 6);
this.groupBox3.Location = new System.Drawing.Point(7, 6);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(296, 148);
this.groupBox3.Size = new System.Drawing.Size(490, 100);
this.groupBox3.TabIndex = 3;
this.groupBox3.TabStop = false;
this.groupBox3.Text = " Flags ";
//
// flags
//
this.flags.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.flags.AutoScroll = true;
this.flags.Columns = 1;
this.flags.Columns = 2;
this.flags.Location = new System.Drawing.Point(15, 21);
this.flags.Name = "flags";
this.flags.Size = new System.Drawing.Size(275, 121);
this.flags.Size = new System.Drawing.Size(469, 73);
this.flags.TabIndex = 5;
this.flags.VerticalSpacing = 2;
this.flags.VerticalSpacing = 1;
//
// tabSurfaces
//
@ -526,7 +688,7 @@
this.tabSurfaces.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.tabSurfaces.Location = new System.Drawing.Point(4, 22);
this.tabSurfaces.Name = "tabSurfaces";
this.tabSurfaces.Size = new System.Drawing.Size(503, 419);
this.tabSurfaces.Size = new System.Drawing.Size(503, 478);
this.tabSurfaces.TabIndex = 2;
this.tabSurfaces.Text = "Surfaces";
this.tabSurfaces.UseVisualStyleBackColor = true;
@ -535,6 +697,9 @@
//
this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox2.Controls.Add(this.resetfloorterrain);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.floorterrain);
this.groupBox2.Controls.Add(this.resetfloorlight);
this.groupBox2.Controls.Add(this.labelFloorOffsets);
this.groupBox2.Controls.Add(this.labelFloorScale);
@ -552,17 +717,48 @@
this.groupBox2.Controls.Add(this.floorScale);
this.groupBox2.Controls.Add(this.floorOffsets);
this.groupBox2.Controls.Add(this.floortex);
this.groupBox2.Location = new System.Drawing.Point(3, 212);
this.groupBox2.Location = new System.Drawing.Point(3, 239);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(497, 203);
this.groupBox2.Size = new System.Drawing.Size(497, 230);
this.groupBox2.TabIndex = 55;
this.groupBox2.TabStop = false;
this.groupBox2.Text = " Floor ";
//
// resetfloorterrain
//
this.resetfloorterrain.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetfloorterrain.Location = new System.Drawing.Point(246, 110);
this.resetfloorterrain.Name = "resetfloorterrain";
this.resetfloorterrain.Size = new System.Drawing.Size(23, 23);
this.resetfloorterrain.TabIndex = 66;
this.resetfloorterrain.Text = " ";
this.resetfloorterrain.UseVisualStyleBackColor = true;
this.resetfloorterrain.Click += new System.EventHandler(this.resetfloorterrain_Click);
//
// label3
//
this.label3.Location = new System.Drawing.Point(24, 114);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(80, 14);
this.label3.TabIndex = 62;
this.label3.Tag = "";
this.label3.Text = "Terrain:";
this.label3.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// floorterrain
//
this.floorterrain.FormattingEnabled = true;
this.floorterrain.Location = new System.Drawing.Point(113, 111);
this.floorterrain.Name = "floorterrain";
this.floorterrain.Size = new System.Drawing.Size(130, 21);
this.floorterrain.TabIndex = 61;
this.floorterrain.MouseDown += new System.Windows.Forms.MouseEventHandler(this.floorterrain_MouseDown);
this.floorterrain.TextChanged += new System.EventHandler(this.floorterrain_TextChanged);
//
// resetfloorlight
//
this.resetfloorlight.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetfloorlight.Location = new System.Drawing.Point(246, 114);
this.resetfloorlight.Location = new System.Drawing.Point(246, 138);
this.resetfloorlight.Name = "resetfloorlight";
this.resetfloorlight.Size = new System.Drawing.Size(23, 23);
this.resetfloorlight.TabIndex = 60;
@ -593,7 +789,7 @@
// cbUseFloorLineAngles
//
this.cbUseFloorLineAngles.AutoSize = true;
this.cbUseFloorLineAngles.Location = new System.Drawing.Point(181, 148);
this.cbUseFloorLineAngles.Location = new System.Drawing.Point(181, 172);
this.cbUseFloorLineAngles.Name = "cbUseFloorLineAngles";
this.cbUseFloorLineAngles.Size = new System.Drawing.Size(113, 17);
this.cbUseFloorLineAngles.TabIndex = 57;
@ -604,9 +800,9 @@
//
// floorAngleControl
//
this.floorAngleControl.Angle = -450;
this.floorAngleControl.Angle = -1350;
this.floorAngleControl.AngleOffset = 90;
this.floorAngleControl.Location = new System.Drawing.Point(6, 132);
this.floorAngleControl.Location = new System.Drawing.Point(6, 156);
this.floorAngleControl.Name = "floorAngleControl";
this.floorAngleControl.Size = new System.Drawing.Size(44, 44);
this.floorAngleControl.TabIndex = 56;
@ -624,7 +820,7 @@
//
// label10
//
this.label10.Location = new System.Drawing.Point(24, 178);
this.label10.Location = new System.Drawing.Point(24, 202);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(80, 14);
this.label10.TabIndex = 52;
@ -643,7 +839,7 @@
this.floorAlpha.ButtonStepSmall = 0.01F;
this.floorAlpha.ButtonStepsUseModifierKeys = true;
this.floorAlpha.ButtonStepsWrapAround = false;
this.floorAlpha.Location = new System.Drawing.Point(113, 173);
this.floorAlpha.Location = new System.Drawing.Point(113, 197);
this.floorAlpha.Name = "floorAlpha";
this.floorAlpha.Size = new System.Drawing.Size(62, 24);
this.floorAlpha.StepValues = null;
@ -652,7 +848,7 @@
//
// label11
//
this.label11.Location = new System.Drawing.Point(24, 148);
this.label11.Location = new System.Drawing.Point(24, 172);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(80, 14);
this.label11.TabIndex = 50;
@ -671,7 +867,7 @@
this.floorRotation.ButtonStepSmall = 0.1F;
this.floorRotation.ButtonStepsUseModifierKeys = true;
this.floorRotation.ButtonStepsWrapAround = false;
this.floorRotation.Location = new System.Drawing.Point(113, 143);
this.floorRotation.Location = new System.Drawing.Point(113, 167);
this.floorRotation.Name = "floorRotation";
this.floorRotation.Size = new System.Drawing.Size(62, 24);
this.floorRotation.StepValues = null;
@ -682,7 +878,7 @@
// floorLightAbsolute
//
this.floorLightAbsolute.AutoSize = true;
this.floorLightAbsolute.Location = new System.Drawing.Point(181, 118);
this.floorLightAbsolute.Location = new System.Drawing.Point(181, 142);
this.floorLightAbsolute.Name = "floorLightAbsolute";
this.floorLightAbsolute.Size = new System.Drawing.Size(67, 17);
this.floorLightAbsolute.TabIndex = 49;
@ -692,7 +888,7 @@
//
// label12
//
this.label12.Location = new System.Drawing.Point(24, 118);
this.label12.Location = new System.Drawing.Point(24, 142);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(80, 14);
this.label12.TabIndex = 47;
@ -711,7 +907,7 @@
this.floorBrightness.ButtonStepSmall = 1F;
this.floorBrightness.ButtonStepsUseModifierKeys = true;
this.floorBrightness.ButtonStepsWrapAround = false;
this.floorBrightness.Location = new System.Drawing.Point(113, 113);
this.floorBrightness.Location = new System.Drawing.Point(113, 137);
this.floorBrightness.Name = "floorBrightness";
this.floorBrightness.Size = new System.Drawing.Size(62, 24);
this.floorBrightness.StepValues = null;
@ -771,7 +967,7 @@
this.floortex.Location = new System.Drawing.Point(300, 13);
this.floortex.MultipleTextures = false;
this.floortex.Name = "floortex";
this.floortex.Size = new System.Drawing.Size(190, 184);
this.floortex.Size = new System.Drawing.Size(190, 204);
this.floortex.TabIndex = 15;
this.floortex.TextureName = "";
this.floortex.UsePreviews = false;
@ -781,6 +977,9 @@
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.resetceilterrain);
this.groupBox1.Controls.Add(this.label7);
this.groupBox1.Controls.Add(this.ceilterrain);
this.groupBox1.Controls.Add(this.resetceillight);
this.groupBox1.Controls.Add(this.labelCeilOffsets);
this.groupBox1.Controls.Add(this.labelCeilScale);
@ -800,15 +999,46 @@
this.groupBox1.Controls.Add(this.ceilingtex);
this.groupBox1.Location = new System.Drawing.Point(3, 3);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(497, 203);
this.groupBox1.Size = new System.Drawing.Size(497, 230);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = " Ceiling ";
//
// resetceilterrain
//
this.resetceilterrain.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetceilterrain.Location = new System.Drawing.Point(246, 110);
this.resetceilterrain.Name = "resetceilterrain";
this.resetceilterrain.Size = new System.Drawing.Size(23, 23);
this.resetceilterrain.TabIndex = 65;
this.resetceilterrain.Text = " ";
this.resetceilterrain.UseVisualStyleBackColor = true;
this.resetceilterrain.Click += new System.EventHandler(this.resetceilterrain_Click);
//
// label7
//
this.label7.Location = new System.Drawing.Point(24, 114);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(80, 14);
this.label7.TabIndex = 64;
this.label7.Tag = "";
this.label7.Text = "Terrain:";
this.label7.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// ceilterrain
//
this.ceilterrain.FormattingEnabled = true;
this.ceilterrain.Location = new System.Drawing.Point(113, 111);
this.ceilterrain.Name = "ceilterrain";
this.ceilterrain.Size = new System.Drawing.Size(130, 21);
this.ceilterrain.TabIndex = 63;
this.ceilterrain.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ceilterrain_MouseDown);
this.ceilterrain.TextChanged += new System.EventHandler(this.ceilterrain_TextChanged);
//
// resetceillight
//
this.resetceillight.Image = global::CodeImp.DoomBuilder.Properties.Resources.Reset;
this.resetceillight.Location = new System.Drawing.Point(246, 114);
this.resetceillight.Location = new System.Drawing.Point(246, 138);
this.resetceillight.Name = "resetceillight";
this.resetceillight.Size = new System.Drawing.Size(23, 23);
this.resetceillight.TabIndex = 62;
@ -839,7 +1069,7 @@
// cbUseCeilLineAngles
//
this.cbUseCeilLineAngles.AutoSize = true;
this.cbUseCeilLineAngles.Location = new System.Drawing.Point(181, 148);
this.cbUseCeilLineAngles.Location = new System.Drawing.Point(181, 172);
this.cbUseCeilLineAngles.Name = "cbUseCeilLineAngles";
this.cbUseCeilLineAngles.Size = new System.Drawing.Size(113, 17);
this.cbUseCeilLineAngles.TabIndex = 56;
@ -850,9 +1080,9 @@
//
// ceilAngleControl
//
this.ceilAngleControl.Angle = -450;
this.ceilAngleControl.Angle = -1350;
this.ceilAngleControl.AngleOffset = 90;
this.ceilAngleControl.Location = new System.Drawing.Point(6, 132);
this.ceilAngleControl.Location = new System.Drawing.Point(6, 156);
this.ceilAngleControl.Name = "ceilAngleControl";
this.ceilAngleControl.Size = new System.Drawing.Size(44, 44);
this.ceilAngleControl.TabIndex = 55;
@ -870,7 +1100,7 @@
//
// label4
//
this.label4.Location = new System.Drawing.Point(24, 178);
this.label4.Location = new System.Drawing.Point(24, 202);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(80, 14);
this.label4.TabIndex = 52;
@ -889,7 +1119,7 @@
this.ceilAlpha.ButtonStepSmall = 0.01F;
this.ceilAlpha.ButtonStepsUseModifierKeys = true;
this.ceilAlpha.ButtonStepsWrapAround = false;
this.ceilAlpha.Location = new System.Drawing.Point(113, 173);
this.ceilAlpha.Location = new System.Drawing.Point(113, 197);
this.ceilAlpha.Name = "ceilAlpha";
this.ceilAlpha.Size = new System.Drawing.Size(62, 24);
this.ceilAlpha.StepValues = null;
@ -898,7 +1128,7 @@
//
// label1
//
this.label1.Location = new System.Drawing.Point(24, 148);
this.label1.Location = new System.Drawing.Point(24, 172);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(80, 14);
this.label1.TabIndex = 50;
@ -917,7 +1147,7 @@
this.ceilRotation.ButtonStepSmall = 0.1F;
this.ceilRotation.ButtonStepsUseModifierKeys = true;
this.ceilRotation.ButtonStepsWrapAround = true;
this.ceilRotation.Location = new System.Drawing.Point(113, 143);
this.ceilRotation.Location = new System.Drawing.Point(113, 167);
this.ceilRotation.Name = "ceilRotation";
this.ceilRotation.Size = new System.Drawing.Size(62, 24);
this.ceilRotation.StepValues = null;
@ -928,7 +1158,7 @@
// ceilLightAbsolute
//
this.ceilLightAbsolute.AutoSize = true;
this.ceilLightAbsolute.Location = new System.Drawing.Point(181, 118);
this.ceilLightAbsolute.Location = new System.Drawing.Point(181, 142);
this.ceilLightAbsolute.Name = "ceilLightAbsolute";
this.ceilLightAbsolute.Size = new System.Drawing.Size(67, 17);
this.ceilLightAbsolute.TabIndex = 49;
@ -939,7 +1169,7 @@
//
// labelLightFront
//
this.labelLightFront.Location = new System.Drawing.Point(24, 118);
this.labelLightFront.Location = new System.Drawing.Point(24, 142);
this.labelLightFront.Name = "labelLightFront";
this.labelLightFront.Size = new System.Drawing.Size(80, 14);
this.labelLightFront.TabIndex = 47;
@ -958,7 +1188,7 @@
this.ceilBrightness.ButtonStepSmall = 1F;
this.ceilBrightness.ButtonStepsUseModifierKeys = true;
this.ceilBrightness.ButtonStepsWrapAround = false;
this.ceilBrightness.Location = new System.Drawing.Point(113, 113);
this.ceilBrightness.Location = new System.Drawing.Point(113, 137);
this.ceilBrightness.Name = "ceilBrightness";
this.ceilBrightness.Size = new System.Drawing.Size(62, 24);
this.ceilBrightness.StepValues = null;
@ -1018,7 +1248,7 @@
this.ceilingtex.Location = new System.Drawing.Point(300, 13);
this.ceilingtex.MultipleTextures = false;
this.ceilingtex.Name = "ceilingtex";
this.ceilingtex.Size = new System.Drawing.Size(190, 184);
this.ceilingtex.Size = new System.Drawing.Size(190, 204);
this.ceilingtex.TabIndex = 15;
this.ceilingtex.TextureName = "";
this.ceilingtex.UsePreviews = false;
@ -1031,7 +1261,7 @@
this.tabslopes.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.tabslopes.Location = new System.Drawing.Point(4, 22);
this.tabslopes.Name = "tabslopes";
this.tabslopes.Size = new System.Drawing.Size(503, 419);
this.tabslopes.Size = new System.Drawing.Size(503, 478);
this.tabslopes.TabIndex = 3;
this.tabslopes.Text = "Slopes";
this.tabslopes.UseVisualStyleBackColor = true;
@ -1039,9 +1269,9 @@
// groupBox5
//
this.groupBox5.Controls.Add(this.floorslopecontrol);
this.groupBox5.Location = new System.Drawing.Point(3, 212);
this.groupBox5.Location = new System.Drawing.Point(3, 239);
this.groupBox5.Name = "groupBox5";
this.groupBox5.Size = new System.Drawing.Size(497, 203);
this.groupBox5.Size = new System.Drawing.Size(497, 230);
this.groupBox5.TabIndex = 1;
this.groupBox5.TabStop = false;
this.groupBox5.Text = " Floor ";
@ -1063,7 +1293,7 @@
this.groupBox4.Controls.Add(this.ceilingslopecontrol);
this.groupBox4.Location = new System.Drawing.Point(3, 3);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(497, 203);
this.groupBox4.Size = new System.Drawing.Size(497, 230);
this.groupBox4.TabIndex = 0;
this.groupBox4.TabStop = false;
this.groupBox4.Text = " Ceiling ";
@ -1086,7 +1316,7 @@
this.tabcomment.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.tabcomment.Location = new System.Drawing.Point(4, 22);
this.tabcomment.Name = "tabcomment";
this.tabcomment.Size = new System.Drawing.Size(503, 419);
this.tabcomment.Size = new System.Drawing.Size(503, 478);
this.tabcomment.TabIndex = 4;
this.tabcomment.Text = "Comment";
this.tabcomment.UseVisualStyleBackColor = true;
@ -1095,7 +1325,7 @@
//
this.commenteditor.Location = new System.Drawing.Point(3, 3);
this.commenteditor.Name = "commenteditor";
this.commenteditor.Size = new System.Drawing.Size(497, 413);
this.commenteditor.Size = new System.Drawing.Size(497, 472);
this.commenteditor.TabIndex = 0;
//
// tabcustom
@ -1105,7 +1335,7 @@
this.tabcustom.Location = new System.Drawing.Point(4, 22);
this.tabcustom.Name = "tabcustom";
this.tabcustom.Padding = new System.Windows.Forms.Padding(3);
this.tabcustom.Size = new System.Drawing.Size(503, 419);
this.tabcustom.Size = new System.Drawing.Size(503, 478);
this.tabcustom.TabIndex = 1;
this.tabcustom.Text = "Custom";
this.tabcustom.UseVisualStyleBackColor = true;
@ -1124,7 +1354,8 @@
this.fieldslist.Name = "fieldslist";
this.fieldslist.PropertyColumnVisible = true;
this.fieldslist.PropertyColumnWidth = 150;
this.fieldslist.Size = new System.Drawing.Size(481, 398);
this.fieldslist.ShowFixedFields = true;
this.fieldslist.Size = new System.Drawing.Size(481, 444);
this.fieldslist.TabIndex = 1;
this.fieldslist.TypeColumnVisible = true;
this.fieldslist.TypeColumnWidth = 100;
@ -1134,7 +1365,7 @@
//
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(407, 459);
this.cancel.Location = new System.Drawing.Point(407, 518);
this.cancel.Name = "cancel";
this.cancel.Size = new System.Drawing.Size(112, 25);
this.cancel.TabIndex = 4;
@ -1145,7 +1376,7 @@
// 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(289, 459);
this.apply.Location = new System.Drawing.Point(289, 518);
this.apply.Name = "apply";
this.apply.Size = new System.Drawing.Size(112, 25);
this.apply.TabIndex = 3;
@ -1166,7 +1397,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.CancelButton = this.cancel;
this.ClientSize = new System.Drawing.Size(531, 489);
this.ClientSize = new System.Drawing.Size(531, 548);
this.Controls.Add(this.cancel);
this.Controls.Add(this.apply);
this.Controls.Add(this.tabs);
@ -1188,6 +1419,7 @@
groupfloorceiling.PerformLayout();
this.tabs.ResumeLayout(false);
this.tabproperties.ResumeLayout(false);
this.groupdamage.ResumeLayout(false);
this.groupBox3.ResumeLayout(false);
this.tabSurfaces.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
@ -1273,5 +1505,17 @@
private CodeImp.DoomBuilder.GZBuilder.Controls.TagsSelector tagsselector;
private System.Windows.Forms.Button resetfloorlight;
private System.Windows.Forms.Button resetceillight;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox floorterrain;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.ComboBox ceilterrain;
private System.Windows.Forms.GroupBox groupdamage;
private CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox leakiness;
private CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox damageinterval;
private System.Windows.Forms.Button resetdamagetype;
private CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox damageamount;
private System.Windows.Forms.ComboBox damagetype;
private System.Windows.Forms.Button resetfloorterrain;
private System.Windows.Forms.Button resetceilterrain;
}
}

View file

@ -24,6 +24,8 @@ namespace CodeImp.DoomBuilder.Windows
#region ================== Constants
private const string NO_SOUND_SEQUENCE = "None"; //mxd
private const string NO_TERRAIN = "Default"; //mxd
private const string NO_DAMAGETYPE = "None"; //mxd
#endregion
@ -206,7 +208,17 @@ namespace CodeImp.DoomBuilder.Windows
// Fill sound sequences list
soundsequence.Items.Add(NO_SOUND_SEQUENCE);
soundsequence.Items.AddRange(General.Map.Data.SoundSequences.ToArray());
soundsequence.Items.AddRange(General.Map.Data.SoundSequences);
// Fill damagetype list
damagetype.Items.Add(NO_DAMAGETYPE);
damagetype.Items.AddRange(General.Map.Data.DamageTypes);
// Fill terrain type lists
ceilterrain.Items.Add(NO_TERRAIN);
ceilterrain.Items.AddRange(General.Map.Data.TerrainNames);
floorterrain.Items.Add(NO_TERRAIN);
floorterrain.Items.AddRange(General.Map.Data.TerrainNames);
// Initialize custom fields editor
fieldslist.Setup("sector");
@ -308,6 +320,16 @@ namespace CodeImp.DoomBuilder.Windows
ceilRenderStyle.SelectedIndex = Array.IndexOf(renderstyles, sc.Fields.GetValue("renderstyleceiling", "translucent"));
floorRenderStyle.SelectedIndex = Array.IndexOf(renderstyles, sc.Fields.GetValue("renderstylefloor", "translucent"));
//Damage
damagetype.Text = sc.Fields.GetValue("damagetype", NO_DAMAGETYPE);
damageamount.Text = sc.Fields.GetValue("damageamount", 0).ToString();
damageinterval.Text = sc.Fields.GetValue("damageinterval", 32).ToString();
leakiness.Text = General.Clamp(sc.Fields.GetValue("leakiness", 0), 0, 256).ToString();
//Terrain
ceilterrain.Text = sc.Fields.GetValue("ceilingterrain", NO_TERRAIN);
floorterrain.Text = sc.Fields.GetValue("floorterrain", NO_TERRAIN);
//Misc
soundsequence.Text = sc.Fields.GetValue("soundsequence", NO_SOUND_SEQUENCE);
gravity.Text = sc.Fields.GetValue("gravity", 1.0f).ToString();
@ -415,8 +437,22 @@ namespace CodeImp.DoomBuilder.Windows
if(floorRenderStyle.SelectedIndex > -1 && floorRenderStyle.SelectedIndex != Array.IndexOf(renderstyles, s.Fields.GetValue("renderstylefloor", "translucent")))
floorRenderStyle.SelectedIndex = -1;
//Damage
if(damagetype.SelectedIndex > -1 && s.Fields.GetValue("damagetype", NO_DAMAGETYPE) != damagetype.Text)
damagetype.SelectedIndex = -1;
if(s.Fields.GetValue("damageamount", 0).ToString() != damageamount.Text) damageamount.Text = "";
if(s.Fields.GetValue("damageinterval", 32).ToString() != damageinterval.Text) damageinterval.Text = "";
if(s.Fields.GetValue("leakiness", 0).ToString() != leakiness.Text) leakiness.Text = "";
//Terrain
if(ceilterrain.SelectedIndex > -1 && s.Fields.GetValue("ceilingterrain", NO_TERRAIN) != ceilterrain.Text)
ceilterrain.SelectedIndex = -1;
if(floorterrain.SelectedIndex > -1 && s.Fields.GetValue("floorterrain", NO_TERRAIN) != floorterrain.Text)
floorterrain.SelectedIndex = -1;
//Misc
if(s.Fields.GetValue("soundsequence", NO_SOUND_SEQUENCE) != soundsequence.Text) soundsequence.Text = "";
if(soundsequence.SelectedIndex > -1 && s.Fields.GetValue("soundsequence", NO_SOUND_SEQUENCE) != soundsequence.Text)
soundsequence.SelectedIndex = -1;
if(s.Fields.GetValue("gravity", 1.0f).ToString() != gravity.Text) gravity.Text = "";
if(s.Fields.GetValue("desaturation", 0.0f).ToString() != desaturation.Text) desaturation.Text = "";
@ -706,15 +742,27 @@ namespace CodeImp.DoomBuilder.Windows
if(rskeys != null)
{
if(ceilRenderStyle.SelectedIndex > -1)
{
UniFields.SetString(s.Fields, "renderstyleceiling", rskeys[ceilRenderStyle.SelectedIndex], "translucent");
}
if(floorRenderStyle.SelectedIndex > -1)
{
UniFields.SetString(s.Fields, "renderstylefloor", rskeys[floorRenderStyle.SelectedIndex], "translucent");
}
}
//Damage
if(!string.IsNullOrEmpty(damagetype.Text))
UniFields.SetString(s.Fields, "damagetype", damagetype.Text, NO_DAMAGETYPE);
if(!string.IsNullOrEmpty(damageamount.Text))
UniFields.SetInteger(s.Fields, "damageamount", damageamount.GetResult(s.Fields.GetValue("damageamount", 0)), 0);
if(!string.IsNullOrEmpty(damageinterval.Text))
UniFields.SetInteger(s.Fields, "damageinterval", damageinterval.GetResult(s.Fields.GetValue("damageinterval", 32)), 32);
if(!string.IsNullOrEmpty(leakiness.Text))
UniFields.SetInteger(s.Fields, "leakiness", General.Clamp(leakiness.GetResult(s.Fields.GetValue("leakiness", 0)), 0, 256), 0);
//Terrain
if(!string.IsNullOrEmpty(ceilterrain.Text))
UniFields.SetString(s.Fields, "ceilingterrain", ceilterrain.Text, NO_TERRAIN);
if(!string.IsNullOrEmpty(floorterrain.Text))
UniFields.SetString(s.Fields, "floorterrain", floorterrain.Text, NO_TERRAIN);
// Misc
if(!string.IsNullOrEmpty(soundsequence.Text))
UniFields.SetString(s.Fields, "soundsequence", soundsequence.Text, NO_SOUND_SEQUENCE);
@ -814,14 +862,61 @@ namespace CodeImp.DoomBuilder.Windows
floorRotation.StepValues = (cbUseFloorLineAngles.Checked ? anglesteps : null);
}
private void resetfloorterrain_Click(object sender, EventArgs e)
{
floorterrain.Text = NO_TERRAIN;
}
private void floorterrain_TextChanged(object sender, EventArgs e)
{
resetfloorterrain.Visible = (floorterrain.Text != NO_TERRAIN);
}
private void floorterrain_MouseDown(object sender, MouseEventArgs e)
{
if(floorterrain.Text == NO_TERRAIN) floorterrain.SelectAll();
}
private void resetceilterrain_Click(object sender, EventArgs e)
{
ceilterrain.Text = NO_TERRAIN;
}
private void ceilterrain_TextChanged(object sender, EventArgs e)
{
resetceilterrain.Visible = (ceilterrain.Text != NO_TERRAIN);
}
private void ceilterrain_MouseDown(object sender, MouseEventArgs e)
{
if(ceilterrain.Text == NO_TERRAIN) ceilterrain.SelectAll();
}
private void resetdamagetype_Click(object sender, EventArgs e)
{
damagetype.Focus();
damagetype.Text = NO_DAMAGETYPE;
}
private void damagetype_TextChanged(object sender, EventArgs e)
{
resetdamagetype.Visible = (damagetype.Text != NO_DAMAGETYPE);
}
private void damagetype_MouseDown(object sender, MouseEventArgs e)
{
if(damagetype.Text == NO_DAMAGETYPE) damagetype.SelectAll();
}
private void resetsoundsequence_Click(object sender, EventArgs e)
{
soundsequence.Focus();
soundsequence.Text = NO_SOUND_SEQUENCE;
}
private void soundsequence_TextChanged(object sender, EventArgs e)
private void soundsequence_TextChanged(object sender, EventArgs e)
{
resetsoundsequence.Enabled = (soundsequence.Text != NO_SOUND_SEQUENCE);
resetsoundsequence.Visible = (soundsequence.Text != NO_SOUND_SEQUENCE);
}
private void soundsequence_MouseDown(object sender, MouseEventArgs e)
@ -1419,7 +1514,7 @@ namespace CodeImp.DoomBuilder.Windows
return new Vector3D(0, 0, offset);
default:
throw new NotImplementedException("SectorEditFormUDMF.GetSectorCenter: Got unknown SlopePivotMode (" + (int)mode + ")");
throw new NotImplementedException("Unknown SlopePivotMode: " + (int)mode);
}
}

View file

@ -138,12 +138,36 @@
<metadata name="label8.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label14.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label9.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label13.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label8.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="groupfloorceiling.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label15.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label6.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label5.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label15.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
@ -153,6 +177,18 @@
<metadata name="label5.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label17.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label16.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label18.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label19.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="tabproperties.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@ -162,4 +198,10 @@
<metadata name="fieldslist.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="fieldslist.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View file

@ -117,7 +117,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// The next token must be the class to inherit from
parser.SkipWhitespace(true);
inheritclass = parser.StripTokenQuotes(parser.ReadToken());
if(string.IsNullOrEmpty(inheritclass) || parser.IsSpecialToken(inheritclass))
if(string.IsNullOrEmpty(inheritclass))
{
parser.ReportError("Expected class name to inherit from");
return;
@ -131,7 +131,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// The next token must be the class to replace
parser.SkipWhitespace(true);
replaceclass = parser.StripTokenQuotes(parser.ReadToken());
if(string.IsNullOrEmpty(replaceclass) || parser.IsSpecialToken(replaceclass))
if(string.IsNullOrEmpty(replaceclass))
{
parser.ReportError("Expected class name to replace");
return;
@ -302,7 +302,7 @@ namespace CodeImp.DoomBuilder.ZDoom
}
if(uservars.ContainsKey(name))
{
parser.ReportError("User Variable \"" + name + "\" is double-defined");
parser.ReportError("User Variable \"" + name + "\" is double defined");
return;
}
if(!skipsuper && baseclass != null && baseclass.uservars.ContainsKey(name))
@ -737,7 +737,7 @@ namespace CodeImp.DoomBuilder.ZDoom
//mxd.
///TODO: rewrite this
public string FindSuitableVoxel(Dictionary<string, bool> voxels)
public string FindSuitableVoxel(HashSet<string> voxels)
{
string result = string.Empty;
@ -790,11 +790,11 @@ namespace CodeImp.DoomBuilder.ZDoom
if(!string.IsNullOrEmpty(result))
{
if(voxels.ContainsKey(result)) return result;
if(voxels.Contains(result)) return result;
// The sprite name may be incomplete. Find an existing sprite with direction.
foreach(string postfix in SPRITE_POSTFIXES)
if(voxels.ContainsKey(result + postfix)) return result + postfix;
if(voxels.Contains(result + postfix)) return result + postfix;
}

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -30,6 +31,8 @@ namespace CodeImp.DoomBuilder.ZDoom
#region ================== Properties
internal override ScriptType ScriptType { get { return ScriptType.ANIMDEFS; } }
public Dictionary<string, CameraTextureData> CameraTextures { get { return cameratextures; } }
#endregion
@ -45,9 +48,17 @@ namespace CodeImp.DoomBuilder.ZDoom
#region ================== Parsing
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
// Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -146,11 +157,6 @@ namespace CodeImp.DoomBuilder.ZDoom
return true;
}
protected override string GetLanguageType()
{
return "ANIMDEFS";
}
#endregion
}
}

View file

@ -20,6 +20,8 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -40,7 +42,10 @@ namespace CodeImp.DoomBuilder.ZDoom
#endregion
#region ================== Variables
//mxd. Script type
internal override ScriptType ScriptType { get { return ScriptType.DECORATE; } }
// These are actors we want to keep
private Dictionary<string, ActorStructure> actors;
@ -48,7 +53,10 @@ namespace CodeImp.DoomBuilder.ZDoom
private Dictionary<string, ActorStructure> archivedactors;
//mxd. Includes tracking
private readonly HashSet<string> parsedlumps;
private readonly HashSet<string> parsedlumps;
//mxd. Custom damagetypes
private readonly HashSet<string> damagetypes;
//mxd. Disposing. Is that really needed?..
private bool isdisposed;
@ -77,6 +85,11 @@ namespace CodeImp.DoomBuilder.ZDoom
/// </summary>
internal Dictionary<string, ActorStructure> AllActorsByClass { get { return archivedactors; } }
/// <summary>
/// mxd. Custom DamageTypes (http://zdoom.org/wiki/Damage_types).
/// </summary>
public IEnumerable<string> DamageTypes { get { return damagetypes; } }
#endregion
#region ================== Constructor / Disposer
@ -92,6 +105,7 @@ namespace CodeImp.DoomBuilder.ZDoom
actors = new Dictionary<string, ActorStructure>(StringComparer.OrdinalIgnoreCase);
archivedactors = new Dictionary<string, ActorStructure>(StringComparer.OrdinalIgnoreCase);
parsedlumps = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd
damagetypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd
}
// Disposer
@ -116,14 +130,24 @@ namespace CodeImp.DoomBuilder.ZDoom
// This parses the given decorate stream
// Returns false on errors
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Keep local data
Stream localstream = datastream;
string localsourcename = sourcename;
BinaryReader localreader = datareader;
DataLocation locallocation = datalocation; //mxd
string localtextresourcepath = textresourcepath; //mxd
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -153,11 +177,14 @@ namespace CodeImp.DoomBuilder.ZDoom
if(GetArchivedActorByName(actor.ReplacesClass) != null)
archivedactors[actor.ReplacesClass.ToLowerInvariant()] = actor;
else
LogWarning("Unable to find '" + actor.ReplacesClass + "' class to replace, while parsing '" + actor.ClassName + "'");
LogWarning("Unable to find \"" + actor.ReplacesClass + "\" class to replace, while parsing \"" + actor.ClassName + "\"");
if(actor.CheckActorSupported() && GetActorByName(actor.ReplacesClass) != null)
actors[actor.ReplacesClass.ToLowerInvariant()] = actor;
}
//mxd. Add to current text resource
if(!textresources[textresourcepath].Entries.Contains(actor.ClassName)) textresources[textresourcepath].Entries.Add(actor.ClassName);
}
break;
@ -206,7 +233,7 @@ namespace CodeImp.DoomBuilder.ZDoom
//mxd. Already parsed?
if(parsedlumps.Contains(filename))
{
ReportError("Already parsed '" + filename + "'. Check your include directives");
ReportError("Already parsed \"" + filename + "\". Check your include directives");
return false;
}
@ -223,9 +250,36 @@ namespace CodeImp.DoomBuilder.ZDoom
datastream = localstream;
datareader = localreader;
sourcename = localsourcename;
datalocation = locallocation; //mxd
textresourcepath = localtextresourcepath; //mxd
}
break;
case "damagetype": //mxd
// Get DamageType name
SkipWhitespace(true);
string damagetype = StripTokenQuotes(ReadToken(false));
if(string.IsNullOrEmpty(damagetype))
{
ReportError("Expected DamageType name");
return false;
}
// Next should be "{"
SkipWhitespace(true);
if(!NextTokenIs("{")) return false;
// Skip the structure
while(SkipWhitespace(true))
{
string t = ReadToken();
if(string.IsNullOrEmpty(t) || t == "}") break;
}
// Add to collection
if(!damagetypes.Contains(damagetype)) damagetypes.Add(damagetype);
break;
case "enum":
case "native":
case "const":
@ -300,12 +354,6 @@ namespace CodeImp.DoomBuilder.ZDoom
name = name.ToLowerInvariant();
return (archivedactors.ContainsKey(name) ? archivedactors[name] : null);
}
//mxd
protected override string GetLanguageType()
{
return "DECORATE";
}
#endregion
}

View file

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
namespace CodeImp.DoomBuilder.ZDoom
{
internal sealed class ReverbsParser : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.REVERBS; } }
private readonly List<string> names;
private readonly List<int> firstargs;
private readonly List<int> secondargs;
@ -20,9 +23,17 @@ namespace CodeImp.DoomBuilder.ZDoom
combinedargs = new List<int>();
}
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -48,7 +59,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(string.IsNullOrEmpty(name))
{
ReportError("Expected sound environment name");
break;
return false;
}
// Read first part of the ID
@ -57,8 +68,8 @@ namespace CodeImp.DoomBuilder.ZDoom
int arg1;
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out arg1))
{
ReportError("Expected first part of '" + name + "' sound environment ID, but got '" + token + "'");
break;
ReportError("Expected first part of \"" + name + "\" sound environment ID, but got \"" + token + "\"");
return false;
}
// Read second part of the ID
@ -67,15 +78,15 @@ namespace CodeImp.DoomBuilder.ZDoom
int arg2;
if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out arg2))
{
ReportError("Expected second part of '" + name + "' sound environment ID, but got '" + token + "'");
break;
ReportError("Expected second part of \"" + name + "\" sound environment ID, but got \"" + token + "\"");
return false;
}
int combined = arg1 * 1000000 + arg2 * 1000;
int combinedindex = combinedargs.IndexOf(combined);
if(combinedindex != -1)
{
LogWarning("'" + names[combinedindex] + "' and '" + name + "' sound environments share the same ID (" + arg1 + " " + arg2 + ")");
LogWarning("\"" + names[combinedindex] + "\" and \"" + name + "\" sound environments share the same ID (" + arg1 + " " + arg2 + ")");
}
else
{
@ -84,7 +95,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// Add to collections
if(names.Contains(name))
{
LogWarning("'" + name + "' sound environment is double-defined in '" + sourcefilename + "'");
LogWarning("\"" + name + "\" sound environment is double defined");
int index = names.IndexOf(name);
firstargs[index] = arg1;
secondargs[index] = arg2;
@ -119,10 +130,5 @@ namespace CodeImp.DoomBuilder.ZDoom
return result;
}
protected override string GetLanguageType()
{
return "REVERBS";
}
}
}

View file

@ -1,7 +1,8 @@
#region ================== Namespaces
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -17,6 +18,12 @@ namespace CodeImp.DoomBuilder.ZDoom
#endregion
#region ================== Properties
internal override ScriptType ScriptType { get { return ScriptType.SNDSEQ; } }
#endregion
#region ================== Constructor
public SndSeqParser()
@ -31,12 +38,20 @@ namespace CodeImp.DoomBuilder.ZDoom
#region ================== Parsing
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
char[] dots = new[] { ':' };
char[] brace = new[] { '[' };
char[] dots = { ':' };
char[] brace = { '[' };
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -71,7 +86,7 @@ namespace CodeImp.DoomBuilder.ZDoom
return true;
}
internal List<string> GetSoundSequences()
internal string[] GetSoundSequences()
{
List<string> result = new List<string>(sequencegroups.Count + sequences.Count);
@ -83,12 +98,7 @@ namespace CodeImp.DoomBuilder.ZDoom
result.AddRange(sequences);
// Return the collection
return result;
}
protected override string GetLanguageType()
{
return "SNDSEQ";
return result.ToArray();
}
#endregion

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.GZBuilder.Data;
namespace CodeImp.DoomBuilder.ZDoom
{
internal sealed class TerrainParser : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.TERRAIN; } }
private readonly HashSet<string> terrainnames;
public HashSet<string> TerrainNames { get { return terrainnames; } }
public TerrainParser()
{
terrainnames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
public override bool Parse(TextResourceData data, bool clearerrors)
{
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
// Continue until at the end of the stream
bool skipdefinitions = false;
while(SkipWhitespace(true))
{
string token = ReadToken().ToLowerInvariant();
if(string.IsNullOrEmpty(token)) continue;
if(skipdefinitions)
{
do
{
SkipWhitespace(true);
token = ReadToken();
} while(!string.IsNullOrEmpty(token) && token != "endif");
skipdefinitions = false;
continue;
}
switch(token)
{
case "ifheretic":
skipdefinitions = (General.Map.Config.GameType != GameType.HERETIC);
break;
case "ifhexen":
skipdefinitions = (General.Map.Config.GameType != GameType.HEXEN);
break;
case "ifstrife":
skipdefinitions = (General.Map.Config.GameType != GameType.STRIFE);
break;
case "ifdoom": // TODO: is it even a thing?..
skipdefinitions = (General.Map.Config.GameType != GameType.DOOM);
break;
case "terrain":
SkipWhitespace(true);
token = ReadToken();
if(string.IsNullOrEmpty(token))
{
ReportError("Expected terrain name");
return false;
}
// Add to collection
if(!terrainnames.Contains(token)) terrainnames.Add(token);
break;
case "{":
// Skip inner properties
do
{
SkipWhitespace(true);
token = ReadToken();
} while(!string.IsNullOrEmpty(token) && token != "}");
break;
}
}
return true;
}
}
}

View file

@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -40,12 +41,14 @@ namespace CodeImp.DoomBuilder.ZDoom
private readonly Dictionary<string, TextureStructure> textures;
private readonly Dictionary<string, TextureStructure> flats;
private readonly Dictionary<string, TextureStructure> sprites;
private readonly char[] pathtrimchars = new[] {'_', '.', ' ', '-'}; //mxd
private readonly char[] pathtrimchars = {'_', '.', ' ', '-'}; //mxd
#endregion
#region ================== Properties
internal override ScriptType ScriptType { get { return ScriptType.TEXTURES; } } //mxd
public IEnumerable<TextureStructure> Textures { get { return textures.Values; } }
public IEnumerable<TextureStructure> Flats { get { return flats.Values; } }
public IEnumerable<TextureStructure> Sprites { get { return sprites.Values; } }
@ -73,20 +76,27 @@ namespace CodeImp.DoomBuilder.ZDoom
// This parses the given stream
// Returns false on errors
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
//mxd. Make vitrual path from filename
string virtualpath;
if(sourcefilename.Contains("#")) // It's TEXTURES lump
if(data.LumpIndex != -1) // It's TEXTURES lump
{
virtualpath = Path.GetFileName(sourcefilename);
if(!string.IsNullOrEmpty(virtualpath)) virtualpath = virtualpath.Substring(0, virtualpath.LastIndexOf("#", StringComparison.Ordinal));
virtualpath = data.Filename;
}
else // If it's actual filename, try to use extension(s) as virtualpath
{
virtualpath = Path.GetFileName(sourcefilename);
virtualpath = Path.GetFileName(data.Filename);
if(!string.IsNullOrEmpty(virtualpath)) virtualpath = virtualpath.Substring(8).TrimStart(pathtrimchars);
if(!string.IsNullOrEmpty(virtualpath) && virtualpath.ToLowerInvariant() == "txt") virtualpath = string.Empty;
if(string.IsNullOrEmpty(virtualpath)) virtualpath = "[TEXTURES]";
@ -240,12 +250,6 @@ namespace CodeImp.DoomBuilder.ZDoom
// Return true when no errors occurred
return (ErrorDescription == null);
}
//mxd
protected override string GetLanguageType()
{
return "TEXTURES";
}
#endregion
}

View file

@ -2,7 +2,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.GZBuilder.Data;
using SlimDX;
@ -13,17 +14,28 @@ namespace CodeImp.DoomBuilder.ZDoom
{
public sealed class VoxeldefParser : ZDTextParser
{
internal override ScriptType ScriptType { get { return ScriptType.VOXELDEF; } }
private Dictionary<string, ModelData> entries; //sprite name, entry
internal Dictionary<string, ModelData> Entries { get { return entries; } }
public override bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public override bool Parse(TextResourceData data, bool clearerrors)
{
entries = new Dictionary<string, ModelData>(StringComparer.Ordinal);
if(!base.Parse(stream, sourcefilename, clearerrors)) return false;
string prevToken = string.Empty;
//mxd. Already parsed?
if(!base.AddTextResource(data))
{
if(clearerrors) ClearError();
return true;
}
// Cannot process?
if(!base.Parse(data, clearerrors)) return false;
List<string> spriteNames = new List<string>();
string modelName = string.Empty;
string prevToken = string.Empty;
// Continue until at the end of the stream
while(SkipWhitespace(true))
@ -101,7 +113,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(!ReadSignedFloat(token, ref angleoffset))
{
// Not numeric!
ReportError("Expected AngleOffset value, but got '" + token + "'");
ReportError("Expected AngleOffset value, but got \"" + token + "\"");
return false;
}
}
@ -113,7 +125,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(!ReadSignedFloat(token, ref scale))
{
// Not numeric!
ReportError("Expected Scale value, but got '" + token + "'");
ReportError("Expected Scale value, but got \"" + token + "\"");
return false;
}
}
@ -131,10 +143,5 @@ namespace CodeImp.DoomBuilder.ZDoom
return entries.Count > 0;
}
protected override string GetLanguageType()
{
return "VOXELDEF";
}
}
}

View file

@ -22,6 +22,7 @@ using System.Globalization;
using System.Text;
using System.IO;
using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
#endregion
@ -49,12 +50,19 @@ namespace CodeImp.DoomBuilder.ZDoom
protected Stream datastream;
protected BinaryReader datareader;
protected string sourcename;
protected int sourcelumpindex; //mxd
protected DataLocation datalocation; //mxd
// Error report
private int errorline;
private string errordesc;
private string errorsource;
private long prevstreamposition; //mxd. Text stream position storted before performing ReadToken.
//mxd. Text lumps
protected string textresourcepath;
protected readonly Dictionary<string, TextResource> textresources;
protected readonly HashSet<string> untrackedtextresources;
#endregion
@ -66,7 +74,9 @@ namespace CodeImp.DoomBuilder.ZDoom
public string ErrorDescription { get { return errordesc; } }
public string ErrorSource { get { return errorsource; } }
public bool HasError { get { return (errordesc != null); } }
internal abstract ScriptType ScriptType { get; } //mxd
internal Dictionary<string, TextResource> TextResources { get { return textresources; } } //mxd
#endregion
#region ================== Constructor / Disposer
@ -76,6 +86,8 @@ namespace CodeImp.DoomBuilder.ZDoom
{
// Initialize
errordesc = null;
textresources = new Dictionary<string, TextResource>(StringComparer.OrdinalIgnoreCase); //mxd
untrackedtextresources = new HashSet<string>(StringComparer.OrdinalIgnoreCase); //mxd
}
#endregion
@ -83,35 +95,76 @@ namespace CodeImp.DoomBuilder.ZDoom
#region ================== Parsing
//mxd. This parses the given decorate stream. Returns false on errors
public virtual bool Parse(Stream stream, string sourcefilename, bool clearerrors)
public virtual bool Parse(TextResourceData parsedata, bool clearerrors)
{
//mxd. Clear error status?
if(clearerrors) ClearError();
//mxd. Integrity checks
if(stream == null)
if(parsedata.Stream == null)
{
ReportError("Unable to load \"" + sourcefilename + "\"");
ReportError("Unable to load \"" + parsedata.Filename + "\"");
return false;
}
if(stream.Length == 0)
if(parsedata.Stream.Length == 0)
{
if(!string.IsNullOrEmpty(sourcename) && sourcename != sourcefilename)
if(!string.IsNullOrEmpty(sourcename) && sourcename != parsedata.Filename)
{
LogWarning("Include file \"" + sourcefilename + "\" is empty");
LogWarning("Include file \"" + parsedata.Filename + "\" is empty");
}
else
{
sourcename = sourcefilename; // LogWarning() needs "sourcename" property to properly log the warning...
sourcename = parsedata.Filename; // LogWarning() needs "sourcename" property to properly log the warning...
LogWarning("File is empty");
}
}
datastream = stream;
datareader = new BinaryReader(stream, Encoding.ASCII);
sourcename = sourcefilename;
datastream = parsedata.Stream;
datareader = new BinaryReader(parsedata.Stream, Encoding.ASCII);
sourcename = parsedata.Filename;
sourcelumpindex = parsedata.LumpIndex; //mxd
datalocation = parsedata.SourceLocation; //mxd
datastream.Seek(0, SeekOrigin.Begin);
return true;
}
//mxd
protected bool AddTextResource(TextResourceData parsedata)
{
// Script Editor resources don't have actual path and should always be parsed
if(string.IsNullOrEmpty(parsedata.SourceLocation.location))
{
if(parsedata.Trackable) throw new NotSupportedException("Trackable TextResource must have a valid path.");
return true;
}
string path = Path.Combine(parsedata.SourceLocation.location, parsedata.Filename + (parsedata.LumpIndex != -1 ? "#" + parsedata.LumpIndex : ""));
if(textresources.ContainsKey(path) || untrackedtextresources.Contains(path))
return false;
//mxd. Create TextResource for this file
if(parsedata.Trackable)
{
textresourcepath = path;
TextResource res = new TextResource
{
Resource = parsedata.Source,
Entries = new HashSet<string>(StringComparer.OrdinalIgnoreCase),
Filename = parsedata.Filename,
LumpIndex = parsedata.LumpIndex
};
textresources.Add(textresourcepath, res);
}
// Track the untrackable!
else
{
untrackedtextresources.Add(path);
textresourcepath = string.Empty;
}
return true;
}
@ -217,6 +270,24 @@ namespace CodeImp.DoomBuilder.ZDoom
datastream.Seek(-1, SeekOrigin.Current);
}
}
//mxd. Region/endregion handling
else if(c == '#')
{
string s = ReadToken(false).ToLowerInvariant();
if(s == "region" || s == "endregion")
{
// Skip entire line
char ch = ' ';
while((ch != '\n') && (datastream.Position < datastream.Length)) { ch = (char)datareader.ReadByte(); }
c = ch;
}
else
{
// Rewind so this structure can be read again
DataStream.Seek(-s.Length - 2, SeekOrigin.Current);
return true;
}
}
}
while(whitespace.IndexOf(c, offset) > -1);
@ -523,7 +594,8 @@ namespace CodeImp.DoomBuilder.ZDoom
// Set error information
errordesc = message;
errorline = (datastream != null ? GetCurrentLineNumber() : CompilerError.NO_LINE_NUMBER); //mxd
errorsource = sourcename;
errorsource = (ScriptType == ScriptType.ACS && sourcename.StartsWith("?") ? sourcename : Path.Combine(datalocation.GetShortName(), sourcename));
if(sourcelumpindex != -1) errorsource += ":" + sourcelumpindex; //mxd
}
//mxd. This adds a warning to the ErrorLogger
@ -531,7 +603,9 @@ namespace CodeImp.DoomBuilder.ZDoom
{
// Add a warning
int errline = (datastream != null ? GetCurrentLineNumber() : CompilerError.NO_LINE_NUMBER);
General.ErrorLogger.Add(ErrorType.Warning, GetLanguageType() + " warning in \"" + sourcename
string errsource = (ScriptType == ScriptType.ACS && sourcename.StartsWith("?") ? sourcename.Substring(1) : Path.Combine(datalocation.GetShortName(), sourcename));
if(sourcelumpindex != -1) errsource += ":" + sourcelumpindex;
General.ErrorLogger.Add(ErrorType.Warning, ScriptType + " warning in \"" + errsource
+ (errline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errline + 1) : "\"") + ". "
+ message + ".");
}
@ -539,7 +613,7 @@ namespace CodeImp.DoomBuilder.ZDoom
//mxd. This adds an error to the ErrorLogger
public void LogError()
{
General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in \"" + errorsource
General.ErrorLogger.Add(ErrorType.Error, ScriptType + " error in \"" + errorsource
+ (errorline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errorline + 1) : "\"") + ". "
+ errordesc + ".");
}
@ -563,7 +637,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// Find the line on which we found this error
datastream.Seek(0, SeekOrigin.Begin);
StreamReader textreader = new StreamReader(datastream, Encoding.ASCII);
while(readpos < finishpos)
while(readpos < finishpos + 1)
{
string line = textreader.ReadLine();
if(line == null) break;
@ -661,9 +735,6 @@ namespace CodeImp.DoomBuilder.ZDoom
return true;
}
//mxd. Language type
protected abstract string GetLanguageType();
#endregion
}
}