public override void Draw() { supportPowerIconsIcons.Clear(); supportPowerIconsBounds.Clear(); var player = GetPlayer(); if (player == null) { return; } var powers = player.PlayerActor.Trait <SupportPowerManager>().Powers .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) { var item = power.a.Value; if (item == null || item.Info == null || item.Info.Icon == null) { continue; } 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]; clock.PlayFetchIndex(ClockSequence, () => item.TotalTime == 0 ? 0 : ((item.TotalTime - item.RemainingTime) * (clock.CurrentSequence.Length - 1) / item.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(ClockPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(item, timestep); tiny.DrawTextWithContrast(text, location + new float2(16, 12) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } }
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, worldRenderer.World.Timestep)) / 2; // Icons Game.Renderer.EnableAntialiasingFilter(); foreach (var p in icons.Values) { WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, p.Palette); // Charge progress var sp = p.Power; clock.PlayFetchIndex(ClockSequence, () => sp.TotalTicks == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTicks - sp.RemainingTicks) * (clock.CurrentSequence.Length - 1) / sp.TotalTicks); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, p.IconClockPalette); } Game.Renderer.DisableAntialiasingFilter(); // Overlay foreach (var p in icons.Values) { var customText = p.Power.IconOverlayTextOverride(); if (customText != null) { var customOffset = iconOffset - overlayFont.Measure(customText) / 2; overlayFont.DrawTextWithContrast(customText, p.Pos + customOffset, Color.White, Color.Black, 1); } else 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.RemainingTicks, worldRenderer.World.Timestep), p.Pos + timeOffset, Color.White, Color.Black, 1); } } }
public override void Draw() { var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, "clock")); } } var iconSize = new float2(IconWidth, IconHeight); foreach (var queue in queues) { var current = queue.Trait.CurrentItem(); if (current == null) { continue; } var race = queue.Trait.Actor.Owner.Country.Race; var actor = queue.Trait.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } var rsi = actor.Traits.Get <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.SequenceProvider, race)); icon.Play(actor.Traits.Get <TooltipInfo>().Icon); var location = new float2(RenderBounds.Location) + new float2(queue.i * (IconWidth + IconSpacing), 0); WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var clock = clocks[queue.Trait]; clock.PlayFetchIndex("idle", () => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(current); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } }
public override void Draw() { if (sprite != null && palette != null) { var scale = Game.Cursor is SoftwareCursor && CursorProvider.CursorViewportZoomed ? 2 : 1; var directionPalette = worldRenderer.Palette(palette); WidgetUtils.DrawSHPCentered(sprite, ChildOrigin, directionPalette, scale); } }
public override void Draw() { if (sprite != null && palette != null) { var directionPalette = worldRenderer.Palette(palette); // Cursor is rendered in native window coordinates // Apply same scaling rules as hardware cursors var scale = (graphicSettings.CursorDouble ? 2 : 1) * (Game.Renderer.NativeWindowScale > 1.5f ? 2 : 1); WidgetUtils.DrawSHPCentered(sprite, ChildOrigin, directionPalette, scale / Game.Renderer.WindowScale); } }
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, p.Palette); // 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, p.Palette); } // 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 override void Draw() { var player = GetPlayer(); if (player == null) { return; } var powers = player.PlayerActor.Trait <SupportPowerManager>().Powers .Select((a, i) => new { a, i }); foreach (var power in powers) { if (!clocks.ContainsKey(power.a.Key)) { clocks.Add(power.a.Key, new Animation(world, "clock")); } } var iconSize = new float2(IconWidth, IconHeight); foreach (var power in powers) { var item = power.a.Value; if (item == null || item.Info == null || item.Info.Icon == null) { continue; } icon.Play(item.Info.Icon); var location = new float2(RenderBounds.Location) + new float2(power.i * (IconWidth + IconSpacing), 0); WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var clock = clocks[power.a.Key]; clock.PlayFetchIndex("idle", () => item.TotalTime == 0 ? 0 : ((item.TotalTime - item.RemainingTime) * (clock.CurrentSequence.Length - 1) / item.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer, 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(item); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } }
public override void Draw() { var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; overlayFont = Game.Renderer.Fonts["TinyBold"]; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2; queuedOffset = new float2(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); // Draw the ProductionIconOverlay's sprite var pio = pios.FirstOrDefault(p => p.IsOverlayActive(icon.Actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, icon.Pos + iconOffset + pio.Offset(IconSize), worldRenderer.Palette(pio.Palette), 1f); } // 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); } } // 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) { if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber * worldRenderer.World.Timestep / 360 % 2 == 0) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); } else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, 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, World.Timestep), 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 override void Draw() { var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, ClockAnimation)); } } var iconSize = new float2(IconWidth, IconHeight); foreach (var queue in queues) { var current = queue.Trait.CurrentItem(); if (current == null) { continue; } var faction = queue.Trait.Actor.Owner.Faction.InternalName; var actor = queue.Trait.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } var rsi = actor.TraitInfo <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.SequenceProvider, faction)); icon.Play(actor.TraitInfo <TooltipInfo>().Icon); var bi = actor.TraitInfo <BuildableInfo>(); var location = new float2(RenderBounds.Location) + new float2(queue.i * (IconWidth + IconSpacing), 0); WidgetUtils.DrawSHPCentered(icon.Image, location + 0.5f * iconSize, worldRenderer.Palette(bi.IconPalette), 0.5f); var pio = queue.Trait.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>() .FirstOrDefault(p => p.IsOverlayActive(actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, location + 0.5f * iconSize + pio.Offset(0.5f * iconSize), worldRenderer.Palette(pio.Palette), 0.5f); } var clock = clocks[queue.Trait]; clock.PlayFetchIndex(ClockSequence, () => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(ClockPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(current, world.Timestep); tiny.DrawTextWithContrast(text, location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } }
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++; } var newWidth = Math.Max(queueCol * (IconWidth + IconSpacing), MinWidth); if (newWidth != Bounds.Width) { var wasInBounds = EventBounds.Contains(Viewport.LastMousePos); Bounds.Width = newWidth; var isInBounds = EventBounds.Contains(Viewport.LastMousePos); // HACK: Ui.MouseOverWidget is normally only updated when the mouse moves // Call ResetTooltips to force a fake mouse movement so the checks in Tick will work properly if (wasInBounds != isInBounds) { Game.RunAfterTick(Ui.ResetTooltips); } } 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 <GradientColorBlockWidget>("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 void Draw() { timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2; if (CurrentQueue == null) { return; } var buildableItems = CurrentQueue.BuildableItems(); // Icons Game.Renderer.EnableAntialiasingFilter(); foreach (var icon in icons.Values) { WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, icon.Palette); // Draw the ProductionIconOverlay's sprite var pio = pios.FirstOrDefault(p => p.IsOverlayActive(icon.Actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, icon.Pos + iconOffset + pio.Offset(IconSize), worldRenderer.Palette(pio.Palette), 1f); } // 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); } } Game.Renderer.DisableAntialiasingFilter(); // Overlays foreach (var icon in icons.Values) { var total = icon.Queued.Count; if (total > 0) { var first = icon.Queued[0]; var waiting = !CurrentQueue.IsProducing(first) && !first.Done; if (first.Done) { if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber * worldRenderer.World.Timestep / 360 % 2 == 0) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); } else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, Color.Black, 1); } } else if (first.Paused) { overlayFont.DrawTextWithContrast(HoldText, icon.Pos + holdOffset, Color.White, Color.Black, 1); } else if (!waiting && DrawTime) { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.Queue.RemainingTimeActual(first), World.Timestep), icon.Pos + timeOffset, Color.White, Color.Black, 1); } if (first.Infinite && symbolFont != null) { symbolFont.DrawTextWithContrast(InfiniteSymbol, icon.Pos + infiniteOffset, Color.White, Color.Black, 1); } else if (total > 1 || waiting) { overlayFont.DrawTextWithContrast(total.ToString(), icon.Pos + queuedOffset, Color.White, Color.Black, 1); } } } }
public override void Draw() { var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, ClockAnimation)); } } if (renderBounds != RenderBounds) { renderBounds = RenderBounds; InitIcons(renderBounds); } else { for (var i = 0; i < icons.Length; i++) { icons[i].Actor = null; } } int queueColumn = -1; var currentItemsByItem = queues.Select(a => a.Trait.AllQueued().FirstOrDefault()).Where(pi => pi != null).GroupBy(pr => pr.Item) .OrderBy(g => g.First().Queue.Info.SpectatorUIOrder) .ThenBy(g => g.First().Queue.Info.Type) .ThenBy(g => world.Map.Rules.Actors[g.First().Item].TraitInfo <BuildableInfo>().BuildPaletteOrder).ToList(); foreach (var currentItems in currentItemsByItem) { var current = currentItems.OrderBy(pi => pi.Done ? 0 : (pi.Paused ? 2 : 1)).ThenBy(q => q.RemainingTimeActual).First(); var queue = current.Queue; var actor = queue.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } queueColumn += 1; var rsi = actor.TraitInfo <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.Rules.Sequences, queue.Actor.Owner.Faction.InternalName)); var bi = actor.TraitInfo <BuildableInfo>(); icon.Play(bi.Icon); var location = new float2(iconRects[queueColumn].Location); WidgetUtils.DrawSHPCentered(icon.Image, location + iconSize, worldRenderer.Palette(bi.IconPalette), 1f); icons[queueColumn].Actor = actor; icons[queueColumn].ProductionQueue = queue; var pio = queue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>() .FirstOrDefault(p => p.IsOverlayActive(actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, location + iconSize + pio.Offset(iconSize * 2f), worldRenderer.Palette(pio.Palette), 1f); } var clock = clocks[queue]; clock.PlayFetchIndex(ClockSequence, () => current.TotalTime == 0 ? 0 : ((current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + iconSize, worldRenderer.Palette(ClockPalette), 1f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(current, timestep); tiny.DrawTextWithContrast(text, location + iconSize - new float2(tiny.Measure(text).X / 2, 3), Color.White, Color.Black, 1); if (currentItems.Count() > 1) { var bold = Game.Renderer.Fonts["Bold"]; text = currentItems.Count().ToString(); bold.DrawTextWithContrast(text, new float2(RenderBounds.Location) + new float2(queueColumn * (IconWidth * 2 + IconSpacing) + 5, 5), Color.White, Color.Black, 1); } } }
public override void Draw() { productionIcons.Clear(); productionIconsBounds.Clear(); var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, ClockAnimation)); } } var currentItemsByItem = queues .Select(a => a.Trait.CurrentItem()) .Where(pi => pi != null) .GroupBy(pr => pr.Item) .OrderBy(g => g.First().Queue.Info.DisplayOrder) .ThenBy(g => g.First().BuildPaletteOrder) .ToList(); Game.Renderer.EnableAntialiasingFilter(); var queueCol = 0; foreach (var currentItems in currentItemsByItem) { var queued = currentItems .OrderBy(pi => pi.Done ? 0 : (pi.Paused ? 2 : 1)) .ThenBy(q => q.RemainingTimeActual) .ToList(); var current = queued.First(); var queue = current.Queue; var faction = queue.Actor.Owner.Faction.InternalName; var actor = queue.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } var rsi = actor.TraitInfo <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.Rules.Sequences, faction)); var bi = actor.TraitInfo <BuildableInfo>(); icon.Play(bi.Icon); var topLeftOffset = new float2(queueCol * (IconWidth + IconSpacing), 0); var iconTopLeft = RenderOrigin + topLeftOffset; var centerPosition = iconTopLeft + 0.5f * iconSize; var palette = bi.IconPaletteIsPlayerPalette ? bi.IconPalette + player.InternalName : bi.IconPalette; WidgetUtils.DrawSHPCentered(icon.Image, centerPosition, worldRenderer.Palette(palette), 0.5f); var rect = new Rectangle((int)iconTopLeft.X, (int)iconTopLeft.Y, (int)iconSize.X, (int)iconSize.Y); productionIcons.Add(new ProductionIcon { Actor = actor, Pos = new float2(rect.Location), Queued = queued, ProductionQueue = current.Queue }); productionIconsBounds.Add(rect); var pio = queue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>() .FirstOrDefault(p => p.IsOverlayActive(actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, centerPosition + pio.Offset(iconSize), worldRenderer.Palette(pio.Palette), 0.5f); } var clock = clocks[queue]; clock.PlayFetchIndex(ClockSequence, () => current.TotalTime == 0 ? 0 : (current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, centerPosition, worldRenderer.Palette(ClockPalette), 0.5f); queueCol++; } var newWidth = Math.Max(queueCol * (IconWidth + IconSpacing), MinWidth); if (newWidth != Bounds.Width) { var wasInBounds = EventBounds.Contains(Viewport.LastMousePos); Bounds.Width = newWidth; var isInBounds = EventBounds.Contains(Viewport.LastMousePos); // HACK: Ui.MouseOverWidget is normally only updated when the mouse moves // Call ResetTooltips to force a fake mouse movement so the checks in Tick will work properly if (wasInBounds != isInBounds) { Game.RunAfterTick(Ui.ResetTooltips); } } Game.Renderer.DisableAntialiasingFilter(); var tiny = Game.Renderer.Fonts["Tiny"]; var bold = Game.Renderer.Fonts["Small"]; foreach (var icon in productionIcons) { var current = icon.Queued.First(); var text = GetOverlayForItem(current, world.Timestep); tiny.DrawTextWithContrast(text, icon.Pos + new float2(16, 12) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); if (icon.Queued.Count > 1) { text = icon.Queued.Count.ToString(); bold.DrawTextWithContrast(text, icon.Pos + new float2(16, 0) - new float2(bold.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } } var parentWidth = Bounds.X + Bounds.Width; Parent.Bounds.Width = parentWidth; var gradient = Parent.Get <GradientColorBlockWidget>("PLAYER_GRADIENT"); var offset = gradient.Bounds.X - Bounds.X; var gradientWidth = Math.Max(MinWidth - offset, currentItemsByItem.Count * (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 void Draw() { var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; overlayFont = Game.Renderer.Fonts["TinyBold"]; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; queuedOffset = new float2(4, 2); holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; if (CurrentQueue == null) { return; } var buildableItems = CurrentQueue.BuildableItems(); // Icons foreach (var icon in icons.Values) { WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, 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.DrawSHPCentered(clock.Image, icon.Pos + iconOffset, worldRenderer); } else if (!buildableItems.Any(a => a.Name == icon.Name)) { WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, 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) { if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber / 9 % 2 == 0) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); } else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, 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 override void Draw() { productionIcons.Clear(); productionIconsBounds.Clear(); var player = GetPlayer(); if (player == null) { return; } var queues = world.ActorsWithTrait <ProductionQueue>() .Where(a => a.Actor.Owner == player) .Select((a, i) => new { a.Trait, i }); foreach (var queue in queues) { if (!clocks.ContainsKey(queue.Trait)) { clocks.Add(queue.Trait, new Animation(world, ClockAnimation)); } } var currentItemsByItem = queues .Select(a => a.Trait.CurrentItem()) .Where(pi => pi != null) .GroupBy(pr => pr.Item) .OrderBy(g => g.First().Queue.Info.DisplayOrder) .ThenBy(g => g.First().BuildPaletteOrder) .ToList(); Bounds.Width = currentItemsByItem.Count * (IconWidth + IconSpacing); var queueCol = 0; foreach (var currentItems in currentItemsByItem) { var current = currentItems.OrderBy(pi => pi.Done ? 0 : (pi.Paused ? 2 : 1)).ThenBy(q => q.RemainingTimeActual).First(); var queue = current.Queue; var faction = queue.Actor.Owner.Faction.InternalName; var actor = queue.AllItems().FirstOrDefault(a => a.Name == current.Item); if (actor == null) { continue; } var rsi = actor.TraitInfo <RenderSpritesInfo>(); var icon = new Animation(world, rsi.GetImage(actor, world.Map.Rules.Sequences, faction)); var bi = actor.TraitInfo <BuildableInfo>(); icon.Play(bi.Icon); var topLeftOffset = new float2(queueCol * (IconWidth + IconSpacing), 0); var iconTopLeft = RenderOrigin + topLeftOffset; var centerPosition = iconTopLeft; WidgetUtils.DrawSHPCentered(icon.Image, centerPosition + 0.5f * iconSize, worldRenderer.Palette(bi.IconPalette), 0.5f); productionIcons.Add(new ProductionIcon { Actor = actor, ProductionQueue = current.Queue }); productionIconsBounds.Add(new Rectangle((int)iconTopLeft.X, (int)iconTopLeft.Y, (int)iconSize.X, (int)iconSize.Y)); var pio = queue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>() .FirstOrDefault(p => p.IsOverlayActive(actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, centerPosition + 0.5f * iconSize + pio.Offset(iconSize), worldRenderer.Palette(pio.Palette), 0.5f); } var clock = clocks[queue]; clock.PlayFetchIndex(ClockSequence, () => current.TotalTime == 0 ? 0 : (current.TotalTime - current.RemainingTime) * (clock.CurrentSequence.Length - 1) / current.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, centerPosition + 0.5f * iconSize, worldRenderer.Palette(ClockPalette), 0.5f); var tiny = Game.Renderer.Fonts["Tiny"]; var text = GetOverlayForItem(current, timestep); tiny.DrawTextWithContrast(text, centerPosition + new float2(16, 12) - new float2(tiny.Measure(text).X / 2, 0), Color.White, Color.Black, 1); if (currentItems.Count() > 1) { var bold = Game.Renderer.Fonts["Small"]; text = currentItems.Count().ToString(); bold.DrawTextWithContrast(text, centerPosition + new float2(16, 0) - new float2(bold.Measure(text).X / 2, 0), Color.White, Color.Black, 1); } queueCol++; } }
public override void Draw() { var iconOffsetToCenter = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; timeOffset = iconOffsetToCenter - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2; queuedOffset = new float2(4, 2); holdOffset = iconOffsetToCenter - overlayFont.Measure(HoldText) / 2; readyOffset = iconOffsetToCenter - overlayFont.Measure(ReadyText) / 2; if (ChromeMetrics.TryGet("InfiniteOffset", out infiniteOffset)) { infiniteOffset += queuedOffset; } else { infiniteOffset = queuedOffset; } if (CurrentQueue == null) { return; } var buildableItems = CurrentQueue.BuildableItems(); var pios = currentQueue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>(); // Icons foreach (ProductionIcon icon in icons.Values) { WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffsetToCenter, icon.Palette, icon.RenderSize); //этот метод использует размер от icon.Sprite.Size для размера в FastQuad // Draw the ProductionIconOverlay's sprite var pio = pios.FirstOrDefault(p => p.IsOverlayActive(icon.Actor)); if (pio != null) { WidgetUtils.DrawSHPCentered(pio.Sprite, icon.Pos + iconOffsetToCenter + pio.Offset(IconSize), worldRenderer.Palette(pio.Palette), 1f); } // Build progress if (icon.Queued.Count > 0) { var first = icon.Queued[0]; if (1 == 2) { clock.PlayFetchIndex(ClockSequence, () => (first.TotalTime - first.RemainingTime) * (clock.CurrentSequence.Length - 1) / first.TotalTime); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, icon.Pos + iconOffsetToCenter, icon.IconClockPalette, icon.RenderSize); } else { int currentframe = (first.TotalTime - first.RemainingTime) * (59) / first.TotalTime; float3 offs = iconOffsetToCenter - 0.5f * icon.RenderSize.ToFloat2(); // из-за icon.Pos + iconOffsetToCenter и DrawSHPCentered Game.Renderer.Flush(); // делаем, это тут, так как рисуем вне очереди, то управляем очередью. Game.Renderer.sproc.AddCommand(1, currentframe, 59, 0, 0, new int2(0, 0), icon.Pos + offs, icon.RenderSize, icon.Sprite, icon.Palette); Game.Renderer.sproc.ExecCommandBuffer(); } } else if (!buildableItems.Any(a => a.Name == icon.Name)) { WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffsetToCenter, icon.IconDarkenPalette, icon.RenderSize); } } // Overlays foreach (ProductionIcon icon in icons.Values) { var total = icon.Queued.Count; if (total > 0) { var first = icon.Queued[0]; var waiting = !CurrentQueue.IsProducing(first) && !first.Done; if (first.Done) { if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber * worldRenderer.World.Timestep / 360 % 2 == 0) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); } else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) { overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, Color.Black, 1); } } else if (first.Paused) { overlayFont.DrawTextWithContrast(HoldText, icon.Pos + holdOffset, Color.White, Color.Black, 1); } else if (!waiting && DrawTime) { overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.Queue.RemainingTimeActual(first), World.Timestep), icon.Pos + timeOffset, Color.White, Color.Black, 1); } if (first.Infinite) { symbolFont.DrawTextWithContrast(InfiniteSymbol, icon.Pos + infiniteOffset, Color.White, Color.Black, 1); } else if (total > 1 || waiting) { overlayFont.DrawTextWithContrast(total.ToString(), icon.Pos + queuedOffset, Color.White, Color.Black, 1); } } } }