#region Copyright & License Information /* * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Traits; using OpenRA.Primitives; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets { public class ObserverArmyIconsWidget : Widget { public Func GetPlayer; readonly World world; readonly WorldRenderer worldRenderer; public int IconWidth = 32; public int IconHeight = 24; public int IconSpacing = 1; float2 iconSize; public int MinWidth = 240; public ArmyUnit TooltipUnit { get; private set; } public Func GetTooltipUnit; public readonly string TooltipTemplate = "ARMY_TOOLTIP"; public readonly string TooltipContainer; readonly Lazy tooltipContainer; readonly List armyIcons = new List(); readonly CachedTransform stats = new CachedTransform(player => player.PlayerActor.TraitOrDefault()); int lastIconIdx; Rectangle currentIconBounds; [ObjectCreator.UseCtor] public ObserverArmyIconsWidget(World world, WorldRenderer worldRenderer) { this.world = world; this.worldRenderer = worldRenderer; GetTooltipUnit = () => TooltipUnit; tooltipContainer = Exts.Lazy(() => Ui.Root.Get(TooltipContainer)); } protected ObserverArmyIconsWidget(ObserverArmyIconsWidget other) : base(other) { GetPlayer = other.GetPlayer; world = other.world; worldRenderer = other.worldRenderer; IconWidth = other.IconWidth; IconHeight = other.IconHeight; IconSpacing = other.IconSpacing; iconSize = new float2(IconWidth, IconHeight); MinWidth = other.MinWidth; TooltipUnit = other.TooltipUnit; GetTooltipUnit = () => TooltipUnit; TooltipTemplate = other.TooltipTemplate; TooltipContainer = other.TooltipContainer; tooltipContainer = Exts.Lazy(() => Ui.Root.Get(TooltipContainer)); } public override void Draw() { armyIcons.Clear(); var player = GetPlayer(); if (player == null) return; var playerStatistics = stats.Update(player); var items = playerStatistics.Units.Values .Where(u => u.Count > 0 && u.Icon != null) .OrderBy(u => u.ProductionQueueOrder) .ThenBy(u => u.BuildPaletteOrder); Game.Renderer.EnableAntialiasingFilter(); var queueCol = 0; foreach (var unit in items) { var icon = unit.Icon; var topLeftOffset = new int2(queueCol * (IconWidth + IconSpacing), 0); var iconTopLeft = RenderOrigin + topLeftOffset; var centerPosition = iconTopLeft; WidgetUtils.DrawSHPCentered(icon.Image, centerPosition + 0.5f * iconSize, worldRenderer.Palette(unit.IconPalette), 0.5f); armyIcons.Add(new ArmyIcon { Bounds = new Rectangle(iconTopLeft.X, iconTopLeft.Y, (int)iconSize.X, (int)iconSize.Y), Unit = unit }); queueCol++; } Bounds.Width = queueCol * (IconWidth + IconSpacing); Game.Renderer.DisableAntialiasingFilter(); var bold = Game.Renderer.Fonts["TinyBold"]; foreach (var armyIcon in armyIcons) { var text = armyIcon.Unit.Count.ToString(); bold.DrawTextWithContrast(text, armyIcon.Bounds.Location + new float2(iconSize.X, 0) - new float2(bold.Measure(text).X, bold.TopOffset), Color.White, Color.Black, 1); } var parentWidth = Bounds.X + Bounds.Width; Parent.Bounds.Width = parentWidth; var gradient = Parent.Get("PLAYER_GRADIENT"); var offset = gradient.Bounds.X - Bounds.X; var gradientWidth = Math.Max(MinWidth - offset, queueCol * (IconWidth + IconSpacing)); gradient.Bounds.Width = gradientWidth; var widestChildWidth = Parent.Parent.Children.Max(x => x.Bounds.Width); Parent.Parent.Bounds.Width = Math.Max(25 + widestChildWidth, Bounds.Left + MinWidth); } public override Widget Clone() { return new ObserverArmyIconsWidget(this); } public override void MouseEntered() { if (TooltipContainer == null) return; foreach (var armyIcon in armyIcons) { if (!armyIcon.Bounds.Contains(Viewport.LastMousePos)) continue; TooltipUnit = armyIcon.Unit; break; } tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs { { "getTooltipUnit", GetTooltipUnit } }); } public override void MouseExited() { if (TooltipContainer == null) return; tooltipContainer.Value.RemoveTooltip(); } public override void Tick() { if (lastIconIdx >= armyIcons.Count) { TooltipUnit = null; return; } if (TooltipUnit != null && currentIconBounds.Contains(Viewport.LastMousePos)) return; for (var i = 0; i < armyIcons.Count; i++) { var armyIcon = armyIcons[i]; if (!armyIcon.Bounds.Contains(Viewport.LastMousePos)) continue; lastIconIdx = i; currentIconBounds = armyIcon.Bounds; TooltipUnit = armyIcon.Unit; return; } TooltipUnit = null; } class ArmyIcon { public Rectangle Bounds { get; set; } public ArmyUnit Unit { get; set; } } } }