diff --git a/OpenRA.Editor/ActorPropertiesDialog.Designer.cs b/OpenRA.Editor/ActorPropertiesDialog.Designer.cs new file mode 100644 index 0000000000..d959e64bde --- /dev/null +++ b/OpenRA.Editor/ActorPropertiesDialog.Designer.cs @@ -0,0 +1,92 @@ +namespace OpenRA.Editor +{ + partial class ActorPropertiesDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.SuspendLayout(); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(226, 333); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "Cancel"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Enabled = false; + this.button2.Location = new System.Drawing.Point(145, 333); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 0; + this.button2.Text = "OK"; + this.button2.UseVisualStyleBackColor = true; + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.AutoScroll = true; + this.flowLayoutPanel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.flowLayoutPanel1.Location = new System.Drawing.Point(13, 13); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(288, 314); + this.flowLayoutPanel1.TabIndex = 1; + // + // ActorPropertiesDialog + // + this.AcceptButton = this.button2; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button1; + this.ClientSize = new System.Drawing.Size(313, 368); + this.Controls.Add(this.flowLayoutPanel1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ActorPropertiesDialog"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Actor Properties"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + } +} \ No newline at end of file diff --git a/OpenRA.Editor/ActorPropertiesDialog.cs b/OpenRA.Editor/ActorPropertiesDialog.cs new file mode 100644 index 0000000000..bc4412ee7a --- /dev/null +++ b/OpenRA.Editor/ActorPropertiesDialog.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using OpenRA.FileFormats; + +namespace OpenRA.Editor +{ + public partial class ActorPropertiesDialog : Form + { + public ActorPropertiesDialog() + { + InitializeComponent(); + } + + public void AddRow(string name, Control c) + { + flowLayoutPanel1.Controls.Add(new Label + { + Text = name, + Width = flowLayoutPanel1.Width * 3 / 10, + Height = 25, + TextAlign = ContentAlignment.MiddleLeft, + }); + + c.Width = flowLayoutPanel1.Width * 6 / 10 - 25; + c.Height = 25; + flowLayoutPanel1.Controls.Add(c); + } + + public Control MakeEditorControl(Type t, Func getter, Action setter) + { + var r = new TextBox(); + r.Text = FieldSaver.FormatValue(getter(), t); + r.LostFocus += (e,_) => setter(FieldLoader.GetValue("", t, r.Text)); + r.Enabled = false; + return r; + } + } +} diff --git a/OpenRA.Editor/ActorPropertiesDialog.resx b/OpenRA.Editor/ActorPropertiesDialog.resx new file mode 100644 index 0000000000..19dc0dd8b3 --- /dev/null +++ b/OpenRA.Editor/ActorPropertiesDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index 1ddd8d2db7..8550762538 100755 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -10,13 +10,13 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.IO; using System.Linq; using System.Windows.Forms; using OpenRA.FileFormats; using OpenRA.Graphics; using OpenRA.Traits; -using System.Drawing; namespace OpenRA.Editor { @@ -57,6 +57,7 @@ namespace OpenRA.Editor surface1.AfterChange += OnMapChanged; surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s; + surface1.ActorDoubleClicked += ActorDoubleClicked; if (args.Length >= 2) LoadMap(args[1]); @@ -68,7 +69,31 @@ namespace OpenRA.Editor pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true)); } + void ActorDoubleClicked(KeyValuePair kv) + { + using( var apd = new ActorPropertiesDialog() ) + { + var name = kv.Key; + apd.AddRow("(Name)", apd.MakeEditorControl(typeof(string), () => name, v => name = (string)v)); + apd.AddRow("(Type)", apd.MakeEditorControl(typeof(string), () => kv.Value.Type, v => kv.Value.Type = (string)v)); + + var objSaved = kv.Value.Save(); + + // TODO: make this work properly + foreach( var init in Rules.Info[kv.Value.Type].GetInitKeys() ) + apd.AddRow(init.First, + apd.MakeEditorControl(init.Second, + () => objSaved.NodesDict.ContainsKey( init.First ) ? objSaved.NodesDict[init.First].Value : null, + _ => {})); + + apd.ShowDialog(); + + // TODO: writeback + } + } + void MakeDirty() { dirty = true; } + string loadedMapName; string currentMod = "ra"; TileSet tileset; diff --git a/OpenRA.Editor/MapSelect.cs b/OpenRA.Editor/MapSelect.cs index a732a4e07b..17744a2283 100644 --- a/OpenRA.Editor/MapSelect.cs +++ b/OpenRA.Editor/MapSelect.cs @@ -10,10 +10,9 @@ using System; using System.IO; -using System.Windows.Forms; -using OpenRA.FileFormats; -using OpenRA.Graphics; using System.Linq; +using System.Windows.Forms; +using OpenRA.Graphics; namespace OpenRA.Editor { @@ -79,6 +78,5 @@ namespace OpenRA.Editor { MapFolderPath = txtPathOut.Text; } - } } diff --git a/OpenRA.Editor/OpenRA.Editor.csproj b/OpenRA.Editor/OpenRA.Editor.csproj index e89bcccdbf..0fa16c44f5 100644 --- a/OpenRA.Editor/OpenRA.Editor.csproj +++ b/OpenRA.Editor/OpenRA.Editor.csproj @@ -1,4 +1,4 @@ - + Debug @@ -53,6 +53,12 @@ + + Form + + + ActorPropertiesDialog.cs + @@ -90,6 +96,9 @@ PropertiesDialog.cs + + ActorPropertiesDialog.cs + Form1.cs diff --git a/OpenRA.Editor/Surface.cs b/OpenRA.Editor/Surface.cs index 62ab9bc62c..de3bf46db5 100755 --- a/OpenRA.Editor/Surface.cs +++ b/OpenRA.Editor/Surface.cs @@ -42,6 +42,7 @@ namespace OpenRA.Editor public event Action AfterChange = () => { }; public event Action MousePositionChanged = _ => { }; + public event Action> ActorDoubleClicked = _ => { }; Dictionary ActorTemplates = new Dictionary(); Dictionary ResourceTemplates = new Dictionary(); @@ -91,6 +92,15 @@ namespace OpenRA.Editor Invalidate(); } + protected override void OnDoubleClick(EventArgs e) + { + base.OnDoubleClick(e); + + var x = Map.Actors.Value.FirstOrDefault(a => a.Value.Location() == GetBrushLocation()); + if (x.Key != null) + ActorDoubleClicked(x); + } + protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); @@ -294,7 +304,7 @@ namespace OpenRA.Editor if (cp != null) bmp.Palette = restorePalette; } - void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t) + void DrawActorBorder(SGraphics g, int2 p, ActorTemplate t) { var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; var drawPos = GetDrawPosition(p, t.Bitmap, centered); diff --git a/OpenRA.FileFormats/FieldLoader.cs b/OpenRA.FileFormats/FieldLoader.cs index 6a16dd73ef..a61990b5b3 100755 --- a/OpenRA.FileFormats/FieldLoader.cs +++ b/OpenRA.FileFormats/FieldLoader.cs @@ -305,14 +305,13 @@ namespace OpenRA.FileFormats return new MiniYamlNode(field, FieldSaver.FormatValue( o, o.GetType().GetField(field) )); } - public static string FormatValue(object o, FieldInfo f) + public static string FormatValue(object v, Type t) { - var v = f.GetValue(o); if (v == null) return ""; // Color.ToString() does the wrong thing; force it to format as an array - if (f.FieldType == typeof(Color)) + if (t == typeof(Color)) { var c = (Color)v; return "{0},{1},{2},{3}".F(((int)c.A).Clamp(0, 255), @@ -321,13 +320,13 @@ namespace OpenRA.FileFormats ((int)c.B).Clamp(0, 255)); } - if (f.FieldType == typeof(Rectangle)) + if (t == typeof(Rectangle)) { var r = (Rectangle)v; return "{0},{1},{2},{3}".F(r.X, r.Y, r.Width, r.Height); } - if (f.FieldType.IsArray) + if (t.IsArray) { var elems = ((Array)v).OfType(); return elems.JoinWith(","); @@ -335,6 +334,11 @@ namespace OpenRA.FileFormats return v.ToString(); } + + public static string FormatValue(object o, FieldInfo f) + { + return FormatValue(f.GetValue(o), f.FieldType); + } } public class FieldFromYamlKeyAttribute : Attribute { } diff --git a/OpenRA.FileFormats/TypeDictionary.cs b/OpenRA.FileFormats/TypeDictionary.cs index eb28785936..c279345c30 100644 --- a/OpenRA.FileFormats/TypeDictionary.cs +++ b/OpenRA.FileFormats/TypeDictionary.cs @@ -64,13 +64,18 @@ namespace OpenRA.FileFormats public T GetOrDefault() { - if( dataMultiple.ContainsKey( typeof( T ) ) ) - throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) ); + return (T)GetOrDefault(typeof(T)); + } + + public object GetOrDefault(Type t) + { + if( dataMultiple.ContainsKey(t) ) + throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", t ) ); object ret; - if( !dataSingular.TryGetValue( typeof( T ), out ret ) ) - return default( T ); - return (T)ret; + if( !dataSingular.TryGetValue(t, out ret ) ) + return null; + return ret; } public IEnumerable WithInterface() diff --git a/OpenRA.Game/ActorReference.cs b/OpenRA.Game/ActorReference.cs index b442d80fba..b042d3bf5a 100755 --- a/OpenRA.Game/ActorReference.cs +++ b/OpenRA.Game/ActorReference.cs @@ -15,8 +15,8 @@ namespace OpenRA.FileFormats { public class ActorReference : IEnumerable { - public readonly string Type; - public readonly TypeDictionary InitDict; + public string Type; + public TypeDictionary InitDict; public ActorReference( string type ) : this( type, new Dictionary() ) { } diff --git a/OpenRA.Game/GameRules/ActorInfo.cs b/OpenRA.Game/GameRules/ActorInfo.cs index 0f3b0421a7..1008d42249 100644 --- a/OpenRA.Game/GameRules/ActorInfo.cs +++ b/OpenRA.Game/GameRules/ActorInfo.cs @@ -121,8 +121,7 @@ namespace OpenRA return inits.Select( i => Pair.New( - i.GetType().Name.Replace( "Init", "" ), - i.GetType().GetInterfaces()[0].GetGenericArguments()[0] ) ); + i.Name.Replace( "Init", "" ), i )); } } } diff --git a/OpenRA.Game/Traits/Health.cs b/OpenRA.Game/Traits/Health.cs index b66a5a0dff..432157094c 100755 --- a/OpenRA.Game/Traits/Health.cs +++ b/OpenRA.Game/Traits/Health.cs @@ -14,7 +14,7 @@ using OpenRA.GameRules; namespace OpenRA.Traits { - public class HealthInfo : ITraitInfo + public class HealthInfo : ITraitInfo, UsesInit { public readonly int HP = 0; public readonly float Radius = 10; diff --git a/OpenRA.Mods.RA/Activities/Transform.cs b/OpenRA.Mods.RA/Activities/Transform.cs index 38dfdccbb2..24718714b8 100644 --- a/OpenRA.Mods.RA/Activities/Transform.cs +++ b/OpenRA.Mods.RA/Activities/Transform.cs @@ -10,8 +10,6 @@ using System.Linq; using OpenRA.FileFormats; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Mods.RA.Render; using OpenRA.Traits; namespace OpenRA.Mods.RA.Activities diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 2cb1081e16..eb9cf23dd5 100755 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.RA.Air [Sync] public int foo { get { return a.Altitude; } } } - public class AircraftInfo : ITraitInfo, IFacingInfo + public class AircraftInfo : ITraitInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { public readonly int CruiseAltitude = 30; [ActorReference] diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index b45d0820c5..2f7c6c5ddb 100755 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA.Buildings public class GivesBuildableAreaInfo : TraitInfo {} public class GivesBuildableArea {} - public class BuildingInfo : ITraitInfo + public class BuildingInfo : ITraitInfo, UsesInit { public readonly int Power = 0; public readonly string[] TerrainTypes = {}; diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index db628e7472..0dddfdd7f0 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -18,7 +18,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA.Move { - public class MobileInfo : ITraitInfo, IFacingInfo + public class MobileInfo : ITraitInfo, IFacingInfo, UsesInit, UsesInit, UsesInit { [FieldLoader.LoadUsing("LoadSpeeds")] public readonly Dictionary TerrainSpeeds; diff --git a/OpenRA.Mods.RA/Turreted.cs b/OpenRA.Mods.RA/Turreted.cs index eb4ac8e314..60e364981f 100755 --- a/OpenRA.Mods.RA/Turreted.cs +++ b/OpenRA.Mods.RA/Turreted.cs @@ -12,7 +12,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - public class TurretedInfo : ITraitInfo + public class TurretedInfo : ITraitInfo, UsesInit { public readonly int ROT = 255; public readonly int InitialFacing = 128;