diff --git a/OpenRA.Mods.RA/Buildings/BibLayer.cs b/OpenRA.Mods.RA/Buildings/BibLayer.cs index 121a2aecba..ce4711c1ea 100755 --- a/OpenRA.Mods.RA/Buildings/BibLayer.cs +++ b/OpenRA.Mods.RA/Buildings/BibLayer.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using OpenRA.FileFormats; using OpenRA.Graphics; @@ -21,14 +22,23 @@ namespace OpenRA.Mods.RA.Buildings { public readonly string[] BibTypes = { "bib3", "bib2", "bib1" }; public readonly int[] BibWidths = { 2, 3, 4 }; + public readonly bool FrozenUnderFog = false; public object Create(ActorInitializer init) { return new BibLayer(init.self, this); } } - class BibLayer : IRenderOverlay, IWorldLoaded + struct CachedBib + { + public Dictionary> Tiles; + public IEnumerable Footprint; + public bool Visible; + } + + class BibLayer : IRenderOverlay, IWorldLoaded, ITickRender { World world; BibLayerInfo info; - Dictionary> tiles; + Dictionary visible; + Dictionary dirty; Sprite[][] bibSprites; public BibLayer(Actor self, BibLayerInfo info) @@ -43,7 +53,8 @@ namespace OpenRA.Mods.RA.Buildings public void WorldLoaded(World w) { world = w; - tiles = new Dictionary>(); + visible = new Dictionary(); + dirty = new Dictionary(); } public void DoBib(Actor b, bool isAdd) @@ -55,40 +66,69 @@ namespace OpenRA.Mods.RA.Buildings var size = buildingInfo.Dimensions.X; var bibOffset = buildingInfo.Dimensions.Y - 1; - int bib = Array.IndexOf(info.BibWidths, size); + var bib = Array.IndexOf(info.BibWidths, size); if (bib < 0) { Log.Write("debug", "Cannot bib {0}-wide building {1}", size, b.Info.Name); return; } + dirty[b] = new CachedBib() + { + Footprint = FootprintUtils.Tiles(b), + Tiles = new Dictionary>(), + Visible = isAdd + }; + for (var i = 0; i < 2 * size; i++) { - var p = b.Location + new CVec(i % size, i / size + bibOffset); - if (isAdd) - tiles[p] = new TileReference((byte)(bib + 1), (byte)i); - else - tiles.Remove(p); + var cell = b.Location + new CVec(i % size, i / size + bibOffset); + var tile = new TileReference((byte)(bib + 1), (byte) i); + dirty[b].Tiles.Add(cell, tile); } } + public void TickRender(WorldRenderer wr, Actor self) + { + var remove = new List(); + foreach (var kv in dirty) + { + if (!info.FrozenUnderFog || kv.Value.Footprint.Any(c => !self.World.FogObscures(c))) + { + if (kv.Value.Visible) + visible[kv.Key] = kv.Value; + else + visible.Remove(kv.Key); + + remove.Add(kv.Key); + } + } + + foreach (var r in remove) + dirty.Remove(r); + } + public void Render(WorldRenderer wr) { var pal = wr.Palette("terrain"); var cliprect = Game.viewport.WorldBounds(world); - foreach (var kv in tiles) + foreach (var bib in visible.Values) { - if (!cliprect.Contains(kv.Key.X, kv.Key.Y)) - continue; - if (world.ShroudObscures(kv.Key)) - continue; + foreach (var kv in bib.Tiles) + { + if (!cliprect.Contains(kv.Key.X, kv.Key.Y)) + continue; + if (world.ShroudObscures(kv.Key)) + continue; - bibSprites[kv.Value.type - 1][kv.Value.index].DrawAt(kv.Key.ToPPos().ToFloat2(), pal); + var tile = bibSprites[kv.Value.type - 1][kv.Value.index]; + tile.DrawAt(wr.ScreenPxPosition(kv.Key.CenterPosition) - 0.5f * tile.size, pal); + } } } } - public class BibInfo : TraitInfo { } + public class BibInfo : TraitInfo, Requires { } public class Bib { } } diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml index 639a37d593..0241c1bd2c 100644 --- a/mods/d2k/rules/system.yaml +++ b/mods/d2k/rules/system.yaml @@ -354,6 +354,7 @@ World: BibLayer: BibTypes: bib3x, bib2x BibWidths: 3, 2 + FrozenUnderFog: true DomainIndex: ResourceLayer: ResourceClaimLayer: