Added, Edit Things window, UDMF: added basic User Variable support. User variables are now automatically shown in the "Custom" tab, are marked with different color and are applied only to actors, which define them.

Fixed, Script Editor: auto-complete can now show the same term several times when it's case is different (like DECORATE's "Bright" keyword and "BRIGHT" flag).
Game configurations, ZDoom: updated "Scroll_Floor" and "Scroll_Ceiling" linedef action argument definitions.
Updated ZDoom_ACS.cfg (Ceiling_CrushAndRaiseSilentDist).
Updated ZDoom_DECORATE.cfg (A_SetChaseThreshold).
This commit is contained in:
MaxED 2016-02-08 21:51:03 +00:00
parent bd56f1db22
commit edcfbb0668
35 changed files with 558 additions and 173 deletions

View file

@ -2982,22 +2982,24 @@ zdoom
type = 11;
enum
{
1 = "Texture only";
2 = "Things only";
4 = "Both";
0 = "Texture only";
1 = "Things only";
2 = "Both";
}
}
arg3
{
title = "Horizontal Speed";
default = 128;
type = 11;
enum = "scroll_speeds";
enum = "sector_scroll_speeds_x";
}
arg4
{
title = "Vertical Speed";
default = 128;
type = 11;
enum = "scroll_speeds";
enum = "sector_scroll_speeds_y";
}
}
224
@ -3025,14 +3027,16 @@ zdoom
arg3
{
title = "Horizontal Speed";
default = 128;
type = 11;
enum = "scroll_speeds";
enum = "sector_scroll_speeds_x";
}
arg4
{
title = "Vertical Speed";
default = 128;
type = 11;
enum = "scroll_speeds";
enum = "sector_scroll_speeds_y";
}
}
225

View file

@ -661,6 +661,36 @@ enums
128 = "128: Very fast";
}
sector_scroll_speeds_x
{
0 = "0: West very fast";
16 = "16: West fast";
32 = "32: West normal";
64 = "64: West slow";
96 = "96: West very slow";
128 = "128: Don't scroll";
160 = "144: East very slow";
192 = "160: East slow";
224 = "176: East normal";
240 = "192: East fast";
256 = "256: East very fast";
}
sector_scroll_speeds_y
{
0 = "0: South very fast";
16 = "16: South fast";
32 = "32: South normal";
64 = "64: South slow";
96 = "96: South very slow";
128 = "128: Don't scroll";
160 = "144: North very slow";
192 = "160: North slow";
224 = "176: North normal";
240 = "192: North fast";
256 = "256: North very fast";
}
stair_speeds
{
2 = "2: Slow";

View file

@ -72,6 +72,7 @@ keywords
Ceiling_CrushAndRaiseA = "Ceiling_CrushAndRaiseA(tag, dspeed, uspeed, crush, crushmode)";
Ceiling_CrushAndRaiseDist = "Ceiling_CrushAndRaiseDist(tag, dist, speed, damage, crushmode)";
Ceiling_CrushAndRaiseSilentA = "Ceiling_CrushAndRaiseSilentA(tag, dspeed, uspeed, crush, crushmode)";
Ceiling_CrushAndRaiseSilentDist = "Ceiling_CrushAndRaiseSilentDist(tag, dist, speed, damage[, crushmode])";
Ceiling_CrushRaiseAndStay = "Ceiling_CrushRaiseAndStay(tag, speed, crush, crushmode)";
Ceiling_CrushRaiseAndStayA = "Ceiling_CrushRaiseAndStayA(tag, dspeed, uspeed, crush, crushmode)";
Ceiling_CrushRaiseAndStaySilA = "Ceiling_CrushRaiseAndStaySilA(tag, dspeed, uspeed, crush, crushmode)";
@ -91,8 +92,8 @@ keywords
Ceiling_RaiseInstant = "Ceiling_RaiseInstant(tag, unused, height)";
Ceiling_RaiseToNearest = "Ceiling_RaiseToNearest(tag, speed)";
Ceiling_Waggle = "Ceiling_Waggle(tag, amp, freq, offset, time)";
ChangeActorAngle = "ChangeActorAngle(int tid, fixed angle[, bool interpolate = false])\nSets the angle for the actors with the specified tid.\nIf tid is 0, it sets the angle for the activator of the script.\nangle: a fixed point angle in the range of 0.0 to 1.0 (N = 0.25, W = 0.5, S = 0.75, E = 1.0).";
ChangeActorPitch = "ChangeActorPitch(int tid, fixed pitch[, bool interpolate = false])\nSets the pitch for the actors with the specified tid. If tid is 0, it sets the pitch for the activator of the script.\npitch: a fixed point angle in the range of 0.0 to 1.0.";
ChangeActorAngle = "void ChangeActorAngle(int tid, fixed angle[, bool interpolate = false])\nSets the angle for the actors with the specified tid.\nIf tid is 0, it sets the angle for the activator of the script.\nangle: a fixed point angle in the range of 0.0 to 1.0 (N = 0.25, W = 0.5, S = 0.75, E = 1.0).";
ChangeActorPitch = "void ChangeActorPitch(int tid, fixed pitch[, bool interpolate = false])\nSets the pitch for the actors with the specified tid. If tid is 0, it sets the pitch for the activator of the script.\npitch: a fixed point angle in the range of 0.0 to 1.0.";
ChangeActorRoll = "void ChangeActorRoll(int tid, fixed angle[, bool interpolate = false])";
ChangeCamera = "ChangeCamera(tid, who, revert)";
ChangeCeiling = "void ChangeCeiling(int tag, str flatname)";

View file

@ -178,6 +178,7 @@ keywords
A_ScreamAndUnblock = "A_ScreamAndUnblock";
A_SetAngle = "A_SetAngle(float angle[, int flags = 0[, int pointer = AAPTR_DEFAULT]])\nangle: the actor's new angle, in degrees.\nflags: SPF flags.";
A_SetArg = "A_SetArg(int position, int value)";
A_SetChaseThreshold = "A_SetChaseThreshold(int threshold[, bool setdefaultthreshhold = false[, int pointer = AAPTR_DEFAULT]])";
A_SetDamageType = "A_SetDamageType(str damagetype)";
A_SetFloat = "A_SetFloat";
A_SetFloatSpeed = "A_SetFloatSpeed(float speed[, int pointer = AAPTR_DEFAULT])";
@ -347,14 +348,9 @@ keywords
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.";
//State keywords
//Bright = "Bright";
CanRaise = "CanRaise";
Fast = "Fast";
//State functions
Light = "Light(str lightname)";
NoDelay = "NoDelay";
Offset = "Offset(int x, int y)";
Slow = "Slow";
//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)";
@ -363,6 +359,11 @@ keywords
properties
{
Actor;
enum;
const;
var;
int;
float;
//WFDS
if;
else;
@ -373,7 +374,13 @@ properties
Wait;
Fail;
goto;
//states:
//State keywords
Bright;
CanRaise;
Fast;
Slow;
NoDelay;
//States
States;
Spawn:;
Idle:;
@ -452,6 +459,8 @@ properties
Activation;
TeleFogSourceType;
TeleFogDestType;
Threshold;
DefThreshold;
//Collision and 'Physics'
Radius;
Height;

View file

@ -242,7 +242,7 @@ namespace CodeImp.DoomBuilder.Controls
//mxd. this sets default value
public void SetDefaultValue()
{
typehandler.SetDefaultValue();
typehandler.ApplyDefaultValue();
combobox.SelectedItem = null;
combobox.Text = typehandler.GetStringValue();
combobox_Validating(this, new CancelEventArgs());

View file

@ -171,6 +171,7 @@ namespace CodeImp.DoomBuilder.Controls
// Go for all rows
bool foundrow = false;
bool skiprow = false; //mxd
foreach(DataGridViewRow row in fieldslist.Rows)
{
// Row is a field?
@ -181,11 +182,18 @@ namespace CodeImp.DoomBuilder.Controls
// Row name matches with field
if(frow.Name == f.Key)
{
//mxd. User vars are set separately
if(frow.RowType == FieldsEditorRowType.USERVAR)
{
skiprow = true;
break;
}
// First time?
if(first)
{
// Set type when row is not fixed
if(!frow.IsFixed) frow.ChangeType(f.Value.Type);
if(frow.RowType == FieldsEditorRowType.DYNAMIC) frow.ChangeType(f.Value.Type);
// Apply value of field to row
frow.Define(f.Value.Value);
@ -207,16 +215,18 @@ namespace CodeImp.DoomBuilder.Controls
}
}
}
//mxd. User vars are set separately
if(skiprow) continue;
// Row not found?
if(!foundrow)
{
// Make new row
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value);
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, f.Key, f.Value.Type, f.Value.Value, false);
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow);
// When not the first, clear the field
// because the others did not define this one
// When not the first, clear the field because the others did not define this one
if(!first) frow.Clear();
}
}
@ -245,6 +255,82 @@ namespace CodeImp.DoomBuilder.Controls
// Sort fields
Sort();
}
//mxd
public void SetUserVars(Dictionary<string, UniversalType> vars, UniFields fromfields, bool first)
{
foreach(KeyValuePair<string, UniversalType> group in vars)
{
// Go for all rows
bool foundrow = false;
TypeHandler vartype = General.Types.GetFieldHandler((int)group.Value, 0);
object value = fromfields.ContainsKey(group.Key) ? fromfields[group.Key].Value : vartype.GetDefaultValue();
foreach(DataGridViewRow row in fieldslist.Rows)
{
// Row is a field?
if(row is FieldsEditorRow)
{
FieldsEditorRow frow = row as FieldsEditorRow;
// Row name matches with user var?
if(frow.RowType == FieldsEditorRowType.USERVAR && frow.Name == group.Key)
{
// First time?
if(first)
{
frow.Define(value);
}
// Check if the value is different
else if(!frow.TypeHandler.GetValue().Equals(value))
{
// Clear the value in the row
frow.Define(value);
frow.Clear();
}
// Done
foundrow = true;
break;
}
}
}
// Row not found?
if(!foundrow)
{
// Make new row
object defaultvalue = vartype.GetDefaultValue();
FieldsEditorRow frow = new FieldsEditorRow(fieldslist, group.Key, (int)group.Value, defaultvalue, true);
if(!value.Equals(defaultvalue)) frow.Define(value);
fieldslist.Rows.Insert(fieldslist.Rows.Count - 1, frow);
}
}
// Now check for rows that the givens fields do NOT have
foreach(DataGridViewRow row in fieldslist.Rows)
{
// Row is a field?
if(row is FieldsEditorRow)
{
FieldsEditorRow frow = row as FieldsEditorRow;
// Don't undefine user var rows defined by other actor types
if(frow.RowType != FieldsEditorRowType.USERVAR || !vars.ContainsKey(frow.Name)) continue;
// Is this row defined previously?
if(frow.IsDefined)
{
// Check if this row can not be found in the fields at all
if(!fromfields.ContainsKey(frow.Name))
{
// It is not defined in these fields, undefine the value
frow.Undefine();
}
}
}
}
}
// This applies the current fields to a UniFields object
public void Apply(UniFields tofields)
@ -259,6 +345,7 @@ namespace CodeImp.DoomBuilder.Controls
// Go for all rows
bool foundrow = false;
bool skiprow = false; //mxd
foreach(DataGridViewRow row in fieldslist.Rows)
{
// Row is a field and matches field name?
@ -266,6 +353,13 @@ namespace CodeImp.DoomBuilder.Controls
{
FieldsEditorRow frow = row as FieldsEditorRow;
//mxd. User vars are stored separately
if(frow.RowType == FieldsEditorRowType.USERVAR)
{
skiprow = true;
break;
}
// Field is defined?
if(frow.IsDefined)
{
@ -275,6 +369,9 @@ namespace CodeImp.DoomBuilder.Controls
}
}
//mxd. User vars are stored separately
if(skiprow) continue;
// No such row?
if(!foundrow)
{
@ -292,7 +389,7 @@ namespace CodeImp.DoomBuilder.Controls
FieldsEditorRow frow = row as FieldsEditorRow;
// Field is defined and not empty?
if(frow.IsDefined && !frow.IsEmpty)
if(frow.RowType != FieldsEditorRowType.USERVAR && frow.IsDefined && !frow.IsEmpty)
{
// Apply field
object oldvalue = null;
@ -300,7 +397,7 @@ namespace CodeImp.DoomBuilder.Controls
tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, frow.GetResult(oldvalue));
// Custom row?
if(!frow.IsFixed)
if(frow.RowType == FieldsEditorRowType.DYNAMIC)
{
// Write type to map configuration
General.Map.Options.SetUniversalFieldType(elementname, frow.Name, frow.TypeHandler.Index);
@ -310,6 +407,38 @@ namespace CodeImp.DoomBuilder.Controls
}
}
//mxd
public void ApplyUserVars(Dictionary<string, UniversalType> vars, UniFields tofields)
{
// Apply user variables when target map element contains user var definition and the value is not default
foreach(DataGridViewRow row in fieldslist.Rows)
{
// Row is a field?
if(row is FieldsEditorRow)
{
FieldsEditorRow frow = row as FieldsEditorRow;
if(frow.RowType != FieldsEditorRowType.USERVAR || !vars.ContainsKey(frow.Name)) continue;
object oldvalue = (tofields.ContainsKey(frow.Name) ? tofields[frow.Name].Value : null);
object newvalue = frow.GetResult(oldvalue);
// Skip field when mixed values
if(newvalue == null) continue;
// Remove field
if(newvalue.Equals(frow.TypeHandler.GetDefaultValue()))
{
if(tofields.ContainsKey(frow.Name)) tofields.Remove(frow.Name);
}
// Add field
else if(!newvalue.Equals(oldvalue))
{
tofields[frow.Name] = new UniValue(frow.TypeHandler.Index, newvalue);
}
}
}
}
#endregion
#region ================== Events
@ -377,8 +506,8 @@ namespace CodeImp.DoomBuilder.Controls
// First column?
if(e.ColumnIndex == 0)
{
// Not a fixed field?
if((frow != null) && !frow.IsFixed)
// Dynamic field?
if((frow != null) && frow.RowType == FieldsEditorRowType.DYNAMIC)
{
lasteditfieldname = frow.Name;
fieldslist.CurrentCell = fieldslist.SelectedRows[0].Cells[0];
@ -399,21 +528,20 @@ namespace CodeImp.DoomBuilder.Controls
{
// Get the row
FieldsEditorRow row = e.Row as FieldsEditorRow;
if(row == null) return;
// Fixed field?
if(row.IsFixed)
// Fixed/uservar field?
if(row.RowType == FieldsEditorRowType.FIXED || row.RowType == FieldsEditorRowType.USERVAR)
{
// Just undefine the field
row.Undefine();
e.Cancel = true;
if(OnFieldUndefined != null)
OnFieldUndefined(row.Name);
if(OnFieldUndefined != null) OnFieldUndefined(row.Name);
}
else
{
if(OnFieldDeleted != null)
OnFieldDeleted(row.Name);
if(OnFieldDeleted != null) OnFieldDeleted(row.Name);
}
}
@ -428,10 +556,7 @@ namespace CodeImp.DoomBuilder.Controls
{
// Remove all text
fieldslist.Rows[e.RowIndex].Cells[0].Style.ForeColor = SystemColors.WindowText;
if(autoinsertuserprefix)
fieldslist.Rows[e.RowIndex].Cells[0].Value = FIELD_PREFIX_SUGGESTION;
else
fieldslist.Rows[e.RowIndex].Cells[0].Value = "";
fieldslist.Rows[e.RowIndex].Cells[0].Value = (autoinsertuserprefix ? FIELD_PREFIX_SUGGESTION : string.Empty);
}
}
// Value cell?
@ -538,12 +663,11 @@ namespace CodeImp.DoomBuilder.Controls
int type = General.Map.Options.GetUniversalFieldType(elementname, validname, 0);
// Make new row
frow = new FieldsEditorRow(fieldslist, validname, type, null);
frow = new FieldsEditorRow(fieldslist, validname, type, null, false);
frow.Visible = false;
fieldslist.Rows.Insert(e.RowIndex + 1, frow);
if(OnFieldInserted != null)
OnFieldInserted(validname);
if(OnFieldInserted != null) OnFieldInserted(validname);
}
}
}
@ -587,11 +711,8 @@ namespace CodeImp.DoomBuilder.Controls
row.Cells[0].Value = validname;
if(type != -1) frow.ChangeType(type);
if(OnFieldNameChanged != null)
OnFieldNameChanged(lasteditfieldname, validname);
if(OnFieldTypeChanged != null)
OnFieldTypeChanged(validname);
if(OnFieldNameChanged != null) OnFieldNameChanged(lasteditfieldname, validname);
if(OnFieldTypeChanged != null) OnFieldTypeChanged(validname);
}
else
{
@ -615,8 +736,7 @@ namespace CodeImp.DoomBuilder.Controls
// Changing field type?
if((e.ColumnIndex == 1) && (frow != null))
{
if(OnFieldTypeChanged != null)
OnFieldTypeChanged(frow.Name);
if(OnFieldTypeChanged != null) OnFieldTypeChanged(frow.Name);
}
// Changing field value?
if((e.ColumnIndex == 2) && (frow != null))
@ -649,7 +769,7 @@ namespace CodeImp.DoomBuilder.Controls
{
//mxd. Preserve fixed fields visibility setting
FieldsEditorRow frow = (fieldslist.Rows[i] as FieldsEditorRow);
if(frow != null && frow.IsFixed) frow.Visible = showfixedfields;
if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields;
else fieldslist.Rows[i].Visible = true;
}
}
@ -730,17 +850,17 @@ namespace CodeImp.DoomBuilder.Controls
private void ApplyValue(FieldsEditorRow frow, object value)
{
// Defined?
if((value != null) && (!frow.IsFixed || !frow.Info.Default.Equals(value)))
if((value != null) && (frow.RowType == FieldsEditorRowType.DYNAMIC || frow.RowType == FieldsEditorRowType.USERVAR
|| !frow.Info.Default.Equals(value)))
{
frow.Define(value);
}
else if(frow.IsFixed)
else if(frow.RowType == FieldsEditorRowType.FIXED)
{
frow.Undefine();
}
if(OnFieldValueChanged != null)
OnFieldValueChanged(frow.Name);
if(OnFieldValueChanged != null) OnFieldValueChanged(frow.Name);
}
// This applies the contents of the enums combobox and hides (if opened)
@ -847,7 +967,7 @@ namespace CodeImp.DoomBuilder.Controls
foreach(var row in fieldslist.Rows)
{
FieldsEditorRow frow = (row as FieldsEditorRow);
if(frow != null && frow.IsFixed) frow.Visible = showfixedfields;
if(frow != null && frow.RowType == FieldsEditorRowType.FIXED) frow.Visible = showfixedfields;
}
}

View file

@ -26,6 +26,23 @@ using CodeImp.DoomBuilder.Types;
namespace CodeImp.DoomBuilder.Controls
{
internal enum FieldsEditorRowType //mxd
{
// This is a fixed field defined in the game configuration
// The field cannot be deleted (delete will result in a reset)
// and cannot change type.
FIXED,
// This is an abstartct variable field enetered by user
// The field can be deleted and can change type.
DYNAMIC,
// This is a user variable field defined in actor's DECORATE
// The field cannot be deleted (delete will result in a reset)
// but can change type.
USERVAR,
}
internal class FieldsEditorRow : DataGridViewRow
{
#region ================== Constants
@ -34,13 +51,11 @@ namespace CodeImp.DoomBuilder.Controls
#region ================== Variables
// This is true when for a fixed field as defined in the game configuration
// This means that the field cannot be deleted (delete will result in a reset)
// and cannot change type.
private bool isfixed;
//mxd. Row type
private readonly FieldsEditorRowType rowtype;
// Field information (only for fixed fields)
private UniversalFieldInfo fieldinfo;
private readonly UniversalFieldInfo fieldinfo;
// This is true when the field is defined. Cannot be false when this field
// is not fixed, because non-fixed fields are deleted from the list when undefined.
@ -53,7 +68,7 @@ namespace CodeImp.DoomBuilder.Controls
#region ================== Properties
public bool IsFixed { get { return isfixed; } }
public FieldsEditorRowType RowType { get { return rowtype; } } //mxd
public bool IsDefined { get { return isdefined; } }
public bool IsEmpty { get { return (this.Cells[2].Value == null) || (this.Cells[2].Value.ToString().Length == 0); } }
public string Name { get { return this.Cells[0].Value.ToString(); } }
@ -73,7 +88,7 @@ namespace CodeImp.DoomBuilder.Controls
// Fixed
this.fieldinfo = fixedfield;
isfixed = true;
this.rowtype = FieldsEditorRowType.FIXED; //mxd
// Type
this.fieldtype = General.Types.GetFieldHandler(fixedfield);
@ -97,31 +112,54 @@ namespace CodeImp.DoomBuilder.Controls
}
// Constructor for a non-fixed, defined field
public FieldsEditorRow(DataGridView view, string name, int type, object value)
//mxd. Also for a user variable field.
public FieldsEditorRow(DataGridView view, string name, int type, object value, bool isuservar)
{
// Defined
this.DefaultCellStyle.ForeColor = SystemColors.WindowText;
isdefined = true;
// Non-fixed
isfixed = false;
//mxd. Row type
this.rowtype = (isuservar ? FieldsEditorRowType.USERVAR : FieldsEditorRowType.DYNAMIC);
// Type
this.fieldtype = General.Types.GetFieldHandler(type, value);
// Make all cells
base.CreateCells(view);
// Setup property cell
this.Cells[0].Value = name;
this.Cells[0].ReadOnly = true;
// Setup type cell
this.Cells[1].Value = fieldtype.GetDisplayType();
this.Cells[1].ReadOnly = false;
//mxd. Our path splits here...
if(isuservar)
{
// Not defined
this.DefaultCellStyle.ForeColor = SystemColors.GrayText;
isdefined = false;
fieldtype.ApplyDefaultValue();
// Setup value cell
this.Cells[2].Value = fieldtype.GetStringValue();
// Setup property cell
this.Cells[0].Value = name;
this.Cells[0].ReadOnly = true;
// Setup type cell
this.Cells[1].Value = fieldtype.GetDisplayType();
this.Cells[1].ReadOnly = true;
// Setup value cell
this.Cells[2].Value = fieldtype.GetStringValue();
}
else
{
// Defined
this.DefaultCellStyle.ForeColor = SystemColors.WindowText;
isdefined = true;
// Setup property cell
this.Cells[0].Value = name;
this.Cells[0].ReadOnly = true;
// Setup type cell
this.Cells[1].Value = fieldtype.GetDisplayType();
this.Cells[1].ReadOnly = false;
// Setup value cell
this.Cells[2].Value = fieldtype.GetStringValue();
}
// We have no destructor
GC.SuppressFinalize(this);
@ -140,7 +178,7 @@ namespace CodeImp.DoomBuilder.Controls
fieldtype.Browse(parent);
// This is a fixed field?
if(isfixed)
if(rowtype == FieldsEditorRowType.FIXED)
{
// Does this match the default setting?
if(fieldtype.GetValue().Equals(fieldinfo.Default))
@ -188,7 +226,7 @@ namespace CodeImp.DoomBuilder.Controls
this.Cells[2].Value = fieldtype.GetStringValue();
// This is a fixed field?
if(isfixed)
if(rowtype == FieldsEditorRowType.FIXED)
{
// Does this match the default setting?
if(fieldtype.GetValue().Equals(fieldinfo.Default))
@ -201,15 +239,19 @@ namespace CodeImp.DoomBuilder.Controls
}
// This undefines the field
// ONLY VALID FOR FIXED FIELDS
// ONLY VALID FOR FIXED AND USERVAR FIELDS
// You should just delete non-fixed fields
public void Undefine()
{
// Must be fixed!
if(!isfixed) throw new InvalidOperationException();
if(rowtype != FieldsEditorRowType.FIXED && rowtype != FieldsEditorRowType.USERVAR) throw new InvalidOperationException();
// Now undefined
fieldtype.SetValue(fieldinfo.Default);
if(rowtype == FieldsEditorRowType.USERVAR)
fieldtype.ApplyDefaultValue();
else
fieldtype.SetValue(fieldinfo.Default);
this.Cells[2].Value = fieldtype.GetStringValue();
this.DefaultCellStyle.ForeColor = SystemColors.GrayText;
isdefined = false;
@ -218,10 +260,13 @@ namespace CodeImp.DoomBuilder.Controls
// This defines the field
public void Define(object value)
{
//mxd. Don't count as defined when default value is passed
if(value.ToString() == fieldtype.GetDefaultValue().ToString()) return;
// Now defined
fieldtype.SetValue(value);
this.Cells[2].Value = fieldtype.GetStringValue();
this.DefaultCellStyle.ForeColor = SystemColors.WindowText;
this.DefaultCellStyle.ForeColor = (rowtype == FieldsEditorRowType.USERVAR ? SystemColors.HotTrack : SystemColors.WindowText);
isdefined = true;
}
@ -229,13 +274,12 @@ namespace CodeImp.DoomBuilder.Controls
public void ChangeType(int typeindex)
{
// Can't do this for a fixed field!
if(isfixed) throw new InvalidOperationException();
if(rowtype == FieldsEditorRowType.FIXED) throw new InvalidOperationException();
// Different?
if(typeindex != fieldtype.Index)
{
// Change field type!
//TypeHandlerAttribute attrib = General.Types.GetAttribute(typeindex); //mxd
fieldtype = General.Types.GetFieldHandler(typeindex, this.Cells[2].Value);
this.Cells[1].Value = fieldtype.GetDisplayType();
}

View file

@ -452,7 +452,7 @@ namespace CodeImp.DoomBuilder.Controls
int keywordsindex = lexercfg.ReadSetting(lexername + ".keywordsindex", -1);
if(keywordsindex > -1)
{
StringBuilder keywordslist = new StringBuilder("");
StringBuilder keywordslist = new StringBuilder();
foreach(string k in scriptconfig.Keywords)
{
if(keywordslist.Length > 0) keywordslist.Append(" ");
@ -460,7 +460,7 @@ namespace CodeImp.DoomBuilder.Controls
//mxd. Skip adding the keyword if we have a snippet with the same name
if(!scriptconfig.Snippets.Contains(k))
autocompletedict.Add(k.ToUpperInvariant(), k + "?" + imageindex);
autocompletedict.Add(k, k + "?" + imageindex);
}
string words = keywordslist.ToString();
scriptedit.SetKeywords(keywordsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant()));
@ -471,9 +471,9 @@ namespace CodeImp.DoomBuilder.Controls
int propertiesindex = lexercfg.ReadSetting(lexername + ".propertiesindex", -1);
if(propertiesindex > -1)
{
StringBuilder propertieslist = new StringBuilder("");
StringBuilder propertieslist = new StringBuilder();
HashSet<string> addedprops = new HashSet<string>();
char[] dot = new[] {'.'};
char[] dot = {'.'};
foreach(string p in scriptconfig.Properties)
{
if(propertieslist.Length > 0) propertieslist.Append(" ");
@ -511,7 +511,9 @@ namespace CodeImp.DoomBuilder.Controls
}
// Autocomplete doesn't mind '.' or ':'
autocompletedict[p.ToUpperInvariant()] = p + "?" + imageindex;
// Skip adding the keyword if we have a snippet with the same name
if(!scriptconfig.Snippets.Contains(p))
autocompletedict.Add(p, p + "?" + imageindex);
}
string words = propertieslist.ToString();
scriptedit.SetKeywords(propertiesindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant()));
@ -522,21 +524,17 @@ namespace CodeImp.DoomBuilder.Controls
int constantsindex = lexercfg.ReadSetting(lexername + ".constantsindex", -1);
if(constantsindex > -1)
{
StringBuilder constantslist = new StringBuilder("");
StringBuilder constantslist = new StringBuilder();
foreach(string c in scriptconfig.Constants)
{
if(autocompletedict.ContainsKey(c.ToUpperInvariant())) //mxd. This happens when there's a keyword and a constant with the same name...
{
General.ErrorLogger.Add(ErrorType.Error, "Constant '" + c + "' is double-defined in '" + scriptconfig.Description + "' script configuration!");
continue;
}
if(autocompletedict.ContainsKey(c)) continue; //mxd. This happens when there's a keyword and a constant with the same name...
if(constantslist.Length > 0) constantslist.Append(" ");
constantslist.Append(c);
//mxd. Skip adding the constant if we have a snippet with the same name
if(!scriptconfig.Snippets.Contains(c))
autocompletedict.Add(c.ToUpperInvariant(), c + "?" + imageindex);
autocompletedict.Add(c, c + "?" + imageindex);
}
string words = constantslist.ToString();
scriptedit.SetKeywords(constantsindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant()));
@ -547,13 +545,12 @@ namespace CodeImp.DoomBuilder.Controls
int snippetindex = lexercfg.ReadSetting(lexername + ".snippetindex", -1);
if(snippetindex > -1 && scriptconfig.Snippets.Count > 0)
{
StringBuilder snippetslist = new StringBuilder("");
foreach(string c in scriptconfig.Snippets)
StringBuilder snippetslist = new StringBuilder();
foreach(string s in scriptconfig.Snippets)
{
if(autocompletedict.ContainsKey(c.ToUpperInvariant())) continue;
if(snippetslist.Length > 0) snippetslist.Append(" ");
snippetslist.Append(c);
autocompletedict.Add(c.ToUpperInvariant(), c + "?" + imageindex);
snippetslist.Append(s);
autocompletedict.Add(s, s + "?" + imageindex);
}
string words = snippetslist.ToString();
scriptedit.SetKeywords(snippetindex, (scriptconfig.CaseSensitive ? words : words.ToLowerInvariant()));

View file

@ -147,7 +147,7 @@ namespace CodeImp.DoomBuilder.Controls
// Boilderplate
if(!General.CompiledScriptConfigs.ContainsKey(General.Map.Options.ScriptCompiler))
{
General.ShowErrorMessage("Unable to compile '" + inputfile + "'. Unable to find required script compiler configuration ('" + General.Map.Options.ScriptCompiler + "').", MessageBoxButtons.OK);
General.ShowErrorMessage("Unable to compile \"" + inputfile + "\". Unable to find required script compiler configuration (\"" + General.Map.Options.ScriptCompiler + "\").", MessageBoxButtons.OK);
return;
}
@ -232,7 +232,7 @@ namespace CodeImp.DoomBuilder.Controls
{
// Fail
compiler.Dispose();
errors.Add(new CompilerError("Output file '" + outputfile + "' doesn't exist."));
errors.Add(new CompilerError("Output file \"" + outputfile + "\" doesn't exist."));
panel.ShowErrors(errors);
return;
}
@ -247,7 +247,7 @@ namespace CodeImp.DoomBuilder.Controls
{
// Fail
compiler.Dispose();
errors.Add(new CompilerError("Unable to create library file '" + targetfilename + "'. " + e.GetType().Name + ": " + e.Message));
errors.Add(new CompilerError("Unable to create library file \"" + targetfilename + "\". " + e.GetType().Name + ": " + e.Message));
panel.ShowErrors(errors);
return;
}
@ -282,7 +282,7 @@ namespace CodeImp.DoomBuilder.Controls
catch(Exception e)
{
// Failed
General.ErrorLogger.Add(ErrorType.Error, "Cannot open file '" + filepathname + "' for writing. Make sure the path exists and that the file is not in use by another application.");
General.ErrorLogger.Add(ErrorType.Error, "Cannot open file \"" + filepathname + "\" for writing. Make sure the path exists and that the file is not in use by another application.");
General.WriteLogLine(e.GetType().Name + ": " + e.Message);
General.ShowErrorMessage("Unable to open file \"" + filepathname + "\" for writing. Make sure the path exists and that the file is not in use by another application.", MessageBoxButtons.OK);
return false;
@ -323,7 +323,7 @@ namespace CodeImp.DoomBuilder.Controls
catch(Exception e)
{
// Failed
General.ErrorLogger.Add(ErrorType.Error, "Cannot open file '" + filepathname + "' for reading. Make sure the path exists and that the file is not in use by another application.");
General.ErrorLogger.Add(ErrorType.Error, "Cannot open file \"" + filepathname + "\" for reading. Make sure the path exists and that the file is not in use by another application.");
General.WriteLogLine(e.GetType().Name + ": " + e.Message);
General.ShowErrorMessage("Unable to open file \"" + filepathname + "\" for reading. Make sure the path exists and that the file is not in use by another application.", MessageBoxButtons.OK);
return false;

View file

@ -102,6 +102,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0f;
}
#endregion
}
}

View file

@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}
}

View file

@ -102,6 +102,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0f;
}
#endregion
}
}

View file

@ -93,7 +93,7 @@ namespace CodeImp.DoomBuilder.Types
public override int GetIntValue()
{
if(this.value) return 1; else return 0;
return (this.value ? 1 : 0);
}
public override string GetStringValue()
@ -106,6 +106,11 @@ namespace CodeImp.DoomBuilder.Types
{
return list;
}
public override object GetDefaultValue()
{
return false;
}
#endregion
}

View file

@ -113,6 +113,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString("X6");
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}
}

View file

@ -38,7 +38,7 @@ namespace CodeImp.DoomBuilder.Types
private EnumList list;
private int value;
private int defaultValue; //mxd
private int defaultvalue; //mxd
#endregion
@ -55,7 +55,7 @@ namespace CodeImp.DoomBuilder.Types
// When set up for an argument
public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo)
{
defaultValue = (int)arginfo.DefaultValue;//mxd
defaultvalue = (int)arginfo.DefaultValue;//mxd
base.SetupArgument(attr, arginfo);
// Keep enum list reference
@ -100,9 +100,9 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultValue;
value = defaultvalue;
}
public override object GetValue()
@ -120,6 +120,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return defaultvalue;
}
#endregion
}
}

View file

@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultvalue;
}
@ -189,6 +189,11 @@ namespace CodeImp.DoomBuilder.Types
{
return General.Types.GetAttribute((int)UniversalType.Integer);
}
public override object GetDefaultValue()
{
return defaultvalue;
}
#endregion
}

