Make color of "Ready" text alternate between red and white. Made the code cleaner. Whitespace correction. Whitespace correction again. Change color from red to green and make it moddable Use enum for ReadyTextStyle Use enum for cnc Made variables public and simplified if statements fix enum fix enum and ) ReadyText settings in ra yaml ReadyText settings in cnc yaml Move values from code to ra yaml Move values from code to cnc yaml revert code changes cnc revert code changes ra move around a bit in ra yaml move around a bit in cnc yaml Add values to d2k yaml
556 lines
18 KiB
C#
556 lines
18 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2014 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.RA.Buildings;
|
|
using OpenRA.Mods.RA.Orders;
|
|
using OpenRA.Network;
|
|
using OpenRA.Primitives;
|
|
using OpenRA.Traits;
|
|
using OpenRA.Widgets;
|
|
|
|
namespace OpenRA.Mods.RA.Widgets
|
|
{
|
|
class BuildPaletteWidget : Widget
|
|
{
|
|
public enum ReadyTextStyleOptions { Solid, AlternatingColor, Blinking }
|
|
public readonly ReadyTextStyleOptions ReadyTextStyle = ReadyTextStyleOptions.AlternatingColor;
|
|
public readonly Color ReadyTextAltColor = Color.LimeGreen;
|
|
public int Columns = 3;
|
|
public int Rows = 5;
|
|
|
|
[Translate] public string ReadyText = "";
|
|
[Translate] public string HoldText = "";
|
|
[Translate] public string RequiresText = "";
|
|
|
|
public int IconWidth = 64;
|
|
public int IconHeight = 48;
|
|
|
|
ProductionQueue CurrentQueue;
|
|
List<ProductionQueue> VisibleQueues;
|
|
|
|
bool paletteOpen = false;
|
|
|
|
float2 paletteOpenOrigin;
|
|
float2 paletteClosedOrigin;
|
|
float2 paletteOrigin;
|
|
|
|
int paletteAnimationLength = 7;
|
|
int paletteAnimationFrame = 0;
|
|
bool paletteAnimating = false;
|
|
|
|
List<Pair<Rectangle, Action<MouseInput>>> buttons = new List<Pair<Rectangle, Action<MouseInput>>>();
|
|
List<Pair<Rectangle, Action<MouseInput>>> tabs = new List<Pair<Rectangle, Action<MouseInput>>>();
|
|
Animation cantBuild;
|
|
Animation clock;
|
|
|
|
readonly WorldRenderer worldRenderer;
|
|
readonly World world;
|
|
readonly OrderManager orderManager;
|
|
|
|
[ObjectCreator.UseCtor]
|
|
public BuildPaletteWidget(OrderManager orderManager, World world, WorldRenderer worldRenderer)
|
|
{
|
|
this.orderManager = orderManager;
|
|
this.world = world;
|
|
this.worldRenderer = worldRenderer;
|
|
|
|
cantBuild = new Animation(world, "clock");
|
|
cantBuild.PlayFetchIndex("idle", () => 0);
|
|
clock = new Animation(world, "clock");
|
|
VisibleQueues = new List<ProductionQueue>();
|
|
CurrentQueue = null;
|
|
}
|
|
|
|
public override void Initialize(WidgetArgs args)
|
|
{
|
|
paletteOpenOrigin = new float2(Game.Renderer.Resolution.Width - Columns*IconWidth - 23, 280);
|
|
paletteClosedOrigin = new float2(Game.Renderer.Resolution.Width - 16, 280);
|
|
paletteOrigin = paletteClosedOrigin;
|
|
base.Initialize(args);
|
|
}
|
|
|
|
public override Rectangle EventBounds
|
|
{
|
|
get { return new Rectangle((int)(paletteOrigin.X) - 24, (int)(paletteOrigin.Y), 239, Math.Max(IconHeight * numActualRows, 40 * tabs.Count + 9)); }
|
|
}
|
|
|
|
public override void Tick()
|
|
{
|
|
VisibleQueues.Clear();
|
|
|
|
var queues = world.ActorsWithTrait<ProductionQueue>()
|
|
.Where(p => p.Actor.Owner == world.LocalPlayer)
|
|
.Select(p => p.Trait);
|
|
|
|
if (CurrentQueue != null && CurrentQueue.self.Destroyed)
|
|
CurrentQueue = null;
|
|
|
|
foreach (var queue in queues)
|
|
{
|
|
if (queue.AllItems().Any())
|
|
VisibleQueues.Add(queue);
|
|
else if (CurrentQueue == queue)
|
|
CurrentQueue = null;
|
|
}
|
|
if (CurrentQueue == null)
|
|
CurrentQueue = VisibleQueues.FirstOrDefault();
|
|
|
|
TickPaletteAnimation(world);
|
|
}
|
|
|
|
void TickPaletteAnimation(World world)
|
|
{
|
|
if (!paletteAnimating)
|
|
return;
|
|
|
|
// Increment frame
|
|
if (paletteOpen)
|
|
paletteAnimationFrame++;
|
|
else
|
|
paletteAnimationFrame--;
|
|
|
|
// Calculate palette position
|
|
if (paletteAnimationFrame <= paletteAnimationLength)
|
|
paletteOrigin = float2.Lerp(paletteClosedOrigin, paletteOpenOrigin, paletteAnimationFrame * 1.0f / paletteAnimationLength);
|
|
|
|
// Play palette-open sound at the start of the activate anim (open)
|
|
if (paletteAnimationFrame == 1 && paletteOpen)
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "BuildPaletteOpen", null);
|
|
|
|
// Play palette-close sound at the start of the activate anim (close)
|
|
if (paletteAnimationFrame == paletteAnimationLength + -1 && !paletteOpen)
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "BuildPaletteClose", null);
|
|
|
|
// Animation is complete
|
|
if ((paletteAnimationFrame == 0 && !paletteOpen)
|
|
|| (paletteAnimationFrame == paletteAnimationLength && paletteOpen))
|
|
{
|
|
paletteAnimating = false;
|
|
}
|
|
}
|
|
|
|
public void SetCurrentTab(ProductionQueue queue)
|
|
{
|
|
if (!paletteOpen)
|
|
paletteAnimating = true;
|
|
|
|
paletteOpen = true;
|
|
CurrentQueue = queue;
|
|
}
|
|
|
|
public override bool HandleKeyPress(KeyInput e)
|
|
{
|
|
if (e.Event == KeyInputEvent.Up)
|
|
return false;
|
|
|
|
var hotkey = Hotkey.FromKeyInput(e);
|
|
|
|
if (hotkey == Game.Settings.Keys.NextProductionTabKey)
|
|
return ChangeTab(false);
|
|
else if (hotkey == Game.Settings.Keys.PreviousProductionTabKey)
|
|
return ChangeTab(true);
|
|
|
|
return DoBuildingHotkey(e, world);
|
|
}
|
|
|
|
public override bool HandleMouseInput(MouseInput mi)
|
|
{
|
|
if (mi.Event != MouseInputEvent.Scroll && mi.Event != MouseInputEvent.Down)
|
|
return true;
|
|
|
|
if (mi.Event == MouseInputEvent.Scroll && mi.ScrollDelta < 0)
|
|
return ChangeTab(false);
|
|
|
|
if (mi.Event == MouseInputEvent.Scroll && mi.ScrollDelta > 0)
|
|
return ChangeTab(true);
|
|
|
|
var action = tabs.Where(a => a.First.Contains(mi.Location))
|
|
.Select(a => a.Second).FirstOrDefault();
|
|
if (action == null && paletteOpen)
|
|
action = buttons.Where(a => a.First.Contains(mi.Location))
|
|
.Select(a => a.Second).FirstOrDefault();
|
|
|
|
if (action == null)
|
|
return false;
|
|
|
|
action(mi);
|
|
return true;
|
|
}
|
|
|
|
public override void Draw()
|
|
{
|
|
if (!IsVisible()) return;
|
|
// TODO: fix
|
|
|
|
DrawPalette(CurrentQueue);
|
|
DrawBuildTabs(world);
|
|
}
|
|
|
|
int numActualRows = 5;
|
|
int DrawPalette(ProductionQueue queue)
|
|
{
|
|
buttons.Clear();
|
|
|
|
string paletteCollection = "palette-" + world.LocalPlayer.Country.Race;
|
|
float2 origin = new float2(paletteOrigin.X + 9, paletteOrigin.Y + 9);
|
|
var iconOffset = 0.5f * new float2(IconWidth, IconHeight);
|
|
var x = 0;
|
|
var y = 0;
|
|
|
|
if (queue != null)
|
|
{
|
|
var buildableItems = queue.BuildableItems().ToArray();
|
|
var allBuildables = queue.AllItems().OrderBy(a => a.Traits.Get<BuildableInfo>().BuildPaletteOrder).ToArray();
|
|
|
|
var overlayBits = new List<Pair<Sprite, float2>>();
|
|
var textBits = new List<Pair<float2, string>>();
|
|
numActualRows = Math.Max((allBuildables.Count() + Columns - 1) / Columns, Rows);
|
|
|
|
// Palette Background
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "top"), new float2(origin.X - 9, origin.Y - 9));
|
|
for (var w = 0; w < numActualRows; w++)
|
|
WidgetUtils.DrawRGBA(
|
|
ChromeProvider.GetImage(paletteCollection, "bg-" + (w % 4)),
|
|
new float2(origin.X - 9, origin.Y + IconHeight * w));
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "bottom"),
|
|
new float2(origin.X - 9, origin.Y - 1 + IconHeight * numActualRows));
|
|
|
|
|
|
// Icons
|
|
string tooltipItem = null;
|
|
foreach (var item in allBuildables)
|
|
{
|
|
var rect = new RectangleF(origin.X + x * IconWidth, origin.Y + IconHeight * y, IconWidth, IconHeight);
|
|
var drawPos = new float2(rect.Location);
|
|
var icon = new Animation(world, RenderSimple.GetImage(item));
|
|
icon.Play(item.Traits.Get<TooltipInfo>().Icon);
|
|
WidgetUtils.DrawSHPCentered(icon.Image, drawPos + iconOffset, worldRenderer);
|
|
|
|
var firstOfThis = queue.AllQueued().FirstOrDefault(a => a.Item == item.Name);
|
|
|
|
if (rect.Contains(Viewport.LastMousePos))
|
|
tooltipItem = item.Name;
|
|
|
|
var overlayPos = drawPos + new float2(32, 16);
|
|
|
|
if (firstOfThis != null)
|
|
{
|
|
clock.PlayFetchIndex("idle",
|
|
() => (firstOfThis.TotalTime - firstOfThis.RemainingTime)
|
|
* (clock.CurrentSequence.Length - 1) / firstOfThis.TotalTime);
|
|
clock.Tick();
|
|
WidgetUtils.DrawSHPCentered(clock.Image, drawPos + iconOffset, worldRenderer);
|
|
|
|
if (queue.CurrentItem() == firstOfThis)
|
|
textBits.Add(Pair.New(overlayPos, GetOverlayForItem(firstOfThis)));
|
|
|
|
var repeats = queue.AllQueued().Count(a => a.Item == item.Name);
|
|
if (repeats > 1 || queue.CurrentItem() != firstOfThis)
|
|
textBits.Add(Pair.New(overlayPos + new float2(-24, -14), repeats.ToString()));
|
|
}
|
|
else
|
|
if (buildableItems.All(a => a.Name != item.Name))
|
|
overlayBits.Add(Pair.New(cantBuild.Image, drawPos));
|
|
|
|
var closureName = buildableItems.Any(a => a.Name == item.Name) ? item.Name : null;
|
|
buttons.Add(Pair.New(new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), HandleClick(closureName, world)));
|
|
|
|
if (++x == Columns) { x = 0; y++; }
|
|
}
|
|
if (x != 0) y++;
|
|
|
|
foreach (var ob in overlayBits)
|
|
WidgetUtils.DrawSHPCentered(ob.First, ob.Second + iconOffset, worldRenderer);
|
|
|
|
var font = Game.Renderer.Fonts["TinyBold"];
|
|
foreach (var tb in textBits)
|
|
{
|
|
var size = font.Measure(tb.Second);
|
|
if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber / 9 % 2 == 0 || tb.Second != ReadyText)
|
|
font.DrawTextWithContrast(tb.Second, tb.First - new float2(size.X / 2, 0),
|
|
Color.White, Color.Black, 1);
|
|
else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor)
|
|
font.DrawTextWithContrast(tb.Second, tb.First - new float2(size.X / 2, 0),
|
|
ReadyTextAltColor, Color.Black, 1);
|
|
}
|
|
|
|
// Tooltip
|
|
if (tooltipItem != null && !paletteAnimating && paletteOpen)
|
|
DrawProductionTooltip(world, tooltipItem,
|
|
new float2(Game.Renderer.Resolution.Width, origin.Y + numActualRows * IconHeight + 9).ToInt2());
|
|
}
|
|
|
|
// Palette Dock
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-top"),
|
|
new float2(Game.Renderer.Resolution.Width - 14, origin.Y - 23));
|
|
|
|
for (int i = 0; i < numActualRows; i++)
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-" + (i % 4)),
|
|
new float2(Game.Renderer.Resolution.Width - 14, origin.Y + IconHeight * i));
|
|
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage(paletteCollection, "dock-bottom"),
|
|
new float2(Game.Renderer.Resolution.Width - 14, origin.Y - 1 + IconHeight * numActualRows));
|
|
|
|
return IconHeight * y + 9;
|
|
}
|
|
|
|
string GetOverlayForItem(ProductionItem item)
|
|
{
|
|
if (item.Paused)
|
|
return HoldText;
|
|
|
|
if (item.Done)
|
|
return ReadyText;
|
|
|
|
return WidgetUtils.FormatTime(item.RemainingTimeActual);
|
|
}
|
|
|
|
Action<MouseInput> HandleClick(string name, World world)
|
|
{
|
|
return mi =>
|
|
{
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
|
|
|
|
if (name != null)
|
|
HandleBuildPalette(world, name, (mi.Button == MouseButton.Left));
|
|
};
|
|
}
|
|
|
|
Action<MouseInput> HandleTabClick(ProductionQueue queue, World world)
|
|
{
|
|
return mi =>
|
|
{
|
|
if (mi.Button != MouseButton.Left)
|
|
return;
|
|
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
|
|
var wasOpen = paletteOpen;
|
|
paletteOpen = CurrentQueue != queue || !wasOpen;
|
|
CurrentQueue = queue;
|
|
if (wasOpen != paletteOpen)
|
|
paletteAnimating = true;
|
|
};
|
|
}
|
|
|
|
static string Description(Ruleset rules, string a)
|
|
{
|
|
ActorInfo ai;
|
|
rules.Actors.TryGetValue(a.ToLowerInvariant(), out ai);
|
|
if (ai != null && ai.Traits.Contains<TooltipInfo>())
|
|
return ai.Traits.Get<TooltipInfo>().Name;
|
|
|
|
return a;
|
|
}
|
|
|
|
void HandleBuildPalette(World world, string item, bool isLmb)
|
|
{
|
|
var unit = world.Map.Rules.Actors[item];
|
|
var producing = CurrentQueue.AllQueued().FirstOrDefault(a => a.Item == item);
|
|
|
|
if (isLmb)
|
|
{
|
|
if (producing != null && producing == CurrentQueue.CurrentItem())
|
|
{
|
|
if (producing.Done)
|
|
{
|
|
if (unit.Traits.Contains<BuildingInfo>())
|
|
world.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue.self, item);
|
|
else
|
|
StartProduction(world, item);
|
|
return;
|
|
}
|
|
|
|
if (producing.Paused)
|
|
{
|
|
world.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, false));
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check if the item's build-limit has already been reached
|
|
var queued = CurrentQueue.AllQueued().Count(a => a.Item == unit.Name);
|
|
var inWorld = world.ActorsWithTrait<Buildable>().Count(a => a.Actor.Info.Name == unit.Name && a.Actor.Owner == world.LocalPlayer);
|
|
var buildLimit = unit.Traits.Get<BuildableInfo>().BuildLimit;
|
|
|
|
if (!((buildLimit != 0) && (inWorld + queued >= buildLimit)))
|
|
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, world.LocalPlayer.Country.Race);
|
|
else
|
|
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.BlockedAudio, world.LocalPlayer.Country.Race);
|
|
}
|
|
|
|
StartProduction(world, item);
|
|
}
|
|
else
|
|
{
|
|
if (producing != null)
|
|
{
|
|
// instant cancel of things we havent really started yet, and things that are finished
|
|
if (producing.Paused || producing.Done || producing.TotalCost == producing.RemainingCost)
|
|
{
|
|
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, world.LocalPlayer.Country.Race);
|
|
int numberToCancel = Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1;
|
|
|
|
world.IssueOrder(Order.CancelProduction(CurrentQueue.self, item, numberToCancel));
|
|
}
|
|
else
|
|
{
|
|
Sound.PlayNotification(world.Map.Rules, world.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, world.LocalPlayer.Country.Race);
|
|
world.IssueOrder(Order.PauseProduction(CurrentQueue.self, item, true));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StartProduction(World world, string item)
|
|
{
|
|
world.IssueOrder(Order.StartProduction(CurrentQueue.self, item,
|
|
Game.GetModifierKeys().HasModifier(Modifiers.Shift) ? 5 : 1));
|
|
}
|
|
|
|
void DrawBuildTabs(World world)
|
|
{
|
|
const int tabWidth = 24;
|
|
const int tabHeight = 40;
|
|
var x = paletteOrigin.X - tabWidth;
|
|
var y = paletteOrigin.Y + 9;
|
|
|
|
tabs.Clear();
|
|
|
|
foreach (var queue in VisibleQueues)
|
|
{
|
|
string[] tabKeys = { "normal", "ready", "selected" };
|
|
var producing = queue.CurrentItem();
|
|
var index = queue == CurrentQueue ? 2 : (producing != null && producing.Done) ? 1 : 0;
|
|
|
|
var race = world.LocalPlayer.Country.Race;
|
|
WidgetUtils.DrawRGBA(ChromeProvider.GetImage("tabs-" + tabKeys[index], race + "-" + queue.Info.Type), new float2(x, y));
|
|
|
|
var rect = new Rectangle((int)x, (int)y, tabWidth, tabHeight);
|
|
tabs.Add(Pair.New(rect, HandleTabClick(queue, world)));
|
|
|
|
if (rect.Contains(Viewport.LastMousePos))
|
|
{
|
|
var text = queue.Info.Type;
|
|
var font = Game.Renderer.Fonts["Bold"];
|
|
var sz = font.Measure(text);
|
|
WidgetUtils.DrawPanelPartial("dialog4",
|
|
Rectangle.FromLTRB(rect.Left - sz.X - 30, rect.Top, rect.Left - 5, rect.Bottom),
|
|
PanelSides.All);
|
|
|
|
font.DrawText(text, new float2(rect.Left - sz.X - 20, rect.Top + 12), Color.White);
|
|
}
|
|
|
|
y += tabHeight;
|
|
}
|
|
}
|
|
|
|
static void DrawRightAligned(string text, int2 pos, Color c)
|
|
{
|
|
var font = Game.Renderer.Fonts["Bold"];
|
|
font.DrawText(text, pos - new int2(font.Measure(text).X, 0), c);
|
|
}
|
|
|
|
void DrawProductionTooltip(World world, string unit, int2 pos)
|
|
{
|
|
pos.Y += 15;
|
|
|
|
var pl = world.LocalPlayer;
|
|
var p = pos.ToFloat2() - new float2(297, -3);
|
|
|
|
var info = world.Map.Rules.Actors[unit];
|
|
var tooltip = info.Traits.Get<TooltipInfo>();
|
|
var buildable = info.Traits.Get<BuildableInfo>();
|
|
var cost = info.Traits.Get<ValuedInfo>().Cost;
|
|
var canBuildThis = CurrentQueue.CanBuild(info);
|
|
|
|
var longDescSize = Game.Renderer.Fonts["Regular"].Measure(tooltip.Description.Replace("\\n", "\n")).Y;
|
|
if (!canBuildThis) longDescSize += 8;
|
|
|
|
WidgetUtils.DrawPanel("dialog4", new Rectangle(Game.Renderer.Resolution.Width - 300, pos.Y, 300, longDescSize + 65));
|
|
|
|
Game.Renderer.Fonts["Bold"].DrawText(
|
|
tooltip.Name + (buildable.Hotkey.IsValid() ? " ({0})".F(buildable.Hotkey.DisplayString()) : ""),
|
|
p.ToInt2() + new int2(5, 5), Color.White);
|
|
|
|
var resources = pl.PlayerActor.Trait<PlayerResources>();
|
|
var power = pl.PlayerActor.Trait<PowerManager>();
|
|
|
|
DrawRightAligned("${0}".F(cost), pos + new int2(-5, 5),
|
|
(resources.DisplayCash + resources.DisplayOre >= cost ? Color.White : Color.Red));
|
|
|
|
var lowpower = power.PowerState != PowerState.Normal;
|
|
var time = CurrentQueue.GetBuildTime(info.Name)
|
|
* ((lowpower) ? CurrentQueue.Info.LowPowerSlowdown : 1);
|
|
DrawRightAligned(WidgetUtils.FormatTime(time), pos + new int2(-5, 35), lowpower ? Color.Red : Color.White);
|
|
|
|
var bi = info.Traits.GetOrDefault<BuildingInfo>();
|
|
if (bi != null)
|
|
DrawRightAligned("{1}{0}".F(bi.Power, bi.Power > 0 ? "+" : ""), pos + new int2(-5, 20),
|
|
((power.PowerProvided - power.PowerDrained) >= -bi.Power || bi.Power > 0) ? Color.White : Color.Red);
|
|
|
|
p += new int2(5, 35);
|
|
if (!canBuildThis)
|
|
{
|
|
var prereqs = buildable.Prerequisites.Select(s => Description(world.Map.Rules, s));
|
|
if (prereqs.Any())
|
|
{
|
|
Game.Renderer.Fonts["Regular"].DrawText(RequiresText.F(prereqs.Where(s => !s.StartsWith("~")).JoinWith(", ")), p.ToInt2(), Color.White);
|
|
|
|
p += new int2(0, 8);
|
|
}
|
|
}
|
|
|
|
p += new int2(0, 15);
|
|
Game.Renderer.Fonts["Regular"].DrawText(tooltip.Description.Replace("\\n", "\n"),
|
|
p.ToInt2(), Color.White);
|
|
}
|
|
|
|
bool DoBuildingHotkey(KeyInput e, World world)
|
|
{
|
|
if (!paletteOpen) return false;
|
|
if (CurrentQueue == null) return false;
|
|
|
|
var toBuild = CurrentQueue.BuildableItems().FirstOrDefault(b => b.Traits.Get<BuildableInfo>().Hotkey == Hotkey.FromKeyInput(e));
|
|
|
|
if (toBuild != null)
|
|
{
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
|
|
HandleBuildPalette(world, toBuild.Name, true);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// NOTE: Always return true here to prevent mouse events from passing through the sidebar and interacting with the world behind it.
|
|
bool ChangeTab(bool reverse)
|
|
{
|
|
Sound.PlayNotification(world.Map.Rules, null, "Sounds", "TabClick", null);
|
|
var queues = VisibleQueues.Concat(VisibleQueues);
|
|
if (reverse)
|
|
queues = queues.Reverse();
|
|
var nextQueue = queues.SkipWhile(q => q != CurrentQueue)
|
|
.ElementAtOrDefault(1);
|
|
if (nextQueue != null)
|
|
{
|
|
SetCurrentTab(nextQueue);
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|