public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette) { var pm = palette.world.LocalPlayer.PlayerActor.Trait <PowerManager>(); var pr = palette.world.LocalPlayer.PlayerActor.Trait <PlayerResources>(); widget.IsVisible = () => palette.TooltipActor != null; var nameLabel = widget.GetWidget <LabelWidget>("NAME"); var requiresLabel = widget.GetWidget <LabelWidget>("REQUIRES"); var powerLabel = widget.GetWidget <LabelWidget>("POWER"); var timeLabel = widget.GetWidget <LabelWidget>("TIME"); var costLabel = widget.GetWidget <LabelWidget>("COST"); var font = Game.Renderer.Fonts[nameLabel.Font]; var requiresFont = Game.Renderer.Fonts[requiresLabel.Font]; string lastActor = null; tooltipContainer.BeforeRender = () => { var actor = palette.TooltipActor; if (actor == null || actor == lastActor) { return; } var info = Rules.Info[actor]; var tooltip = info.Traits.Get <TooltipInfo>(); var buildable = info.Traits.Get <BuildableInfo>(); var cost = info.Traits.Get <ValuedInfo>().Cost; var bi = info.Traits.GetOrDefault <BuildingInfo>(); nameLabel.GetText = () => tooltip.Name; var prereqs = buildable.Prerequisites.Select(a => ActorName(a)); var requiresString = prereqs.Any() ? "Requires {0}".F(prereqs.JoinWith(", ")) : ""; requiresLabel.GetText = () => requiresString; var power = bi != null ? bi.Power : 0; var powerString = "P: {0}".F(power); powerLabel.GetText = () => powerString; powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0) ? Color.White : Color.Red; powerLabel.IsVisible = () => power != 0; var timeString = "T: {0}".F(WidgetUtils.FormatTime(palette.CurrentQueue.GetBuildTime(actor))); timeLabel.GetText = () => timeString; var costString = "$: {0}".F(cost); costLabel.GetText = () => costString; costLabel.GetColor = () => pr.DisplayCash + pr.DisplayOre >= cost ? Color.White : Color.Red; var leftWidth = Math.Max(font.Measure(tooltip.Name).X, requiresFont.Measure(requiresString).X); var rightWidth = new [] { font.Measure(powerString).X, font.Measure(timeString).X, font.Measure(costString).X }.Aggregate(Math.Max); timeLabel.Bounds.X = powerLabel.Bounds.X = costLabel.Bounds.X = leftWidth + 2 * nameLabel.Bounds.X; widget.Bounds.Width = leftWidth + rightWidth + 3 * nameLabel.Bounds.X; widget.Bounds.Height = power != 0 ? 65 : 45; lastActor = actor; }; }
public GameTimerLogic(Widget widget, OrderManager orderManager, World world) { var timer = widget.GetOrNull <LabelWidget>("GAME_TIMER"); if (timer != null) { timer.GetText = () => WidgetUtils.FormatTime(world.WorldTick); } var status = widget.GetOrNull <LabelWidget>("GAME_TIMER_STATUS"); if (status != null) { var startTick = Ui.LastTickTime; // Blink the status line status.IsVisible = () => (world.Paused || world.Timestep != Game.Timestep) && (Ui.LastTickTime - startTick) / 1000 % 2 == 0; status.GetText = () => { if (world.Paused || world.Timestep == 0) { return("Paused"); } if (world.Timestep == 1) { return("Max Speed"); } return("{0:F1}x Speed".F(Game.Timestep * 1f / world.Timestep)); }; } }
private void DrawSuperweapons() { var index = 0; foreach (var player in this.ingameUi.World.Players) { var powers = player.PlayerActor.TraitOrDefault <SupportPowerManager>().Powers.Where(p => p.Value.Active).OrderBy(p => p.Value.RemainingTicks); foreach (var power in powers) { var text = WidgetUtils.FormatTime(power.Value.RemainingTicks, false, this.ingameUi.World.Timestep); this.font?.DrawTextWithContrast( text, new int2( this.RenderBounds.X + 10 + index % 4 * ((this.RenderBounds.Width - 20) / 4), this.RenderBounds.Y + 25 + index / 4 * this.powerHeight ), player.Color, player.Color.GetBrightness() > .5 ? Color.Black : Color.White, 1 ); index++; } } }
void SelectReplay(string filename) { if (filename == null) { return; } try { currentReplay = new Replay(filename); currentMap = currentReplay.Map(); panel.GetWidget <LabelWidget>("DURATION").GetText = () => WidgetUtils.FormatTime(currentReplay.Duration * 3 /* todo: 3:1 ratio isnt always true. */); panel.GetWidget <MapPreviewWidget>("MAP_PREVIEW").Map = () => currentMap; panel.GetWidget <LabelWidget>("MAP_TITLE").GetText = () => currentMap != null ? currentMap.Title : "(Unknown Map)"; var players = currentReplay.LobbyInfo.Slots .Count(s => currentReplay.LobbyInfo.ClientInSlot(s.Key) != null); panel.GetWidget <LabelWidget>("PLAYERS").GetText = () => players.ToString(); } catch (Exception e) { Log.Write("debug", "Exception while parsing replay: {0}", e); currentReplay = null; currentMap = null; } }
public GameTimerLogic(Widget widget, OrderManager orderManager, World world) { var timer = widget.GetOrNull <LabelWidget>("GAME_TIMER"); var status = widget.GetOrNull <LabelWidget>("GAME_TIMER_STATUS"); var startTick = Ui.LastTickTime; Func <bool> shouldShowStatus = () => (world.Paused || world.Timestep != world.LobbyInfo.GlobalSettings.Timestep) && (Ui.LastTickTime - startTick) / 1000 % 2 == 0; Func <string> statusText = () => { if (world.Paused || world.Timestep == 0) { return("Paused"); } if (world.Timestep == 1) { return("Max Speed"); } return("{0}% Speed".F(world.LobbyInfo.GlobalSettings.Timestep * 100 / world.Timestep)); }; if (timer != null) { timer.GetText = () => { if (status == null && shouldShowStatus()) { return(statusText()); } return(WidgetUtils.FormatTime(world.WorldTick, world.Timestep)); }; } if (status != null) { // Blink the status line status.IsVisible = shouldShowStatus; status.GetText = statusText; } var percentage = widget.GetOrNull <LabelWidget>("GAME_TIMER_PERCENTAGE"); if (percentage != null) { var connection = orderManager.Connection as ReplayConnection; if (connection != null && connection.TickCount != 0) { percentage.GetText = () => "({0}%)".F(orderManager.NetFrameNumber * 100 / connection.TickCount); } else if (timer != null) { timer.Bounds.Width += percentage.Bounds.Width; } } }
public override void Tick() { texts = powers.Select(p => { var time = WidgetUtils.FormatTime(p.RemainingTime, false); var text = Format.F(p.Info.Description, time); var color = !p.Ready || Game.LocalTick % 50 < 25 ? p.Instances[0].self.Owner.Color.RGB : Color.White; return(Pair.New(text, color)); }).ToArray(); }
public override void Draw() { if (!IsVisible()) { return; } var font = Game.Renderer.Fonts["Bold"]; var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft)); font.DrawTextWithContrast(text, Position, Timer.TicksLeft <= 25 * 10 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1); }
static string GetOverlayForItem(ProductionItem item) { if (item.Paused) { return("ON HOLD"); } if (item.Done) { return("READY"); } return(WidgetUtils.FormatTime(item.RemainingTimeActual)); }
string GetOverlayForItem(ProductionItem item) { if (item.Paused) { return(HoldText); } if (item.Done) { return(ReadyText); } return(WidgetUtils.FormatTime(item.RemainingTimeActual)); }
static string GetOverlayForItem(SupportPowerInstance item) { if (item.Disabled) { return("ON HOLD"); } if (item.Ready) { return("READY"); } return(WidgetUtils.FormatTime(item.RemainingTime)); }
public override void Draw() { var iconSize = new float2(64, 48); var iconOffset = 0.5f * iconSize; overlayFont = Game.Renderer.Fonts["TinyBold"]; holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; // Background foreach (var rect in icons.Keys) { WidgetUtils.DrawPanel("panel-black", rect.InflateBy(1, 1, 1, 1)); } // Icons foreach (var p in icons.Values) { WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, worldRenderer); // Charge progress clock.PlayFetchIndex("idle", () => (p.Power.TotalTime - p.Power.RemainingTime) * (clock.CurrentSequence.Length - 1) / p.Power.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, worldRenderer); } // Overlay foreach (var p in icons.Values) { if (p.Power.Ready) { overlayFont.DrawTextWithContrast(ReadyText, p.Pos + readyOffset, Color.White, Color.Black, 1); } else if (!p.Power.Active) { overlayFont.DrawTextWithContrast(HoldText, p.Pos + holdOffset, Color.White, Color.Black, 1); } else { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), p.Pos + timeOffset, Color.White, Color.Black, 1); } } }
public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette) { widget.IsVisible = () => palette.TooltipPower != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var timeLabel = widget.Get <LabelWidget>("TIME"); var descLabel = widget.Get <LabelWidget>("DESC"); var nameFont = Game.Renderer.Fonts[nameLabel.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; SupportPowerInstance lastPower = null; tooltipContainer.BeforeRender = () => { var sp = palette.TooltipPower; if (sp == null) { return; } if (sp.Info == null) { return; // no instances actually exist (race with destroy) } time = "{0} / {1}".F(WidgetUtils.FormatTime(sp.RemainingTime), WidgetUtils.FormatTime(sp.Info.ChargeTime * 25)); if (sp == lastPower) { return; } name = sp.Info.Description; desc = sp.Info.LongDesc.Replace("\\n", "\n"); var timeWidth = timeFont.Measure(time).X; var topWidth = nameFont.Measure(name).X + timeWidth + timeOffset; var descSize = descFont.Measure(desc); 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; }; nameLabel.GetText = () => name; timeLabel.GetText = () => time; descLabel.GetText = () => desc; }
public override void Draw() { if (!IsVisible()) { return; } var font = Game.Renderer.Fonts["Bold"]; var text = Format.F(WidgetUtils.FormatTime(Timer.TicksLeft)); var pos = new float2(Game.viewport.Width * 0.5f - font.Measure(text).X / 2, Game.viewport.Height * 0.1f); font.DrawTextWithContrast(text, pos, Timer.TicksLeft <= 25 * 10 && Game.LocalTick % 50 < 25 ? Color.Red : Color.White, Color.Black, 1); }
string GetOverlayForItem(ProductionItem item) { if (item.Paused) { return(HoldText); } if (item.Done) { return(orderManager.LocalFrameNumber / 9 % 2 == 0 ? ReadyText : ""); } return(WidgetUtils.FormatTime(item.RemainingTimeActual)); }
public override void Draw() { var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; overlayFont = Game.Renderer.Fonts["TinyBold"]; holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; // Icons foreach (var p in icons.Values) { WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, worldRenderer); // Charge progress var sp = p.Power; clock.PlayFetchIndex("idle", () => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime) * (clock.CurrentSequence.Length - 1) / sp.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, worldRenderer); } // Overlay foreach (var p in icons.Values) { if (p.Power.Ready) { overlayFont.DrawTextWithContrast(ReadyText, p.Pos + readyOffset, Color.White, Color.Black, 1); } else if (!p.Power.Active) { overlayFont.DrawTextWithContrast(HoldText, p.Pos + holdOffset, Color.White, Color.Black, 1); } else { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), p.Pos + timeOffset, Color.White, Color.Black, 1); } } }
void IWorldLoaded.WorldLoaded(World w, OpenRA.Graphics.WorldRenderer wr) { mapOptions = w.WorldActor.Trait <MapOptions>(); if (string.IsNullOrWhiteSpace(info.CountdownLabel) || string.IsNullOrWhiteSpace(info.CountdownText)) { return; } countdownLabel = Ui.Root.GetOrNull <LabelWidget>(info.CountdownLabel); if (countdownLabel != null) { countdown = new CachedTransform <int, string>(t => info.CountdownText.F(WidgetUtils.FormatTime(t, true, w.IsReplay ? mapOptions.GameSpeed.Timestep : w.Timestep))); countdownLabel.GetText = () => countdown.Update(ticksRemaining); } }
private void DrawSuperweapons() { var index = 0; foreach (var player in ingameUi.World.Players) { var powers = player.PlayerActor.Trait <SupportPowerManager>().Powers.Where(p => p.Value.Active).OrderBy(p => p.Value.RemainingTime); foreach (var power in powers) { var text = WidgetUtils.FormatTime(power.Value.RemainingTime, false, ingameUi.World.Timestep); font.DrawTextWithContrast(text, new int2( RenderBounds.X + 10 + index % 4 * ((RenderBounds.Width - 20) / 4), RenderBounds.Y + 25 + index / 4 * powerHeight), player.Color.RGB, player.Color.L > 50 ? Color.Black : Color.White, 1); index++; } } }
public override void Draw() { // Background foreach (var rect in Icons.Keys) { WidgetUtils.DrawPanel("panel-black", rect.InflateBy(1, 1, 1, 1)); } // Icons foreach (var p in Icons.Values) { WidgetUtils.DrawSHP(p.Sprite, p.Pos, worldRenderer); // Charge progress clock.PlayFetchIndex("idle", () => (p.Power.TotalTime - p.Power.RemainingTime) * (clock.CurrentSequence.Length - 1) / p.Power.TotalTime); clock.Tick(); WidgetUtils.DrawSHP(clock.Image, p.Pos, worldRenderer); } // Overlay foreach (var p in Icons.Values) { if (p.Power.Ready) { overlayFont.DrawTextWithContrast("Ready", p.Pos + readyOffset, Color.White, Color.Black, 1); } else if (!p.Power.Active) { overlayFont.DrawTextWithContrast("On Hold", p.Pos + holdOffset, Color.White, Color.Black, 1); } else { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), p.Pos + timeOffset, Color.White, Color.Black, 1); } } }
public SupportPowersWidget(World world, WorldRenderer worldRenderer) { this.worldRenderer = worldRenderer; spm = world.LocalPlayer.PlayerActor.Trait <SupportPowerManager>(); tooltipContainer = Lazy.New(() => Ui.Root.GetWidget <TooltipContainerWidget>(TooltipContainer)); iconSprites = Rules.Info.Values.SelectMany(u => u.Traits.WithInterface <SupportPowerInfo>()) .Select(u => u.Image).Distinct() .ToDictionary( u => u, u => Game.modData.SpriteLoader.LoadAllSprites(u)[0]); clock = new Animation("clock"); overlayFont = Game.Renderer.Fonts["TinyBold"]; holdOffset = new float2(32, 24) - overlayFont.Measure("On Hold") / 2; readyOffset = new float2(32, 24) - overlayFont.Measure("Ready") / 2; timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; }
public override void Draw() { var iconOffset = 0.5f * IconSize.ToVector2() + IconSpriteOffset; overlayFont = WarGame.Renderer.Fonts["TinyBold"]; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2; queuedOffset = new Vector2(4, 2); holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; if (CurrentQueue == null) { return; } var buildableItems = CurrentQueue.BuildableItems(); var pios = currentQueue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>(); //Icons foreach (var icon in icons.Values) { WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, icon.Palette); //Build progress if (icon.Queued.Count > 0) { var first = icon.Queued[0]; clock.PlayFetchIndex(ClockSequence, () => (first.TotalTime - first.RemainingTime) * (clock.CurrentSequence.Length - 1) / first.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, icon.Pos + iconOffset, icon.IconClockPalette); } else if (!buildableItems.Any(a => a.Name == icon.Name)) { WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, icon.IconDarkenPalette); } } }
public GameTimerLogic(Widget widget, OrderManager orderManager, World world) { var timer = widget.GetOrNull <LabelWidget>("GAME_TIMER"); var status = widget.GetOrNull <LabelWidget>("GAME_TIMER_STATUS"); var startTick = UI.LastTickTime; if (timer != null) { //Timers in replays should be synced to the effective game time,not the playback time. var timestep = world.Timestep; if (world.IsReplay) { timestep = world.WorldActor.Trait <MapOptions>().GameSpeed.Timestep; } timer.GetText = () => { //if(status == null &&) return(WidgetUtils.FormatTime(world.WorldTick, timestep)); }; } }
public ProductionPaletteWidget(World world, WorldRenderer worldRenderer) { this.world = world; this.worldRenderer = worldRenderer; tooltipContainer = Lazy.New(() => Widget.RootWidget.GetWidget <TooltipContainerWidget>(TooltipContainer)); cantBuild = new Animation("clock"); cantBuild.PlayFetchIndex("idle", () => 0); clock = new Animation("clock"); iconSprites = Rules.Info.Values .Where(u => u.Traits.Contains <BuildableInfo>() && u.Name[0] != '^') .ToDictionary( u => u.Name, u => Game.modData.SpriteLoader.LoadAllSprites( u.Traits.Get <TooltipInfo>().Icon ?? (u.Name + "icon"))[0]); overlayFont = Game.Renderer.Fonts["TinyBold"]; holdOffset = new float2(32, 24) - overlayFont.Measure("On Hold") / 2; readyOffset = new float2(32, 24) - overlayFont.Measure("Ready") / 2; timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; queuedOffset = new float2(4, 2); }
public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Func <SupportPowersWidget.SupportPowerIcon> getTooltipIcon, World world) { widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Power.Info != null; var nameLabel = widget.Get <LabelWidget>("NAME"); var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY"); var timeLabel = widget.Get <LabelWidget>("TIME"); var descLabel = widget.Get <LabelWidget>("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 baseHeight = widget.Bounds.Height; var timeOffset = timeLabel.Bounds.X; SupportPowerInstance lastPower = null; Hotkey lastHotkey = Hotkey.Invalid; var lastRemainingSeconds = 0; tooltipContainer.BeforeRender = () => { var icon = getTooltipIcon(); if (icon == null || icon.Power == null || icon.Power.Instances.Count == 0) { return; } var sp = icon.Power; // 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.RemainingTicks * world.Timestep / 1000f); var hotkey = 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 customLabel = sp.TooltipTimeTextOverride(); if (customLabel == null) { var remaining = WidgetUtils.FormatTime(sp.RemainingTicks, world.Timestep); var total = WidgetUtils.FormatTime(sp.Info.ChargeInterval, world.Timestep); timeLabel.Text = $"{remaining} / {total}"; } else { timeLabel.Text = customLabel; } var timeSize = timeFont.Measure(timeLabel.Text); var hotkeyWidth = 0; hotkeyLabel.Visible = hotkey.IsValid(); if (hotkeyLabel.Visible) { var hotkeyText = $"({hotkey.DisplayString()})"; hotkeyWidth = hotkeyFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X; hotkeyLabel.Text = hotkeyText; hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X; } 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; }; timeLabel.GetColor = () => getTooltipIcon() != null && !getTooltipIcon().Power.Active ? Color.Red : Color.White; }
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette, World world) { var mapRules = palette.World.Map.Rules; var pm = palette.World.LocalPlayer.PlayerActor.Trait <PowerManager>(); var pr = palette.World.LocalPlayer.PlayerActor.Trait <PlayerResources>(); widget.IsVisible = () => palette.TooltipIcon != 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]; ActorInfo lastActor = null; tooltipContainer.BeforeRender = () => { if (palette.TooltipIcon == null) { return; } var actor = palette.TooltipIcon.Actor; if (actor == null || actor == lastActor) { return; } var tooltip = actor.TraitInfo <TooltipInfo>(); var buildable = actor.TraitInfo <BuildableInfo>(); var cost = actor.TraitInfo <ValuedInfo>().Cost; nameLabel.GetText = () => tooltip.Name; var hotkey = palette.TooltipIcon.Hotkey; var nameWidth = font.Measure(tooltip.Name).X; var hotkeyText = "({0})".F(hotkey.DisplayString()); var hotkeyWidth = hotkey.IsValid() ? font.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X : 0; hotkeyLabel.GetText = () => hotkeyText; hotkeyLabel.Bounds.X = nameWidth + 2 * nameLabel.Bounds.X; hotkeyLabel.Visible = hotkey.IsValid(); var prereqs = buildable.Prerequisites.Select(a => ActorName(mapRules, a)).Where(s => !s.StartsWith("~")); var requiresString = prereqs.Any() ? requiresLabel.Text.F(prereqs.JoinWith(", ")) : ""; requiresLabel.GetText = () => requiresString; var power = actor.TraitInfos <PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(i => i.Amount); var powerString = power.ToString(); powerLabel.GetText = () => powerString; powerLabel.GetColor = () => ((pm.PowerProvided - pm.PowerDrained) >= -power || power > 0) ? Color.White : Color.Red; powerLabel.IsVisible = () => power != 0; powerIcon.IsVisible = () => power != 0; var lowpower = pm.PowerState != PowerState.Normal; var time = palette.CurrentQueue == null ? 0 : palette.CurrentQueue.GetBuildTime(actor.Name) * (lowpower ? palette.CurrentQueue.Info.LowPowerSlowdown : 1); var timeString = WidgetUtils.FormatTime(time, world.Timestep); timeLabel.GetText = () => timeString; timeLabel.GetColor = () => lowpower ? Color.Red : Color.White; var costString = cost.ToString(); costLabel.GetText = () => costString; costLabel.GetColor = () => pr.DisplayCash + pr.DisplayResources >= cost ? Color.White : Color.Red; var descString = tooltip.Description.Replace("\\n", "\n"); descLabel.GetText = () => descString; var leftWidth = new[] { nameWidth + hotkeyWidth, requiresFont.Measure(requiresString).X, descFont.Measure(descString).X }.Aggregate(Math.Max); var rightWidth = new[] { font.Measure(powerString).X, font.Measure(timeString).X, font.Measure(costString).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 = font.Measure(tooltip.Name).Y + requiresFont.Measure(requiresString).Y + descFont.Measure(descString).Y; var rightHeight = font.Measure(powerString).Y + font.Measure(timeString).Y + font.Measure(costString).Y; widget.Bounds.Height = Math.Max(leftHeight, rightHeight) * 3 / 2 + 3 * nameLabel.Bounds.Y; lastActor = actor; }; }
public GameTimerLogic(Widget widget, OrderManager orderManager, World world) { var timer = widget.GetOrNull <LabelWidget>("GAME_TIMER"); var status = widget.GetOrNull <LabelWidget>("GAME_TIMER_STATUS"); var tlm = world.WorldActor.TraitOrDefault <TimeLimitManager>(); var startTick = Ui.LastTickTime; Func <bool> shouldShowStatus = () => (world.Paused || world.Timestep != world.LobbyInfo.GlobalSettings.Timestep) && (Ui.LastTickTime - startTick) / 1000 % 2 == 0; Func <string> statusText = () => { if (world.Paused || world.Timestep == 0) { return("Paused"); } if (world.Timestep == 1) { return("Max Speed"); } return("{0}% Speed".F(world.LobbyInfo.GlobalSettings.Timestep * 100 / world.Timestep)); }; if (timer != null) { // Timers in replays should be synced to the effective game time, not the playback time. var timestep = world.Timestep; if (world.IsReplay) { timestep = world.WorldActor.Trait <MapOptions>().GameSpeed.Timestep; } timer.GetText = () => { if (status == null && shouldShowStatus()) { return(statusText()); } var timeLimit = tlm != null ? tlm.TimeLimit : 0; var displayTick = timeLimit > 0 ? timeLimit - world.WorldTick : world.WorldTick; return(WidgetUtils.FormatTime(Math.Max(0, displayTick), timestep)); }; } if (status != null) { // Blink the status line status.IsVisible = shouldShowStatus; status.GetText = statusText; } var timerTooltip = timer as LabelWithTooltipWidget; if (timerTooltip != null) { var connection = orderManager.Connection as ReplayConnection; if (connection != null && connection.FinalGameTick != 0) { timerTooltip.GetTooltipText = () => "{0}% complete".F(world.WorldTick * 100 / connection.FinalGameTick); } else if (connection != null && connection.TickCount != 0) { timerTooltip.GetTooltipText = () => "{0}% complete".F(orderManager.NetFrameNumber * 100 / connection.TickCount); } else { timerTooltip.GetTooltipText = null; } } }
public override void Draw() { buttons.Clear(); if (world.LocalPlayer == null) { return; } var manager = world.LocalPlayer.PlayerActor.Trait <SupportPowerManager>(); var powers = manager.Powers.Where(p => !p.Value.Disabled); var numPowers = powers.Count(); if (numPowers == 0) { return; } var rectBounds = RenderBounds; WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-top"), new float2(rectBounds.X, rectBounds.Y)); for (var i = 1; i < numPowers; i++) { WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-middle"), new float2(rectBounds.X, rectBounds.Y + i * 51)); } WidgetUtils.DrawRGBA(WidgetUtils.GetChromeImage(world, "specialbin-bottom"), new float2(rectBounds.X, rectBounds.Y + numPowers * 51)); // Hack Hack Hack rectBounds.Width = 69; rectBounds.Height = 10 + numPowers * 51 + 21; var y = rectBounds.Y + 10; foreach (var kv in powers) { var sp = kv.Value; var image = spsprites[sp.Info.Image]; var drawPos = new float2(rectBounds.X + 5, y); var rect = new Rectangle(rectBounds.X + 5, y, 64, 48); if (rect.Contains(Viewport.LastMousePos)) { var pos = drawPos.ToInt2(); var tl = new int2(pos.X - 3, pos.Y - 3); var m = new int2(pos.X + 64 + 3, pos.Y + 48 + 3); var br = tl + new int2(64 + 3 + 20, 40); if (sp.TotalTime > 0) { br += new int2(0, 20); } if (sp.Info.LongDesc != null) { br += Game.Renderer.Fonts["Regular"].Measure(sp.Info.LongDesc.Replace("\\n", "\n")); } else { br += new int2(300, 0); } var border = WidgetUtils.GetBorderSizes("dialog4"); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(tl.X, tl.Y, m.X + border[3], m.Y), PanelSides.Left | PanelSides.Top | PanelSides.Bottom | PanelSides.Center); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X - border[2], tl.Y, br.X, m.Y + border[1]), PanelSides.Top | PanelSides.Right | PanelSides.Center); WidgetUtils.DrawPanelPartial("dialog4", Rectangle.FromLTRB(m.X, m.Y - border[1], br.X, br.Y), PanelSides.Left | PanelSides.Right | PanelSides.Bottom | PanelSides.Center); pos += new int2(77, 5); Game.Renderer.Fonts["Bold"].DrawText(sp.Info.Description, pos, Color.White); if (sp.TotalTime > 0) { pos += new int2(0, 20); Game.Renderer.Fonts["Bold"].DrawText(WidgetUtils.FormatTime(sp.RemainingTime).ToString(), pos, Color.White); Game.Renderer.Fonts["Bold"].DrawText("/ {0}".F(WidgetUtils.FormatTime(sp.TotalTime)), pos + new int2(45, 0), Color.White); } if (sp.Info.LongDesc != null) { pos += new int2(0, 20); Game.Renderer.Fonts["Regular"].DrawText(sp.Info.LongDesc.Replace("\\n", "\n"), pos, Color.White); } } WidgetUtils.DrawSHP(image, drawPos, worldRenderer); clock.PlayFetchIndex("idle", () => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime) * (clock.CurrentSequence.Length - 1) / sp.TotalTime); clock.Tick(); WidgetUtils.DrawSHP(clock.Image, drawPos, worldRenderer); var overlay = sp.Ready ? ReadyText : sp.Active ? null : HoldText; var font = Game.Renderer.Fonts["TinyBold"]; if (overlay != null) { var size = font.Measure(overlay); var overlayPos = drawPos + new float2(32, 16); font.DrawTextWithContrast(overlay, overlayPos - new float2(size.X / 2, 0), Color.White, Color.Black, 1); } buttons.Add(Pair.New(rect, HandleSupportPower(kv.Key, manager))); y += 51; } }
void DrawProductionTooltip(World world, string unit, Hotkey hotkey, int2 pos) { pos.Y += 15; var pl = world.LocalPlayer; var p = pos.ToFloat2() - new float2(297, -3); var info = world.Map.Rules.Actors[unit]; var tooltip = info.Traits.Get <TooltipInfo>(); var buildable = info.Traits.Get <BuildableInfo>(); var cost = info.Traits.Get <ValuedInfo>().Cost; var canBuildThis = CurrentQueue.CanBuild(info); var longDescSize = Game.Renderer.Fonts["Regular"].Measure(tooltip.Description.Replace("\\n", "\n")).Y; if (!canBuildThis) { longDescSize += 8; } WidgetUtils.DrawPanel("dialog4", new Rectangle(Game.Renderer.Resolution.Width - 300, pos.Y, 300, longDescSize + 65)); Game.Renderer.Fonts["Bold"].DrawText( tooltip.Name + (hotkey.IsValid() ? " ({0})".F(hotkey.DisplayString()) : ""), p.ToInt2() + new int2(5, 5), Color.White); var resources = pl.PlayerActor.Trait <PlayerResources>(); var power = pl.PlayerActor.Trait <PowerManager>(); DrawRightAligned("${0}".F(cost), pos + new int2(-5, 5), (resources.DisplayCash + resources.DisplayResources >= cost ? Color.White : Color.Red)); var lowpower = power.PowerState != PowerState.Normal; var time = CurrentQueue.GetBuildTime(info.Name) * ((lowpower) ? CurrentQueue.Info.LowPowerSlowdown : 1); DrawRightAligned(WidgetUtils.FormatTime(time), pos + new int2(-5, 35), lowpower ? Color.Red : Color.White); var pi = info.Traits.GetOrDefault <PowerInfo>(); if (pi != null) { DrawRightAligned("{1}{0}".F(pi.Amount, pi.Amount > 0 ? "+" : ""), pos + new int2(-5, 20), ((power.PowerProvided - power.PowerDrained) >= -pi.Amount || pi.Amount > 0) ? Color.White : Color.Red); } p += new int2(5, 35); if (!canBuildThis) { var prereqs = buildable.Prerequisites.Select(s => Description(world.Map.Rules, s)).Where(s => !s.StartsWith("~")); if (prereqs.Any()) { Game.Renderer.Fonts["Regular"].DrawText(RequiresText.F(prereqs.JoinWith(", ")), p.ToInt2(), Color.White); p += new int2(0, 8); } } p += new int2(0, 15); Game.Renderer.Fonts["Regular"].DrawText(tooltip.Description.Replace("\\n", "\n"), p.ToInt2(), Color.White); }
public override void Draw() { overlayFont = Game.Renderer.Fonts["TinyBold"]; timeOffset = new float2(32, 24) - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; queuedOffset = new float2(4, 2); holdOffset = new float2(32, 24) - overlayFont.Measure(HoldText) / 2; readyOffset = new float2(32, 24) - overlayFont.Measure(ReadyText) / 2; if (CurrentQueue == null) { return; } var buildableItems = CurrentQueue.BuildableItems().OrderBy(a => a.Traits.Get <BuildableInfo>().BuildPaletteOrder); // Background foreach (var rect in icons.Keys) { WidgetUtils.DrawPanel("panel-black", rect.InflateBy(1, 1, 1, 1)); } // Icons foreach (var icon in icons.Values) { WidgetUtils.DrawSHP(icon.Sprite, icon.Pos, worldRenderer); // Build progress if (icon.Queued.Count > 0) { var first = icon.Queued[0]; clock.PlayFetchIndex("idle", () => (first.TotalTime - first.RemainingTime) * (clock.CurrentSequence.Length - 1) / first.TotalTime); clock.Tick(); WidgetUtils.DrawSHP(clock.Image, icon.Pos, worldRenderer); } else if (!buildableItems.Any(a => a.Name == icon.Name)) { WidgetUtils.DrawSHP(cantBuild.Image, icon.Pos, worldRenderer); } } // Overlays foreach (var icon in icons.Values) { var total = icon.Queued.Count; if (total > 0) { var first = icon.Queued[0]; var waiting = first != CurrentQueue.CurrentItem() && !first.Done; if (first.Done) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); } else if (first.Paused) { overlayFont.DrawTextWithContrast(HoldText, icon.Pos + holdOffset, Color.White, Color.Black, 1); } else if (!waiting) { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.RemainingTimeActual), icon.Pos + timeOffset, Color.White, Color.Black, 1); } if (total > 1 || waiting) { overlayFont.DrawTextWithContrast(total.ToString(), icon.Pos + queuedOffset, Color.White, Color.Black, 1); } } } }
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, Func <ProductionIcon> getTooltipIcon) { var world = player.World; var mapRules = world.Map.Rules; var pm = player.PlayerActor.TraitOrDefault <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 == null ? PowerState.Normal : 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 == null || 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) && !s.StartsWith("!", StringComparison.Ordinal)); requiresLabel.Text = prereqs.Any() ? requiresFormat.F(prereqs.JoinWith(", ")) : ""; var requiresSize = requiresFont.Measure(requiresLabel.Text); var powerSize = new int2(0, 0); if (pm != null) { 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; powerSize = font.Measure(powerLabel.Text); } var buildTime = tooltipIcon.ProductionQueue == null ? 0 : tooltipIcon.ProductionQueue.GetBuildTime(actor, buildable); var timeMultiplier = pm != null && pm.PowerState != PowerState.Normal ? tooltipIcon.ProductionQueue.Info.LowPowerSlowdown : 1; timeLabel.Text = formatBuildTime.Update(buildTime * timeMultiplier); timeLabel.TextColor = (pm != null && 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; if (pm != null) { lastPowerState = pm.PowerState; } }; }
public string FormatTime(int ticks, bool leadingMinuteZero = true) { return(WidgetUtils.FormatTime(ticks, leadingMinuteZero, 40)); }