#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.IO;
using System.IO;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Controls;
using CodeImp.DoomBuilder.GZBuilder.Data;
#endregion
namespace CodeImp.DoomBuilder.Windows
{
///
/// Dialog window that allows viewing and editing of Thing properties.
///
public partial class ThingEditForm : DelayedForm
{
#region ================== Variables
private ICollection things;
private List nodes;
private ThingTypeInfo thinginfo;
private bool preventchanges = false;
//mxd
private Vector2D initialPosition; //initial position of a thing used to fill posX and posY fields
#endregion
#region ================== Properties
#endregion
#region ================== Constructor
// Constructor
public ThingEditForm()
{
// Initialize
InitializeComponent();
// Fill flags list
foreach(KeyValuePair tf in General.Map.Config.ThingFlags)
flags.Add(tf.Value, tf.Key);
// Fill actions list
action.GeneralizedCategories = General.Map.Config.GenActionCategories;
action.AddInfo(General.Map.Config.SortedLinedefActions.ToArray());
// Fill universal fields list
fieldslist.ListFixedFields(General.Map.Config.ThingFields);
// Initialize custom fields editor
fieldslist.Setup("thing");
// Custom fields?
if(!General.Map.FormatInterface.HasCustomFields)
tabs.TabPages.Remove(tabcustom);
// Tag/Effects?
if(!General.Map.FormatInterface.HasThingAction && !General.Map.FormatInterface.HasThingTag)
tabs.TabPages.Remove(tabeffects);
// Thing height?
height.Visible = General.Map.FormatInterface.HasThingHeight;
heightlabel.Visible = General.Map.FormatInterface.HasThingHeight;
// Setup types list
thingtype.Setup();
}
// This sets up the form to edit the given things
public void Setup(ICollection things)
{
Thing ft;
preventchanges = true;
// Keep this list
this.things = things;
if(things.Count > 1) this.Text = "Edit Things (" + things.Count + ")";
////////////////////////////////////////////////////////////////////////
// Set all options to the first thing properties
////////////////////////////////////////////////////////////////////////
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();
height.Text = ((int)ft.Position.z).ToString();
//mxd
initialPosition = ft.Position;
posX.Text = ((int)ft.Position.x).ToString();
posY.Text = ((int)ft.Position.y).ToString();
posX.ButtonStep = General.Map.Grid.GridSize;
posY.ButtonStep = General.Map.Grid.GridSize;
// Action/tags
action.Value = ft.Action;
tag.Text = ft.Tag.ToString();
arg0.SetValue(ft.Args[0]);
arg1.SetValue(ft.Args[1]);
arg2.SetValue(ft.Args[2]);
arg3.SetValue(ft.Args[3]);
arg4.SetValue(ft.Args[4]);
// Custom fields
fieldslist.SetValues(ft.Fields, true);
////////////////////////////////////////////////////////////////////////
// Now go for all lines and change the options when a setting is different
////////////////////////////////////////////////////////////////////////
// Go for all things
foreach(Thing t in things)
{
// Type does not match?
if((thingtype.GetSelectedInfo() != null) &&
(thingtype.GetSelectedInfo().Index != t.Type))
thingtype.ClearSelectedType();
// Flags
foreach(CheckBox c in flags.Checkboxes)
{
if(t.Flags.ContainsKey(c.Tag.ToString()))
{
if(t.Flags[c.Tag.ToString()] != c.Checked)
{
c.ThreeState = true;
c.CheckState = CheckState.Indeterminate;
}
}
}
// Coordination
if(t.AngleDoom.ToString() != angle.Text) angle.Text = "";
if(((int)t.Position.z).ToString() != height.Text) height.Text = "";
// Action/tags
if(t.Action != action.Value) action.Empty = true;
if(t.Tag.ToString() != tag.Text) tag.Text = "";
if(t.Args[0] != arg0.GetResult(-1)) arg0.ClearValue();
if(t.Args[1] != arg1.GetResult(-1)) arg1.ClearValue();
if(t.Args[2] != arg2.GetResult(-1)) arg2.ClearValue();
if(t.Args[3] != arg3.GetResult(-1)) arg3.ClearValue();
if(t.Args[4] != arg4.GetResult(-1)) arg4.ClearValue();
// Custom fields
fieldslist.SetValues(t.Fields, false);
}
preventchanges = false;
}
#endregion
#region ================== Interface
// This finds a new (unused) tag
private void newtag_Click(object sender, EventArgs e)
{
tag.Text = General.Map.Map.GetNewTag().ToString();
}
// Selected type changes
private void thingtype_OnTypeChanged(ThingTypeInfo value)
{
thinginfo = value;
// Update preview image
if(thinginfo != null)
{
if(thinginfo.Sprite.ToLowerInvariant().StartsWith(DataManager.INTERNAL_PREFIX) &&
(thinginfo.Sprite.Length > DataManager.INTERNAL_PREFIX.Length))
{
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(thinginfo.Sprite).GetBitmap());
}
else if((thinginfo.Sprite.Length <= 8) && (thinginfo.Sprite.Length > 0))
{
General.DisplayZoomedImage(spritetex, General.Map.Data.GetSpriteImage(thinginfo.Sprite).GetPreview());
}
else
{
spritetex.BackgroundImage = null;
}
}
else
{
spritetex.BackgroundImage = null;
}
// Update arguments
action_ValueChanges(this, EventArgs.Empty);
}
// Action changes
private void action_ValueChanges(object sender, EventArgs e)
{
int showaction = 0;
ArgumentInfo[] arginfo;
// Only when line type is known, otherwise use the thing arguments
if(General.Map.Config.LinedefActions.ContainsKey(action.Value)) showaction = action.Value;
if((showaction == 0) && (thinginfo != null)) arginfo = thinginfo.Args; else arginfo = General.Map.Config.LinedefActions[showaction].Args;
// Change the argument descriptions
arg0label.Text = arginfo[0].Title + ":";
arg1label.Text = arginfo[1].Title + ":";
arg2label.Text = arginfo[2].Title + ":";
arg3label.Text = arginfo[3].Title + ":";
arg4label.Text = arginfo[4].Title + ":";
arg0label.Enabled = arginfo[0].Used;
arg1label.Enabled = arginfo[1].Used;
arg2label.Enabled = arginfo[2].Used;
arg3label.Enabled = arginfo[3].Used;
arg4label.Enabled = arginfo[4].Used;
if(arg0label.Enabled) arg0.ForeColor = SystemColors.WindowText; else arg0.ForeColor = SystemColors.GrayText;
if(arg1label.Enabled) arg1.ForeColor = SystemColors.WindowText; else arg1.ForeColor = SystemColors.GrayText;
if(arg2label.Enabled) arg2.ForeColor = SystemColors.WindowText; else arg2.ForeColor = SystemColors.GrayText;
if(arg3label.Enabled) arg3.ForeColor = SystemColors.WindowText; else arg3.ForeColor = SystemColors.GrayText;
if(arg4label.Enabled) arg4.ForeColor = SystemColors.WindowText; else arg4.ForeColor = SystemColors.GrayText;
arg0.Setup(arginfo[0]);
arg1.Setup(arginfo[1]);
arg2.Setup(arginfo[2]);
arg3.Setup(arginfo[3]);
arg4.Setup(arginfo[4]);
// Zero all arguments when linedef action 0 (normal) is chosen
if(!preventchanges && (showaction == 0))
{
//mxd. If thing is light, set default light settings
int[] args = GZDoomLight.GetDefaultLightSettings(thingtype.GetResult(1));
if (args != null) {
arg0.SetValue(args[0]);
arg1.SetValue(args[1]);
arg2.SetValue(args[2]);
arg3.SetValue(args[3]);
arg4.SetValue(args[4]);
} else {
arg0.SetValue(0);
arg1.SetValue(0);
arg2.SetValue(0);
arg3.SetValue(0);
arg4.SetValue(0);
}
}
}
// Browse Action clicked
private void browseaction_Click(object sender, EventArgs e)
{
action.Value = ActionBrowserForm.BrowseAction(this, action.Value);
}
// Angle text changes
private void angle_TextChanged(object sender, EventArgs e)
{
anglecontrol.Value = angle.GetResult(int.MinValue);
}
// Angle control clicked
private void anglecontrol_ButtonClicked(object sender, EventArgs e)
{
angle.Text = anglecontrol.Value.ToString();
}
// Apply clicked
private void apply_Click(object sender, EventArgs e)
{
List defaultflags = new List();
string undodesc = "thing";
// Verify the tag
if(General.Map.FormatInterface.HasThingTag && ((tag.GetResult(0) < General.Map.FormatInterface.MinTag) || (tag.GetResult(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(((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;
}
// Make undo
if(things.Count > 1) undodesc = things.Count + " things";
General.Map.UndoRedo.CreateUndo("Edit " + undodesc);
//mxd
Vector2D delta = new Vector2D((float)posX.GetResult((int)initialPosition.x) - initialPosition.x, (float)posY.GetResult((int)initialPosition.y) - initialPosition.y);
// Go for all the things
foreach(Thing t in things)
{
// Thing type index
t.Type = General.Clamp(thingtype.GetResult(t.Type), General.Map.FormatInterface.MinThingType, General.Map.FormatInterface.MaxThingType);
// Coordination
t.Rotate(angle.GetResult(t.AngleDoom));
//mxd
//t.Move(t.Position.x, t.Position.y, (float)height.GetResult((int)t.Position.z));
t.Move(t.Position.x + delta.x, t.Position.y + delta.y, (float)height.GetResult((int)t.Position.z));
// 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);
}
// Action/tags
t.Tag = tag.GetResult(t.Tag);
if(!action.Empty) t.Action = action.Value;
t.Args[0] = arg0.GetResult(t.Args[0]);
t.Args[1] = arg1.GetResult(t.Args[1]);
t.Args[2] = arg2.GetResult(t.Args[2]);
t.Args[3] = arg3.GetResult(t.Args[3]);
t.Args[4] = arg4.GetResult(t.Args[4]);
// Custom fields
fieldslist.Apply(t.Fields);
// Update settings
t.UpdateConfiguration();
}
// 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);
// Done
General.Map.IsChanged = true;
this.DialogResult = DialogResult.OK;
this.Close();
}
// Cancel clicked
private void cancel_Click(object sender, EventArgs e)
{
// Be gone
this.DialogResult = DialogResult.Cancel;
this.Close();
}
// Help
private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("w_thingeditor.html");
hlpevent.Handled = true;
}
#endregion
}
}