Moves SupportPowers and related Widgets to Mods.Common

This commit is contained in:
reaperrr
2015-01-11 12:29:19 +01:00
parent f897a9ff01
commit be9d37f30e
20 changed files with 37 additions and 41 deletions

View File

@@ -0,0 +1,72 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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 OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
public class SupportPowerBinLogic
{
[ObjectCreator.UseCtor]
public SupportPowerBinLogic(Widget widget, World world)
{
var palette = widget.Get<SupportPowersWidget>("SUPPORT_PALETTE");
var background = widget.GetOrNull("PALETTE_BACKGROUND");
var foreground = widget.GetOrNull("PALETTE_FOREGROUND");
if (background != null || foreground != null)
{
Widget backgroundTemplate = null;
Widget foregroundTemplate = null;
if (background != null)
backgroundTemplate = background.Get("ICON_TEMPLATE");
if (foreground != null)
foregroundTemplate = foreground.Get("ICON_TEMPLATE");
Action<int, int> updateBackground = (_, icons) =>
{
var rowHeight = palette.IconSize.Y + palette.IconMargin;
if (background != null)
{
background.RemoveChildren();
for (var i = 0; i < icons; i++)
{
var row = backgroundTemplate.Clone();
row.Bounds.Y += i * rowHeight;
background.AddChild(row);
}
}
if (foreground != null)
{
foreground.RemoveChildren();
for (var i = 0; i < icons; i++)
{
var row = foregroundTemplate.Clone();
row.Bounds.Y += i * rowHeight;
foreground.AddChild(row);
}
}
};
palette.OnIconCountChanged += updateBackground;
// Set the initial palette state
updateBackground(0, 0);
}
}
}
}

View File

@@ -0,0 +1,67 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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 OpenRA.Mods.Common.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
public class SupportPowerTooltipLogic
{
[ObjectCreator.UseCtor]
public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette)
{
widget.IsVisible = () => palette.TooltipPower != null;
var nameLabel = widget.Get<LabelWidget>("NAME");
var timeLabel = widget.Get<LabelWidget>("TIME");
var descLabel = widget.Get<LabelWidget>("DESC");
var nameFont = Game.Renderer.Fonts[nameLabel.Font];
var timeFont = Game.Renderer.Fonts[timeLabel.Font];
var descFont = Game.Renderer.Fonts[descLabel.Font];
var name = "";
var time = "";
var desc = "";
var baseHeight = widget.Bounds.Height;
var timeOffset = timeLabel.Bounds.X;
SupportPowerInstance lastPower = null;
tooltipContainer.BeforeRender = () =>
{
var sp = palette.TooltipPower;
if (sp == null)
return;
if (sp.Info == null)
return; // no instances actually exist (race with destroy)
time = "{0} / {1}".F(WidgetUtils.FormatTime(sp.RemainingTime),
WidgetUtils.FormatTime(sp.Info.ChargeTime * 25));
if (sp == lastPower)
return;
name = sp.Info.Description;
desc = sp.Info.LongDesc.Replace("\\n", "\n");
var timeWidth = timeFont.Measure(time).X;
var topWidth = nameFont.Measure(name).X + timeWidth + timeOffset;
var descSize = descFont.Measure(desc);
widget.Bounds.Width = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X);
widget.Bounds.Height = baseHeight + descSize.Y;
timeLabel.Bounds.X = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth;
lastPower = sp;
};
nameLabel.GetText = () => name;
timeLabel.GetText = () => time;
descLabel.GetText = () => desc;
}
}
}

View File

@@ -0,0 +1,108 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets
{
public class ObserverSupportPowerIconsWidget : Widget
{
public Func<Player> GetPlayer;
Animation icon;
World world;
WorldRenderer worldRenderer;
Dictionary<string, Animation> clocks;
public int IconWidth = 32;
public int IconHeight = 24;
public int IconSpacing = 8;
[ObjectCreator.UseCtor]
public ObserverSupportPowerIconsWidget(World world, WorldRenderer worldRenderer)
{
this.world = world;
this.worldRenderer = worldRenderer;
clocks = new Dictionary<string, Animation>();
icon = new Animation(world, "icon");
}
protected ObserverSupportPowerIconsWidget(ObserverSupportPowerIconsWidget other)
: base(other)
{
GetPlayer = other.GetPlayer;
icon = other.icon;
world = other.world;
worldRenderer = other.worldRenderer;
clocks = other.clocks;
}
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);
}
}
static string GetOverlayForItem(SupportPowerInstance item)
{
if (item.Disabled) return "ON HOLD";
if (item.Ready) return "READY";
return WidgetUtils.FormatTime(item.RemainingTime);
}
public override Widget Clone()
{
return new ObserverSupportPowerIconsWidget(this);
}
}
}

View File

@@ -0,0 +1,65 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets
{
public class SupportPowerTimerWidget : Widget
{
public readonly string Font = "Bold";
public readonly string Format = "{0}: {1}";
public readonly TimerOrder Order = TimerOrder.Descending;
readonly IEnumerable<SupportPowerInstance> powers;
Pair<string, Color>[] texts;
[ObjectCreator.UseCtor]
public SupportPowerTimerWidget(World world)
{
powers = world.ActorsWithTrait<SupportPowerManager>()
.Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant)
.SelectMany(s => s.Trait.Powers.Values)
.Where(p => p.Instances.Any() && p.Info.DisplayTimer && !p.Disabled);
}
public override void Tick()
{
texts = powers.Select(p =>
{
var time = WidgetUtils.FormatTime(p.RemainingTime, false);
var text = Format.F(p.Info.Description, time);
var color = !p.Ready || Game.LocalTick % 50 < 25 ? p.Instances[0].Self.Owner.Color.RGB : Color.White;
return Pair.New(text, color);
}).ToArray();
}
public override void Draw()
{
if (!IsVisible() || texts == null)
return;
var y = 0;
foreach (var t in texts)
{
var font = Game.Renderer.Fonts[Font];
font.DrawTextWithContrast(t.First, new float2(Bounds.Location) + new float2(0, y), t.Second, Color.Black, 1);
y += (font.Measure(t.First).Y + 5) * (int)Order;
}
}
public enum TimerOrder { Ascending = -1, Descending = 1 }
}
}

View File

@@ -0,0 +1,194 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets
{
public class SupportPowersWidget : Widget
{
[Translate] public readonly string ReadyText = "";
[Translate] public readonly string HoldText = "";
public readonly int2 IconSize = new int2(64, 48);
public readonly int IconMargin = 10;
public readonly int2 IconSpriteOffset = int2.Zero;
public readonly string TooltipContainer;
public readonly string TooltipTemplate = "SUPPORT_POWER_TOOLTIP";
public int IconCount { get; private set; }
public event Action<int, int> OnIconCountChanged = (a, b) => { };
readonly WorldRenderer worldRenderer;
readonly SupportPowerManager spm;
Animation icon;
Animation clock;
Dictionary<Rectangle, SupportPowerIcon> icons = new Dictionary<Rectangle, SupportPowerIcon>();
public SupportPowerInstance TooltipPower { get; private set; }
Lazy<TooltipContainerWidget> tooltipContainer;
Rectangle eventBounds;
public override Rectangle EventBounds { get { return eventBounds; } }
SpriteFont overlayFont;
float2 holdOffset, readyOffset, timeOffset;
[ObjectCreator.UseCtor]
public SupportPowersWidget(World world, WorldRenderer worldRenderer)
{
this.worldRenderer = worldRenderer;
spm = world.LocalPlayer.PlayerActor.Trait<SupportPowerManager>();
tooltipContainer = Exts.Lazy(() =>
Ui.Root.Get<TooltipContainerWidget>(TooltipContainer));
icon = new Animation(world, "icon");
clock = new Animation(world, "clock");
}
public class SupportPowerIcon
{
public SupportPowerInstance Power;
public float2 Pos;
public Sprite Sprite;
}
public void RefreshIcons()
{
icons = new Dictionary<Rectangle, SupportPowerIcon>();
var powers = spm.Powers.Values.Where(p => !p.Disabled);
var oldIconCount = IconCount;
IconCount = 0;
var rb = RenderBounds;
foreach (var p in powers)
{
var rect = new Rectangle(rb.X, rb.Y + IconCount * (IconSize.Y + IconMargin), IconSize.X, IconSize.Y);
icon.Play(p.Info.Icon);
var power = new SupportPowerIcon()
{
Power = p,
Pos = new float2(rect.Location),
Sprite = icon.Image
};
icons.Add(rect, power);
IconCount++;
}
eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty;
if (oldIconCount != IconCount)
OnIconCountChanged(oldIconCount, IconCount);
}
public override void Draw()
{
var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset;
overlayFont = Game.Renderer.Fonts["TinyBold"];
holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2;
// Icons
foreach (var p in icons.Values)
{
WidgetUtils.DrawSHPCentered(p.Sprite, p.Pos + iconOffset, worldRenderer);
// Charge progress
var sp = p.Power;
clock.PlayFetchIndex("idle",
() => sp.TotalTime == 0 ? clock.CurrentSequence.Length - 1 : (sp.TotalTime - sp.RemainingTime)
* (clock.CurrentSequence.Length - 1) / sp.TotalTime);
clock.Tick();
WidgetUtils.DrawSHPCentered(clock.Image, p.Pos + iconOffset, worldRenderer);
}
// Overlay
foreach (var p in icons.Values)
{
if (p.Power.Ready)
overlayFont.DrawTextWithContrast(ReadyText,
p.Pos + readyOffset,
Color.White, Color.Black, 1);
else if (!p.Power.Active)
overlayFont.DrawTextWithContrast(HoldText,
p.Pos + holdOffset,
Color.White, Color.Black, 1);
else
overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime),
p.Pos + timeOffset,
Color.White, Color.Black, 1);
}
}
public override void Tick()
{
// TODO: Only do this when the powers have changed
RefreshIcons();
}
public override void MouseEntered()
{
if (TooltipContainer == null)
return;
tooltipContainer.Value.SetTooltip(TooltipTemplate,
new WidgetArgs() { { "palette", this } });
}
public override void MouseExited()
{
if (TooltipContainer == null)
return;
tooltipContainer.Value.RemoveTooltip();
}
public override bool HandleMouseInput(MouseInput mi)
{
if (mi.Event == MouseInputEvent.Move)
{
var icon = icons.Where(i => i.Key.Contains(mi.Location))
.Select(i => i.Value).FirstOrDefault();
TooltipPower = icon != null ? icon.Power : null;
return false;
}
if (mi.Event != MouseInputEvent.Down)
return false;
var clicked = icons.Where(i => i.Key.Contains(mi.Location))
.Select(i => i.Value).FirstOrDefault();
if (clicked != null)
{
if (!clicked.Power.Active)
Sound.PlayToPlayer(spm.Self.Owner, clicked.Power.Info.InsufficientPowerSound);
clicked.Power.Target();
}
return true;
}
}
}