Files
OpenRA/OpenRA.Mods.Common/Widgets/Logic/Ingame/ProductionTooltipLogic.cs
Alexis Hunt 157a783df5 Correct UI for unslowed queues in low power.
Because of the way the tick logic works, 0 (or any negative number) for
LowPowerSlowdown is functionally equivalent to 1. But LowPowerSlowdown
is multipled by a time in several cases, so while 1 will produce the
correct result (no slowdown), 0 will say that the time remaining is
00:00. Forbid nonpositive values, and correct the d2k mod which was
using 0.

Additionally, in the production tooltip, the colour should display as
white even in low power if there is no slowdown.
2018-01-13 16:13:59 +01:00

147 lines
5.7 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2017 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.Drawing;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Support;
using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
public class ProductionTooltipLogic : ChromeLogic
{
[ObjectCreator.UseCtor]
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, Func<ProductionIcon> getTooltipIcon)
{
var world = player.World;
var mapRules = world.Map.Rules;
var pm = player.PlayerActor.Trait<PowerManager>();
var pr = player.PlayerActor.Trait<PlayerResources>();
widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Actor != null;
var nameLabel = widget.Get<LabelWidget>("NAME");
var hotkeyLabel = widget.Get<LabelWidget>("HOTKEY");
var requiresLabel = widget.Get<LabelWidget>("REQUIRES");
var powerLabel = widget.Get<LabelWidget>("POWER");
var powerIcon = widget.Get<ImageWidget>("POWER_ICON");
var timeLabel = widget.Get<LabelWidget>("TIME");
var timeIcon = widget.Get<ImageWidget>("TIME_ICON");
var costLabel = widget.Get<LabelWidget>("COST");
var costIcon = widget.Get<ImageWidget>("COST_ICON");
var descLabel = widget.Get<LabelWidget>("DESC");
var iconMargin = timeIcon.Bounds.X;
var font = Game.Renderer.Fonts[nameLabel.Font];
var descFont = Game.Renderer.Fonts[descLabel.Font];
var requiresFont = Game.Renderer.Fonts[requiresLabel.Font];
var formatBuildTime = new CachedTransform<int, string>(time => WidgetUtils.FormatTime(time, world.Timestep));
var requiresFormat = requiresLabel.Text;
ActorInfo lastActor = null;
Hotkey lastHotkey = Hotkey.Invalid;
var lastPowerState = pm.PowerState;
tooltipContainer.BeforeRender = () =>
{
var tooltipIcon = getTooltipIcon();
if (tooltipIcon == null)
return;
var actor = tooltipIcon.Actor;
if (actor == null)
return;
var hotkey = tooltipIcon.Hotkey != null ? tooltipIcon.Hotkey.GetValue() : Hotkey.Invalid;
if (actor == lastActor && hotkey == lastHotkey && pm.PowerState == lastPowerState)
return;
var tooltip = actor.TraitInfos<TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault);
var name = tooltip != null ? tooltip.Name : actor.Name;
var buildable = actor.TraitInfo<BuildableInfo>();
var cost = actor.TraitInfo<ValuedInfo>().Cost;
nameLabel.Text = name;
var nameSize = font.Measure(name);
var hotkeyWidth = 0;
hotkeyLabel.Visible = hotkey.IsValid();
if (hotkeyLabel.Visible)
{
var hotkeyText = "({0})".F(hotkey.DisplayString());
hotkeyWidth = font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X;
hotkeyLabel.Text = hotkeyText;
hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X;
}
var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)).Where(s => !s.StartsWith("~", StringComparison.Ordinal));
requiresLabel.Text = prereqs.Any() ? requiresFormat.F(prereqs.JoinWith(", ")) : "";
var requiresSize = requiresFont.Measure(requiresLabel.Text);
var power = actor.TraitInfos<PowerInfo>().Where(i => i.EnabledByDefault).Sum(i => i.Amount);
powerLabel.Text = power.ToString();
powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0)
? Color.White : Color.Red;
powerLabel.Visible = power != 0;
powerIcon.Visible = power != 0;
var powerSize = font.Measure(powerLabel.Text);
var buildTime = tooltipIcon.ProductionQueue == null ? 0 : tooltipIcon.ProductionQueue.GetBuildTime(actor, buildable);
var timeMultiplier = pm.PowerState != PowerState.Normal ? tooltipIcon.ProductionQueue.Info.LowPowerSlowdown : 1;
timeLabel.Text = formatBuildTime.Update(buildTime * timeMultiplier);
timeLabel.TextColor = (pm.PowerState != PowerState.Normal && tooltipIcon.ProductionQueue.Info.LowPowerSlowdown > 1) ? Color.Red : Color.White;
var timeSize = font.Measure(timeLabel.Text);
costLabel.Text = cost.ToString();
costLabel.GetColor = () => pr.Cash + pr.Resources >= cost ? Color.White : Color.Red;
var costSize = font.Measure(costLabel.Text);
descLabel.Text = buildable.Description.Replace("\\n", "\n");
var descSize = descFont.Measure(descLabel.Text);
var leftWidth = new[] { nameSize.X + hotkeyWidth, requiresSize.X, descSize.X }.Aggregate(Math.Max);
var rightWidth = new[] { powerSize.X, timeSize.X, costSize.X }.Aggregate(Math.Max);
timeIcon.Bounds.X = powerIcon.Bounds.X = costIcon.Bounds.X = leftWidth + 2 * nameLabel.Bounds.X;
timeLabel.Bounds.X = powerLabel.Bounds.X = costLabel.Bounds.X = timeIcon.Bounds.Right + iconMargin;
widget.Bounds.Width = leftWidth + rightWidth + 3 * nameLabel.Bounds.X + timeIcon.Bounds.Width + iconMargin;
var leftHeight = nameSize.Y + requiresSize.Y + descSize.Y;
var rightHeight = powerSize.Y + timeSize.Y + costSize.Y;
widget.Bounds.Height = Math.Max(leftHeight, rightHeight) * 3 / 2 + 3 * nameLabel.Bounds.Y;
lastActor = actor;
lastHotkey = hotkey;
lastPowerState = pm.PowerState;
};
}
static string ActorName(Ruleset rules, string a)
{
ActorInfo ai;
if (rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai))
{
var actorTooltip = ai.TraitInfos<TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault);
if (actorTooltip != null)
return actorTooltip.Name;
}
return a;
}
}
}