diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs index 06cd5ceef4..bb4d32e01c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/SupportPowerTooltipLogic.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Drawing; using OpenRA.Mods.Common.Traits; using OpenRA.Widgets; @@ -18,70 +19,75 @@ 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, Player player, SupportPowersWidget palette, World world) { - widget.IsVisible = () => palette.TooltipIcon != null; + widget.IsVisible = () => palette.TooltipIcon != null && palette.TooltipIcon.Power.Info != null; var nameLabel = widget.Get("NAME"); var hotkeyLabel = widget.Get("HOTKEY"); var timeLabel = widget.Get("TIME"); var descLabel = widget.Get("DESC"); var nameFont = Game.Renderer.Fonts[nameLabel.Font]; + var hotkeyFont = Game.Renderer.Fonts[hotkeyLabel.Font]; var timeFont = Game.Renderer.Fonts[timeLabel.Font]; var descFont = Game.Renderer.Fonts[descLabel.Font]; - var name = ""; - var time = ""; - var desc = ""; var baseHeight = widget.Bounds.Height; var timeOffset = timeLabel.Bounds.X; + var pm = player.PlayerActor.Trait(); SupportPowerInstance lastPower = null; + Hotkey lastHotkey = Hotkey.Invalid; + var lastRemainingSeconds = 0; + tooltipContainer.BeforeRender = () => { var icon = palette.TooltipIcon; - if (icon == null) return; var sp = icon.Power; - if (sp.Info == null) - return; // no instances actually exist (race with destroy) + // HACK: This abuses knowledge of the internals of WidgetUtils.FormatTime + // to efficiently work when the label is going to change, requiring a panel relayout + var remainingSeconds = (int)Math.Ceiling(sp.RemainingTime * world.Timestep / 1000f); + + var hotkey = icon.Hotkey != null ? icon.Hotkey.GetValue() : Hotkey.Invalid; + if (sp == lastPower && hotkey == lastHotkey && lastRemainingSeconds == remainingSeconds) + return; + + nameLabel.Text = sp.Info.Description; + var nameSize = nameFont.Measure(nameLabel.Text); + + descLabel.Text = sp.Info.LongDesc.Replace("\\n", "\n"); + var descSize = descFont.Measure(descLabel.Text); var remaining = WidgetUtils.FormatTime(sp.RemainingTime, world.Timestep); var total = WidgetUtils.FormatTime(sp.Info.ChargeTime * 25, world.Timestep); - time = "{0} / {1}".F(remaining, total); - - if (sp == lastPower) - return; - - name = sp.Info.Description; - desc = sp.Info.LongDesc.Replace("\\n", "\n"); + timeLabel.Text = "{0} / {1}".F(remaining, total); + var timeSize = timeFont.Measure(timeLabel.Text); var hotkeyWidth = 0; - var hotkey = icon.Hotkey != null ? icon.Hotkey.GetValue() : Hotkey.Invalid; hotkeyLabel.Visible = hotkey.IsValid(); - if (hotkeyLabel.Visible) { var hotkeyText = "({0})".F(hotkey.DisplayString()); - hotkeyWidth = nameFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; + hotkeyWidth = hotkeyFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; - hotkeyLabel.Bounds.X = nameFont.Measure(name).X + 2 * nameLabel.Bounds.X; + hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } - var timeWidth = timeFont.Measure(time).X; - var topWidth = nameFont.Measure(name).X + hotkeyWidth + timeWidth + timeOffset; - var descSize = descFont.Measure(desc); + var timeWidth = timeSize.X; + var topWidth = nameSize.X + hotkeyWidth + timeWidth + timeOffset; widget.Bounds.Width = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X); widget.Bounds.Height = baseHeight + descSize.Y; timeLabel.Bounds.X = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth; + lastPower = sp; + lastHotkey = hotkey; + lastRemainingSeconds = remainingSeconds; }; - nameLabel.GetText = () => name; - timeLabel.GetText = () => time; - descLabel.GetText = () => desc; + timeLabel.GetColor = () => pm.PowerState != PowerState.Normal ? Color.Red : Color.White; } } -} \ No newline at end of file +} diff --git a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs index 1d649ec1fb..53f071efe9 100644 --- a/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs +++ b/OpenRA.Mods.Common/Widgets/SupportPowersWidget.cs @@ -228,7 +228,7 @@ namespace OpenRA.Mods.Common.Widgets return; tooltipContainer.Value.SetTooltip(TooltipTemplate, - new WidgetArgs() { { "world", worldRenderer.World }, { "palette", this } }); + new WidgetArgs() { { "world", worldRenderer.World }, { "player", spm.Self.Owner }, { "palette", this } }); } public override void MouseExited()