private static void DrawWorld(RenderContext ctx, FontCache styleRes, World world, WorldLayer layer) { bool isCapital = world.IsCapital; bool isHiPop = world.Population >= 1e9; bool renderName = ctx.styles.worldDetails.HasFlag(WorldDetails.AllNames) || (ctx.styles.worldDetails.HasFlag(WorldDetails.KeyNames) && (isCapital || isHiPop)); bool renderUWP = ctx.styles.worldDetails.HasFlag(WorldDetails.Uwp); using (RenderUtil.SaveState(ctx.graphics)) { XPen pen = new XPen(XColor.Empty); XSolidBrush solidBrush = new XSolidBrush(); ctx.graphics.SmoothingMode = XSmoothingMode.AntiAlias; // Center on the parsec PointF center = Astrometrics.HexToCenter(world.Coordinates); XMatrix matrix = new XMatrix(); matrix.TranslatePrepend(center.X, center.Y); matrix.ScalePrepend(ctx.styles.hexContentScale / Astrometrics.ParsecScaleX, ctx.styles.hexContentScale / Astrometrics.ParsecScaleY); ctx.graphics.MultiplyTransform(matrix, XMatrixOrder.Prepend); if (!ctx.styles.useWorldImages) { if (layer == WorldLayer.Background) { #region Zone if (ctx.styles.worldDetails.HasFlag(WorldDetails.Zone)) { if (world.IsAmber || world.IsRed || world.IsBlue) { PenInfo pi = world.IsAmber ? ctx.styles.amberZone.pen : world.IsRed ? ctx.styles.redZone.pen : ctx.styles.blueZone.pen; pi.Apply(ref pen); if (renderName && ctx.styles.fillMicroBorders) { using (RenderUtil.SaveState(ctx.graphics)) { ctx.graphics.IntersectClip(new RectangleF(-.5f, -.5f, 1f, renderUWP ? 0.65f : 0.75f)); ctx.graphics.DrawEllipse(pen, -0.4f, -0.4f, 0.8f, 0.8f); } } else { ctx.graphics.DrawEllipse(pen, -0.4f, -0.4f, 0.8f, 0.8f); } } } #endregion #region Hex if (ctx.styles.worldDetails.HasFlag(WorldDetails.Hex)) { int coords; switch (ctx.styles.hexCoordinateStyle) { default: case Stylesheet.HexCoordinateStyle.Sector: coords = world.Hex; break; case Stylesheet.HexCoordinateStyle.Subsector: coords = world.SubsectorHex; break; } String hex = coords.ToString("0000", CultureInfo.InvariantCulture); XSize size = ctx.graphics.MeasureString(hex, ctx.styles.hexNumber.Font); solidBrush.Color = ctx.styles.hexNumber.textColor; ctx.graphics.DrawString(hex, ctx.styles.hexNumber.Font, solidBrush, 0.0f, -0.5f, RenderUtil.StringFormatTopCenter); } #endregion } if (layer == WorldLayer.Foreground) { #region Disc if (ctx.styles.worldDetails.HasFlag(WorldDetails.Type)) { // Blank out world area, so routes are shown correctly if (!ctx.styles.fillMicroBorders) { solidBrush.Color = ctx.styles.backgroundColor; ctx.graphics.DrawEllipse(solidBrush, -0.15f, -0.15f, 0.3f, 0.3f); } if (world.Size <= 0) { #region Asteroid-Belt if (ctx.styles.worldDetails.HasFlag(WorldDetails.Asteroids)) { // Basic pattern, with probability varying per position: // o o o // o o o o // o o o int[] lpx = { -2, 0, 2, -3, -1, 1, 3, -2, 0, 2 }; int[] lpy = { -2, -2, -2, 0, 0, 0, 0, 2, 2, 2 }; float[] lpr = { 0.5f, 0.9f, 0.5f, 0.6f, 0.9f, 0.9f, 0.6f, 0.5f, 0.9f, 0.5f }; solidBrush.Color = ctx.styles.worlds.textColor; // Random generator is seeded with world location so it is always the same Random rand = new Random(world.Coordinates.X ^ world.Coordinates.Y); for (int i = 0; i < lpx.Length; ++i) { if (rand.NextDouble() < lpr[i]) { float px = lpx[i] * 0.035f; float py = lpy[i] * 0.035f; float w = 0.04f + (float)rand.NextDouble() * 0.03f; float h = 0.04f + (float)rand.NextDouble() * 0.03f; // If necessary, add jitter here float dx = 0, dy = 0; ctx.graphics.DrawEllipse(solidBrush, px + dx - w / 2, py + dy - h / 2, w, h); } } } else { // Just a glyph solidBrush.Color = ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, Glyph.DiamondX, styleRes, solidBrush, 0.0f, 0.0f); } #endregion } else { XColor penColor, brushColor; ctx.styles.WorldColors(world, out penColor, out brushColor); if (!brushColor.IsEmpty) { solidBrush.Color = brushColor; ctx.graphics.DrawEllipse(solidBrush, -0.1f, -0.1f, 0.2f, 0.2f); } if (!penColor.IsEmpty) { ctx.styles.worldWater.pen.Apply(ref pen); pen.Color = penColor; ctx.graphics.DrawEllipse(pen, -0.1f, -0.1f, 0.2f, 0.2f); } } } else { // Dotmap solidBrush.Color = ctx.styles.worlds.textColor; ctx.graphics.DrawEllipse(solidBrush, -0.2f, -0.2f, 0.4f, 0.4f); } #endregion #region GasGiant if (ctx.styles.worldDetails.HasFlag(WorldDetails.GasGiant)) { if (world.GasGiants > 0) { solidBrush.Color = ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, Glyph.Circle, styleRes, solidBrush, ctx.styles.GasGiantPosition.X, ctx.styles.GasGiantPosition.Y); } } #endregion #region Name if (renderName) { string name = world.Name; if (isHiPop) name = name.ToUpperInvariant(); Color textColor = isCapital ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; if (ctx.styles.worlds.textStyle.Uppercase) name = name.ToUpper(); DrawWorldLabel(ctx, ctx.styles.worlds.textBackgroundStyle, solidBrush, textColor, ctx.styles.worlds.textStyle.Translation, ctx.styles.worlds.Font, name); } #endregion #region Starport if (ctx.styles.worldDetails.HasFlag(WorldDetails.Starport)) { string starport = world.Starport.ToString(); DrawWorldLabel(ctx, ctx.styles.worlds.textBackgroundStyle, solidBrush, ctx.styles.worlds.textColor, ctx.styles.StarportPosition, styleRes.StarportFont, starport); } #endregion #region UWP if (renderUWP) { string uwp = world.UWP; solidBrush.Color = ctx.styles.worlds.textColor; ctx.graphics.DrawString(uwp, ctx.styles.hexNumber.Font, solidBrush, ctx.styles.StarportPosition.X, -ctx.styles.StarportPosition.Y, RenderUtil.StringFormatCentered); } #endregion #region Allegiance // TODO: Mask off background for allegiance if (ctx.styles.worldDetails.HasFlag(WorldDetails.Allegiance)) { if (!world.HasDefaultAllegiance()) { string alleg = world.Allegiance; solidBrush.Color = ctx.styles.worlds.textColor; if (ctx.styles.lowerCaseAllegiance) alleg = alleg.ToLowerInvariant(); ctx.graphics.DrawString(alleg, ctx.styles.worlds.SmallFont, solidBrush, ctx.styles.AllegiancePosition.X, ctx.styles.AllegiancePosition.Y, RenderUtil.StringFormatCentered); } } #endregion #region Bases // TODO: Mask off background for glyphs if (ctx.styles.worldDetails.HasFlag(WorldDetails.Bases)) { int num_bases = world.Bases.Length; // Base 1 bool bottomUsed = false; if (num_bases > 0) { Glyph glyph = Glyph.FromBaseCode(world.BaseAllegiance, world.Bases[0]); if (glyph.Printable) { PointF pt = ctx.styles.BaseTopPosition; if (glyph.Bias == Glyph.GlyphBias.Bottom) { pt = ctx.styles.BaseBottomPosition; bottomUsed = true; } solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, pt.X, pt.Y); } } // Base 2 if (num_bases > 1) { Glyph glyph = Glyph.FromBaseCode(world.Allegiance, world.Bases[1]); if (glyph.Printable) { PointF pt = bottomUsed ? ctx.styles.BaseTopPosition : ctx.styles.BaseBottomPosition; solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, pt.X, pt.Y); } } // Research Stations string rs; if ((rs = world.ResearchStation) != null) { Glyph glyph = Glyph.FromResearchCode(rs); solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, ctx.styles.BaseMiddlePosition.Y); } else if (world.IsReserve) { Glyph glyph = Glyph.Reserve; solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0); } else if (world.IsPenalColony) { Glyph glyph = Glyph.Prison; solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0); } else if (world.IsPrisonExileCamp) { Glyph glyph = Glyph.ExileCamp; solidBrush.Color = glyph.IsHighlighted ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; RenderUtil.DrawGlyph(ctx.graphics, glyph, styleRes, solidBrush, ctx.styles.BaseMiddlePosition.X, 0); } } #endregion } } else { float imageRadius = ((world.Size <= 0) ? 0.6f : (0.3f * (world.Size / 5.0f + 0.2f))) / 2; float decorationRadius = imageRadius; if (layer == WorldLayer.Background) { #region Disc if (ctx.styles.worldDetails.HasFlag(WorldDetails.Type)) { if (world.Size <= 0) { const float scaleX = 1.5f; const float scaleY = 1.0f; XImage img = s_worldImages["Belt"]; lock (img) { ctx.graphics.DrawImage(img, -imageRadius * scaleX, -imageRadius * scaleY, imageRadius * 2 * scaleX, imageRadius * 2 * scaleY); } } else { XImage img; switch (world.Hydrographics) { default: case 0x0: img = s_worldImages["Hyd0"]; break; case 0x1: img = s_worldImages["Hyd1"]; break; case 0x2: img = s_worldImages["Hyd2"]; break; case 0x3: img = s_worldImages["Hyd3"]; break; case 0x4: img = s_worldImages["Hyd4"]; break; case 0x5: img = s_worldImages["Hyd5"]; break; case 0x6: img = s_worldImages["Hyd6"]; break; case 0x7: img = s_worldImages["Hyd7"]; break; case 0x8: img = s_worldImages["Hyd8"]; break; case 0x9: img = s_worldImages["Hyd9"]; break; case 0xA: img = s_worldImages["HydA"]; break; } if (img != null) { lock (img) { ctx.graphics.DrawImage(img, -imageRadius, -imageRadius, imageRadius * 2, imageRadius * 2); } } } } else { // Dotmap solidBrush.Color = ctx.styles.worlds.textColor; ctx.graphics.DrawEllipse(solidBrush, -0.2f, -0.2f, 0.4f, 0.4f); } #endregion } if (layer == WorldLayer.Foreground) { #region Zone if (ctx.styles.worldDetails.HasFlag(WorldDetails.Zone)) { if (world.IsAmber || world.IsRed || world.IsBlue) { PenInfo pi = world.IsAmber ? ctx.styles.amberZone.pen : world.IsRed ? ctx.styles.redZone.pen : ctx.styles.blueZone.pen; pi.Apply(ref pen); // TODO: Try and accomplish this using dash pattern decorationRadius += 0.1f; ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 5, 80); ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 95, 80); ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 185, 80); ctx.graphics.DrawArc(pen, -decorationRadius, -decorationRadius, decorationRadius * 2, decorationRadius * 2, 275, 80); } } #endregion #region GasGiant if (ctx.styles.worldDetails.HasFlag(WorldDetails.GasGiant)) { if (world.GasGiants > 0) { decorationRadius += 0.1f; const float symbolRadius = 0.05f; solidBrush.Color = ctx.styles.worlds.textHighlightColor; ; ctx.graphics.DrawEllipse(solidBrush, decorationRadius - symbolRadius, 0.0f - symbolRadius, symbolRadius * 2, symbolRadius * 2); } } #endregion #region UWP if (renderUWP) { string uwp = world.UWP; solidBrush.Color = ctx.styles.worlds.textColor; using (RenderUtil.SaveState(ctx.graphics)) { XMatrix uwpMatrix = new XMatrix(); uwpMatrix.TranslatePrepend(decorationRadius, 0.0f); uwpMatrix.ScalePrepend(ctx.styles.worlds.textStyle.Scale.Width, ctx.styles.worlds.textStyle.Scale.Height); uwpMatrix.Multiply(uwpMatrix, XMatrixOrder.Prepend); ctx.graphics.DrawString(uwp, ctx.styles.hexNumber.Font, solidBrush, ctx.styles.StarportPosition.X, -ctx.styles.StarportPosition.Y, RenderUtil.StringFormatCenterLeft); } } #endregion #region Name if (renderName) { string name = world.Name; if (isHiPop) name = name.ToUpperInvariant(); using (RenderUtil.SaveState(ctx.graphics)) { Color textColor = isCapital ? ctx.styles.worlds.textHighlightColor : ctx.styles.worlds.textColor; if (ctx.styles.worlds.textStyle.Uppercase) name = name.ToUpper(); decorationRadius += 0.1f; XMatrix imageMatrix = new XMatrix(); imageMatrix.TranslatePrepend(decorationRadius, 0.0f); imageMatrix.ScalePrepend(ctx.styles.worlds.textStyle.Scale.Width, ctx.styles.worlds.textStyle.Scale.Height); imageMatrix.TranslatePrepend(ctx.graphics.MeasureString(name, ctx.styles.worlds.Font).Width / 2, 0.0f); // Left align ctx.graphics.MultiplyTransform(imageMatrix, XMatrixOrder.Prepend); DrawWorldLabel(ctx, ctx.styles.worlds.textBackgroundStyle, solidBrush, textColor, ctx.styles.worlds.textStyle.Translation, ctx.styles.worlds.Font, name); } } #endregion } } } }