using Godot; namespace IslaApocalypse.Tools { /// /// The offshore TAG / HEMISPHERE debug overlay (chat2/05): mainland one tint, offshore-island /// land tinted by hemisphere, the midline drawn — so the island count, /// the N/S split and the tag's correctness are all visible at one glance. /// /// ⚠ A DIAGNOSTIC, NOT A MAP. It draws the tag layer, which is DATA the shape pass set; it is /// the one artifact in the batch that shows what a downstream consumer of the tag would see. /// No hypsometry, no hillshade — three flat tints and some rings, on purpose. /// /// Presentation only: it is handed arrays and returns a PNG. It cannot change them. /// public static class TagOverlayRenderer { private static readonly Color Sea = new(0.055f, 0.110f, 0.235f); private static readonly Color Mainland = new(0.310f, 0.360f, 0.300f); private static readonly Color IslandN = new(0.250f, 0.850f, 0.950f); // cool — north private static readonly Color IslandS = new(0.980f, 0.600f, 0.200f); // warm — south private static readonly Color Untagged = new(0.950f, 0.150f, 0.800f); // ⚠ land that is neither — must never appear private static readonly Color Midline = new(0.700f, 0.720f, 0.760f); private static readonly Color Ink = new(0.941f, 0.949f, 0.961f); /// /// Per cell, land that is NOT offshore (from the offshore-OFF field, so a tag bug cannot hide /// by mis-tagging mainland). Null ⇒ derived as "land and not tagged", which is weaker. /// public static void SavePng(float[,] height, bool[,] tag, byte[,] hemi, int mapSize, float sea, int countN, int countS, string absolutePath) { var img = Image.CreateEmpty(mapSize, mapSize, false, Image.Format.Rgb8); for (int x = 0; x < mapSize; x++) { for (int y = 0; y < mapSize; y++) { Color c; bool land = height[x, y] >= sea; bool tagged = tag != null && tag[x, y]; if (!land) c = Sea; else if (!tagged) c = Mainland; else if (hemi == null) c = Untagged; else c = hemi[x, y] switch { OffshoreAnalysis.HemiNorth => IslandN, OffshoreAnalysis.HemiSouth => IslandS, _ => Untagged, }; img.SetPixel(x, y, c); } } // The hemisphere midline — the tag's convention, drawn where it bites. int mid = mapSize / 2; for (int x = 0; x < mapSize; x += 3) img.SetPixel(x, mid, Midline); // A legend that cannot be separated from the picture. int s = mapSize >= 4096 ? 4 : 3; int lh = TinyFont.Height(s) + 6; TinyFont.Draw(img, "OFFSHORE TAG OVERLAY", 12, 12, s, Ink); TinyFont.Draw(img, "GREY: MAINLAND CYAN: ISLAND N ORANGE: ISLAND S", 12, 12 + lh, s, Ink); TinyFont.Draw(img, $"ISLANDS: {countN} NORTH {countS} SOUTH - ALL ORGANIC, NONE FORCED", 12, 12 + lh * 2, s, Ink); TinyFont.Draw(img, "N ABOVE THE LINE - S BELOW - Y RUNS SOUTH", 12, 12 + lh * 3, s, Ink); Error err = img.SavePng(absolutePath); if (err != Error.Ok) GD.PrintErr($"[TagOverlayRenderer] SavePng failed ({err}) for {absolutePath}"); } } }