public void CreateMiniMap(GUIComponent parent, IEnumerable <Entity> pointsOfInterest = null, bool ignoreOutpost = false) { Rectangle worldBorders = GetDockedBorders(); worldBorders.Location += WorldPosition.ToPoint(); //create a container that has the same "aspect ratio" as the sub float aspectRatio = worldBorders.Width / (float)worldBorders.Height; float parentAspectRatio = parent.Rect.Width / (float)parent.Rect.Height; float scale = 0.9f; GUIFrame hullContainer = new GUIFrame(new RectTransform( (parentAspectRatio > aspectRatio ? new Vector2(aspectRatio / parentAspectRatio, 1.0f) : new Vector2(1.0f, parentAspectRatio / aspectRatio)) * scale, parent.RectTransform, Anchor.Center), style: null) { UserData = "hullcontainer" }; var connectedSubs = GetConnectedSubs(); HashSet <Hull> hullList = Hull.hullList.Where(hull => hull.Submarine == this || connectedSubs.Contains(hull.Submarine)).Where(hull => !ignoreOutpost || IsEntityFoundOnThisSub(hull, true)).ToHashSet(); Dictionary <Hull, HashSet <Hull> > combinedHulls = new Dictionary <Hull, HashSet <Hull> >(); foreach (Hull hull in hullList) { if (combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull))) { continue; } List <Hull> linkedHulls = new List <Hull>(); MiniMap.GetLinkedHulls(hull, linkedHulls); linkedHulls.Remove(hull); foreach (Hull linkedHull in linkedHulls) { if (!combinedHulls.ContainsKey(hull)) { combinedHulls.Add(hull, new HashSet <Hull>()); } combinedHulls[hull].Add(linkedHull); } } foreach (Hull hull in hullList) { Vector2 relativeHullPos = new Vector2( (hull.WorldRect.X - worldBorders.X) / (float)worldBorders.Width, (worldBorders.Y - hull.WorldRect.Y) / (float)worldBorders.Height); Vector2 relativeHullSize = new Vector2(hull.Rect.Width / (float)worldBorders.Width, hull.Rect.Height / (float)worldBorders.Height); bool hideHull = combinedHulls.ContainsKey(hull) || combinedHulls.Values.Any(hh => hh.Contains(hull)); if (hideHull) { continue; } Color color = Color.DarkCyan * 0.8f; var hullFrame = new GUIFrame(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, style: "MiniMapRoom", color: color) { UserData = hull }; new GUIFrame(new RectTransform(Vector2.One, hullFrame.RectTransform), style: "ScanLines", color: color); } foreach (var(mainHull, linkedHulls) in combinedHulls) { MiniMapHullData data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders); Vector2 relativeHullPos = new Vector2( (data.Bounds.X - worldBorders.X) / worldBorders.Width, (worldBorders.Y - data.Bounds.Y) / worldBorders.Height); Vector2 relativeHullSize = new Vector2(data.Bounds.Width / worldBorders.Width, data.Bounds.Height / worldBorders.Height); Color color = Color.DarkCyan * 0.8f; float highestY = 0f, highestX = 0f; foreach (var(r, _) in data.RectDatas) { float y = r.Y - -r.Height, x = r.X; if (y > highestY) { highestY = y; } if (x > highestX) { highestX = x; } } HashSet <GUIFrame> frames = new HashSet <GUIFrame>(); foreach (var(snappredRect, hull) in data.RectDatas) { RectangleF rect = snappredRect; rect.Height = -rect.Height; rect.Y -= rect.Height; var(parentW, parentH) = hullContainer.Rect.Size.ToVector2(); Vector2 size = new Vector2(rect.Width / parentW, rect.Height / parentH); // TODO this won't be required if we some day switch RectTransform to use RectangleF Vector2 pos = new Vector2(rect.X / parentW, rect.Y / parentH); GUIFrame hullFrame = new GUIFrame(new RectTransform(size, hullContainer.RectTransform) { RelativeOffset = pos }, style: "ScanLinesSeamless", color: color) { UserData = hull, UVOffset = new Vector2(highestX - rect.X, highestY - rect.Y) }; frames.Add(hullFrame); } new GUICustomComponent(new RectTransform(relativeHullSize, hullContainer.RectTransform) { RelativeOffset = relativeHullPos }, (spriteBatch, component) => { foreach (List <Vector2> list in data.Polygon) { spriteBatch.DrawPolygonInner(hullContainer.Rect.Location.ToVector2(), list, component.Color, 2f); } }, (deltaTime, component) => { if (component.Parent.Rect.Size != data.ParentSize) { data = ConstructLinkedHulls(mainHull, linkedHulls, hullContainer, worldBorders); } }) { UserData = frames, Color = color, CanBeFocused = false }; } if (pointsOfInterest != null) { foreach (Entity entity in pointsOfInterest) { Vector2 relativePos = new Vector2( (entity.WorldPosition.X - worldBorders.X) / worldBorders.Width, (worldBorders.Y - entity.WorldPosition.Y) / worldBorders.Height); new GUIFrame(new RectTransform(new Point(1, 1), hullContainer.RectTransform) { RelativeOffset = relativePos }, style: null) { CanBeFocused = false, UserData = entity }; } } }