diff --git a/OpenRA.Editor/ActorTool.cs b/OpenRA.Editor/ActorTool.cs new file mode 100644 index 0000000000..c8a6fcc9d2 --- /dev/null +++ b/OpenRA.Editor/ActorTool.cs @@ -0,0 +1,45 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using System.Linq; +using OpenRA.FileFormats; + +using SGraphics = System.Drawing.Graphics; + +namespace OpenRA.Editor +{ + class ActorTool : ITool + { + ActorTemplate Actor; + public ActorTool(ActorTemplate actor) { this.Actor = actor; } + + public void Preview(Surface surface, SGraphics g) + { + /* todo: include the player + * in the brush so we can color new buildings too */ + + surface.DrawActor(g, surface.GetBrushLocation(), Actor, null); + } + + public void Apply(Surface surface) + { + if (surface.Map.Actors.Any(a => a.Value.Location() == surface.GetBrushLocation())) + return; + + var owner = "Neutral"; + var id = surface.NextActorName(); + surface.Map.Actors[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant()) + { + new LocationInit( surface.GetBrushLocation() ), + new OwnerInit( owner) + }; + } + } +} diff --git a/OpenRA.Editor/BrushTool.cs b/OpenRA.Editor/BrushTool.cs new file mode 100644 index 0000000000..fed80f5fa1 --- /dev/null +++ b/OpenRA.Editor/BrushTool.cs @@ -0,0 +1,124 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using OpenRA.FileFormats; + +using SGraphics = System.Drawing.Graphics; + +namespace OpenRA.Editor +{ + class BrushTool : ITool + { + BrushTemplate Brush; + + public BrushTool(BrushTemplate brush) { this.Brush = brush; } + + public void Apply(Surface surface) + { + // change the bits in the map + var tile = surface.TileSet.Tiles[Brush.N]; + var template = surface.TileSet.Templates[Brush.N]; + var pos = surface.GetBrushLocation(); + + if (surface.GetModifiers() == Keys.Shift) + { + FloodFillWithBrush(surface, pos); + return; + } + + for (var u = 0; u < template.Size.X; u++) + for (var v = 0; v < template.Size.Y; v++) + { + if (surface.Map.IsInMap(new int2(u, v) + pos)) + { + var z = u + v * template.Size.X; + if (tile.TileBitmapBytes[z] != null) + surface.Map.MapTiles[u + pos.X, v + pos.Y] = + new TileReference + { + type = Brush.N, + index = template.PickAny ? byte.MaxValue : (byte)z, + image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z, + }; + + var ch = new int2((pos.X + u) / Surface.ChunkSize, (pos.Y + v) / Surface.ChunkSize); + if (surface.Chunks.ContainsKey(ch)) + { + surface.Chunks[ch].Dispose(); + surface.Chunks.Remove(ch); + } + } + } + } + + public void Preview(Surface surface, SGraphics g) + { + g.DrawImage(Brush.Bitmap, + surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X, + surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y, + Brush.Bitmap.Width * surface.Zoom, + Brush.Bitmap.Height * surface.Zoom); + } + + void FloodFillWithBrush(Surface s, int2 pos) + { + var queue = new Queue(); + var replace = s.Map.MapTiles[pos.X, pos.Y]; + var touched = new bool[s.Map.MapSize.X, s.Map.MapSize.Y]; + + Action MaybeEnqueue = (x, y) => + { + if (s.Map.IsInMap(x, y) && !touched[x, y]) + { + queue.Enqueue(new int2(x, y)); + touched[x, y] = true; + } + }; + + queue.Enqueue(pos); + while (queue.Count > 0) + { + var p = queue.Dequeue(); + if (!s.Map.MapTiles[p.X, p.Y].Equals(replace)) + continue; + + var a = FindEdge(s, p, new int2(-1, 0), replace); + var b = FindEdge(s, p, new int2(1, 0), replace); + + for (var x = a.X; x <= b.X; x++) + { + s.Map.MapTiles[x, p.Y] = new TileReference { type = Brush.N, image = (byte)0, index = (byte)0 }; + if (s.Map.MapTiles[x, p.Y - 1].Equals(replace)) + MaybeEnqueue(x, p.Y - 1); + if (s.Map.MapTiles[x, p.Y + 1].Equals(replace)) + MaybeEnqueue(x, p.Y + 1); + } + } + + /* todo: optimize */ + foreach (var ch in s.Chunks.Values) ch.Dispose(); + s.Chunks.Clear(); + } + + int2 FindEdge(Surface s, int2 p, int2 d, TileReference replace) + { + for (; ; ) + { + var q = p + d; + if (!s.Map.IsInMap(q)) return p; + if (!s.Map.MapTiles[q.X, q.Y].Equals(replace)) return p; + p = q; + } + } + } +} diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index 665c8cad8f..13faf0fce4 100755 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -131,7 +131,7 @@ namespace OpenRA.Editor }; var brushTemplate = new BrushTemplate { Bitmap = bitmap, N = t.Key }; - ibox.Click += (_, e) => surface1.SetBrush(brushTemplate); + ibox.Click += (_, e) => surface1.SetTool(new BrushTool(brushTemplate)); var template = t.Value; tilePalette.Controls.Add(ibox); @@ -164,7 +164,7 @@ namespace OpenRA.Editor }; - ibox.Click += (_, e) => surface1.SetActor(template); + ibox.Click += (_, e) => surface1.SetTool(new ActorTool(template)); actorPalette.Controls.Add(ibox); @@ -197,7 +197,7 @@ namespace OpenRA.Editor - ibox.Click += (_, e) => surface1.SetResource(template); + ibox.Click += (_, e) => surface1.SetTool(new ResourceTool(template)); resourcePalette.Controls.Add(ibox); @@ -347,7 +347,7 @@ namespace OpenRA.Editor } } - void SpawnPointsClicked(object sender, EventArgs e) { surface1.SetWaypoint(new WaypointTemplate()); } + void SpawnPointsClicked(object sender, EventArgs e) { surface1.SetTool(new WaypointTool(new WaypointTemplate())); } void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = true; } void Form1_KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) surface1.IsPanning = false; } diff --git a/OpenRA.Editor/ITool.cs b/OpenRA.Editor/ITool.cs new file mode 100644 index 0000000000..7d0199bbd0 --- /dev/null +++ b/OpenRA.Editor/ITool.cs @@ -0,0 +1,20 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using SGraphics = System.Drawing.Graphics; + +namespace OpenRA.Editor +{ + interface ITool + { + void Apply(Surface surface); + void Preview(Surface surface, SGraphics g); + } +} diff --git a/OpenRA.Editor/OpenRA.Editor.csproj b/OpenRA.Editor/OpenRA.Editor.csproj index a83a03a11a..b6344efc84 100644 --- a/OpenRA.Editor/OpenRA.Editor.csproj +++ b/OpenRA.Editor/OpenRA.Editor.csproj @@ -1,4 +1,4 @@ - + Debug @@ -54,12 +54,15 @@ + + Form Form1.cs + Form @@ -130,9 +133,11 @@ ResizeDialog.cs + Component + diff --git a/OpenRA.Editor/ResourceTool.cs b/OpenRA.Editor/ResourceTool.cs new file mode 100644 index 0000000000..580977f09e --- /dev/null +++ b/OpenRA.Editor/ResourceTool.cs @@ -0,0 +1,48 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using OpenRA.FileFormats; + +using SGraphics = System.Drawing.Graphics; + +namespace OpenRA.Editor +{ + class ResourceTool : ITool + { + ResourceTemplate Resource; + + public ResourceTool(ResourceTemplate resource) { Resource = resource; } + + public void Apply(Surface surface) + { + surface.Map.MapResources[surface.GetBrushLocation().X, surface.GetBrushLocation().Y] + = new TileReference + { + type = (byte)Resource.Info.ResourceType, + index = (byte)surface.random.Next(Resource.Info.SpriteNames.Length), + image = (byte)Resource.Value + }; + + var ch = new int2((surface.GetBrushLocation().X) / Surface.ChunkSize, + (surface.GetBrushLocation().Y) / Surface.ChunkSize); + + if (surface.Chunks.ContainsKey(ch)) + { + surface.Chunks[ch].Dispose(); + surface.Chunks.Remove(ch); + } + } + + public void Preview(Surface surface, SGraphics g) + { + surface.DrawImage(g, Resource.Bitmap, surface.GetBrushLocation()); + } + } +} diff --git a/OpenRA.Editor/Surface.cs b/OpenRA.Editor/Surface.cs index d1c24247a5..3c82a8950b 100755 --- a/OpenRA.Editor/Surface.cs +++ b/OpenRA.Editor/Surface.cs @@ -17,6 +17,8 @@ using System.Windows.Forms; using OpenRA.FileFormats; using OpenRA.Traits; +using SGraphics = System.Drawing.Graphics; + namespace OpenRA.Editor { class Surface : Control @@ -24,15 +26,14 @@ namespace OpenRA.Editor public Map Map { get; private set; } public TileSet TileSet { get; private set; } public Palette Palette { get; private set; } - int2 Offset; + public int2 Offset; - float Zoom = 1.0f; + public int2 GetOffset() { return Offset; } - BrushTemplate Brush; - ActorTemplate Actor; - ResourceTemplate Resource; - WaypointTemplate Waypoint; + public float Zoom = 1.0f; + ITool Tool; + public bool IsPanning; public event Action AfterChange = () => { }; public event Action MousePositionChanged = _ => { }; @@ -40,20 +41,19 @@ namespace OpenRA.Editor Dictionary ActorTemplates = new Dictionary(); Dictionary ResourceTemplates = new Dictionary(); + public Keys GetModifiers() { return ModifierKeys; } + public void Bind(Map m, TileSet ts, Palette p) { Map = m; TileSet = ts; Palette = p; - Brush = null; PlayerPalettes = null; Chunks.Clear(); + Tool = null; } - public void SetBrush(BrushTemplate brush) { Actor = null; Brush = brush; Resource = null; Waypoint = null; } - public void SetActor(ActorTemplate actor) { Brush = null; Actor = actor; Resource = null; Waypoint = null; } - public void SetResource(ResourceTemplate resource) { Brush = null; Actor = null; Resource = resource; Waypoint = null; } - public void SetWaypoint(WaypointTemplate waypoint) { Brush = null; Actor = null; Resource = null; Waypoint = waypoint; } + public void SetTool(ITool tool) { Tool = tool; } public void BindActorTemplates(IEnumerable templates) { @@ -65,7 +65,7 @@ namespace OpenRA.Editor ResourceTemplates = templates.ToDictionary(a => a.Info.ResourceType); } - Dictionary Chunks = new Dictionary(); + public Dictionary Chunks = new Dictionary(); public Surface() : base() @@ -139,101 +139,8 @@ namespace OpenRA.Editor } } - void FloodFillWithBrush(int2 pos) - { - var queue = new Queue(); - var replace = Map.MapTiles[pos.X, pos.Y]; - var touched = new bool[Map.MapSize.X, Map.MapSize.Y]; - - Action MaybeEnqueue = (x, y) => - { - if (Map.IsInMap(x, y) && !touched[x, y]) - { - queue.Enqueue(new int2(x, y)); - touched[x, y] = true; - } - }; - - queue.Enqueue(pos); - while (queue.Count > 0) - { - var p = queue.Dequeue(); - if (!Map.MapTiles[p.X, p.Y].Equals(replace)) - continue; - - var a = FindEdge(p, new int2(-1, 0), replace); - var b = FindEdge(p, new int2(1, 0), replace); - - for (var x = a.X; x <= b.X; x++) - { - Map.MapTiles[x, p.Y] = new TileReference { type = Brush.N, image = (byte)0, index = (byte)0 }; - if (Map.MapTiles[x, p.Y - 1].Equals(replace)) - MaybeEnqueue(x, p.Y - 1); - if (Map.MapTiles[x, p.Y + 1].Equals(replace)) - MaybeEnqueue(x, p.Y + 1); - } - } - - /* todo: optimize */ - foreach (var ch in Chunks.Values) ch.Dispose(); - Chunks.Clear(); - - AfterChange(); - } - - int2 FindEdge(int2 p, int2 d, TileReference replace) - { - for (; ; ) - { - var q = p + d; - if (!Map.IsInMap(q)) return p; - if (!Map.MapTiles[q.X, q.Y].Equals(replace)) return p; - p = q; - } - } - - void DrawWithBrush() - { - // change the bits in the map - var tile = TileSet.Tiles[Brush.N]; - var template = TileSet.Templates[Brush.N]; - var pos = GetBrushLocation(); - - if (ModifierKeys == Keys.Shift) - { - FloodFillWithBrush(pos); - return; - } - - for (var u = 0; u < template.Size.X; u++) - for (var v = 0; v < template.Size.Y; v++) - { - if (Map.IsInMap(new int2(u, v) + pos)) - { - var z = u + v * template.Size.X; - if (tile.TileBitmapBytes[z] != null) - Map.MapTiles[u + pos.X, v + pos.Y] = - new TileReference - { - type = Brush.N, - index = template.PickAny ? byte.MaxValue : (byte)z, - image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z, - }; - - var ch = new int2((pos.X + u) / ChunkSize, (pos.Y + v) / ChunkSize); - if (Chunks.ContainsKey(ch)) - { - Chunks[ch].Dispose(); - Chunks.Remove(ch); - } - } - } - - AfterChange(); - } - int wpid; - string NextWpid() + public string NextWpid() { for (; ; ) { @@ -245,10 +152,7 @@ namespace OpenRA.Editor void DrawWithWaypoint() { - var k = Map.Waypoints.FirstOrDefault(a => a.Value == GetBrushLocation()); - if (k.Key != null) Map.Waypoints.Remove(k.Key); - - Map.Waypoints.Add(NextWpid(), GetBrushLocation()); + AfterChange(); } @@ -264,11 +168,8 @@ namespace OpenRA.Editor BrushLocation.Y < 0) return; - Actor = null; - Brush = null; - Resource = null; - Waypoint = null; - + Tool = null; + var key = Map.Actors.FirstOrDefault(a => a.Value.Location() == BrushLocation); if (key.Key != null) Map.Actors.Remove(key.Key); @@ -291,16 +192,13 @@ namespace OpenRA.Editor void Draw() { - if (Brush != null) DrawWithBrush(); - if (Actor != null) DrawWithActor(); - if (Resource != null) DrawWithResource(); - if (Waypoint != null) DrawWithWaypoint(); - + if (Tool != null) Tool.Apply(this); + AfterChange(); } int id; - string NextActorName() + public string NextActorName() { for (; ; ) { @@ -309,39 +207,10 @@ namespace OpenRA.Editor } } - void DrawWithActor() - { - if (Map.Actors.Any(a => a.Value.Location() == GetBrushLocation())) - return; - - var owner = "Neutral"; - var id = NextActorName(); - Map.Actors[id] = new ActorReference(Actor.Info.Name.ToLowerInvariant()) - { - new LocationInit( GetBrushLocation() ), - new OwnerInit( owner) - }; - - AfterChange(); - } - - System.Random r = new System.Random(); + public System.Random random = new System.Random(); void DrawWithResource() { - Map.MapResources[GetBrushLocation().X, GetBrushLocation().Y] - = new TileReference - { - type = (byte)Resource.Info.ResourceType, - index = (byte)r.Next(Resource.Info.SpriteNames.Length), - image = (byte)Resource.Value - }; - - var ch = new int2((GetBrushLocation().X) / ChunkSize, (GetBrushLocation().Y) / ChunkSize); - if (Chunks.ContainsKey(ch)) - { - Chunks[ch].Dispose(); - Chunks.Remove(ch); - } + AfterChange(); } @@ -361,7 +230,7 @@ namespace OpenRA.Editor Invalidate(); } - const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps. + public const int ChunkSize = 8; // 8x8 chunks ==> 192x192 bitmaps. Bitmap RenderChunk(int u, int v) { @@ -414,14 +283,14 @@ namespace OpenRA.Editor return bitmap; } - int2 GetBrushLocation() + public int2 GetBrushLocation() { var vX = (int)Math.Floor((MousePos.X - Offset.X) / Zoom); var vY = (int)Math.Floor((MousePos.Y - Offset.Y) / Zoom); return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize); } - void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t, ColorPalette cp) + public void DrawActor(SGraphics g, int2 p, ActorTemplate t, ColorPalette cp) { var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft; @@ -442,7 +311,7 @@ namespace OpenRA.Editor if (cp != null) t.Bitmap.Palette = restorePalette; } - void DrawImage(System.Drawing.Graphics g, Bitmap bmp, int2 location) + public void DrawImage(SGraphics g, Bitmap bmp, int2 location) { float OffsetX = bmp.Width / 2 - TileSet.TileSize / 2; float DrawX = TileSet.TileSize * location.X * Zoom + Offset.X - OffsetX; @@ -530,27 +399,10 @@ namespace OpenRA.Editor TileSet.TileSize * wp.Value.Y * Zoom + Offset.Y + 4, (TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom); - if (Brush != null) - e.Graphics.DrawImage(Brush.Bitmap, - TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X, - TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y, - Brush.Bitmap.Width * Zoom, - Brush.Bitmap.Height * Zoom); - - if (Actor != null) - DrawActor(e.Graphics, GetBrushLocation(), Actor, null); /* todo: include the player - * in the brush so we can color new buildings too */ - - if (Resource != null) - DrawImage(e.Graphics, Resource.Bitmap, GetBrushLocation()); - - if (Waypoint != null) - e.Graphics.DrawRectangle(Pens.LimeGreen, - TileSet.TileSize * GetBrushLocation().X * Zoom + Offset.X + 4, - TileSet.TileSize * GetBrushLocation().Y * Zoom + Offset.Y + 4, - (TileSet.TileSize - 8) * Zoom, (TileSet.TileSize - 8) * Zoom); - - if (Brush == null && Actor == null && Resource == null) + if (Tool != null) + Tool.Preview(this, e.Graphics); + + if (Tool == null) { var x = Map.Actors.FirstOrDefault(a => a.Value.Location() == GetBrushLocation()); if (x.Key != null) diff --git a/OpenRA.Editor/WaypointTool.cs b/OpenRA.Editor/WaypointTool.cs new file mode 100644 index 0000000000..8e5b554b88 --- /dev/null +++ b/OpenRA.Editor/WaypointTool.cs @@ -0,0 +1,40 @@ +#region Copyright & License Information +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#endregion + +using System.Drawing; +using System.Linq; + +using SGraphics = System.Drawing.Graphics; + +namespace OpenRA.Editor +{ + class WaypointTool : ITool + { + WaypointTemplate Waypoint; + + public WaypointTool(WaypointTemplate waypoint) { Waypoint = waypoint; } + + public void Apply(Surface surface) + { + var k = surface.Map.Waypoints.FirstOrDefault(a => a.Value == surface.GetBrushLocation()); + if (k.Key != null) surface.Map.Waypoints.Remove(k.Key); + + surface.Map.Waypoints.Add(surface.NextWpid(), surface.GetBrushLocation()); + } + + public void Preview(Surface surface, SGraphics g) + { + g.DrawRectangle(Pens.LimeGreen, + surface.TileSet.TileSize * surface.GetBrushLocation().X * surface.Zoom + surface.GetOffset().X + 4, + surface.TileSet.TileSize * surface.GetBrushLocation().Y * surface.Zoom + surface.GetOffset().Y + 4, + (surface.TileSet.TileSize - 8) * surface.Zoom, (surface.TileSet.TileSize - 8) * surface.Zoom); + } + } +} diff --git a/SequenceEditor.vshost.exe.manifest b/SequenceEditor.vshost.exe.manifest new file mode 100644 index 0000000000..f96b1d6b3f --- /dev/null +++ b/SequenceEditor.vshost.exe.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + +