Move ownership of tile sprites to the terrain renderer.
This commit is contained in:
@@ -162,32 +162,6 @@ namespace OpenRA.Graphics
|
||||
return template.Sprites[start * template.Stride + r.Index];
|
||||
}
|
||||
|
||||
public Rectangle TemplateBounds(TerrainTemplateInfo template, Size tileSize, MapGridType mapGrid)
|
||||
{
|
||||
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++));
|
||||
if (!tileset.TryGetTileInfo(tile, out var tileInfo))
|
||||
continue;
|
||||
|
||||
var sprite = TileSprite(tile);
|
||||
var u = mapGrid == MapGridType.Rectangular ? x : (x - y) / 2f;
|
||||
var v = mapGrid == MapGridType.Rectangular ? 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; } }
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace OpenRA.Graphics
|
||||
public readonly Size TileSize;
|
||||
public readonly int TileScale;
|
||||
public readonly World World;
|
||||
public readonly Theater Theater;
|
||||
public Viewport Viewport { get; private set; }
|
||||
public readonly ITerrainLighting TerrainLighting;
|
||||
|
||||
@@ -68,7 +67,6 @@ namespace OpenRA.Graphics
|
||||
|
||||
palette.Initialize();
|
||||
|
||||
Theater = new Theater(world.Map.Rules.TileSet);
|
||||
TerrainLighting = world.WorldActor.TraitOrDefault<ITerrainLighting>();
|
||||
terrainRenderer = world.WorldActor.TraitOrDefault<IRenderTerrain>();
|
||||
|
||||
@@ -425,7 +423,6 @@ namespace OpenRA.Graphics
|
||||
World.Dispose();
|
||||
|
||||
palette.Dispose();
|
||||
Theater.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,9 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||
{
|
||||
if (!rules.Actors["world"].HasTraitInfo<ITiledTerrainRendererInfo>())
|
||||
throw new YamlException("Bridge requires a tile-based terrain renderer.");
|
||||
|
||||
if (string.IsNullOrEmpty(DemolishWeapon))
|
||||
throw new YamlException("A value for DemolishWeapon of a Bridge trait is missing.");
|
||||
|
||||
@@ -93,6 +96,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly BuildingInfo buildingInfo;
|
||||
readonly Bridge[] neighbours = new Bridge[2];
|
||||
readonly LegacyBridgeHut[] huts = new LegacyBridgeHut[2]; // Huts before this / first & after this / last
|
||||
readonly ITiledTerrainRenderer terrainRenderer;
|
||||
readonly Health health;
|
||||
readonly Actor self;
|
||||
readonly BridgeInfo info;
|
||||
@@ -114,6 +118,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
type = self.Info.Name;
|
||||
isDangling = new Lazy<bool>(() => huts[0] == huts[1] && (neighbours[0] == null || neighbours[1] == null));
|
||||
buildingInfo = self.Info.TraitInfo<BuildingInfo>();
|
||||
terrainRenderer = self.World.WorldActor.Trait<ITiledTerrainRenderer>();
|
||||
}
|
||||
|
||||
public Bridge Neighbour(int direction) { return neighbours[direction]; }
|
||||
@@ -198,7 +203,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var offset = buildingInfo.CenterOffset(self.World).Y + 1024;
|
||||
|
||||
return footprint.Select(c => (IRenderable)(new SpriteRenderable(
|
||||
wr.Theater.TileSprite(new TerrainTile(template, c.Value)),
|
||||
terrainRenderer.TileSprite(new TerrainTile(template, c.Value)),
|
||||
wr.World.Map.CenterOfCell(c.Key), WVec.Zero, -offset, palette, 1f, true))).ToArray();
|
||||
}
|
||||
|
||||
@@ -224,7 +229,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
foreach (var kv in footprint)
|
||||
{
|
||||
var xy = wr.ScreenPxPosition(wr.World.Map.CenterOfCell(kv.Key));
|
||||
var size = wr.Theater.TileSprite(new TerrainTile(template, kv.Value)).Bounds.Size;
|
||||
var size = terrainRenderer.TileSprite(new TerrainTile(template, kv.Value)).Bounds.Size;
|
||||
|
||||
// Add an extra pixel padding to avoid issues with odd-sized sprites
|
||||
var halfWidth = size.Width / 2 + 1;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public enum EditorCursorType { None, Actor, TerrainTemplate, Resource }
|
||||
|
||||
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||
public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>
|
||||
public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo>
|
||||
{
|
||||
public readonly WAngle PreviewFacing = new WAngle(384);
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
readonly EditorCursorLayerInfo info;
|
||||
readonly EditorActorLayer editorLayer;
|
||||
readonly ITiledTerrainRenderer terrainRenderer;
|
||||
readonly World world;
|
||||
|
||||
public int CurrentToken { get; private set; }
|
||||
@@ -51,6 +52,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
this.info = info;
|
||||
world = self.World;
|
||||
editorLayer = self.Trait<EditorActorLayer>();
|
||||
terrainRenderer = self.Trait<ITiledTerrainRenderer>();
|
||||
|
||||
Type = EditorCursorType.None;
|
||||
}
|
||||
@@ -81,7 +83,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!world.Map.Rules.TileSet.TryGetTileInfo(tile, out var tileInfo))
|
||||
continue;
|
||||
|
||||
var sprite = wr.Theater.TileSprite(tile, 0);
|
||||
var sprite = terrainRenderer.TileSprite(tile, 0);
|
||||
var offset = world.Map.Offset(new CVec(x, y), tileInfo.Height);
|
||||
var palette = wr.Palette(TerrainTemplate.Palette ?? TileSet.TerrainPaletteInternalName);
|
||||
|
||||
|
||||
@@ -11,31 +11,31 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class TerrainRendererInfo : TraitInfo
|
||||
public class TerrainRendererInfo : TraitInfo, ITiledTerrainRendererInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new TerrainRenderer(init.World); }
|
||||
}
|
||||
|
||||
public sealed class TerrainRenderer : IRenderTerrain, IWorldLoaded, INotifyActorDisposing
|
||||
public sealed class TerrainRenderer : IRenderTerrain, IWorldLoaded, INotifyActorDisposing, ITiledTerrainRenderer
|
||||
{
|
||||
readonly Map map;
|
||||
readonly Dictionary<string, TerrainSpriteLayer> spriteLayers = new Dictionary<string, TerrainSpriteLayer>();
|
||||
Theater theater;
|
||||
readonly Theater theater;
|
||||
bool disposed;
|
||||
|
||||
public TerrainRenderer(World world)
|
||||
{
|
||||
map = world.Map;
|
||||
theater = new Theater(world.Map.Rules.TileSet);
|
||||
}
|
||||
|
||||
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
|
||||
{
|
||||
theater = wr.Theater;
|
||||
|
||||
foreach (var template in map.Rules.TileSet.Templates)
|
||||
{
|
||||
var palette = template.Value.Palette ?? TileSet.TerrainPaletteInternalName;
|
||||
@@ -57,9 +57,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (map.Rules.TileSet.Templates.ContainsKey(tile.Type))
|
||||
palette = map.Rules.TileSet.Templates[tile.Type].Palette ?? palette;
|
||||
|
||||
var sprite = theater.TileSprite(tile);
|
||||
foreach (var kv in spriteLayers)
|
||||
kv.Value.Update(cell, palette == kv.Key ? sprite : null, false);
|
||||
kv.Value.Update(cell, palette == kv.Key ? theater.TileSprite(tile) : null, false);
|
||||
}
|
||||
|
||||
void IRenderTerrain.RenderTerrain(WorldRenderer wr, Viewport viewport)
|
||||
@@ -82,7 +81,42 @@ namespace OpenRA.Mods.Common.Traits
|
||||
foreach (var kv in spriteLayers.Values)
|
||||
kv.Dispose();
|
||||
|
||||
theater.Dispose();
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
Sheet ITiledTerrainRenderer.Sheet { get { return theater.Sheet; } }
|
||||
|
||||
Sprite ITiledTerrainRenderer.TileSprite(TerrainTile r, int? variant)
|
||||
{
|
||||
return theater.TileSprite(r, variant);
|
||||
}
|
||||
|
||||
Rectangle ITiledTerrainRenderer.TemplateBounds(TerrainTemplateInfo template)
|
||||
{
|
||||
Rectangle? templateRect = null;
|
||||
var tileSize = map.Grid.TileSize;
|
||||
|
||||
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++));
|
||||
if (!map.Rules.TileSet.TryGetTileInfo(tile, out var tileInfo))
|
||||
continue;
|
||||
|
||||
var sprite = theater.TileSprite(tile);
|
||||
var u = map.Grid.Type == MapGridType.Rectangular ? x : (x - y) / 2f;
|
||||
var v = map.Grid.Type == MapGridType.Rectangular ? 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 ?? Rectangle.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,4 +643,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
IEnumerable<IRenderable> RenderDecoration(Actor self, WorldRenderer wr, ISelectionDecorations container);
|
||||
}
|
||||
|
||||
[RequireExplicitImplementation]
|
||||
public interface ITiledTerrainRendererInfo : ITraitInfoInterface { }
|
||||
|
||||
[RequireExplicitImplementation]
|
||||
public interface ITiledTerrainRenderer
|
||||
{
|
||||
Sheet Sheet { get; }
|
||||
Sprite TileSprite(TerrainTile r, int? variant = null);
|
||||
Rectangle TemplateBounds(TerrainTemplateInfo template);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
@@ -36,6 +37,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
|
||||
readonly TileSet tileset;
|
||||
readonly ITiledTerrainRenderer terrainRenderer;
|
||||
readonly TileSelectorTemplate[] allTemplates;
|
||||
readonly EditorCursorLayer editorCursor;
|
||||
|
||||
@@ -44,6 +46,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
: base(widget, world, worldRenderer, "TILETEMPLATE_LIST", "TILEPREVIEW_TEMPLATE")
|
||||
{
|
||||
tileset = world.Map.Rules.TileSet;
|
||||
terrainRenderer = world.WorldActor.TraitOrDefault<ITiledTerrainRenderer>();
|
||||
if (terrainRenderer == null)
|
||||
throw new YamlException("TileSelectorLogic requires a tile-based terrain renderer.");
|
||||
|
||||
allTemplates = tileset.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray();
|
||||
editorCursor = world.WorldActor.Trait<EditorCursorLayer>();
|
||||
|
||||
@@ -106,8 +112,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
var preview = item.Get<TerrainTemplatePreviewWidget>("TILE_PREVIEW");
|
||||
var template = tileset.Templates[tileId];
|
||||
var grid = WorldRenderer.World.Map.Grid;
|
||||
var bounds = WorldRenderer.Theater.TemplateBounds(template, grid.TileSize, grid.Type);
|
||||
var bounds = terrainRenderer.TemplateBounds(template);
|
||||
|
||||
// Scale templates to fit within the panel
|
||||
var scale = 1f;
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
using System;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets
|
||||
@@ -20,6 +22,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public Func<float> GetScale = () => 1f;
|
||||
|
||||
readonly ITiledTerrainRenderer terrainRenderer;
|
||||
readonly WorldRenderer worldRenderer;
|
||||
readonly TileSet tileset;
|
||||
|
||||
@@ -39,8 +42,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
if (template == null)
|
||||
return;
|
||||
|
||||
var grid = Game.ModData.Manifest.Get<MapGrid>();
|
||||
bounds = worldRenderer.Theater.TemplateBounds(template, grid.TileSize, grid.Type);
|
||||
bounds = terrainRenderer.TemplateBounds(template);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +51,9 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
this.worldRenderer = worldRenderer;
|
||||
tileset = world.Map.Rules.TileSet;
|
||||
terrainRenderer = world.WorldActor.TraitOrDefault<ITiledTerrainRenderer>();
|
||||
if (terrainRenderer == null)
|
||||
throw new YamlException("TerrainTemplatePreviewWidget requires a tile-based terrain renderer.");
|
||||
}
|
||||
|
||||
protected TerrainTemplatePreviewWidget(TerrainTemplatePreviewWidget other)
|
||||
@@ -56,6 +61,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
worldRenderer = other.worldRenderer;
|
||||
tileset = other.worldRenderer.World.Map.Rules.TileSet;
|
||||
terrainRenderer = other.terrainRenderer;
|
||||
Template = other.Template;
|
||||
GetScale = other.GetScale;
|
||||
}
|
||||
@@ -84,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
if (!tileset.TryGetTileInfo(tile, out var tileInfo))
|
||||
continue;
|
||||
|
||||
var sprite = worldRenderer.Theater.TileSprite(tile, 0);
|
||||
var sprite = terrainRenderer.TileSprite(tile, 0);
|
||||
var size = new float2(sprite.Size.X * scale, sprite.Size.Y * scale);
|
||||
|
||||
var u = gridType == MapGridType.Rectangular ? x : (x - y) / 2f;
|
||||
|
||||
@@ -18,7 +18,7 @@ using OpenRA.Traits;
|
||||
namespace OpenRA.Mods.D2k.Traits
|
||||
{
|
||||
[Desc("Attach this to the world actor. Required for LaysTerrain to work.")]
|
||||
public class BuildableTerrainLayerInfo : TraitInfo
|
||||
public class BuildableTerrainLayerInfo : TraitInfo, Requires<ITiledTerrainRendererInfo>
|
||||
{
|
||||
[Desc("Palette to render the layer sprites in.")]
|
||||
public readonly string Palette = TileSet.TerrainPaletteInternalName;
|
||||
@@ -33,11 +33,11 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
{
|
||||
readonly BuildableTerrainLayerInfo info;
|
||||
readonly Dictionary<CPos, TerrainTile?> dirty = new Dictionary<CPos, TerrainTile?>();
|
||||
readonly ITiledTerrainRenderer terrainRenderer;
|
||||
readonly World world;
|
||||
readonly CellLayer<int> strength;
|
||||
|
||||
TerrainSpriteLayer render;
|
||||
Theater theater;
|
||||
bool disposed;
|
||||
|
||||
public BuildableTerrainLayer(Actor self, BuildableTerrainLayerInfo info)
|
||||
@@ -45,12 +45,12 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
this.info = info;
|
||||
world = self.World;
|
||||
strength = new CellLayer<int>(world.Map);
|
||||
terrainRenderer = self.Trait<ITiledTerrainRenderer>();
|
||||
}
|
||||
|
||||
public void WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
theater = wr.Theater;
|
||||
render = new TerrainSpriteLayer(w, wr, theater.Sheet, BlendMode.Alpha, wr.Palette(info.Palette), wr.World.Type != WorldType.Editor);
|
||||
render = new TerrainSpriteLayer(w, wr, terrainRenderer.Sheet, BlendMode.Alpha, wr.Palette(info.Palette), wr.World.Type != WorldType.Editor);
|
||||
}
|
||||
|
||||
public void AddTile(CPos cell, TerrainTile tile)
|
||||
@@ -98,7 +98,7 @@ namespace OpenRA.Mods.D2k.Traits
|
||||
if (tile.HasValue)
|
||||
{
|
||||
// Terrain tiles define their origin at the topleft
|
||||
var s = theater.TileSprite(tile.Value);
|
||||
var s = terrainRenderer.TileSprite(tile.Value);
|
||||
var ss = new Sprite(s.Sheet, s.Bounds, s.ZRamp, float2.Zero, s.Channel, s.BlendMode);
|
||||
render.Update(kv.Key, ss, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user