mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-30 15:41:30 +00:00
bfd57379bb
Added, Map Analysis mode: added "Edit Thing..." option to "Unknown Thing" and "Obsolete Thing" error check results. Added: a warning is now displayed when a thing has both voxel and model attached. Changed, Thing/Linedef Info panels: unknown ACS script names/numbers are now shown in red. Fixed, Edit Things window, UDMF: unneeded undo was created when opening the window. Re-fixed: in some cases invalid sectors were created after dragging map elements when using "Merge Dragged Geometry" and "Replace with Dragged Geometry" drag modes, when at least one of dragged linedef was facing into an enclosed void area (previous fix entirely disabled the associated logic).
950 lines
No EOL
29 KiB
C#
950 lines
No EOL
29 KiB
C#
|
|
#region ================== Copyright (c) 2007 Pascal vd Heiden
|
|
|
|
/*
|
|
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
|
|
* This program is released under GNU General Public License
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region ================== Namespaces
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using CodeImp.DoomBuilder.Config;
|
|
using CodeImp.DoomBuilder.Controls;
|
|
using CodeImp.DoomBuilder.Geometry;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using CodeImp.DoomBuilder.Types;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.Windows
|
|
{
|
|
/// <summary>
|
|
/// Dialog window that allows viewing and editing of Thing properties.
|
|
/// </summary>
|
|
internal partial class ThingEditFormUDMF : DelayedForm
|
|
{
|
|
#region ================== Events
|
|
|
|
public event EventHandler OnValuesChanged; //mxd
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
private ICollection<Thing> things;
|
|
private ThingTypeInfo thinginfo;
|
|
private bool preventchanges;
|
|
private bool preventmapchange; //mxd
|
|
private bool undocreated; //mxd
|
|
private static bool useabsoluteheight; //mxd
|
|
private List<ThingProperties> thingprops; //mxd
|
|
private readonly string[] renderstyles; //mxd
|
|
private Dictionary<string, string> flagsrename; //mxd
|
|
|
|
//mxd. Window setup stuff
|
|
private static int activetab;
|
|
|
|
//mxd. Persistent settings
|
|
private static bool linkscale;
|
|
|
|
private struct ThingProperties //mxd
|
|
{
|
|
//public readonly int Type;
|
|
public readonly int AngleDoom;
|
|
public readonly int Pitch;
|
|
public readonly int Roll;
|
|
public readonly float ScaleX;
|
|
public readonly float ScaleY;
|
|
public readonly float Alpha;
|
|
public readonly float X;
|
|
public readonly float Y;
|
|
public readonly float Z;
|
|
public readonly Dictionary<string, bool> Flags;
|
|
|
|
public ThingProperties(Thing t)
|
|
{
|
|
X = t.Position.x;
|
|
Y = t.Position.y;
|
|
Z = t.Position.z;
|
|
//Type = t.Type;
|
|
AngleDoom = t.AngleDoom;
|
|
Pitch = t.Pitch;
|
|
Roll = t.Roll;
|
|
ScaleX = t.ScaleX;
|
|
ScaleY = t.ScaleY;
|
|
Alpha = UniFields.GetFloat(t.Fields, "alpha", 1.0f);
|
|
Flags = t.GetFlags();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor
|
|
|
|
// Constructor
|
|
public ThingEditFormUDMF()
|
|
{
|
|
// Initialize
|
|
InitializeComponent();
|
|
|
|
//mxd. Widow setup
|
|
if(General.Settings.StoreSelectedEditTab && activetab > 0) tabs.SelectTab(activetab);
|
|
|
|
// Fill flags list
|
|
foreach(KeyValuePair<string, string> tf in General.Map.Config.ThingFlags)
|
|
flags.Add(tf.Value, tf.Key);
|
|
flags.Enabled = (General.Map.Config.ThingFlags.Count > 0);
|
|
|
|
// Fill actions list
|
|
action.GeneralizedCategories = General.Map.Config.GenActionCategories;
|
|
action.AddInfo(General.Map.Config.SortedLinedefActions.ToArray());
|
|
|
|
// Setup renderstyles
|
|
renderstyles = new string[General.Map.Config.ThingRenderStyles.Count];
|
|
General.Map.Config.ThingRenderStyles.Keys.CopyTo(renderstyles, 0);
|
|
|
|
// Fill renderstyles
|
|
foreach(KeyValuePair<string, string> lf in General.Map.Config.ThingRenderStyles)
|
|
renderStyle.Items.Add(lf.Value);
|
|
renderStyle.Enabled = (General.Map.Config.ThingRenderStyles.Count > 0);
|
|
labelrenderstyle.Enabled = (General.Map.Config.ThingRenderStyles.Count > 0);
|
|
|
|
// Initialize custom fields editor
|
|
fieldslist.Setup("thing");
|
|
|
|
// Fill universal fields list
|
|
fieldslist.ListFixedFields(General.Map.Config.ThingFields);
|
|
|
|
//mxd. Show fixed fields?
|
|
hidefixedfields.Checked = !General.Settings.ReadSetting("windows." + configname + ".customfieldsshowfixed", true);
|
|
|
|
// Thing height?
|
|
posZ.Visible = General.Map.FormatInterface.HasThingHeight;
|
|
zlabel.Visible = General.Map.FormatInterface.HasThingHeight;
|
|
cbAbsoluteHeight.Visible = General.Map.FormatInterface.HasThingHeight; //mxd
|
|
|
|
//mxd. Decimals allowed?
|
|
if(General.Map.FormatInterface.VertexDecimals > 0)
|
|
{
|
|
posX.AllowDecimal = true;
|
|
posY.AllowDecimal = true;
|
|
posZ.AllowDecimal = true;
|
|
}
|
|
|
|
//mxd. Use doom angle clamping?
|
|
anglecontrol.DoomAngleClamping = General.Map.Config.DoomThingRotationAngles;
|
|
|
|
// Value linking
|
|
scale.LinkValues = linkscale;
|
|
|
|
// Setup types list
|
|
thingtype.Setup();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This sets up the form to edit the given things
|
|
public void Setup(ICollection<Thing> things)
|
|
{
|
|
preventchanges = true;
|
|
|
|
// Keep this list
|
|
this.things = things;
|
|
if(things.Count > 1) this.Text = "Edit Things (" + things.Count + ")";
|
|
hint.Visible = things.Count > 1; //mxd
|
|
hintlabel.Visible = things.Count > 1; //mxd
|
|
thingtype.UseMultiSelection = things.Count > 1; //mxd
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Set all options to the first thing properties
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
Thing ft = General.GetByIndex(things, 0);
|
|
|
|
// Set type
|
|
thingtype.SelectType(ft.Type);
|
|
|
|
// Flags
|
|
foreach(CheckBox c in flags.Checkboxes)
|
|
{
|
|
if(ft.Flags.ContainsKey(c.Tag.ToString())) c.Checked = ft.Flags[c.Tag.ToString()];
|
|
}
|
|
|
|
// Coordination
|
|
angle.Text = ft.AngleDoom.ToString();
|
|
cbAbsoluteHeight.Checked = useabsoluteheight; //mxd
|
|
|
|
//mxd
|
|
ft.DetermineSector();
|
|
float floorheight = (ft.Sector != null ? Sector.GetFloorPlane(ft.Sector).GetZ(ft.Position) : 0);
|
|
posX.Text = (ft.Position.x).ToString();
|
|
posY.Text = (ft.Position.y).ToString();
|
|
posZ.Text = (useabsoluteheight ? ((float)Math.Round(ft.Position.z + floorheight, General.Map.FormatInterface.VertexDecimals)).ToString() : (ft.Position.z).ToString());
|
|
posX.ButtonStep = General.Map.Grid.GridSize;
|
|
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);
|
|
thinginfo = fti; //mxd
|
|
|
|
// Custom fields
|
|
fieldslist.SetValues(ft.Fields, true);
|
|
commenteditor.SetValues(ft.Fields, true);
|
|
conversationID.Text = ft.Fields.GetValue("conversation", 0).ToString();
|
|
floatbobphase.Text = ft.Fields.GetValue("floatbobphase", -1).ToString();
|
|
gravity.Text = ft.Fields.GetValue("gravity", 1.0f).ToString();
|
|
score.Text = ft.Fields.GetValue("score", 0).ToString();
|
|
health.Text = ft.Fields.GetValue("health", 1).ToString();
|
|
alpha.Text = ft.Fields.GetValue("alpha", 1.0f).ToString();
|
|
color.SetValueFrom(ft.Fields, true);
|
|
scale.SetValues(ft.ScaleX, ft.ScaleY, true);
|
|
pitch.Text = ft.Pitch.ToString();
|
|
roll.Text = ft.Roll.ToString();
|
|
renderStyle.SelectedIndex = Array.IndexOf(renderstyles, ft.Fields.GetValue("renderstyle", "normal"));
|
|
|
|
// Action/tags
|
|
action.Value = ft.Action;
|
|
tagSelector.Setup(UniversalType.ThingTag);
|
|
tagSelector.SetTag(ft.Tag);
|
|
|
|
//mxd. Args
|
|
argscontrol.SetValue(ft, true);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Now go for all lines and change the options when a setting is different
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
thingprops = new List<ThingProperties>();
|
|
|
|
// Go for all things
|
|
foreach(Thing t in things)
|
|
{
|
|
//mxd. Update sector info
|
|
t.DetermineSector();
|
|
|
|
// Type does not match?
|
|
ThingTypeInfo info = thingtype.GetSelectedInfo(); //mxd
|
|
if(info != null && info.Index != t.Type)
|
|
{
|
|
thingtype.ClearSelectedType();
|
|
thinginfo = null; //mxd
|
|
}
|
|
|
|
// Flags
|
|
foreach(CheckBox c in flags.Checkboxes)
|
|
{
|
|
if(c.CheckState == CheckState.Indeterminate) continue; //mxd
|
|
if(t.IsFlagSet(c.Tag.ToString()) != c.Checked)
|
|
{
|
|
c.ThreeState = true;
|
|
c.CheckState = CheckState.Indeterminate;
|
|
}
|
|
}
|
|
|
|
// Coordination
|
|
if(t.AngleDoom.ToString() != angle.Text) angle.Text = "";
|
|
|
|
//mxd. Position
|
|
if((t.Position.x).ToString() != posX.Text) posX.Text = "";
|
|
if((t.Position.y).ToString() != posY.Text) posY.Text = "";
|
|
if(useabsoluteheight && t.Sector != null)
|
|
{
|
|
if(((float)Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position) + t.Position.z, General.Map.FormatInterface.VertexDecimals)).ToString() != posZ.Text)
|
|
posZ.Text = "";
|
|
}
|
|
else if((t.Position.z).ToString() != posZ.Text)
|
|
{
|
|
posZ.Text = "";
|
|
}
|
|
|
|
// Action/tags
|
|
if(t.Action != action.Value) action.Empty = true;
|
|
if(t.Tag != ft.Tag) tagSelector.ClearTag(); //mxd
|
|
|
|
//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
|
|
if(t.Fields.GetValue("conversation", 0).ToString() != conversationID.Text) conversationID.Text = "";
|
|
if(t.Fields.GetValue("floatbobphase", -1).ToString() != floatbobphase.Text) floatbobphase.Text = "";
|
|
if(t.Fields.GetValue("gravity", 1.0f).ToString() != gravity.Text) gravity.Text = "";
|
|
if(t.Fields.GetValue("score", 0).ToString() != score.Text) score.Text = "";
|
|
if(t.Fields.GetValue("health", 1).ToString() != health.Text) health.Text = "";
|
|
if(t.Fields.GetValue("alpha", 1.0f).ToString() != alpha.Text) alpha.Text = "";
|
|
|
|
scale.SetValues(t.ScaleX, t.ScaleY, false);
|
|
color.SetValueFrom(t.Fields, false);
|
|
|
|
if(t.Pitch.ToString() != pitch.Text) pitch.Text = "";
|
|
if(t.Roll.ToString() != roll.Text) roll.Text = "";
|
|
|
|
//Render style
|
|
if(renderStyle.SelectedIndex > -1 && renderStyle.SelectedIndex != Array.IndexOf(renderstyles, t.Fields.GetValue("renderstyle", "normal")))
|
|
renderStyle.SelectedIndex = -1;
|
|
|
|
//mxd. Store initial properties
|
|
thingprops.Add(new ThingProperties(t));
|
|
}
|
|
|
|
preventchanges = false;
|
|
|
|
//mxd. Trigger updates manually...
|
|
preventmapchange = true;
|
|
angle_WhenTextChanged(angle, EventArgs.Empty);
|
|
pitch_WhenTextChanged(pitch, EventArgs.Empty);
|
|
roll_WhenTextChanged(roll, EventArgs.Empty);
|
|
flags_OnValueChanged(flags, EventArgs.Empty);
|
|
preventmapchange = false;
|
|
|
|
argscontrol.UpdateScriptControls(); //mxd
|
|
actionhelp.UpdateAction(action.GetValue()); //mxd
|
|
labelScale.Enabled = scale.NonDefaultValue; //mxd
|
|
commenteditor.FinishSetup(); //mxd
|
|
UpdateFlagNames(); //mxd
|
|
}
|
|
|
|
//mxd
|
|
private void MakeUndo()
|
|
{
|
|
if(undocreated) return;
|
|
undocreated = true;
|
|
|
|
//mxd. Make undo
|
|
General.Map.UndoRedo.CreateUndo("Edit " + (things.Count > 1 ? things.Count + " things" : "thing"));
|
|
foreach(Thing t in things) t.Fields.BeforeFieldsChange();
|
|
}
|
|
|
|
//mxd
|
|
private void UpdateFlagNames()
|
|
{
|
|
Dictionary<string, string> newflagsrename = (thinginfo != null ? thinginfo.FlagsRename : null);
|
|
|
|
// Update flag names?
|
|
if(flagsrename != null || newflagsrename != null)
|
|
{
|
|
flags.SuspendLayout();
|
|
|
|
// Restore default flags?
|
|
if(flagsrename != null)
|
|
{
|
|
foreach(CheckBox cb in flags.Checkboxes)
|
|
{
|
|
string flag = cb.Tag.ToString();
|
|
if(flagsrename.ContainsKey(flag))
|
|
{
|
|
cb.Text = General.Map.Config.ThingFlags[flag];
|
|
cb.ForeColor = SystemColors.WindowText;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Apply new renaming?
|
|
if(newflagsrename != null)
|
|
{
|
|
foreach(CheckBox cb in flags.Checkboxes)
|
|
{
|
|
string flag = cb.Tag.ToString();
|
|
if(newflagsrename.ContainsKey(flag))
|
|
{
|
|
cb.Text = newflagsrename[flag];
|
|
cb.ForeColor = SystemColors.HotTrack;
|
|
}
|
|
}
|
|
}
|
|
|
|
flags.ResumeLayout();
|
|
}
|
|
|
|
// Store current flag names
|
|
flagsrename = newflagsrename;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
//mxd
|
|
private void thingtype_OnTypeDoubleClicked()
|
|
{
|
|
apply_Click(this, EventArgs.Empty);
|
|
}
|
|
|
|
// Action changes
|
|
private void action_ValueChanges(object sender, EventArgs e)
|
|
{
|
|
int showaction = 0;
|
|
|
|
// Only when line type is known, otherwise use the thing arguments
|
|
if(General.Map.Config.LinedefActions.ContainsKey(action.Value)) showaction = action.Value;
|
|
|
|
//mxd. Change the argument descriptions
|
|
argscontrol.UpdateAction(showaction, preventchanges, (action.Empty ? null : thinginfo));
|
|
|
|
if(!preventchanges)
|
|
{
|
|
MakeUndo(); //mxd
|
|
|
|
//mxd. Update what must be updated
|
|
argscontrol.UpdateScriptControls();
|
|
actionhelp.UpdateAction(showaction);
|
|
}
|
|
}
|
|
|
|
// Browse Action clicked
|
|
private void browseaction_Click(object sender, EventArgs e)
|
|
{
|
|
action.Value = ActionBrowserForm.BrowseAction(this, action.Value);
|
|
}
|
|
|
|
// Angle text changes
|
|
private void angle_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
preventchanges = true;
|
|
anglecontrol.Angle = angle.GetResult(AngleControlEx.NO_ANGLE);
|
|
preventchanges = false;
|
|
if(!preventmapchange) ApplyAngleChange(); //mxd
|
|
}
|
|
|
|
//mxd. Angle control clicked
|
|
private void anglecontrol_AngleChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
angle.Text = anglecontrol.Angle.ToString();
|
|
if(!preventmapchange) ApplyAngleChange();
|
|
}
|
|
|
|
private void pitch_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
int p = pitch.GetResult(AngleControlEx.NO_ANGLE);
|
|
preventchanges = true;
|
|
pitchControl.Angle = (p == AngleControlEx.NO_ANGLE ? p : p + 90);
|
|
preventchanges = false;
|
|
if(!preventmapchange) ApplyPitchChange();
|
|
}
|
|
|
|
private void pitchControl_AngleChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
pitch.Text = (General.ClampAngle(pitchControl.Angle - 90)).ToString();
|
|
if(!preventmapchange) ApplyPitchChange();
|
|
}
|
|
|
|
private void roll_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
int r = roll.GetResult(AngleControlEx.NO_ANGLE);
|
|
preventchanges = true;
|
|
rollControl.Angle = (r == AngleControlEx.NO_ANGLE ? r : r + 90);
|
|
preventchanges = false;
|
|
if(!preventmapchange) ApplyRollChange();
|
|
}
|
|
|
|
private void rollControl_AngleChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
roll.Text = (General.ClampAngle(rollControl.Angle - 90)).ToString();
|
|
if(!preventmapchange) ApplyRollChange();
|
|
}
|
|
|
|
// Apply clicked
|
|
private void apply_Click(object sender, EventArgs e)
|
|
{
|
|
//mxd. Make Undo
|
|
MakeUndo();
|
|
|
|
List<string> defaultflags = new List<string>();
|
|
|
|
// Verify the tag
|
|
if(General.Map.FormatInterface.HasThingTag) //mxd
|
|
{
|
|
tagSelector.ValidateTag();//mxd
|
|
if(((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag)))
|
|
{
|
|
General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Verify the type
|
|
if(!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType)))
|
|
{
|
|
General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
|
|
return;
|
|
}
|
|
|
|
// Verify the action
|
|
if(General.Map.FormatInterface.HasThingAction && ((action.Value < General.Map.FormatInterface.MinAction) || (action.Value > General.Map.FormatInterface.MaxAction)))
|
|
{
|
|
General.ShowWarningMessage("Thing action must be between " + General.Map.FormatInterface.MinAction + " and " + General.Map.FormatInterface.MaxAction + ".", MessageBoxButtons.OK);
|
|
return;
|
|
}
|
|
|
|
// Go for all the things
|
|
int offset = 0; //mxd
|
|
foreach(Thing t in things)
|
|
{
|
|
// Coordination
|
|
//mxd. Randomize rotations?
|
|
if(cbrandomangle.Checked)
|
|
{
|
|
int newangle = General.Random(0, 359);
|
|
if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
|
|
t.Rotate(newangle);
|
|
}
|
|
if(cbrandompitch.Checked) t.SetPitch(General.Random(0, 359));
|
|
if(cbrandomroll.Checked) t.SetRoll(General.Random(0, 359));
|
|
|
|
//mxd. Check position
|
|
float px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
|
|
float py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary);
|
|
if(t.Position.x != px || t.Position.y != py) t.Move(new Vector2D(px, py));
|
|
|
|
// Action/tags
|
|
t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag); //mxd
|
|
if(!action.Empty) t.Action = action.Value;
|
|
|
|
//mxd. Apply args
|
|
argscontrol.Apply(t, offset);
|
|
|
|
//mxd. Custom fields
|
|
fieldslist.Apply(t.Fields);
|
|
if(!string.IsNullOrEmpty(conversationID.Text))
|
|
UniFields.SetInteger(t.Fields, "conversation", conversationID.GetResult(t.Fields.GetValue("conversation", 0)), 0);
|
|
if(!string.IsNullOrEmpty(floatbobphase.Text))
|
|
UniFields.SetInteger(t.Fields, "floatbobphase", General.Clamp(floatbobphase.GetResult(t.Fields.GetValue("floatbobphase", -1)), -1, 63), -1);
|
|
if(!string.IsNullOrEmpty(gravity.Text))
|
|
UniFields.SetFloat(t.Fields, "gravity", gravity.GetResultFloat(t.Fields.GetValue("gravity", 1.0f)), 1.0f);
|
|
if(!string.IsNullOrEmpty(health.Text))
|
|
UniFields.SetInteger(t.Fields, "health", health.GetResult(t.Fields.GetValue("health", 1)), 1);
|
|
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
|
|
commenteditor.Apply(t.Fields);
|
|
|
|
// Update settings
|
|
t.UpdateConfiguration();
|
|
|
|
//mxd. Increase offset...
|
|
offset++;
|
|
}
|
|
|
|
// Set as defaults
|
|
foreach(CheckBox c in flags.Checkboxes)
|
|
{
|
|
if(c.CheckState == CheckState.Checked) defaultflags.Add(c.Tag.ToString());
|
|
}
|
|
General.Settings.DefaultThingType = thingtype.GetResult(General.Settings.DefaultThingType);
|
|
General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
|
|
General.Settings.SetDefaultThingFlags(defaultflags);
|
|
|
|
// Store value linking
|
|
linkscale = scale.LinkValues;
|
|
|
|
// Done
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); //mxd
|
|
this.DialogResult = DialogResult.OK;
|
|
this.Close();
|
|
}
|
|
|
|
// Cancel clicked
|
|
private void cancel_Click(object sender, EventArgs e)
|
|
{
|
|
//mxd. Perform undo?
|
|
if(undocreated) General.Map.UndoRedo.WithdrawUndo();
|
|
|
|
// Be gone
|
|
this.DialogResult = DialogResult.Cancel;
|
|
this.Close();
|
|
}
|
|
|
|
//mxd
|
|
private void cbAbsoluteHeight_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo();
|
|
|
|
useabsoluteheight = cbAbsoluteHeight.Checked;
|
|
|
|
preventchanges = true;
|
|
|
|
//update label text
|
|
Thing ft = General.GetByIndex(things, 0);
|
|
float z = ft.Position.z;
|
|
if(useabsoluteheight && ft.Sector != null) z += Sector.GetFloorPlane(ft.Sector).GetZ(ft.Position);
|
|
posZ.Text = ((float)Math.Round(z, General.Map.FormatInterface.VertexDecimals)).ToString();
|
|
|
|
foreach(Thing t in things)
|
|
{
|
|
z = t.Position.z;
|
|
if(useabsoluteheight && t.Sector != null) z += Sector.GetFloorPlane(t.Sector).GetZ(t.Position);
|
|
string ztext = ((float)Math.Round(z, General.Map.FormatInterface.VertexDecimals)).ToString();
|
|
if(posZ.Text != ztext)
|
|
{
|
|
posZ.Text = "";
|
|
break;
|
|
}
|
|
}
|
|
|
|
preventchanges = false;
|
|
}
|
|
|
|
//mxd
|
|
private void tabcustom_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
fieldslist.Focus();
|
|
}
|
|
|
|
//mxd
|
|
private void ThingEditFormUDMF_Shown(object sender, EventArgs e)
|
|
{
|
|
if(activetab == 0)
|
|
{
|
|
thingtype.Focus();
|
|
thingtype.FocusTextbox();
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void ThingEditForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
activetab = tabs.SelectedIndex;
|
|
General.Settings.WriteSetting("windows." + configname + ".customfieldsshowfixed", !hidefixedfields.Checked);
|
|
}
|
|
|
|
// Help
|
|
private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
|
|
{
|
|
General.ShowHelp("w_thingedit.html");
|
|
hlpevent.Handled = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== mxd. Realtime events
|
|
|
|
private void posX_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
// Update values
|
|
foreach(Thing t in things)
|
|
t.Move(new Vector2D(posX.GetResultFloat(thingprops[i++].X), t.Position.y));
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void posY_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
// Update values
|
|
foreach(Thing t in things)
|
|
t.Move(new Vector2D(t.Position.x, posY.GetResultFloat(thingprops[i++].Y)));
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void posZ_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
if(string.IsNullOrEmpty(posZ.Text))
|
|
{
|
|
// Restore values
|
|
foreach(Thing t in things)
|
|
t.Move(new Vector3D(t.Position.x, t.Position.y, thingprops[i++].Z));
|
|
}
|
|
else
|
|
{
|
|
// Update values
|
|
foreach(Thing t in things)
|
|
{
|
|
float z = posZ.GetResultFloat(thingprops[i++].Z);
|
|
if(useabsoluteheight && !posZ.CheckIsRelative() && t.Sector != null)
|
|
z -= (float)Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position.x, t.Position.y), General.Map.FormatInterface.VertexDecimals);
|
|
t.Move(new Vector3D(t.Position.x, t.Position.y, z));
|
|
}
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void scale_OnValuesChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
foreach(Thing t in things)
|
|
{
|
|
float sx = scale.GetValue1(thingprops[i].ScaleX);
|
|
float sy = scale.GetValue2(thingprops[i].ScaleY);
|
|
t.SetScale((sx == 0 ? 1.0f : sx), (sy == 0 ? 1.0f : sy));
|
|
i++;
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
labelScale.Enabled = scale.NonDefaultValue;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
// Selected type changes
|
|
private void thingtype_OnTypeChanged(ThingTypeInfo value)
|
|
{
|
|
thinginfo = value;
|
|
|
|
// Update arguments
|
|
action_ValueChanges(this, EventArgs.Empty);
|
|
|
|
//mxd. Update things
|
|
if(preventchanges ||
|
|
(!string.IsNullOrEmpty(thingtype.TypeStringValue) &&
|
|
thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType
|
|
|| thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))
|
|
return;
|
|
|
|
MakeUndo(); //mxd
|
|
|
|
foreach(Thing t in things)
|
|
{
|
|
//Set type
|
|
t.Type = thingtype.GetResult(t.Type);
|
|
|
|
// Update settings
|
|
t.UpdateConfiguration();
|
|
}
|
|
|
|
UpdateFlagNames(); //mxd
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
//mxd
|
|
private void ApplyAngleChange()
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
//restore values
|
|
if(string.IsNullOrEmpty(angle.Text))
|
|
{
|
|
foreach(Thing t in things) t.Rotate(thingprops[i++].AngleDoom);
|
|
}
|
|
else //update values
|
|
{
|
|
foreach(Thing t in things)
|
|
t.Rotate(angle.GetResult(thingprops[i++].AngleDoom));
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void ApplyPitchChange()
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
//restore values
|
|
if(string.IsNullOrEmpty(pitch.Text))
|
|
{
|
|
foreach(Thing t in things) t.SetPitch(thingprops[i++].Pitch);
|
|
}
|
|
else //update values
|
|
{
|
|
foreach(Thing t in things)
|
|
t.SetPitch(pitch.GetResult(thingprops[i++].Pitch));
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
//mxd
|
|
private void ApplyRollChange()
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
//restore values
|
|
if(string.IsNullOrEmpty(roll.Text))
|
|
{
|
|
foreach(Thing t in things) t.SetRoll(thingprops[i++].Roll);
|
|
}
|
|
else //update values
|
|
{
|
|
foreach(Thing t in things)
|
|
t.SetRoll(roll.GetResult(thingprops[i++].Roll));
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void flags_OnValueChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
if(!preventmapchange) //mxd
|
|
{
|
|
MakeUndo();
|
|
int i = 0;
|
|
|
|
// Apply flags
|
|
foreach(Thing t in things)
|
|
{
|
|
// Apply all flags
|
|
foreach(CheckBox c in flags.Checkboxes)
|
|
{
|
|
if(c.CheckState == CheckState.Checked)
|
|
t.SetFlag(c.Tag.ToString(), true);
|
|
else if(c.CheckState == CheckState.Unchecked)
|
|
t.SetFlag(c.Tag.ToString(), false);
|
|
else if(thingprops[i].Flags.ContainsKey(c.Tag.ToString()))
|
|
t.SetFlag(c.Tag.ToString(), thingprops[i].Flags[c.Tag.ToString()]);
|
|
else //things created in the editor have empty Flags by default
|
|
t.SetFlag(c.Tag.ToString(), false);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
// Dispatch event
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
// Gather enabled flags
|
|
HashSet<string> activeflags = new HashSet<string>();
|
|
foreach(CheckBox cb in flags.Checkboxes)
|
|
{
|
|
if(cb.CheckState != CheckState.Unchecked) activeflags.Add(cb.Tag.ToString());
|
|
}
|
|
|
|
// Check em
|
|
List<string> warnings = ThingFlagsCompare.CheckFlags(activeflags);
|
|
if(warnings.Count > 0)
|
|
{
|
|
// Got missing flags
|
|
tooltip.SetToolTip(missingflags, string.Join(Environment.NewLine, warnings.ToArray()));
|
|
missingflags.Visible = true;
|
|
settingsgroup.ForeColor = Color.DarkRed;
|
|
return;
|
|
}
|
|
|
|
// Everything is OK
|
|
missingflags.Visible = false;
|
|
settingsgroup.ForeColor = SystemColors.ControlText;
|
|
}
|
|
|
|
private void cbrandomangle_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
angle.Enabled = !cbrandomangle.Checked;
|
|
groupangle.Enabled = !cbrandomangle.Checked;
|
|
}
|
|
|
|
private void cbrandompitch_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
pitch.Enabled = !cbrandompitch.Checked;
|
|
grouppitch.Enabled = !cbrandompitch.Checked;
|
|
}
|
|
|
|
private void cbrandomroll_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
roll.Enabled = !cbrandomroll.Checked;
|
|
grouproll.Enabled = !cbrandomroll.Checked;
|
|
}
|
|
|
|
private void renderStyle_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
|
|
//update values
|
|
foreach(Thing t in things)
|
|
UniFields.SetString(t.Fields, "renderstyle", renderstyles[renderStyle.SelectedIndex], "normal");
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void alpha_WhenTextChanged(object sender, EventArgs e)
|
|
{
|
|
if(preventchanges) return;
|
|
MakeUndo(); //mxd
|
|
int i = 0;
|
|
|
|
//restore values
|
|
if(string.IsNullOrEmpty(alpha.Text))
|
|
{
|
|
foreach(Thing t in things) UniFields.SetFloat(t.Fields, "alpha", thingprops[i++].Alpha, 1.0f);
|
|
}
|
|
else //update values
|
|
{
|
|
foreach(Thing t in things)
|
|
{
|
|
float value = General.Clamp(alpha.GetResultFloat(t.Fields.GetValue("alpha", 1.0f)), 0f, 1.0f);
|
|
UniFields.SetFloat(t.Fields, "alpha", value, 1.0f);
|
|
}
|
|
}
|
|
|
|
General.Map.IsChanged = true;
|
|
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
|
|
}
|
|
|
|
private void hidefixedfields_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
fieldslist.ShowFixedFields = !hidefixedfields.Checked;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |