public override void Display() { if (r == null || loadTimer.Elapsed.TotalSeconds < 0.25) { return; } loadTimer.Restart(); loadTick = ++loadTick % 8; r.BeginFrame(int2.Zero, 1f); r.RgbaSpriteRenderer.DrawSprite(gdiLogo, gdiPos); r.RgbaSpriteRenderer.DrawSprite(nodLogo, nodPos); r.RgbaSpriteRenderer.DrawSprite(evaLogo, evaPos); WidgetUtils.DrawPanelPartial(bounds, PanelSides.Edges, borderTop, borderBottom, borderLeft, borderRight, cornerTopLeft, cornerTopRight, cornerBottomLeft, cornerBottomRight, null); var barY = bounds.Height - 78; // The fonts dictionary may change when switching between the mod and content installer if (r.Fonts != rendererFonts) { rendererFonts = r.Fonts; loadingFont = r.Fonts["BigBold"]; loadingText = loadInfo["Text"]; loadingPos = new float2((bounds.Width - loadingFont.Measure(loadingText).X) / 2, barY); versionFont = r.Fonts["Regular"]; var versionSize = versionFont.Measure(versionText); versionPos = new float2(bounds.Width - 107 - versionSize.X / 2, 115 - versionSize.Y / 2); } if (loadingFont != null) { loadingFont.DrawText(loadingText, loadingPos, Color.Gray); } if (versionFont != null) { versionFont.DrawTextWithContrast(versionText, versionPos, Color.White, Color.Black, 2); } for (var i = 0; i <= 8; i++) { var block = loadTick == i ? brightBlock : dimBlock; r.RgbaSpriteRenderer.DrawSprite(block, new float2(bounds.Width / 2 - 114 - i * 32, barY)); r.RgbaSpriteRenderer.DrawSprite(block, new float2(bounds.Width / 2 + 114 + i * 32 - 16, barY)); } r.EndFrame(nih); }
public void Display() { var r = Game.Renderer; if (r == null) { return; } r.BeginFrame(int2.Zero, 1f); WidgetUtils.FillRectWithSprite(bounds, sprite); r.EndFrame(new NullInputHandler()); }
public override void Display() { if (r == null) { return; } // Update text at most every 0.5 seconds if (lastUpdate.Elapsed.TotalSeconds < 0.5) { return; } if (r.Fonts == null) { return; } lastUpdate.Restart(); var text = messages.Random(Game.CosmeticRandom); var textSize = r.Fonts["Bold"].Measure(text); r.BeginFrame(int2.Zero, 1f); if (stripe != null) { WidgetUtils.FillRectWithSprite(stripeRect, stripe); } if (logo != null) { r.RgbaSpriteRenderer.DrawSprite(logo, logoPos); } r.Fonts["Bold"].DrawText(text, new float2(r.Resolution.Width - textSize.X - 20, r.Resolution.Height - textSize.Y - 20), Color.White); r.EndFrame(new NullInputHandler()); }
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 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() { WidgetUtils.FillRectWithColor(RenderBounds, GetColor()); }
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() { if (!initialised) { Init(); } if (!IsVisible()) { return; } var rb = RenderBounds; var offset = int2.Zero; var svc = world.Players.Select(p => p.PlayerActor.TraitOrDefault <StrategicVictoryConditions>()).FirstOrDefault(); var totalWidth = svc.Total * 32; var curX = -totalWidth / 2; foreach (var a in svc.AllPoints) { WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "critical_unowned"), offset + new float2(rb.Left + curX, rb.Top)); if (world.LocalPlayer != null && WorldUtils.AreMutualAllies(a.Actor.Owner, world.LocalPlayer)) { WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "player_owned"), offset + new float2(rb.Left + curX, rb.Top)); } else if (!a.Actor.Owner.NonCombatant) { WidgetUtils.DrawRGBA(ChromeProvider.GetImage("strategic", "enemy_owned"), offset + new float2(rb.Left + curX, rb.Top)); } curX += 32; } offset += new int2(0, 32); if (world.LocalPlayer == null) { return; } var pendingWinner = FindFirstWinningPlayer(world); if (pendingWinner == null) { return; } var winnerSvc = pendingWinner.PlayerActor.Trait <StrategicVictoryConditions>(); var isVictory = pendingWinner == world.LocalPlayer || !WorldUtils.AreMutualAllies(pendingWinner, world.LocalPlayer); var tc = "Strategic {0} in {1}".F( isVictory ? "victory" : "defeat", WidgetUtils.FormatTime(winnerSvc.TicksLeft)); var font = Game.Renderer.Fonts["Bold"]; var size = font.Measure(tc); font.DrawTextWithContrast(tc, offset + new float2(rb.Left - size.X / 2 + 1, rb.Top + 1), Color.White, Color.Black, 1); offset += new int2(0, size.Y + 1); }
public string FormatTime(int ticks, bool leadingMinuteZero = true) { return(WidgetUtils.FormatTime(ticks, leadingMinuteZero, 40)); }
public override void Draw() { var pos = RenderOrigin; var chatLogArea = new Rectangle(pos.X, pos.Y, Bounds.Width, Bounds.Height); var chatPos = new int2(chatLogArea.X + 5, chatLogArea.Bottom - 8); var font = Game.Renderer.Fonts["Regular"]; Game.Renderer.EnableScissor(chatLogArea); foreach (var line in recentLines.AsEnumerable().Reverse()) { var lineHeight = TextLineBoxHeight; var inset = 0; string name = null; if (!string.IsNullOrEmpty(line.Name)) { name = line.Name + ":"; inset = font.Measure(name).X + 5; } var text = WidgetUtils.WrapText(line.Text, chatLogArea.Width - inset - 6, font); var textSize = font.Measure(text).Y; var offset = font.TopOffset; if (chatPos.Y - font.TopOffset < pos.Y) { break; } var textLineHeight = lineHeight; var dh = textSize - textLineHeight; if (dh > 0) { textLineHeight += dh; } var textOffset = textLineHeight - (textLineHeight - textSize - offset) / 2; var textPos = new int2(chatPos.X + inset, chatPos.Y - textOffset); if (name != null) { var nameSize = font.Measure(name).Y; var namePos = chatPos.WithY(chatPos.Y - (textLineHeight - (lineHeight - nameSize - offset) / 2)); if (UseContrast) { font.DrawTextWithContrast(name, namePos, line.NameColor, BackgroundColorDark, BackgroundColorLight, 1); } else if (UseShadow) { font.DrawTextWithShadow(name, namePos, line.NameColor, BackgroundColorDark, BackgroundColorLight, 1); } else { font.DrawText(name, namePos, line.NameColor); } } if (UseContrast) { font.DrawTextWithContrast(text, textPos, line.TextColor, Color.Black, 1); } else if (UseShadow) { font.DrawTextWithShadow(text, textPos, line.TextColor, Color.Black, 1); } else { font.DrawText(text, textPos, Color.White); } chatPos = chatPos.WithY(chatPos.Y - Space - textLineHeight); } Game.Renderer.DisableScissor(); }
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() { var pos = RenderOrigin; var chatLogArea = new Rectangle(pos.X, pos.Y, Bounds.Width, Bounds.Height); var chatpos = new int2(chatLogArea.X + 5, chatLogArea.Bottom - 5); var font = Game.Renderer.Fonts["Regular"]; Game.Renderer.EnableScissor(chatLogArea); foreach (var line in recentLines.AsEnumerable().Reverse()) { var inset = 0; string owner = null; if (!string.IsNullOrEmpty(line.Owner)) { owner = line.Owner + ":"; inset = font.Measure(owner).X + 5; } var text = WidgetUtils.WrapText(line.Text, chatLogArea.Width - inset - 6, font); chatpos = chatpos.WithY(chatpos.Y - (Math.Max(15, font.Measure(text).Y) + 5)); if (chatpos.Y < pos.Y) { break; } if (owner != null) { if (UseContrast) { font.DrawTextWithContrast(owner, chatpos, line.Color, BackgroundColorDark, BackgroundColorLight, 1); } else if (UseShadow) { font.DrawTextWithShadow(owner, chatpos, line.Color, BackgroundColorDark, BackgroundColorLight, 1); } else { font.DrawText(owner, chatpos, line.Color); } } if (UseContrast) { font.DrawTextWithContrast(text, chatpos + new int2(inset, 0), Color.White, Color.Black, 1); } else if (UseShadow) { font.DrawTextWithShadow(text, chatpos + new int2(inset, 0), Color.White, Color.Black, 1); } else { font.DrawText(text, chatpos + new int2(inset, 0), Color.White); } } Game.Renderer.DisableScissor(); }
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 && x.Value.GetLevel() != 0) .OrderBy(p => p.Value.Info.SupportPowerPaletteOrder) .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); Game.Renderer.EnableAntialiasingFilter(); var iconSize = new float2(IconWidth, IconHeight); foreach (var power in powers) { var item = power.a.Value; if (item == null || item.Info == null || item.Info.Icons == null) { continue; } var level = item.GetLevel(); icon = new Animation(worldRenderer.World, item.Info.IconImage); icon.Play(item.Info.Icons.First(i => i.Key == level).Value); var location = new float2(RenderBounds.Location) + new float2(power.i * (IconWidth + IconSpacing), 0); supportPowerIconsIcons.Add(new SupportPowersWidget.SupportPowerIcon { Power = item, Pos = location }); 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.TotalTicks == 0 ? 0 : ((item.TotalTicks - item.RemainingTicks) * (clock.CurrentSequence.Length - 1) / item.TotalTicks)); clock.Tick(); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(ClockPalette), 0.5f); } Game.Renderer.DisableAntialiasingFilter(); var tiny = Game.Renderer.Fonts["Tiny"]; foreach (var icon in supportPowerIconsIcons) { var text = GetOverlayForItem(icon.Power, timestep); tiny.DrawTextWithContrast(text, icon.Pos + new float2(16, 12) - new float2(tiny.Measure(text).X / 2, 0), 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 OpenRA.Mods.Common.Widgets.CachedTransform <int, string>(t => info.CountdownText.F(WidgetUtils.FormatTime(t, true, w.IsReplay ? mapOptions.GameSpeed.Timestep : w.Timestep))); countdownLabel.GetText = () => countdown.Update(ticksRemaining); } }
public override void Draw() { WidgetUtils.DrawPanel(Background, RenderBounds); }
public override void Draw() { WidgetUtils.FillRectWithColor(RenderBounds, GetTopLeftColor(), GetTopRightColor(), GetBottomRightColor(), GetBottomLeftColor()); }
public static void BindButtonIcon(ButtonWidget button) { var icon = button.Get <ImageWidget>("ICON"); var hasActiveImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-active") != null; var hasActiveDisabledImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-active-disabled") != null; var hasActivePressedImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-active-pressed") != null; var hasActiveHoverImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-active-hover") != null; var hasImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName) != null; var hasDisabledImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-disabled") != null; var hasPressedImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-pressed") != null; var hasHoverImage = ChromeProvider.GetImage(icon.ImageCollection, icon.ImageName + "-hover") != null; icon.GetImageName = () => { var isActive = button.IsHighlighted(); var isDisabled = button.IsDisabled(); var isPressed = button.Depressed; var isHovered = Ui.MouseOverWidget == button; var baseName = button.IsHighlighted() ? icon.ImageName + "-active" : icon.ImageName; var stateName = WidgetUtils.GetStatefulImageName(baseName, isDisabled, isPressed, isHovered); if (isActive) { if (isDisabled) { return(hasActiveDisabledImage ? stateName : hasActiveImage?baseName : icon.ImageName); } else if (isPressed) { return(hasActivePressedImage ? stateName : hasActiveImage?baseName : icon.ImageName); } else if (isHovered) { return(hasActiveHoverImage ? stateName : hasActiveImage?baseName : icon.ImageName); } else { return(hasActiveImage ? baseName : icon.ImageName); } } else { if (isDisabled) { return(hasDisabledImage ? stateName : baseName); } else if (isPressed) { return(hasPressedImage ? stateName : baseName); } else if (isHovered) { return(hasHoverImage ? stateName : baseName); } else { return(baseName); } } }; }
public override void Draw() { var apparentText = GetApparentText(); var font = Game.Renderer.Fonts[Font]; var pos = RenderOrigin; var textSize = font.Measure(apparentText); var cursorPosition = font.Measure(apparentText.Substring(0, CursorPosition)); var disabled = IsDisabled(); var state = disabled ? "textfield-disabled" : HasKeyboardFocus ? "textfield-focused" : Ui.MouseOverWidget == this || Children.Any(c => c == Ui.MouseOverWidget) ? "textfield-hover" : "textfield"; WidgetUtils.DrawPanel(state, new Rectangle(pos.X, pos.Y, Bounds.Width, Bounds.Height)); // Inset text by the margin and center vertically var verticalMargin = (Bounds.Height - textSize.Y) / 2 - VisualHeight; var textPos = pos + new int2(LeftMargin, verticalMargin); // Right align when editing and scissor when the text overflows if (textSize.X > Bounds.Width - LeftMargin - RightMargin) { if (HasKeyboardFocus) { textPos += new int2(Bounds.Width - LeftMargin - RightMargin - textSize.X, 0); } Game.Renderer.EnableScissor(new Rectangle(pos.X + LeftMargin, pos.Y, Bounds.Width - LeftMargin - RightMargin, Bounds.Bottom)); } // Draw the highlight around the selected area if (selectionStartIndex != -1) { var visualSelectionStartIndex = selectionStartIndex < selectionEndIndex ? selectionStartIndex : selectionEndIndex; var visualSelectionEndIndex = selectionStartIndex < selectionEndIndex ? selectionEndIndex : selectionStartIndex; var highlightStartX = font.Measure(apparentText.Substring(0, visualSelectionStartIndex)).X; var highlightEndX = font.Measure(apparentText.Substring(0, visualSelectionEndIndex)).X; WidgetUtils.FillRectWithColor( new Rectangle(textPos.X + highlightStartX, textPos.Y, highlightEndX - highlightStartX, Bounds.Height - (verticalMargin * 2)), TextColorHighlight); } var color = disabled ? TextColorDisabled : IsValid() ? TextColor : TextColorInvalid; font.DrawText(apparentText, textPos, color); if (showCursor && HasKeyboardFocus) { font.DrawText("|", new float2(textPos.X + cursorPosition.X - 2, textPos.Y), TextColor); } if (textSize.X > Bounds.Width - LeftMargin - RightMargin) { Game.Renderer.DisableScissor(); } }
public override void Draw() { var preview = Preview(); if (preview == null) { return; } // Stash a copy of the minimap to ensure consistency // (it may be modified by another thread) minimap = preview.GetMinimap(); if (minimap == null) { return; } // Update map rect previewScale = Math.Min(RenderBounds.Width / minimap.Size.X, RenderBounds.Height / minimap.Size.Y); var w = (int)(previewScale * minimap.Size.X); var h = (int)(previewScale * minimap.Size.Y); var x = RenderBounds.X + (RenderBounds.Width - w) / 2; var y = RenderBounds.Y + (RenderBounds.Height - h) / 2; mapRect = new Rectangle(x, y, w, h); Game.Renderer.RgbaSpriteRenderer.DrawSprite(minimap, new float2(mapRect.Location), new float2(mapRect.Size)); TooltipSpawnIndex = -1; if (ShowSpawnPoints) { var spawnPoints = preview.SpawnPoints; var occupants = SpawnOccupants(); var disabledSpawnPoints = DisabledSpawnPoints(); var gridType = preview.GridType; for (var i = 0; i < spawnPoints.Length; i++) { var p = spawnPoints[i]; // Spawn numbers are 1 indexed with 0 meaning "random spawn". var occupied = occupants.TryGetValue(i + 1, out var occupant); var disabled = disabledSpawnPoints.Contains(i + 1); var pos = ConvertToPreview(p, gridType); var sprite = disabled ? spawnDisabled : occupied ? spawnClaimed : spawnUnclaimed; var offset = sprite.Size.XY.ToInt2() / 2; if (((pos - Viewport.LastMousePos).ToFloat2() / offset.ToFloat2()).LengthSquared <= 1) { TooltipSpawnIndex = spawnPoints.IndexOf(p) + 1; } if (disabled) { Game.Renderer.RgbaSpriteRenderer.DrawSprite(spawnDisabled, pos - offset); continue; } if (occupied) { WidgetUtils.FillEllipseWithColor(new Rectangle(pos.X - offset.X + 1, pos.Y - offset.Y + 1, (int)sprite.Size.X - 2, (int)sprite.Size.Y - 2), occupant.Color); } Game.Renderer.RgbaSpriteRenderer.DrawSprite(sprite, pos - offset); var number = Convert.ToChar('A' + spawnPoints.IndexOf(p)).ToString(); var textOffset = spawnFont.Measure(number) / 2 + spawnLabelOffset; spawnFont.DrawTextWithContrast(number, pos - textOffset, spawnColor, spawnContrastColor, 1); } } }
public override void Draw() { SpriteFont font; if (!Game.Renderer.Fonts.TryGetValue(Font, out font)) { throw new ArgumentException("Requested font '{0}' was not found.".F(Font)); } var text = GetText(); if (text == null) { return; } var textSize = font.Measure(text); var position = RenderOrigin; var offset = font.TopOffset; if (VAlign == TextVAlign.Top) { position += new int2(0, -offset); } if (VAlign == TextVAlign.Middle) { position += new int2(0, (Bounds.Height - textSize.Y - offset) / 2); } if (VAlign == TextVAlign.Bottom) { position += new int2(0, Bounds.Height - textSize.Y); } if (Align == TextAlign.Center) { position += new int2((Bounds.Width - textSize.X) / 2, 0); } if (Align == TextAlign.Right) { position += new int2(Bounds.Width - textSize.X, 0); } if (WordWrap) { text = WidgetUtils.WrapText(text, Bounds.Width, font); } var color = GetColor(); var bgDark = GetContrastColorDark(); var bgLight = GetContrastColorLight(); if (Contrast) { font.DrawTextWithContrast(text, position, color, bgDark, bgLight, 2); } else if (Shadow) { font.DrawTextWithShadow(text, position, color, bgDark, bgLight, 1); } else { font.DrawText(text, position, color); } }
public CommandBarLogic(Widget widget, World world, Dictionary <string, MiniYaml> logicArgs) { this.world = world; var highlightOnButtonPress = false; if (logicArgs.ContainsKey("HighlightOnButtonPress")) { highlightOnButtonPress = FieldLoader.GetValue <bool>("HighlightOnButtonPress", logicArgs["HighlightOnButtonPress"].Value); } var attackMoveButton = widget.GetOrNull <ButtonWidget>("ATTACK_MOVE"); if (attackMoveButton != null) { WidgetUtils.BindButtonIcon(attackMoveButton); attackMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(attackMoveDisabled); }; attackMoveButton.IsHighlighted = () => world.OrderGenerator is AttackMoveOrderGenerator; Action <bool> toggle = allowCancel => { if (attackMoveButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new AttackMoveOrderGenerator(selectedActors, Game.Settings.Game.MouseButtonPreference.Action); } }; attackMoveButton.OnClick = () => toggle(true); attackMoveButton.OnKeyPress = _ => toggle(false); } var forceMoveButton = widget.GetOrNull <ButtonWidget>("FORCE_MOVE"); if (forceMoveButton != null) { WidgetUtils.BindButtonIcon(forceMoveButton); forceMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceMoveDisabled); }; forceMoveButton.IsHighlighted = () => !forceMoveButton.IsDisabled() && IsForceModifiersActive(Modifiers.Alt); forceMoveButton.OnClick = () => { if (forceMoveButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Alt, true); } }; } var forceAttackButton = widget.GetOrNull <ButtonWidget>("FORCE_ATTACK"); if (forceAttackButton != null) { WidgetUtils.BindButtonIcon(forceAttackButton); forceAttackButton.IsDisabled = () => { UpdateStateIfNecessary(); return(forceAttackDisabled); }; forceAttackButton.IsHighlighted = () => !forceAttackButton.IsDisabled() && IsForceModifiersActive(Modifiers.Ctrl) && !(world.OrderGenerator is AttackMoveOrderGenerator); forceAttackButton.OnClick = () => { if (forceAttackButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Ctrl, true); } }; } var guardButton = widget.GetOrNull <ButtonWidget>("GUARD"); if (guardButton != null) { WidgetUtils.BindButtonIcon(guardButton); guardButton.IsDisabled = () => { UpdateStateIfNecessary(); return(guardDisabled); }; guardButton.IsHighlighted = () => world.OrderGenerator is GuardOrderGenerator; Action <bool> toggle = allowCancel => { if (guardButton.IsHighlighted()) { if (allowCancel) { world.CancelInputMode(); } } else { world.OrderGenerator = new GuardOrderGenerator(selectedActors, "Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action); } }; guardButton.OnClick = () => toggle(true); guardButton.OnKeyPress = _ => toggle(false); } var scatterButton = widget.GetOrNull <ButtonWidget>("SCATTER"); if (scatterButton != null) { WidgetUtils.BindButtonIcon(scatterButton); scatterButton.IsDisabled = () => { UpdateStateIfNecessary(); return(scatterDisabled); }; scatterButton.IsHighlighted = () => scatterHighlighted > 0; scatterButton.OnClick = () => { if (highlightOnButtonPress) { scatterHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, false)); }; scatterButton.OnKeyPress = ki => { scatterHighlighted = 2; scatterButton.OnClick(); }; } var deployButton = widget.GetOrNull <ButtonWidget>("DEPLOY"); if (deployButton != null) { WidgetUtils.BindButtonIcon(deployButton); deployButton.IsDisabled = () => { UpdateStateIfNecessary(); var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); return(!selectedDeploys.Any(pair => pair.Trait.CanIssueDeployOrder(pair.Actor, queued))); }; deployButton.IsHighlighted = () => deployHighlighted > 0; deployButton.OnClick = () => { if (highlightOnButtonPress) { deployHighlighted = 2; } var queued = Game.GetModifierKeys().HasModifier(Modifiers.Shift); PerformDeployOrderOnSelection(queued); }; deployButton.OnKeyPress = ki => { deployHighlighted = 2; deployButton.OnClick(); }; } var stopButton = widget.GetOrNull <ButtonWidget>("STOP"); if (stopButton != null) { WidgetUtils.BindButtonIcon(stopButton); stopButton.IsDisabled = () => { UpdateStateIfNecessary(); return(stopDisabled); }; stopButton.IsHighlighted = () => stopHighlighted > 0; stopButton.OnClick = () => { if (highlightOnButtonPress) { stopHighlighted = 2; } PerformKeyboardOrderOnSelection(a => new Order("Stop", a, false)); }; stopButton.OnKeyPress = ki => { stopHighlighted = 2; stopButton.OnClick(); }; } var queueOrdersButton = widget.GetOrNull <ButtonWidget>("QUEUE_ORDERS"); if (queueOrdersButton != null) { WidgetUtils.BindButtonIcon(queueOrdersButton); queueOrdersButton.IsDisabled = () => { UpdateStateIfNecessary(); return(waypointModeDisabled); }; queueOrdersButton.IsHighlighted = () => !queueOrdersButton.IsDisabled() && IsForceModifiersActive(Modifiers.Shift); queueOrdersButton.OnClick = () => { if (queueOrdersButton.IsHighlighted()) { world.CancelInputMode(); } else { world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Shift, false); } }; } var keyOverrides = widget.GetOrNull <LogicKeyListenerWidget>("MODIFIER_OVERRIDES"); if (keyOverrides != null) { var noShiftButtons = new[] { guardButton, deployButton, attackMoveButton }; var keyUpButtons = new[] { guardButton, attackMoveButton }; keyOverrides.AddHandler(e => { // HACK: allow command buttons to be triggered if the shift (queue order modifier) key is held if (e.Modifiers.HasModifier(Modifiers.Shift)) { var eNoShift = e; eNoShift.Modifiers &= ~Modifiers.Shift; foreach (var b in noShiftButtons) { // Button is not used by this mod if (b == null) { continue; } // Button is not valid for this event if (b.IsDisabled() || !b.Key.IsActivatedBy(eNoShift)) { continue; } // Event is not valid for this button if (!(b.DisableKeyRepeat ^ e.IsRepeat) || (e.Event == KeyInputEvent.Up && !keyUpButtons.Contains(b))) { continue; } b.OnKeyPress(e); return(true); } } // HACK: Attack move can be triggered if the ctrl (assault move modifier) // or shift (queue order modifier) keys are pressed, on both key down and key up var eNoMods = e; eNoMods.Modifiers &= ~(Modifiers.Ctrl | Modifiers.Shift); if (attackMoveButton != null && !attackMoveDisabled && attackMoveButton.Key.IsActivatedBy(eNoMods)) { attackMoveButton.OnKeyPress(e); return(true); } return(false); }); } }
public override void DrawOuter() { if (!IsVisible()) { return; } UpdateSmoothScrolling(); var rb = RenderBounds; var scrollbarHeight = rb.Height - 2 * ScrollbarWidth; var thumbHeight = ContentHeight == 0 ? 0 : Math.Max(MinimumThumbSize, (int)(scrollbarHeight * Math.Min(rb.Height * 1f / ContentHeight, 1f))); var thumbOrigin = rb.Y + ScrollbarWidth + (int)((scrollbarHeight - thumbHeight) * (-1f * currentListOffset / (ContentHeight - rb.Height))); if (thumbHeight == scrollbarHeight) { thumbHeight = 0; } switch (ScrollBar) { case ScrollBar.Left: backgroundRect = new Rectangle(rb.X + ScrollbarWidth, rb.Y, rb.Width + 1, rb.Height); upButtonRect = new Rectangle(rb.X, rb.Y, ScrollbarWidth, ScrollbarWidth); downButtonRect = new Rectangle(rb.X, rb.Bottom - ScrollbarWidth, ScrollbarWidth, ScrollbarWidth); scrollbarRect = new Rectangle(rb.X, rb.Y + ScrollbarWidth - 1, ScrollbarWidth, scrollbarHeight + 2); thumbRect = new Rectangle(rb.X, thumbOrigin, ScrollbarWidth, thumbHeight); break; case ScrollBar.Right: backgroundRect = new Rectangle(rb.X, rb.Y, rb.Width - ScrollbarWidth + 1, rb.Height); upButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y, ScrollbarWidth, ScrollbarWidth); downButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Bottom - ScrollbarWidth, ScrollbarWidth, ScrollbarWidth); scrollbarRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y + ScrollbarWidth - 1, ScrollbarWidth, scrollbarHeight + 2); thumbRect = new Rectangle(rb.Right - ScrollbarWidth, thumbOrigin, ScrollbarWidth, thumbHeight); break; case ScrollBar.Hidden: backgroundRect = new Rectangle(rb.X, rb.Y, rb.Width + 1, rb.Height); break; default: throw new ArgumentOutOfRangeException(); } WidgetUtils.DrawPanel(Background, backgroundRect); if (ScrollBar != ScrollBar.Hidden) { var upHover = Ui.MouseOverWidget == this && upButtonRect.Contains(Viewport.LastMousePos); upDisabled = thumbHeight == 0 || currentListOffset >= 0; var downHover = Ui.MouseOverWidget == this && downButtonRect.Contains(Viewport.LastMousePos); downDisabled = thumbHeight == 0 || currentListOffset <= Bounds.Height - ContentHeight; var thumbHover = Ui.MouseOverWidget == this && thumbRect.Contains(Viewport.LastMousePos); WidgetUtils.DrawPanel(ScrollBarBackground, scrollbarRect); ButtonWidget.DrawBackground(Button, upButtonRect, upDisabled, upPressed, upHover, false); ButtonWidget.DrawBackground(Button, downButtonRect, downDisabled, downPressed, downHover, false); if (thumbHeight > 0) { ButtonWidget.DrawBackground(Button, thumbRect, false, HasMouseFocus && thumbHover, thumbHover, false); } var upOffset = !upPressed || upDisabled ? 4 : 4 + ButtonDepth; var downOffset = !downPressed || downDisabled ? 4 : 4 + ButtonDepth; WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", upPressed || upDisabled ? "up_pressed" : "up_arrow"), new float2(upButtonRect.Left + upOffset, upButtonRect.Top + upOffset)); WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", downPressed || downDisabled ? "down_pressed" : "down_arrow"), new float2(downButtonRect.Left + downOffset, downButtonRect.Top + downOffset)); } var drawBounds = backgroundRect.InflateBy(-BorderWidth, -BorderWidth, -BorderWidth, -BorderWidth); Game.Renderer.EnableScissor(drawBounds); // ChildOrigin enumerates the widget tree, so only evaluate it once var co = ChildOrigin; drawBounds.X -= co.X; drawBounds.Y -= co.Y; foreach (var child in Children) { if (child.Bounds.IntersectsWith(drawBounds)) { child.DrawOuter(); } } Game.Renderer.DisableScissor(); }
public override void Draw() { if (video == null) { return; } if (!stopped && !paused) { var nextFrame = 0; if (video.HasAudio && !Game.Sound.DummyEngine) { nextFrame = (int)float2.Lerp(0, video.Frames, Game.Sound.VideoSeekPosition * invLength); } else { nextFrame = video.CurrentFrame + 1; } // Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame if (nextFrame > video.Frames || nextFrame < video.CurrentFrame) { Stop(); return; } var skippedFrames = 0; while (nextFrame > video.CurrentFrame) { video.AdvanceFrame(); videoSprite.Sheet.GetTexture().SetData(video.FrameData); skippedFrames++; } if (skippedFrames > 1) { Log.Write("perf", "VqaPlayer : {0} skipped {1} frames at position {2}", cachedVideo, skippedFrames, video.CurrentFrame); } } WidgetUtils.DrawSprite(videoSprite, videoOrigin, videoSize); if (DrawOverlay) { // Create the scan line grid to render over the video // To avoid aliasing, this must be an integer number of screen pixels. // A few complications to be aware of: // - The video may have a different aspect ratio to the widget RenderBounds // - The RenderBounds coordinates may be a non-integer scale of the screen pixel size // - The screen pixel size may change while the video is playing back // (user moves a window between displays with different DPI on macOS) var scale = Game.Renderer.WindowScale; if (overlaySheet == null || overlayScale != scale) { overlaySheet?.Dispose(); // Calculate the scan line height by converting the video scale (copied from Open()) to screen // pixels, halving it (scan lines cover half the pixel height), and rounding to the nearest integer. var videoScale = Math.Min((float)RenderBounds.Width / video.Width, RenderBounds.Height / (video.Height * AspectRatio)); var halfRowHeight = (int)(videoScale * scale / 2 + 0.5f); // The overlay can be minimally stored in a 1px column which is stretched to cover the full screen var overlayHeight = (int)(RenderBounds.Height * scale / halfRowHeight); var overlaySheetSize = new Size(1, Exts.NextPowerOf2(overlayHeight)); var overlay = new byte[4 * Exts.NextPowerOf2(overlayHeight)]; overlaySheet = new Sheet(SheetType.BGRA, overlaySheetSize); // Every second pixel is the scan line - set alpha to 128 to make the lines less harsh for (var i = 3; i < 4 * overlayHeight; i += 8) { overlay[i] = 128; } overlaySheet.GetTexture().SetData(overlay, overlaySheetSize.Width, overlaySheetSize.Height); overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, overlayHeight), TextureChannel.RGBA); // Overlay origin must be rounded to the nearest screen pixel to prevent aliasing overlayOrigin = new float2((int)(RenderBounds.X * scale + 0.5f), (int)(RenderBounds.Y * scale + 0.5f)) / scale; overlaySize = new float2(RenderBounds.Width, overlayHeight * halfRowHeight / scale); overlayScale = scale; } WidgetUtils.DrawSprite(overlaySprite, overlayOrigin, overlaySize); } }
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; var palette = unit.IconPaletteIsPlayerPalette ? unit.IconPalette + player.InternalName : unit.IconPalette; WidgetUtils.DrawSpriteCentered(icon.Image, worldRenderer.Palette(palette), centerPosition + 0.5f * iconSize, 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() { 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 DrawOuter() { if (!IsVisible()) { return; } var rb = RenderBounds; var scrollbarHeight = rb.Height - 2 * ScrollbarWidth; var thumbHeight = ContentHeight == 0 ? 0 : Math.Max(MinimumThumbSize, (int)(scrollbarHeight * Math.Min(rb.Height * 1f / ContentHeight, 1f))); var thumbOrigin = rb.Y + ScrollbarWidth + (int)((scrollbarHeight - thumbHeight) * (-1f * currentListOffset / (ContentHeight - rb.Height))); if (thumbHeight == scrollbarHeight) { thumbHeight = 0; } backgroundRect = new Rectangle(rb.X, rb.Y, rb.Width - ScrollbarWidth + 1, rb.Height); upButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y, ScrollbarWidth, ScrollbarWidth); downButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Bottom - ScrollbarWidth, ScrollbarWidth, ScrollbarWidth); scrollbarRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y + ScrollbarWidth - 1, ScrollbarWidth, scrollbarHeight + 2); thumbRect = new Rectangle(rb.Right - ScrollbarWidth, thumbOrigin, ScrollbarWidth, thumbHeight); var upHover = Ui.MouseOverWidget == this && upButtonRect.Contains(Viewport.LastMousePos); upDisabled = thumbHeight == 0 || currentListOffset >= 0; var downHover = Ui.MouseOverWidget == this && downButtonRect.Contains(Viewport.LastMousePos); downDisabled = thumbHeight == 0 || currentListOffset <= Bounds.Height - ContentHeight; var thumbHover = Ui.MouseOverWidget == this && thumbRect.Contains(Viewport.LastMousePos); WidgetUtils.DrawPanel(Background, backgroundRect); WidgetUtils.DrawPanel(Background, scrollbarRect); ButtonWidget.DrawBackground(Button, upButtonRect, upDisabled, upPressed, upHover, false); ButtonWidget.DrawBackground(Button, downButtonRect, downDisabled, downPressed, downHover, false); if (thumbHeight > 0) { ButtonWidget.DrawBackground(Button, thumbRect, false, HasMouseFocus && thumbHover, thumbHover, false); } var upOffset = !upPressed || upDisabled ? 4 : 4 + ButtonDepth; var downOffset = !downPressed || downDisabled ? 4 : 4 + ButtonDepth; WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", upPressed || upDisabled ? "up_pressed" : "up_arrow"), new float2(upButtonRect.Left + upOffset, upButtonRect.Top + upOffset)); WidgetUtils.DrawRGBA(ChromeProvider.GetImage("scrollbar", downPressed || downDisabled ? "down_pressed" : "down_arrow"), new float2(downButtonRect.Left + downOffset, downButtonRect.Top + downOffset)); var drawBounds = backgroundRect.InflateBy(-BorderWidth, -BorderWidth, -BorderWidth, -BorderWidth); Game.Renderer.EnableScissor(drawBounds); drawBounds.Offset((-ChildOrigin).ToPoint()); foreach (var child in Children) { if (child.Bounds.IntersectsWith(drawBounds)) { child.DrawOuter(); } } Game.Renderer.DisableScissor(); }
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() { 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, 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.DrawSpriteCentered(icon.Image, worldRenderer.Palette(palette), centerPosition, 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.DrawSpriteCentered(pio.Sprite, worldRenderer.Palette(pio.Palette), centerPosition + pio.Offset(iconSize), 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.DrawSpriteCentered(clock.Image, worldRenderer.Palette(ClockPalette), centerPosition, 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 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); } } } }