ZoneBuilder/Source/Core/Windows/ThingEditFormUDMF.cs
MaxED 7435d4bd5b Added: action argument inputs now support incremental increase/decrease prefixes (+++ and ---).
Probably fixed probable I/O race condition when loading images.
Fixed Visual mode stuttering due to floating point precision degradation when running the editor for several days without restarting (internal timer is now reset when saving the map or creating a new one).
Fixed, Nodes Viewer, cosmetic: Nodes Viewer window position was reset after pressing the "Rebuild Nodes" button.
Added Eternity Game configurations by printz.
Updated ZDoom_ACS.cfg (CheckClass).
Updated ZDoom ACC (CheckClass).
2023-01-06 12:11:22 +01:00

899 lines
No EOL
27 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.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
//mxd. Window setup stuff
private static Point location = Point.Empty;
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(location != Point.Empty)
{
this.StartPosition = FormStartPosition.Manual;
this.Location = location;
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("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.SRB2Type);
// 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.SRB2Type);
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);
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.SRB2Type) thingtype.ClearSelectedType();
// 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.SRB2Type);
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
}
//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();
}
#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(GZBuilder.Controls.AngleControl.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(GZBuilder.Controls.AngleControl.NO_ANGLE);
preventchanges = true;
pitchControl.Angle = (p == GZBuilder.Controls.AngleControl.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(GZBuilder.Controls.AngleControl.NO_ANGLE);
preventchanges = true;
rollControl.Angle = (r == GZBuilder.Controls.AngleControl.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.SRB2Type);
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 = (int)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)
{
location = this.Location;
activetab = tabs.SelectedIndex;
General.Settings.WriteSetting("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.SRB2Type = thingtype.GetResult(t.SRB2Type);
// Update settings
t.UpdateConfiguration();
}
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;
MakeUndo(); //mxd
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
}
}