View file

@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.Types
private EnumList list;
private EnumItem value;
private EnumItem defaultValue; //mxd
private EnumItem defaultvalue; //mxd
#endregion
@ -50,7 +50,7 @@ namespace CodeImp.DoomBuilder.Types
// When set up for an argument
public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo)
{
defaultValue = new EnumItem(arginfo.DefaultValue.ToString(), arginfo.DefaultValue.ToString()); //mxd
defaultvalue = new EnumItem(arginfo.DefaultValue.ToString(), arginfo.DefaultValue.ToString()); //mxd
base.SetupArgument(attr, arginfo);
// Keep enum list reference
@ -121,9 +121,9 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultValue;
value = defaultvalue;
}
public override object GetValue()
@ -171,6 +171,11 @@ namespace CodeImp.DoomBuilder.Types
return General.Types.GetAttribute((int)UniversalType.String);
}
public override object GetDefaultValue()
{
return defaultvalue;
}
#endregion
}
}

View file

@ -70,6 +70,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value;
}
public override object GetDefaultValue()
{
return string.Empty;
}
#endregion
}
}

View file

@ -85,6 +85,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0f;
}
#endregion
}
}

View file

@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.Types
#region ================== Variables
private int value;
private int defaultValue; //mxd
private int defaultvalue; //mxd
#endregion
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Types
//mxd
public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo)
{
defaultValue = (int)arginfo.DefaultValue;
defaultvalue = (int)arginfo.DefaultValue;
base.SetupArgument(attr, arginfo);
}
@ -85,9 +85,9 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultValue;
value = defaultvalue;
}
public override object GetValue()
@ -104,6 +104,11 @@ namespace CodeImp.DoomBuilder.Types
{
return this.value.ToString();
}
public override object GetDefaultValue()
{
return defaultvalue;
}
#endregion
}

View file

@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}
}

View file

@ -62,6 +62,11 @@ namespace CodeImp.DoomBuilder.Types
{
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}

View file

@ -18,7 +18,7 @@ namespace CodeImp.DoomBuilder.Types
#region ================== Variables
private float value;
private bool randomValue;
private bool randomvalue;
private float min;
private float max;
@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.Types
if(float.TryParse(parts[0], NumberStyles.Float, CultureInfo.CurrentCulture, out min) &&
float.TryParse(parts[1], NumberStyles.Float, CultureInfo.CurrentCulture, out max))
{
randomValue = (min != max);
randomvalue = (min != max);
if(min == max) this.value = min;
else if(min > max) General.Swap(ref min, ref max);
@ -91,22 +91,27 @@ namespace CodeImp.DoomBuilder.Types
public override object GetValue()
{
if(randomValue) return General.Random(min, max); //mxd
if(randomvalue) return General.Random(min, max); //mxd
return this.value;
}
public override int GetIntValue()
{
if(randomValue) return (int)General.Random(min, max); //mxd
if(randomvalue) return (int)General.Random(min, max); //mxd
return (int)this.value;
}
public override string GetStringValue()
{
if(randomValue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd
if(randomvalue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd
return this.value.ToString(CultureInfo.InvariantCulture);
}
public override object GetDefaultValue()
{
return 0f;
}
#endregion
}
}

View file

@ -14,8 +14,8 @@ namespace CodeImp.DoomBuilder.Types
#region ================== Variables
private int value;
private int defaultValue;
private bool randomValue;
private int defaultvalue;
private bool randomvalue;
private int min;
private int max;
@ -29,7 +29,7 @@ namespace CodeImp.DoomBuilder.Types
public override void SetupArgument(TypeHandlerAttribute attr, ArgumentInfo arginfo)
{
defaultValue = (int)arginfo.DefaultValue;
defaultvalue = (int)arginfo.DefaultValue;
base.SetupArgument(attr, arginfo);
//mxd. We don't want to store this type
@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Types
if(int.TryParse(parts[0], NumberStyles.Integer, CultureInfo.CurrentCulture, out min) &&
int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.CurrentCulture, out max))
{
randomValue = (min != max);
randomvalue = (min != max);
if(min == max) this.value = min;
else if(min > max) General.Swap(ref min, ref max);
}
@ -89,29 +89,34 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultValue;
value = defaultvalue;
}
public override object GetValue()
{
if(randomValue) return General.Random(min, max); //mxd
if(randomvalue) return General.Random(min, max); //mxd
return this.value;
}
public override int GetIntValue()
{
if(randomValue) return General.Random(min, max); //mxd
if(randomvalue) return General.Random(min, max); //mxd
return this.value;
}
public override string GetStringValue()
{
if(randomValue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd
if(randomvalue) return General.Random(min, max).ToString(CultureInfo.InvariantCulture); //mxd
return this.value.ToString(CultureInfo.InvariantCulture);
}
public override object GetDefaultValue()
{
return defaultvalue;
}
#endregion
}
}

View file

@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}
}

View file

@ -170,7 +170,7 @@ namespace CodeImp.DoomBuilder.Types
}
//mxd
public override void SetDefaultValue()
public override void ApplyDefaultValue()
{
value = defaultvalue;
}
@ -197,6 +197,11 @@ namespace CodeImp.DoomBuilder.Types
return (this.value != null ? this.value.Title : "0: No Tag");
}
public override object GetDefaultValue()
{
return defaultvalue;
}
// This returns an enum list
public override EnumList GetEnumList()
{

View file

@ -68,8 +68,7 @@ namespace CodeImp.DoomBuilder.Types
public override int GetIntValue()
{
int result;
if(int.TryParse(this.value, out result)) return result;
else return 0;
return (int.TryParse(this.value, out result) ? result : 0);
}
public override string GetStringValue()
@ -77,6 +76,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value;
}
public override object GetDefaultValue()
{
return string.Empty;
}
#endregion
}
}

View file

@ -70,6 +70,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value;
}
public override object GetDefaultValue()
{
return string.Empty;
}
#endregion
}
}

View file

@ -91,6 +91,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value;
}
public override object GetDefaultValue()
{
return string.Empty;
}
#endregion
}
}

View file

@ -101,6 +101,11 @@ namespace CodeImp.DoomBuilder.Types
return this.value.ToString();
}
public override object GetDefaultValue()
{
return 0;
}
#endregion
}
}

View file

@ -120,11 +120,14 @@ namespace CodeImp.DoomBuilder.Types
public abstract void SetValue(object value);
//mxd. This should replace current value with the default one
public virtual void SetDefaultValue() { }
public virtual void ApplyDefaultValue() { }
// This must return the value as one of the primitive data types
// supported by UDMF: int, string, float or bool
public abstract object GetValue();
//mxd. This should return the default value
public abstract object GetDefaultValue();
// This must return the value as integer (for arguments)
public virtual int GetIntValue()
@ -136,9 +139,7 @@ namespace CodeImp.DoomBuilder.Types
public abstract string GetStringValue();
// This is called when the user presses the browse button
public virtual void Browse(IWin32Window parent)
{
}
public virtual void Browse(IWin32Window parent) { }
// This must returns an enum list when IsEnumerable is true
public virtual EnumList GetEnumList()

View file

@ -199,6 +199,11 @@ namespace CodeImp.DoomBuilder.Windows
posY.ButtonStep = General.Map.Grid.GridSize;
posZ.ButtonStep = General.Map.Grid.GridSize;
//mxd. User vars. Should be done before adding regular fields
ThingTypeInfo fti = General.Map.Data.GetThingInfoEx(ft.Type);
if(fti != null && fti.Actor != null && fti.Actor.UserVars.Count > 0)
fieldslist.SetUserVars(fti.Actor.UserVars, ft.Fields, true);
// Custom fields
fieldslist.SetValues(ft.Fields, true);
commenteditor.SetValues(ft.Fields, true);
@ -272,6 +277,11 @@ namespace CodeImp.DoomBuilder.Windows
//mxd. Arguments
argscontrol.SetValue(t, false);
//mxd. User vars. Should be done before adding regular fields
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
if(ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0)
fieldslist.SetUserVars(ti.Actor.UserVars, t.Fields, false);
//mxd. Custom fields
fieldslist.SetValues(t.Fields, false);
commenteditor.SetValues(t.Fields, false); //mxd. Comments
@ -294,16 +304,6 @@ namespace CodeImp.DoomBuilder.Windows
//mxd. Store initial properties
thingprops.Add(new ThingProperties(t));
//mxd. add user vars
/*if(info != null && info.Actor != null && info.Actor.UserVars.Count > 0)
{
foreach(string s in info.Actor.UserVars)
{
if(!t.Fields.ContainsKey(s))
fieldslist.SetValue(s, 0, CodeImp.DoomBuilder.Types.UniversalType.Integer);
}
}*/
}
preventchanges = false;
@ -490,6 +490,11 @@ namespace CodeImp.DoomBuilder.Windows
if(!string.IsNullOrEmpty(score.Text))
UniFields.SetInteger(t.Fields, "score", score.GetResult(t.Fields.GetValue("score", 0)), 0);
//mxd. User vars. Should be called after fieldslist.Apply()
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
if(ti != null && ti.Actor != null && ti.Actor.UserVars.Count > 0)
fieldslist.ApplyUserVars(ti.Actor.UserVars, t.Fields);
color.ApplyTo(t.Fields, t.Fields.GetValue("fillcolor", 0));
//mxd. Comments

View file

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Globalization;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Types;
#endregion
@ -52,7 +53,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// Properties
private Dictionary<string, List<string>> props;
private readonly List<string> userVars; //mxd
private readonly Dictionary<string, UniversalType> uservars; //mxd
// States
private Dictionary<string, StateStructure> states;
@ -68,7 +69,7 @@ namespace CodeImp.DoomBuilder.ZDoom
public string ReplacesClass { get { return replaceclass; } }
public ActorStructure BaseClass { get { return baseclass; } }
internal int DoomEdNum { get { return doomednum; } set { doomednum = value; } }
public List<string> UserVars { get { return userVars; } } //mxd
public Dictionary<string, UniversalType> UserVars { get { return uservars; } } //mxd
#endregion
@ -78,10 +79,10 @@ namespace CodeImp.DoomBuilder.ZDoom
internal ActorStructure(DecorateParser parser)
{
// Initialize
flags = new Dictionary<string, bool>(StringComparer.Ordinal);
props = new Dictionary<string, List<string>>(StringComparer.Ordinal);
states = new Dictionary<string, StateStructure>(StringComparer.Ordinal);
userVars = new List<string>();//mxd
flags = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
props = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
states = new Dictionary<string, StateStructure>(StringComparer.OrdinalIgnoreCase);
uservars = new Dictionary<string, UniversalType>(StringComparer.OrdinalIgnoreCase);//mxd
bool done = false; //mxd
// Always define a game property, but default to 0 values
@ -163,7 +164,7 @@ namespace CodeImp.DoomBuilder.ZDoom
else if(!int.TryParse(token, NumberStyles.Integer, CultureInfo.InvariantCulture, out doomednum)) // Check if numeric
{
// Not numeric!
parser.ReportError("Expected editor thing number or start of actor scope while parsing '" + classname + "'");
parser.ReportError("Expected editor thing number or start of actor scope while parsing \"" + classname + "\"");
return;
}
break;
@ -271,18 +272,87 @@ namespace CodeImp.DoomBuilder.ZDoom
break;
case "var": //mxd
while(parser.SkipWhitespace(true))
// Type
parser.SkipWhitespace(true);
string typestr = parser.ReadToken().ToUpperInvariant();
UniversalType type = UniversalType.EnumOption; // There is no Unknown type, so let's use something impossiburu...
switch(typestr)
{
string t = parser.ReadToken();
if(string.IsNullOrEmpty(t) || t == ";") break;
if(t.StartsWith("user_") && !userVars.Contains(t))
userVars.Add(t);
case "INT":
type = UniversalType.Integer;
break;
default:
parser.LogWarning("Unknown user variable type");
break;
}
// Name
parser.SkipWhitespace(true);
string name = parser.ReadToken();
if(string.IsNullOrEmpty(name))
{
parser.ReportError("Expected User Variable name");
return;
}
if(!name.StartsWith("user_", StringComparison.OrdinalIgnoreCase))
{
parser.ReportError("User Variable name must start with \"user_\" prefix");
return;
}
if(uservars.ContainsKey(name))
{
parser.ReportError("User Variable \"" + name + "\" is double-defined");
return;
}
if(!skipsuper && baseclass != null && baseclass.uservars.ContainsKey(name))
{
parser.ReportError("User variable \"" + name + "\" is already defined in one of the parent classes");
return;
}
// Rest
parser.SkipWhitespace(true);
string next = parser.ReadToken();
if(next == "[") // that's User Array. Let's skip it...
{
int arrlen = -1;
if(!parser.ReadSignedInt(ref arrlen))
{
parser.ReportError("Expected User Array length, but got \"" + next + "\"");
return;
}
if(arrlen < 1)
{
parser.ReportError("User Array length must be a positive value");
return;
}
if(!parser.NextTokenIs("]") || !parser.NextTokenIs(";"))
{
return;
}
}
else if(next != ";")
{
parser.ReportError("Expected \";\", but got \"" + next + "\"");
return;
}
else
{
// Add to collection
uservars.Add(name, type);
}
break;
case "}":
// Actor scope ends here,
// break out of this parse loop
//mxd. Get user vars from the BaseClass, if we have one
if(!skipsuper && baseclass != null && baseclass.uservars.Count > 0)
{
foreach(var group in baseclass.uservars)
uservars.Add(group.Key, group.Value);
}
// Actor scope ends here, break out of this parse loop
done = true;
break;
@ -414,7 +484,7 @@ namespace CodeImp.DoomBuilder.ZDoom
}
}
parser.LogWarning("Unable to find '" + inheritclass + "' class to inherit from, while parsing '" + classname + ":" + doomednum + "'");
parser.LogWarning("Unable to find \"" + inheritclass + "\" class to inherit from, while parsing \"" + classname + ":" + doomednum + "\"");
}
}
@ -554,7 +624,7 @@ namespace CodeImp.DoomBuilder.ZDoom
/// </summary>
public Dictionary<string, StateStructure> GetAllStates()
{
Dictionary<string, StateStructure> list = new Dictionary<string, StateStructure>(states);
Dictionary<string, StateStructure> list = new Dictionary<string, StateStructure>(states, StringComparer.OrdinalIgnoreCase);
if(!skipsuper && (baseclass != null))
{

View file

@ -86,7 +86,7 @@ namespace CodeImp.DoomBuilder.ZDoom
{
// Syntax
whitespace = "\n \t\r\u00A0"; //mxd. non-breaking space is also space :)
specialtokens = ":{}+-\n;,";
specialtokens = ":{}[]+-\n;,";
// Initialize
actors = new Dictionary<string, ActorStructure>(StringComparer.OrdinalIgnoreCase);

View file

@ -201,7 +201,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(datastream.Position == datastream.Length) //mxd
{
// ZDoom doesn't give even a warning message about this, so we shouldn't report error or fail parsing.
General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in '" + sourcename + "', line " + GetCurrentLineNumber() + ". Block comment is not closed.");
General.ErrorLogger.Add(ErrorType.Warning, "DECORATE warning in \"" + sourcename + "\", line " + GetCurrentLineNumber() + ". Block comment is not closed.");
return false;
}
@ -441,7 +441,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(string.Compare(token, expectedtoken, true) != 0)
{
if(reporterror) ReportError("Expected '" + expectedtoken + "', but got '" + token + "'");
if(reporterror) ReportError("Expected \"" + expectedtoken + "\", but got \"" + token + "\"");
// Rewind so this structure can be read again
DataStream.Seek(-token.Length - 1, SeekOrigin.Current);
@ -531,16 +531,16 @@ 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
+ (errline != CompilerError.NO_LINE_NUMBER ? "', line " + (errline + 1) : "'") + ". "
General.ErrorLogger.Add(ErrorType.Warning, GetLanguageType() + " warning in \"" + sourcename
+ (errline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errline + 1) : "\"") + ". "
+ message + ".");
}
//mxd. This adds an error to the ErrorLogger
public void LogError()
{
General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in '" + errorsource
+ (errorline != CompilerError.NO_LINE_NUMBER ? "', line " + (errorline + 1) : "'") + ". "
General.ErrorLogger.Add(ErrorType.Error, GetLanguageType() + " error in \"" + errorsource
+ (errorline != CompilerError.NO_LINE_NUMBER ? "\", line " + (errorline + 1) : "\"") + ". "
+ errordesc + ".");
}
@ -611,7 +611,7 @@ namespace CodeImp.DoomBuilder.ZDoom
// includefilename references something above the root?
if(index-- < 0)
{
ReportError("Unable to construct rooted path from '" + includefilename + "'");
ReportError("Unable to construct rooted path from \"" + includefilename + "\"");
return string.Empty;
}