diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs index 453f6eecea..598c2eb846 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs @@ -19,9 +19,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class SupportPowerTooltipLogic : ChromeLogic { [ObjectCreator.UseCtor] - public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette, World world) + public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Func getTooltipIcon, World world) { - widget.IsVisible = () => palette.TooltipIcon != null && palette.TooltipIcon.Power.Info != null; + widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Power.Info != null; var nameLabel = widget.Get("NAME"); var hotkeyLabel = widget.Get("HOTKEY"); var timeLabel = widget.Get("TIME"); @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic tooltipContainer.BeforeRender = () => { - var icon = palette.TooltipIcon; + var icon = getTooltipIcon(); if (icon == null || icon.Power == null || icon.Power.Instances.Count == 0) return; @@ -86,7 +86,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic lastRemainingSeconds = remainingSeconds; }; - timeLabel.GetColor = () => palette.TooltipIcon != null && !palette.TooltipIcon.Power.Active + timeLabel.GetColor = () => getTooltipIcon() != null && !getTooltipIcon().Power.Active ? Color.Red : Color.White; } } diff --git a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs index d186bf7813..ca545530eb 100644 --- a/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs +++ b/OpenRA.Mods.Common/Widgets/ObserverSupportPowerIconsWidget.cs @@ -21,12 +21,19 @@ namespace OpenRA.Mods.Common.Widgets { public class ObserverSupportPowerIconsWidget : Widget { + public readonly string TooltipTemplate = "SUPPORT_POWER_TOOLTIP"; + public readonly string TooltipContainer; readonly Animation icon; readonly World world; readonly WorldRenderer worldRenderer; readonly Dictionary clocks; readonly int timestep; + readonly Lazy tooltipContainer; + + public Func GetTooltipIcon; + public SupportPowersWidget.SupportPowerIcon TooltipIcon { get; private set; } + public int IconWidth = 32; public int IconHeight = 24; public int IconSpacing = 1; @@ -36,6 +43,10 @@ namespace OpenRA.Mods.Common.Widgets public string ClockPalette = "chrome"; public Func GetPlayer; + readonly List supportPowerIconsIcons = new List(); + readonly List supportPowerIconsBounds = new List(); + int lastIconIdx; + [ObjectCreator.UseCtor] public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer) { @@ -48,6 +59,9 @@ namespace OpenRA.Mods.Common.Widgets timestep = world.Timestep; if (world.IsReplay) timestep = world.WorldActor.Trait().GameSpeed.Timestep; + + tooltipContainer = Exts.Lazy(() => + Ui.Root.Get(TooltipContainer)); } protected ObserverSupportPowerIconsWidget(ObserverSupportPowerIconsWidget other) @@ -67,22 +81,38 @@ namespace OpenRA.Mods.Common.Widgets ClockAnimation = other.ClockAnimation; ClockSequence = other.ClockSequence; ClockPalette = other.ClockPalette; + + TooltipIcon = other.TooltipIcon; + GetTooltipIcon = () => TooltipIcon; + + TooltipTemplate = other.TooltipTemplate; + TooltipContainer = other.TooltipContainer; + + tooltipContainer = Exts.Lazy(() => + Ui.Root.Get(TooltipContainer)); } public override void Draw() { + supportPowerIconsIcons.Clear(); + supportPowerIconsBounds.Clear(); + var player = GetPlayer(); if (player == null) return; var powers = player.PlayerActor.Trait().Powers - .Where(x => !x.Value.Disabled).Select((a, i) => new { a, i }); + .Where(x => !x.Value.Disabled).Select((a, i) => new { a, i }) + .ToList(); + foreach (var power in powers) { if (!clocks.ContainsKey(power.a.Key)) clocks.Add(power.a.Key, new Animation(world, ClockAnimation)); } + Bounds.Width = powers.Count() * (IconWidth + IconSpacing); + var iconSize = new float2(IconWidth, IconHeight); foreach (var power in powers) { @@ -92,6 +122,10 @@ namespace OpenRA.Mods.Common.Widgets icon.Play(item.Info.Icon); var location = new float2(RenderBounds.Location) + new float2(power.i * (IconWidth + IconSpacing), 0); + + supportPowerIconsIcons.Add(new SupportPowersWidget.SupportPowerIcon { Power = item }); + supportPowerIconsBounds.Add(new Rectangle((int)location.X, (int)location.Y, (int)iconSize.X, (int)iconSize.Y)); + WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer.Palette(item.Info.IconPalette), 0.5f); var clock = clocks[power.a.Key]; @@ -120,5 +154,46 @@ namespace OpenRA.Mods.Common.Widgets { return new ObserverSupportPowerIconsWidget(this); } + + public override void MouseEntered() + { + if (TooltipContainer == null) + return; + + tooltipContainer.Value.SetTooltip(TooltipTemplate, + new WidgetArgs() { { "world", worldRenderer.World }, { "player", GetPlayer() }, { "getTooltipIcon", GetTooltipIcon } }); + } + + public override void MouseExited() + { + if (TooltipContainer == null) + return; + + tooltipContainer.Value.RemoveTooltip(); + } + + public override void Tick() + { + if (lastIconIdx >= supportPowerIconsBounds.Count) + { + TooltipIcon = null; + return; + } + + if (TooltipIcon != null && supportPowerIconsBounds[lastIconIdx].Contains(Viewport.LastMousePos)) + return; + + for (var i = 0; i < supportPowerIconsBounds.Count; i++) + { + if (!supportPowerIconsBounds[i].Contains(Viewport.LastMousePos)) + continue; + + lastIconIdx = i; + TooltipIcon = supportPowerIconsIcons[i]; + return; + } + + TooltipIcon = null; + } } } diff --git a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs index 3e32e6bfa9..e66e64a5d2 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs @@ -57,6 +57,7 @@ namespace OpenRA.Mods.Common.Widgets Dictionary icons = new Dictionary(); public SupportPowerIcon TooltipIcon { get; private set; } + public Func GetTooltipIcon; Lazy tooltipContainer; HotkeyReference[] hotkeys; @@ -92,6 +93,7 @@ namespace OpenRA.Mods.Common.Widgets { this.modData = modData; this.worldRenderer = worldRenderer; + GetTooltipIcon = () => TooltipIcon; spm = world.LocalPlayer.PlayerActor.Trait(); tooltipContainer = Exts.Lazy(() => Ui.Root.Get(TooltipContainer)); @@ -239,7 +241,7 @@ namespace OpenRA.Mods.Common.Widgets return; tooltipContainer.Value.SetTooltip(TooltipTemplate, - new WidgetArgs() { { "world", worldRenderer.World }, { "player", spm.Self.Owner }, { "palette", this } }); + new WidgetArgs() { { "world", worldRenderer.World }, { "player", spm.Self.Owner }, { "getTooltipIcon", GetTooltipIcon } }); } public override void MouseExited() diff --git a/mods/cnc/chrome/ingame.yaml b/mods/cnc/chrome/ingame.yaml index 2f79871f27..0017c2650e 100644 --- a/mods/cnc/chrome/ingame.yaml +++ b/mods/cnc/chrome/ingame.yaml @@ -982,6 +982,7 @@ Container@OBSERVER_WIDGETS: Y: 0 Width: 0 Height: PARENT_BOTTOM + TooltipContainer: TOOLTIP_CONTAINER ScrollItem@COMBAT_PLAYER_TEMPLATE: X: 0 Y: 0 @@ -1155,6 +1156,7 @@ Container@PLAYER_WIDGETS: X: 1 Y: 1 TooltipContainer: TOOLTIP_CONTAINER + TooltipTemplate: SUPPORT_POWER_TOOLTIP_FACTIONSUFFIX ReadyText: Ready HoldText: On Hold HotkeyPrefix: SupportPower diff --git a/mods/cnc/chrome/tooltips.yaml b/mods/cnc/chrome/tooltips.yaml index cf85413ac1..f1c6e2ff2b 100644 --- a/mods/cnc/chrome/tooltips.yaml +++ b/mods/cnc/chrome/tooltips.yaml @@ -287,6 +287,31 @@ Background@PRODUCTION_TOOLTIP_FACTIONSUFFIX: Font: Bold Background@SUPPORT_POWER_TOOLTIP: + Logic: SupportPowerTooltipLogic + Background: panel-black + Width: 200 + Height: 25 + Children: + Label@NAME: + X: 5 + Height: 20 + Font: Bold + Label@HOTKEY: + Visible: false + Height: 20 + TextColor: FFFF00 + Font: Bold + Label@TIME: + Y: 6 + Font: TinyBold + VAlign: Top + Label@DESC: + X: 5 + Y: 20 + Font: TinyBold + VAlign: Top + +Background@SUPPORT_POWER_TOOLTIP_FACTIONSUFFIX: Logic: SupportPowerTooltipLogic, AddFactionSuffixLogic Background: panel-black Width: 200 diff --git a/mods/common/chrome/ingame-observer.yaml b/mods/common/chrome/ingame-observer.yaml index 0accdb9edd..bffd5c172e 100644 --- a/mods/common/chrome/ingame-observer.yaml +++ b/mods/common/chrome/ingame-observer.yaml @@ -879,6 +879,7 @@ Container@OBSERVER_WIDGETS: Y: 0 Width: 0 Height: PARENT_BOTTOM + TooltipContainer: TOOLTIP_CONTAINER ScrollItem@COMBAT_PLAYER_TEMPLATE: X: 0 Y: 0 diff --git a/mods/ra/chrome/ingame-observer.yaml b/mods/ra/chrome/ingame-observer.yaml index 9c2e58ba03..e3b4a04a3a 100644 --- a/mods/ra/chrome/ingame-observer.yaml +++ b/mods/ra/chrome/ingame-observer.yaml @@ -925,6 +925,7 @@ Container@OBSERVER_WIDGETS: Y: 0 Width: 0 Height: PARENT_BOTTOM + TooltipContainer: TOOLTIP_CONTAINER ScrollItem@COMBAT_PLAYER_TEMPLATE: X: 0 Y: 0 diff --git a/mods/ts/chrome/ingame-observer.yaml b/mods/ts/chrome/ingame-observer.yaml index 1d07e52397..1426c463d6 100644 --- a/mods/ts/chrome/ingame-observer.yaml +++ b/mods/ts/chrome/ingame-observer.yaml @@ -889,6 +889,7 @@ Container@OBSERVER_WIDGETS: Width: 0 Height: PARENT_BOTTOM ClockPalette: iconclock + TooltipContainer: TOOLTIP_CONTAINER ScrollItem@COMBAT_PLAYER_TEMPLATE: X: 0 Y: 0