diff --git a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj index 0713fd3395..67d44f1880 100644 --- a/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj +++ b/OpenRA.Mods.Cnc/OpenRA.Mods.Cnc.csproj @@ -102,7 +102,6 @@ - @@ -110,7 +109,6 @@ - diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs index 9a941734d3..12f6995fa0 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs @@ -9,6 +9,8 @@ #endregion using System.Drawing; +using System.Linq; +using OpenRA.Mods.RA; using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Orders; using OpenRA.Mods.RA.Widgets; @@ -100,9 +102,22 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic playerWidgets.Get("OPTIONS_BUTTON").OnClick = OptionsClicked; - var winLossWatcher = playerWidgets.Get("WIN_LOSS_WATCHER"); - winLossWatcher.OnTick = () => + var radarEnabled = false; + var cachedRadarEnabled = false; + sidebarRoot.Get("RADAR_MINIMAP").IsEnabled = () => radarEnabled; + + var sidebarTicker = playerWidgets.Get("SIDEBAR_TICKER"); + sidebarTicker.OnTick = () => { + // Update radar bin + radarEnabled = world.ActorsWithTrait() + .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); + + if (radarEnabled != cachedRadarEnabled) + Sound.PlayNotification(null, "Sounds", (radarEnabled ? "RadarUp" : "RadarDown"), null); + cachedRadarEnabled = radarEnabled; + + // Switch to observer mode after win/loss if (world.LocalPlayer.WinState != WinState.Undefined) Game.RunAfterTick(() => { @@ -115,11 +130,12 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic siloBar.GetProvided = () => playerResources.OreCapacity; siloBar.GetUsed = () => playerResources.Ore; siloBar.TooltipFormat = "Silo Usage: {0}/{1}"; - siloBar.RightIndicator = true; siloBar.GetBarColor = () => { - if (playerResources.Ore == playerResources.OreCapacity) return Color.Red; - if (playerResources.Ore >= 0.8 * playerResources.OreCapacity) return Color.Orange; + if (playerResources.Ore == playerResources.OreCapacity) + return Color.Red; + if (playerResources.Ore >= 0.8 * playerResources.OreCapacity) + return Color.Orange; return Color.LimeGreen; }; @@ -127,11 +143,12 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic powerBar.GetProvided = () => powerManager.PowerProvided; powerBar.GetUsed = () => powerManager.PowerDrained; powerBar.TooltipFormat = "Power Usage: {0}/{1}"; - powerBar.RightIndicator = false; powerBar.GetBarColor = () => { - if (powerManager.PowerState == PowerState.Critical) return Color.Red; - if (powerManager.PowerState == PowerState.Low) return Color.Orange; + if (powerManager.PowerState == PowerState.Critical) + return Color.Red; + if (powerManager.PowerState == PowerState.Low) + return Color.Orange; return Color.LimeGreen; }; } diff --git a/OpenRA.Mods.Cnc/Widgets/ResourceBarWidget.cs b/OpenRA.Mods.Cnc/Widgets/ResourceBarWidget.cs deleted file mode 100755 index 7038fb46ba..0000000000 --- a/OpenRA.Mods.Cnc/Widgets/ResourceBarWidget.cs +++ /dev/null @@ -1,84 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Drawing; -using OpenRA.FileFormats; -using OpenRA.Graphics; -using OpenRA.Traits; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Cnc.Widgets -{ - public class ResourceBarWidget : Widget - { - public readonly string TooltipTemplate = "SIMPLE_TOOLTIP"; - public readonly string TooltipContainer; - Lazy tooltipContainer; - - public float LowStorageThreshold = 0.8f; - EWMA providedLerp = new EWMA(0.3f); - EWMA usedLerp = new EWMA(0.3f); - - public Func GetProvided = () => 0; - public Func GetUsed = () => 0; - public string TooltipFormat = ""; - public bool RightIndicator = false; - public Func GetBarColor = () => Color.White; - - [ObjectCreator.UseCtor] - public ResourceBarWidget(World world) - { - tooltipContainer = Lazy.New(() => - Ui.Root.Get(TooltipContainer)); - } - - public override void MouseEntered() - { - if (TooltipContainer == null) return; - Func getText = () => TooltipFormat.F(GetUsed(), GetProvided()); - tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() {{ "getText", getText }}); - } - - public override void MouseExited() - { - if (TooltipContainer == null) return; - tooltipContainer.Value.RemoveTooltip(); - } - - public override void Draw() - { - var scaleBy = 100.0f; - var provided = GetProvided(); - var used = GetUsed(); - var max = Math.Max(provided, used); - while (max >= scaleBy) scaleBy *= 2; - - var providedFrac = providedLerp.Update(provided/scaleBy); - var usedFrac = usedLerp.Update(used/scaleBy); - - var color = GetBarColor(); - - var b = RenderBounds; - var rect = new RectangleF(b.X, float2.Lerp( b.Bottom, b.Top, providedFrac ), - b.Width, providedFrac*b.Height); - Game.Renderer.LineRenderer.FillRect(rect, color); - - var indicator = ChromeProvider.GetImage("sidebar-bits", - RightIndicator ? "right-indicator" : "left-indicator"); - - var indicatorX = RightIndicator ? (b.Right - indicator.size.X) : b.Left; - - var pos = new float2(indicatorX, float2.Lerp( b.Bottom, b.Top, usedFrac ) - indicator.size.Y / 2); - - Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, pos); - } - } -} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 421f9d8589..6713cdc609 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -408,8 +408,6 @@ - - @@ -456,6 +454,9 @@ + + + diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs index 6a532d3a2c..e8a1743cea 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs @@ -11,6 +11,7 @@ using System.Drawing; using System.Linq; using OpenRA.Network; +using OpenRA.Mods.RA.Buildings; using OpenRA.Traits; using OpenRA.Widgets; @@ -77,6 +78,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic observerWidgets.Get("INGAME_STATS_BUTTON").OnClick = () => gameRoot.Get("OBSERVER_STATS").Visible ^= true; } + enum RadarBinState { Closed, BinAnimating, RadarAnimating, Open }; void InitPlayerWidgets() { var playerWidgets = Game.LoadWidget(world, "PLAYER_WIDGETS", playerRoot, new WidgetArgs()); @@ -104,9 +106,48 @@ namespace OpenRA.Mods.RA.Widgets.Logic moneyBin.Get("POWER_DOWN").GetKey = _ => Game.Settings.Keys.PowerDownKey; moneyBin.Get("REPAIR").GetKey = _ => Game.Settings.Keys.RepairKey; - var winLossWatcher = playerWidgets.Get("WIN_LOSS_WATCHER"); - winLossWatcher.OnTick = () => + bool radarActive = false; + RadarBinState binState = RadarBinState.Closed; + var radarBin = playerWidgets.Get("INGAME_RADAR_BIN"); + radarBin.IsOpen = () => radarActive || binState > RadarBinState.BinAnimating; + radarBin.AfterOpen = () => binState = RadarBinState.RadarAnimating; + radarBin.AfterClose = () => binState = RadarBinState.Closed; + + var radarMap = radarBin.Get("RADAR_MINIMAP"); + radarMap.IsEnabled = () => radarActive && binState >= RadarBinState.RadarAnimating; + radarMap.AfterOpen = () => binState = RadarBinState.Open; + radarMap.AfterClose = () => binState = RadarBinState.BinAnimating; + + radarBin.Get("RADAR_BIN_BG").GetImageCollection = () => "chrome-"+world.LocalPlayer.Country.Race; + + var powerManager = world.LocalPlayer.PlayerActor.Trait(); + var powerBar = radarBin.Get("POWERBAR"); + powerBar.IndicatorCollection = "power-"+world.LocalPlayer.Country.Race; + powerBar.GetProvided = () => powerManager.PowerProvided; + powerBar.GetUsed = () => powerManager.PowerDrained; + powerBar.TooltipFormat = "Power Usage: {0}/{1}"; + powerBar.GetBarColor = () => { + if (powerManager.PowerState == PowerState.Critical) + return Color.Red; + if (powerManager.PowerState == PowerState.Low) + return Color.Orange; + return Color.LimeGreen; + }; + + var cachedRadarActive = false; + var sidebarTicker = playerWidgets.Get("SIDEBAR_TICKER"); + sidebarTicker.OnTick = () => + { + // Update radar bin + radarActive = world.ActorsWithTrait() + .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); + + if (radarActive != cachedRadarActive) + Sound.PlayNotification(null, "Sounds", (radarActive ? "RadarUp" : "RadarDown"), null); + cachedRadarActive = radarActive; + + // Switch to observer mode after win/loss if (world.LocalPlayer.WinState != WinState.Undefined) Game.RunAfterTick(() => { diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/SimpleTooltipLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/SimpleTooltipLogic.cs similarity index 90% rename from OpenRA.Mods.Cnc/Widgets/Logic/SimpleTooltipLogic.cs rename to OpenRA.Mods.RA/Widgets/Logic/SimpleTooltipLogic.cs index 3939b26bce..f47a072bb6 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/SimpleTooltipLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/SimpleTooltipLogic.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, @@ -11,7 +11,7 @@ using System; using OpenRA.Widgets; -namespace OpenRA.Mods.Cnc.Widgets.Logic +namespace OpenRA.Mods.RA.Widgets.Logic { public class SimpleTooltipLogic { diff --git a/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs b/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs deleted file mode 100755 index c9957b170a..0000000000 --- a/OpenRA.Mods.RA/Widgets/PowerBinWidget.cs +++ /dev/null @@ -1,119 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Drawing; -using OpenRA.Graphics; -using OpenRA.Mods.RA.Buildings; -using OpenRA.Widgets; - -namespace OpenRA.Mods.RA.Widgets -{ - public class PowerBinWidget : Widget - { - // Power bar - float2 powerOrigin = new float2(42, 205); // Relative to radarOrigin - Size powerSize = new Size(138, 5); - - float? lastPowerProvidedPos; - float? lastPowerDrainedPos; - string powerCollection; - - readonly string RadarBin = "INGAME_RADAR_BIN"; - readonly PowerManager power; - readonly World world; - - [ObjectCreator.UseCtor] - public PowerBinWidget(World world) - { - this.world = world; - - if (world.LocalPlayer != null) - power = world.LocalPlayer.PlayerActor.Trait(); - } - - static Color GetPowerColor(PowerManager pm) - { - if (pm.PowerState == PowerState.Critical) return Color.Red; - if (pm.PowerState == PowerState.Low) return Color.Orange; - return Color.LimeGreen; - } - - const float PowerBarLerpFactor = .2f; - - public override void Draw() - { - if( world.LocalPlayer == null ) return; - if( world.LocalPlayer.WinState != WinState.Undefined ) return; - - var radarBin = Ui.Root.Get(RadarBin); - - powerCollection = "power-" + world.LocalPlayer.Country.Race; - - // Nothing to draw - if (power.PowerProvided == 0 && power.PowerDrained == 0) - return; - - // Draw bar horizontally - var barStart = powerOrigin + radarBin.RadarOrigin; - var barEnd = barStart + new float2(powerSize.Width, 0); - - float powerScaleBy = 100; - var maxPower = Math.Max(power.PowerProvided, power.PowerDrained); - - while (maxPower >= powerScaleBy) powerScaleBy *= 2; - - // Current power supply - var powerLevelTemp = barStart.X + (barEnd.X - barStart.X) * (power.PowerProvided / powerScaleBy); - lastPowerProvidedPos = float2.Lerp(lastPowerProvidedPos.GetValueOrDefault(powerLevelTemp), powerLevelTemp, PowerBarLerpFactor); - var powerLevel = new float2(lastPowerProvidedPos.Value, barStart.Y); - - var color = GetPowerColor(power); - - var colorDark = Exts.ColorLerp(0.25f, color, Color.Black); - for (int i = 0; i < powerSize.Height; i++) - { - color = (i - 1 < powerSize.Height / 2) ? color : colorDark; - var leftOffset = new float2(0, i); - var rightOffset = new float2(0, i); - // Indent corners - if ((i == 0 || i == powerSize.Height - 1) && powerLevel.X - barStart.X > 1) - { - leftOffset.X += 1; - rightOffset.X -= 1; - } - Game.Renderer.LineRenderer.DrawLine(barStart + leftOffset, powerLevel + rightOffset, color, color); - } - - // Power usage indicator - var indicator = ChromeProvider.GetImage( powerCollection, "power-indicator"); - var powerDrainedTemp = barStart.X + (barEnd.X - barStart.X) * (power.PowerDrained / powerScaleBy); - lastPowerDrainedPos = float2.Lerp(lastPowerDrainedPos.GetValueOrDefault(powerDrainedTemp), powerDrainedTemp, PowerBarLerpFactor); - var powerDrainLevel = new float2(lastPowerDrainedPos.Value - indicator.size.X / 2, barStart.Y - 1); - - Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, powerDrainLevel); - - // Render the tooltip - var rect = new Rectangle((int) barStart.X, (int) barStart.Y, powerSize.Width, powerSize.Height); - - if (rect.InflateBy(0, 5, 0, 5).Contains(Viewport.LastMousePos)) - { - var pos = new int2(rect.Left + 5, rect.Top + 5); - - var border = WidgetUtils.GetBorderSizes("dialog4"); - WidgetUtils.DrawPanel("dialog4", rect.InflateBy(0, 0, 0, 50 + border[1])); - - Game.Renderer.Fonts["Bold"].DrawText("Power", pos, Color.White); - pos += new int2(0, 20); - Game.Renderer.Fonts["Regular"].DrawText("Provided: {0}\nDrained: {1}".F(power.PowerProvided, power.PowerDrained), pos, Color.White); - } - } - } -} diff --git a/OpenRA.Mods.RA/Widgets/RadarBinWidget.cs b/OpenRA.Mods.RA/Widgets/RadarBinWidget.cs deleted file mode 100755 index 9505c29cb4..0000000000 --- a/OpenRA.Mods.RA/Widgets/RadarBinWidget.cs +++ /dev/null @@ -1,232 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Drawing; -using System.Linq; -using OpenRA.Graphics; -using OpenRA.Traits; -using OpenRA.Widgets; - -namespace OpenRA.Mods.RA.Widgets -{ - public class RadarBinWidget : Widget - { - public string WorldInteractionController = null; - - static float2 radarOpenOrigin = new float2(Game.viewport.Width - 215, 29); - static float2 radarClosedOrigin = new float2(Game.viewport.Width - 215, -166); - float2 radarOrigin = radarClosedOrigin; - float radarMinimapHeight; - const int radarSlideAnimationLength = 15; - const int radarActivateAnimationLength = 5; - int radarAnimationFrame = 0; - bool radarAnimating = false; - bool hasRadar = false; - string radarCollection; - - float previewScale = 0; - RectangleF mapRect = Rectangle.Empty; - int2 previewOrigin; - - Sprite terrainSprite; - Sprite customTerrainSprite; - Sprite actorSprite; - Sprite shroudSprite; - - /* hack to expose this to other broken widgets which rely on it */ - public float2 RadarOrigin { get { return radarOrigin; } } - - readonly World world; - - [ObjectCreator.UseCtor] - public RadarBinWidget(World world) - { - this.world = world; - var size = Math.Max(world.Map.Bounds.Width, world.Map.Bounds.Height); - previewScale = Math.Min(192f / world.Map.Bounds.Width, 192f / world.Map.Bounds.Height); - previewOrigin = new int2(9 + (int)(radarOpenOrigin.X + previewScale * (size - world.Map.Bounds.Width)/2), (int)(radarOpenOrigin.Y + previewScale * (size - world.Map.Bounds.Height)/2)); - mapRect = new RectangleF(previewOrigin.X, previewOrigin.Y, (int)(world.Map.Bounds.Width * previewScale), (int)(world.Map.Bounds.Height * previewScale)); - - // Only needs to be done once - var terrainBitmap = Minimap.TerrainBitmap(world.Map); - var r = new Rectangle( 0, 0, world.Map.Bounds.Width, world.Map.Bounds.Height ); - var s = new Size( terrainBitmap.Width, terrainBitmap.Height ); - terrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); - terrainSprite.sheet.Texture.SetData(terrainBitmap); - - // Data is set in Tick() - customTerrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); - actorSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); - shroudSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); - } - - public override string GetCursor(int2 pos) - { - if (world == null || !hasRadar) - return null; - - var loc = MinimapPixelToCell(pos); - - var mi = new MouseInput - { - Location = loc.ToInt2(), - Button = MouseButton.Right, - Modifiers = Game.GetModifierKeys() - }; - - var cursor = world.OrderGenerator.GetCursor( world, loc, mi ); - if (cursor == null) - return "default"; - - return CursorProvider.HasCursorSequence(cursor+"-minimap") ? cursor+"-minimap" : cursor; - } - - public override bool HandleMouseInput(MouseInput mi) - { - if (!hasRadar || radarAnimating) return false; // we're not set up for this. - - if (!mapRect.Contains(mi.Location)) - return false; - - var loc = MinimapPixelToCell(mi.Location); - if ((mi.Event == MouseInputEvent.Down || mi.Event == MouseInputEvent.Move) && mi.Button == MouseButton.Left) - Game.viewport.Center(loc.ToFloat2()); - - if (mi.Event == MouseInputEvent.Down && mi.Button == MouseButton.Right) - { - // fake a mousedown/mouseup here - var fakemi = new MouseInput - { - Event = MouseInputEvent.Down, - Button = MouseButton.Right, - Modifiers = mi.Modifiers, - Location = (((loc.ToPPos().ToFloat2()) - Game.viewport.Location) * Game.viewport.Zoom).ToInt2() - }; - - if (WorldInteractionController != null) - { - var controller = Ui.Root.Get(WorldInteractionController); - controller.HandleMouseInput(fakemi); - fakemi.Event = MouseInputEvent.Up; - controller.HandleMouseInput(fakemi); - } - } - - return true; - } - - public override Rectangle EventBounds - { - get { return new Rectangle((int)mapRect.X, (int)mapRect.Y, (int)mapRect.Width, (int)mapRect.Height);} - } - - public override void Draw() - { - if( world == null || world.LocalPlayer == null ) return; - if( world.LocalPlayer.WinState != WinState.Undefined ) return; - - radarCollection = "radar-" + world.LocalPlayer.Country.Race; - var rsr = Game.Renderer.RgbaSpriteRenderer; - rsr.DrawSprite(ChromeProvider.GetImage(radarCollection, "left"), radarOrigin); - rsr.DrawSprite(ChromeProvider.GetImage(radarCollection, "right"), radarOrigin + new float2(201, 0)); - rsr.DrawSprite(ChromeProvider.GetImage(radarCollection, "bottom"), radarOrigin + new float2(0, 192)); - rsr.DrawSprite(ChromeProvider.GetImage(radarCollection, "bg"), radarOrigin + new float2(9, 0)); - - // Don't draw the radar if the tray is moving - if (radarAnimationFrame >= radarSlideAnimationLength) - { - var o = new float2(mapRect.Location.X, mapRect.Location.Y + world.Map.Bounds.Height * previewScale * (1 - radarMinimapHeight)/2); - var s = new float2(mapRect.Size.Width, mapRect.Size.Height*radarMinimapHeight); - rsr.DrawSprite(terrainSprite, o, s); - rsr.DrawSprite(customTerrainSprite, o, s); - rsr.DrawSprite(actorSprite, o, s); - rsr.DrawSprite(shroudSprite, o, s); - - // Draw viewport rect - if (radarAnimationFrame == radarSlideAnimationLength + radarActivateAnimationLength) - { - var wr = Game.viewport.WorldRect; - var wro = new CPos(wr.X, wr.Y); - var tl = CellToMinimapPixel(wro); - var br = CellToMinimapPixel(wro + new CVec(wr.Width, wr.Height)); - - Game.Renderer.EnableScissor((int)mapRect.Left, (int)mapRect.Top, (int)mapRect.Width, (int)mapRect.Height); - Game.Renderer.LineRenderer.DrawRect(tl, br, Color.White); - Game.Renderer.DisableScissor(); - } - } - } - - int updateTicks = 0; - public override void Tick() - { - var hasRadarNew = world - .ActorsWithTrait() - .Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); - - if (hasRadarNew != hasRadar) - { - radarAnimating = true; - Sound.PlayNotification(null, "Sounds", (hasRadarNew ? "RadarUp" : "RadarDown"), null); - } - - hasRadar = hasRadarNew; - - // Build the radar image - if (hasRadar) - { - --updateTicks; - if (updateTicks <= 0) - { - updateTicks = 12; - customTerrainSprite.sheet.Texture.SetData(Minimap.CustomTerrainBitmap(world)); - } - - if (updateTicks == 8) - actorSprite.sheet.Texture.SetData(Minimap.ActorsBitmap(world)); - - if (updateTicks == 4) - shroudSprite.sheet.Texture.SetData(Minimap.ShroudBitmap(world)); - } - - if (!radarAnimating) - return; - - // Increment frame - if (hasRadar) - radarAnimationFrame++; - else - radarAnimationFrame--; - - // Calculate radar bin position - if (radarAnimationFrame <= radarSlideAnimationLength) - radarOrigin = float2.Lerp(radarClosedOrigin, radarOpenOrigin, radarAnimationFrame * 1.0f / radarSlideAnimationLength); - - // Minimap height - if (radarAnimationFrame >= radarSlideAnimationLength) - radarMinimapHeight = float2.Lerp(0, 1, (radarAnimationFrame - radarSlideAnimationLength) * 1.0f / radarActivateAnimationLength); - - // Animation is complete - if (radarAnimationFrame == (hasRadar ? radarSlideAnimationLength + radarActivateAnimationLength : 0)) - radarAnimating = false; - } - - int2 CellToMinimapPixel(CPos p) - { - return new int2((int)(mapRect.X +previewScale*(p.X - world.Map.Bounds.Left)), (int)(mapRect.Y + previewScale*(p.Y - world.Map.Bounds.Top))); - } - - CPos MinimapPixelToCell(int2 p) - { - return new CPos(world.Map.Bounds.Left + (int)((p.X - mapRect.X) / previewScale), world.Map.Bounds.Top + (int)((p.Y - mapRect.Y) / previewScale)); - } - } -} diff --git a/OpenRA.Mods.RA/Widgets/RadarWidget.cs b/OpenRA.Mods.RA/Widgets/RadarWidget.cs index c9b0248b49..6e4f57c716 100755 --- a/OpenRA.Mods.RA/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.RA/Widgets/RadarWidget.cs @@ -22,16 +22,18 @@ namespace OpenRA.Mods.RA.Widgets public int AnimationLength = 5; public string RadarOnlineSound = null; public string RadarOfflineSound = null; + public Func IsEnabled = () => false; + public Action AfterOpen = () => {}; + public Action AfterClose = () => {}; float radarMinimapHeight; - int AnimationFrame = 0; + int frame = 0; bool hasRadar = false; - bool animating = false; int updateTicks = 0; float previewScale = 0; - RectangleF mapRect = Rectangle.Empty; - int2 previewOrigin; + int2 previewOrigin = int2.Zero; + Rectangle mapRect = Rectangle.Empty; Sprite terrainSprite; Sprite customTerrainSprite; @@ -47,15 +49,19 @@ namespace OpenRA.Mods.RA.Widgets { base.Initialize(args); - var size = Math.Max(world.Map.Bounds.Width, world.Map.Bounds.Height); - previewScale = Math.Min(RenderBounds.Width * 1f / world.Map.Bounds.Width, RenderBounds.Height * 1f / world.Map.Bounds.Height); - previewOrigin = new int2(RenderOrigin.X, RenderOrigin.Y + (int)(previewScale * (size - world.Map.Bounds.Height)/2)); - mapRect = new RectangleF(previewOrigin.X, previewOrigin.Y, (int)(world.Map.Bounds.Width * previewScale), (int)(world.Map.Bounds.Height * previewScale)); + var width = world.Map.Bounds.Width; + var height = world.Map.Bounds.Height; + var size = Math.Max(width, height); + var rb = RenderBounds; + + previewScale = Math.Min(rb.Width * 1f / width, rb.Height * 1f / height); + previewOrigin = new int2((int)(previewScale*(size - width)/2), (int)(previewScale*(size - height)/2)); + mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale*width), (int)(previewScale*height)); // Only needs to be done once var terrainBitmap = Minimap.TerrainBitmap(world.Map); - var r = new Rectangle( 0, 0, world.Map.Bounds.Width, world.Map.Bounds.Height ); - var s = new Size( terrainBitmap.Width, terrainBitmap.Height ); + var r = new Rectangle(0, 0, width, height); + var s = new Size(terrainBitmap.Width, terrainBitmap.Height); terrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha); terrainSprite.sheet.Texture.SetData(terrainBitmap); @@ -88,10 +94,11 @@ namespace OpenRA.Mods.RA.Widgets public override bool HandleMouseInput(MouseInput mi) { - if (!hasRadar || animating) return false; + if (!hasRadar) + return true; if (!mapRect.Contains(mi.Location)) - return false; + return true; var loc = MinimapPixelToCell(mi.Location); if ((mi.Event == MouseInputEvent.Down || mi.Event == MouseInputEvent.Move) && mi.Button == MouseButton.Left) @@ -120,17 +127,16 @@ namespace OpenRA.Mods.RA.Widgets return true; } - public override Rectangle EventBounds - { - get { return new Rectangle((int)mapRect.X, (int)mapRect.Y, (int)mapRect.Width, (int)mapRect.Height);} - } + public override Rectangle EventBounds { get { return mapRect; } } public override void Draw() { - if (world == null) return; + if (world == null) + return; var o = new float2(mapRect.Location.X, mapRect.Location.Y + world.Map.Bounds.Height * previewScale * (1 - radarMinimapHeight)/2); var s = new float2(mapRect.Size.Width, mapRect.Size.Height*radarMinimapHeight); + var rsr = Game.Renderer.RgbaSpriteRenderer; rsr.DrawSprite(terrainSprite, o, s); rsr.DrawSprite(customTerrainSprite, o, s); @@ -138,63 +144,64 @@ namespace OpenRA.Mods.RA.Widgets rsr.DrawSprite(shroudSprite, o, s); // Draw viewport rect - if (hasRadar && !animating) + if (hasRadar) { var wr = Game.viewport.WorldRect; var wro = new CPos(wr.X, wr.Y); var tl = CellToMinimapPixel(wro); var br = CellToMinimapPixel(wro + new CVec(wr.Width, wr.Height)); - Game.Renderer.EnableScissor((int)mapRect.Left, (int)mapRect.Top, (int)mapRect.Width, (int)mapRect.Height); + Game.Renderer.EnableScissor(mapRect.Left, mapRect.Top, mapRect.Width, mapRect.Height); Game.Renderer.LineRenderer.DrawRect(tl, br, Color.White); Game.Renderer.DisableScissor(); } } + bool cachedEnabled; public override void Tick() { - var hasRadarNew = world.LocalPlayer == null || world.LocalPlayer.WinState != WinState.Undefined || - world.ActorsWithTrait().Any(a => a.Actor.Owner == world.LocalPlayer && a.Trait.IsActive); - - if (hasRadarNew != hasRadar) + // Update the radar animation even when its closed + // This avoids obviously stale data from being shown when first opened. + // TODO: This delayed updating is a giant hack + --updateTicks; + if (updateTicks <= 0) { - animating = true; - Sound.Play(hasRadarNew ? RadarOnlineSound : RadarOfflineSound); - } - hasRadar = hasRadarNew; - - // Build the radar image - if (hasRadar) - { - --updateTicks; - if (updateTicks <= 0) - { - updateTicks = 12; - customTerrainSprite.sheet.Texture.SetData(Minimap.CustomTerrainBitmap(world)); - } - - if (updateTicks == 8) - actorSprite.sheet.Texture.SetData(Minimap.ActorsBitmap(world)); - - if (updateTicks == 4) - shroudSprite.sheet.Texture.SetData(Minimap.ShroudBitmap(world)); + updateTicks = 12; + customTerrainSprite.sheet.Texture.SetData(Minimap.CustomTerrainBitmap(world)); } - if (!animating) + if (updateTicks == 8) + actorSprite.sheet.Texture.SetData(Minimap.ActorsBitmap(world)); + + if (updateTicks == 4) + shroudSprite.sheet.Texture.SetData(Minimap.ShroudBitmap(world)); + + // Enable/Disable the radar + var enabled = IsEnabled(); + if (enabled != cachedEnabled) + Sound.Play(enabled ? RadarOnlineSound : RadarOfflineSound); + cachedEnabled = enabled; + + var targetFrame = enabled ? AnimationLength : 0; + hasRadar = enabled && frame == AnimationLength; + if (frame == targetFrame) return; - // Increment frame - if (hasRadar) - AnimationFrame++; - else - AnimationFrame--; + frame += enabled ? 1 : -1; + radarMinimapHeight = float2.Lerp(0, 1, (float)frame / AnimationLength); - // Minimap height - radarMinimapHeight = float2.Lerp(0, 1, AnimationFrame*1.0f / AnimationLength); + // Update map rectangle for event handling + var ro = RenderOrigin; + mapRect = new Rectangle(previewOrigin.X + ro.X, previewOrigin.Y + ro.Y, mapRect.Width, mapRect.Height); // Animation is complete - if (AnimationFrame == (hasRadar ? AnimationLength : 0)) - animating = false; + if (frame == targetFrame) + { + if (enabled) + AfterOpen(); + else + AfterClose(); + } } int2 CellToMinimapPixel(CPos p) diff --git a/OpenRA.Mods.RA/Widgets/ResourceBarWidget.cs b/OpenRA.Mods.RA/Widgets/ResourceBarWidget.cs new file mode 100755 index 0000000000..32d0c28d5a --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/ResourceBarWidget.cs @@ -0,0 +1,138 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Drawing; +using OpenRA.FileFormats; +using OpenRA.Graphics; +using OpenRA.Traits; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets +{ + public enum ResourceBarOrientation { Vertical, Horizontal } + public enum ResourceBarStyle { Flat, Bevelled } + public class ResourceBarWidget : Widget + { + public readonly string TooltipTemplate = "SIMPLE_TOOLTIP"; + public readonly string TooltipContainer; + Lazy tooltipContainer; + + public string TooltipFormat = ""; + public ResourceBarOrientation Orientation = ResourceBarOrientation.Vertical; + public ResourceBarStyle Style = ResourceBarStyle.Flat; + public string IndicatorCollection = "sidebar-bits"; + public string IndicatorImage = "indicator"; + + public Func GetProvided = () => 0; + public Func GetUsed = () => 0; + public Func GetBarColor = () => Color.White; + EWMA providedLerp = new EWMA(0.3f); + EWMA usedLerp = new EWMA(0.3f); + + [ObjectCreator.UseCtor] + public ResourceBarWidget(World world) + { + tooltipContainer = Lazy.New(() => + Ui.Root.Get(TooltipContainer)); + } + + public override void MouseEntered() + { + if (TooltipContainer == null) + return; + + Func getText = () => TooltipFormat.F(GetUsed(), GetProvided()); + tooltipContainer.Value.SetTooltip(TooltipTemplate, new WidgetArgs() {{ "getText", getText }}); + } + + public override void MouseExited() + { + if (TooltipContainer == null) + return; + tooltipContainer.Value.RemoveTooltip(); + } + + public override void Draw() + { + var scaleBy = 100.0f; + var provided = GetProvided(); + var used = GetUsed(); + var max = Math.Max(provided, used); + while (max >= scaleBy) + scaleBy *= 2; + + var providedFrac = providedLerp.Update(provided/scaleBy); + var usedFrac = usedLerp.Update(used/scaleBy); + + var b = RenderBounds; + var indicator = ChromeProvider.GetImage(IndicatorCollection, IndicatorImage); + + var color = GetBarColor(); + if (Orientation == ResourceBarOrientation.Vertical) + { + if (Style == ResourceBarStyle.Bevelled) + { + var colorDark = Exts.ColorLerp(0.25f, color, Color.Black); + for (var i = 0; i < b.Height; i++) + { + color = (i - 1 < b.Height / 2) ? color : colorDark; + var bottom = new float2(b.Left + i, b.Bottom); + var top = new float2(b.Left + i, b.Bottom + providedFrac*b.Height); + + // Indent corners + if ((i == 0 || i == b.Width - 1) && providedFrac*b.Height > 1) + { + bottom.Y += 1; + top.Y -= 1; + } + + Game.Renderer.LineRenderer.DrawLine(bottom, top, color, color); + } + } + else + Game.Renderer.LineRenderer.FillRect(new Rectangle(b.X, (int)float2.Lerp(b.Bottom, b.Top, providedFrac), + b.Width, (int)(providedFrac*b.Height)), color); + + var x = (b.Left + b.Right - indicator.size.X) / 2; + var y = float2.Lerp(b.Bottom, b.Top, usedFrac) - indicator.size.Y / 2; + Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, new float2(x, y)); + } + else + { + if (Style == ResourceBarStyle.Bevelled) + { + var colorDark = Exts.ColorLerp(0.25f, color, Color.Black); + for (var i = 0; i < b.Height; i++) + { + color = (i - 1 < b.Height / 2) ? color : colorDark; + var left = new float2(b.Left, b.Top + i); + var right = new float2(b.Left + providedFrac*b.Width, b.Top + i); + + // Indent corners + if ((i == 0 || i == b.Height - 1) && providedFrac*b.Width > 1) + { + left.X += 1; + right.X -= 1; + } + + Game.Renderer.LineRenderer.DrawLine(left, right, color, color); + } + } + else + Game.Renderer.LineRenderer.FillRect(new Rectangle(b.X, b.Y, (int)(providedFrac*b.Width), b.Height), color); + + var x = float2.Lerp(b.Left, b.Right, usedFrac) - indicator.size.X / 2; + var y = (b.Bottom + b.Top - indicator.size.Y) / 2; + Game.Renderer.RgbaSpriteRenderer.DrawSprite(indicator, new float2(x, y)); + } + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/SlidingContainerWidget.cs b/OpenRA.Mods.RA/Widgets/SlidingContainerWidget.cs new file mode 100755 index 0000000000..134a91014a --- /dev/null +++ b/OpenRA.Mods.RA/Widgets/SlidingContainerWidget.cs @@ -0,0 +1,66 @@ +#region Copyright & License Information +/* + * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Drawing; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Traits; +using OpenRA.Widgets; + +namespace OpenRA.Mods.RA.Widgets +{ + public class SlidingContainerWidget : Widget + { + public int2 OpenOffset = int2.Zero; + public int2 ClosedOffset = int2.Zero; + public int AnimationLength = 0; + public Func IsOpen = () => false; + public Action AfterOpen = () => {}; + public Action AfterClose = () => {}; + + int2 offset; + int frame; + + public SlidingContainerWidget() : base() { } + public override void Initialize(WidgetArgs args) + { + base.Initialize(args); + + // Start in the closed position + offset = ClosedOffset; + } + + public override void Tick() + { + var open = IsOpen(); + + var targetFrame = open ? AnimationLength : 0; + if (frame == targetFrame) + return; + + // Update child origin + frame += open ? 1 : -1; + offset = int2.Lerp(ClosedOffset, OpenOffset, frame, AnimationLength); + + // Animation is complete + if (frame == targetFrame) + { + if (open) + AfterOpen(); + else + AfterClose(); + } + } + + public override Rectangle EventBounds { get { return Rectangle.Empty; } } + public override int2 ChildOrigin { get { return RenderOrigin + offset; } } + } +} diff --git a/artsrc/cnc/chrome.svg b/artsrc/cnc/chrome.svg index 56a282f7ca..7f653feeee 100644 --- a/artsrc/cnc/chrome.svg +++ b/artsrc/cnc/chrome.svg @@ -99,9 +99,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="15.999999" - inkscape:cx="385.97751" - inkscape:cy="397.09537" + inkscape:zoom="5.6568539" + inkscape:cx="371.83537" + inkscape:cy="425.37964" inkscape:document-units="px" inkscape:current-layer="svg2" showgrid="false" @@ -205,13 +205,6 @@ - - + x="403" + y="591.36224" /> + +