From 61c393234072d65c5e19023a57949e70482128dc Mon Sep 17 00:00:00 2001 From: Curtis Shmyr Date: Sat, 30 Jun 2012 22:31:32 -0600 Subject: [PATCH] Selection tool / copy paste for editor --- OpenRA.Editor/Form1.Designer.cs | 30 ++++++++- OpenRA.Editor/Form1.cs | 5 ++ OpenRA.Editor/Form1.resx | 73 +++++++++++---------- OpenRA.Editor/Surface.cs | 108 ++++++++++++++++++++++++++++++-- 4 files changed, 172 insertions(+), 44 deletions(-) diff --git a/OpenRA.Editor/Form1.Designer.cs b/OpenRA.Editor/Form1.Designer.cs index 82f7f76bbe..854561d7d7 100755 --- a/OpenRA.Editor/Form1.Designer.cs +++ b/OpenRA.Editor/Form1.Designer.cs @@ -82,6 +82,9 @@ namespace OpenRA.Editor this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabelFiller = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripStatusLabelMousePosition = new System.Windows.Forms.ToolStripStatusLabel(); + this.copySelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); @@ -417,8 +420,11 @@ namespace OpenRA.Editor this.resizeToolStripMenuItem, this.showActorNamesToolStripMenuItem, this.showGridToolStripMenuItem, + this.toolStripSeparator5, this.fixOpenAreasToolStripMenuItem, - this.setupDefaultPlayersMenuItem}); + this.setupDefaultPlayersMenuItem, + this.toolStripSeparator4, + this.copySelectionToolStripMenuItem}); this.mapToolStripMenuItem.Name = "mapToolStripMenuItem"; this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 23); this.mapToolStripMenuItem.Text = "&Map"; @@ -507,6 +513,23 @@ namespace OpenRA.Editor this.toolStripStatusLabelMousePosition.Size = new System.Drawing.Size(22, 17); this.toolStripStatusLabelMousePosition.Text = "0,0"; // + // copySelectionToolStripMenuItem + // + this.copySelectionToolStripMenuItem.Name = "copySelectionToolStripMenuItem"; + this.copySelectionToolStripMenuItem.Size = new System.Drawing.Size(185, 22); + this.copySelectionToolStripMenuItem.Text = "Copy Selection"; + this.copySelectionToolStripMenuItem.Click += new System.EventHandler(this.copySelectionToolStripMenuItem_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(182, 6); + // + // toolStripSeparator5 + // + this.toolStripSeparator5.Name = "toolStripSeparator5"; + this.toolStripSeparator5.Size = new System.Drawing.Size(182, 6); + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -520,9 +543,9 @@ namespace OpenRA.Editor this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "OpenRA Editor"; - this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing); this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); + this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); this.splitContainer1.ResumeLayout(false); @@ -592,6 +615,9 @@ namespace OpenRA.Editor private System.Windows.Forms.Panel panel1; private System.Windows.Forms.FlowLayoutPanel actorPalette; private System.Windows.Forms.ComboBox actorOwnerChooser; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem copySelectionToolStripMenuItem; } } diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index 53351cb450..4eda4f950e 100755 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -545,5 +545,10 @@ namespace OpenRA.Editor var player = actorOwnerChooser.SelectedItem as PlayerReference; surface1.NewActorOwner = player.Name; } + + private void copySelectionToolStripMenuItem_Click(object sender, EventArgs e) + { + surface1.CopySelection(); + } } } diff --git a/OpenRA.Editor/Form1.resx b/OpenRA.Editor/Form1.resx index e21860adab..9757275de8 100755 --- a/OpenRA.Editor/Form1.resx +++ b/OpenRA.Editor/Form1.resx @@ -120,13 +120,45 @@ 17, 17 - - 76, 17 - 198, 17 + + + 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 @@ -260,41 +292,6 @@ z2ki+Wo1CWklROkMCiT8wEm0kXEsCTmrAiTbDtcEpTVdZOS1oDfWk5xZ6RPeQZeUR8zxK0Qe1BO65xjr t0YotXhjAEAeQ7It8ZSESUjkznIq2bYsTGYW29JZxIs2nFEdLOSdfwFwpvLxRKIY2AAAAABJRU5ErkJg gg== - - - - - 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 diff --git a/OpenRA.Editor/Surface.cs b/OpenRA.Editor/Surface.cs index 9185036e87..65079e5041 100755 --- a/OpenRA.Editor/Surface.cs +++ b/OpenRA.Editor/Surface.cs @@ -38,6 +38,12 @@ namespace OpenRA.Editor public bool ShowActorNames; public bool ShowGrid; + public bool IsPaste { get { return TileSelection != null && ResourceSelection != null; } } + public TileReference[,] TileSelection; + public TileReference[,] ResourceSelection; + public CPos SelectionStart; + public CPos SelectionEnd; + public string NewActorOwner; public event Action AfterChange = () => { }; @@ -59,7 +65,7 @@ namespace OpenRA.Editor Tool = null; } - public void SetTool(ITool tool) { Tool = tool; } + public void SetTool(ITool tool) { Tool = tool; ClearSelection(); } public void BindActorTemplates(IEnumerable templates) { @@ -83,6 +89,8 @@ namespace OpenRA.Editor UpdateStyles(); } + static readonly Pen SelectionPen = new Pen(Color.Blue); + static readonly Pen PastePen = new Pen(Color.Green); static readonly Pen CordonPen = new Pen(Color.Red); int2 MousePos; @@ -182,12 +190,20 @@ namespace OpenRA.Editor } AfterChange(); + ClearSelection(); } void Draw() { - if (Tool != null) Tool.Apply(this); - AfterChange(); + if (Tool != null) + { + Tool.Apply(this); + AfterChange(); + } + else if (IsPaste) + PasteSelection(); + else + SelectionEnd = GetBrushLocation(); } protected override void OnMouseDown(MouseEventArgs e) @@ -199,7 +215,11 @@ namespace OpenRA.Editor if (!IsPanning) { if (e.Button == MouseButtons.Right) Erase(); - if (e.Button == MouseButtons.Left) Draw(); + if (e.Button == MouseButtons.Left) + { + Draw(); + if (!IsPaste) SelectionStart = GetBrushLocation(); + } } Invalidate(); @@ -367,6 +387,25 @@ namespace OpenRA.Editor Map.Bounds.Width * TileSet.TileSize * Zoom, Map.Bounds.Height * TileSet.TileSize * Zoom); + e.Graphics.DrawRectangle(SelectionPen, + (SelectionStart.X * TileSet.TileSize * Zoom) + Offset.X, + (SelectionStart.Y * TileSet.TileSize * Zoom) + Offset.Y, + (SelectionEnd - SelectionStart).X * TileSet.TileSize * Zoom, + (SelectionEnd - SelectionStart).Y * TileSet.TileSize * Zoom); + + if (IsPaste) + { + var loc = GetBrushLocation(); + var width = Math.Abs((SelectionStart - SelectionEnd).X); + var height = Math.Abs((SelectionStart - SelectionEnd).Y); + + e.Graphics.DrawRectangle(PastePen, + (loc.X * TileSet.TileSize * Zoom) + Offset.X, + (loc.Y * TileSet.TileSize * Zoom) + Offset.Y, + width * (TileSet.TileSize * Zoom), + height * (TileSet.TileSize * Zoom)); + } + foreach (var ar in Map.Actors.Value) { if (ActorTemplates.ContainsKey(ar.Value.Type)) @@ -395,6 +434,67 @@ namespace OpenRA.Editor DrawActorBorder(e.Graphics, x.Value.Location(), ActorTemplates[x.Value.Type]); } } + + public void CopySelection() + { + // Grab tiles and resources within selection (doesn't do actors) + var start = SelectionStart; + var end = SelectionEnd; + + if (start == end) return; + + int width = Math.Abs((start - end).X); + int height = Math.Abs((start - end).Y); + + TileSelection = new TileReference[width, height]; + ResourceSelection = new TileReference[width, height]; + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + //todo: crash prevention + TileSelection[x, y] = Map.MapTiles.Value[start.X + x, start.Y + y]; + ResourceSelection[x, y] = Map.MapResources.Value[start.X + x, start.Y + y]; + } + } + } + + void PasteSelection() + { + var loc = GetBrushLocation(); + var width = Math.Abs((SelectionStart - SelectionEnd).X); + var height = Math.Abs((SelectionStart - SelectionEnd).Y); + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < height; y++) + { + var mapX = loc.X + x; + var mapY = loc.Y + y; + + //todo: crash prevention for outside of bounds + Map.MapTiles.Value[mapX, mapY] = TileSelection[x, y]; + Map.MapResources.Value[mapX, mapY] = ResourceSelection[x, y]; + + var ch = new int2(mapX / ChunkSize, mapY / ChunkSize); + if (Chunks.ContainsKey(ch)) + { + Chunks[ch].Dispose(); + Chunks.Remove(ch); + } + } + } + AfterChange(); + } + + void ClearSelection() + { + SelectionStart = CPos.Zero; + SelectionEnd = CPos.Zero; + TileSelection = null; + ResourceSelection = null; + } } static class ActorReferenceExts