diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index 02589fb638..dc7c9f3b57 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -21,9 +21,11 @@ namespace OpenRA.Graphics SheetBuilder sheetBuilder; Dictionary templates; Sprite missingTile; + TileSet tileset; public Theater(TileSet tileset) { + this.tileset = tileset; var allocated = false; Func allocate = () => { @@ -69,6 +71,35 @@ namespace OpenRA.Graphics return template[r.Index]; } + public Rectangle TemplateBounds(TerrainTemplateInfo template, Size tileSize, TileShape tileShape) + { + Rectangle? templateRect = null; + + var i = 0; + for (var y = 0; y < template.Size.Y; y++) + { + for (var x = 0; x < template.Size.X; x++) + { + var tile = new TerrainTile(template.Id, (byte)(i++)); + var tileInfo = tileset.GetTileInfo(tile); + + // Empty tile + if (tileInfo == null) + continue; + + var sprite = TileSprite(tile); + var u = tileShape == TileShape.Rectangle ? x : (x - y) / 2f; + var v = tileShape == TileShape.Rectangle ? y : (x + y) / 2f; + + var tl = new float2(u * tileSize.Width, (v - 0.5f * tileInfo.Height) * tileSize.Height) - 0.5f * sprite.size; + var rect = new Rectangle((int)(tl.X + sprite.offset.X), (int)(tl.Y + sprite.offset.Y), (int)sprite.size.X, (int)sprite.size.Y); + templateRect = templateRect.HasValue ? Rectangle.Union(templateRect.Value, rect) : rect; + } + } + + return templateRect.HasValue ? templateRect.Value : Rectangle.Empty; + } + public Sheet Sheet { get { return sheetBuilder.Current; } } } } diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index c687c7e184..6e2e228ed0 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -129,6 +129,7 @@ + diff --git a/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs new file mode 100644 index 0000000000..705c17b143 --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs @@ -0,0 +1,103 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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 COPYING. + */ +#endregion + +using System; +using System.Drawing; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Graphics; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets +{ + public class TerrainTemplatePreviewWidget : Widget + { + public Func GetScale = () => 1f; + public string Palette = "terrain"; + + readonly WorldRenderer worldRenderer; + readonly TileSet tileset; + + TerrainTemplateInfo template; + Rectangle bounds; + + public TerrainTemplateInfo Template + { + get + { + return template; + } + + set + { + template = value; + if (template == null) + return; + + var ts = Game.modData.Manifest.TileSize; + var shape = Game.modData.Manifest.TileShape; + bounds = worldRenderer.Theater.TemplateBounds(template, ts, shape); + } + } + + [ObjectCreator.UseCtor] + public TerrainTemplatePreviewWidget(WorldRenderer worldRenderer, World world) + { + this.worldRenderer = worldRenderer; + tileset = world.Map.Rules.TileSets[world.Map.Tileset]; + } + + protected TerrainTemplatePreviewWidget(TerrainTemplatePreviewWidget other) + : base(other) + { + worldRenderer = other.worldRenderer; + tileset = other.worldRenderer.world.Map.Rules.TileSets[other.worldRenderer.world.Map.Tileset]; + Template = other.Template; + GetScale = other.GetScale; + } + + public override Widget Clone() { return new TerrainTemplatePreviewWidget(this); } + + public override void Draw() + { + if (template == null) + return; + + var ts = Game.modData.Manifest.TileSize; + var shape = Game.modData.Manifest.TileShape; + var scale = GetScale(); + + var sb = new Rectangle((int)(scale * bounds.X), (int)(scale * bounds.Y), (int)(scale * bounds.Width), (int)(scale * bounds.Height)); + var origin = RenderOrigin + new int2((RenderBounds.Size.Width - sb.Width) / 2 - sb.X, (RenderBounds.Size.Height - sb.Height) / 2 - sb.Y); + + var i = 0; + for (var y = 0; y < Template.Size.Y; y++) + { + for (var x = 0; x < Template.Size.X; x++) + { + var tile = new TerrainTile(Template.Id, (byte)(i++)); + var tileInfo = tileset.GetTileInfo(tile); + + // Empty tile + if (tileInfo == null) + continue; + + var sprite = worldRenderer.Theater.TileSprite(tile); + var size = new float2(sprite.size.X * scale, sprite.size.Y * scale); + + var u = shape == TileShape.Rectangle ? x : (x - y) / 2f; + var v = shape == TileShape.Rectangle ? y : (x + y) / 2f; + var pos = origin + scale * (new float2(u * ts.Width, (v - 0.5f * tileInfo.Height) * ts.Height) - 0.5f * sprite.size); + Game.Renderer.SpriteRenderer.DrawSprite(sprite, pos, worldRenderer.Palette(Palette), size); + } + } + } + } +}