Merge pull request #4147 from Mailaender/cycle-hotkeys

Fixed and improved cycle hotkeys
This commit is contained in:
Paul Chote
2013-12-08 11:15:10 -08:00
7 changed files with 84 additions and 42 deletions

View File

@@ -15,6 +15,8 @@ NEW:
Added a setting to always display unit status bars (can also be toggled by hotkey). Added a setting to always display unit status bars (can also be toggled by hotkey).
Added a setting for team health bar colors. Added a setting for team health bar colors.
Added a new hotkey to select all units on screen (default: CTRL + A). Added a new hotkey to select all units on screen (default: CTRL + A).
Added a new hotkey to jump to production buildings (default: TAB).
Changed default hotkey (PageUp/Down) for build palette cycling and made reverse user configurable.
Asset Browser: Asset Browser:
Fixed crashes when trying to load invalid filenames or sprites with just 1 frame. Fixed crashes when trying to load invalid filenames or sprites with just 1 frame.
Added support for all sprite types. Added support for all sprite types.

View File

@@ -155,7 +155,9 @@ namespace OpenRA.GameRules
public Hotkey PowerDownKey = new Hotkey(Keycode.F11, Modifiers.None); public Hotkey PowerDownKey = new Hotkey(Keycode.F11, Modifiers.None);
public Hotkey RepairKey = new Hotkey(Keycode.F12, Modifiers.None); public Hotkey RepairKey = new Hotkey(Keycode.F12, Modifiers.None);
public Hotkey CycleTabsKey = new Hotkey(Keycode.TAB, Modifiers.None); public Hotkey NextProductionTabKey = new Hotkey(Keycode.PAGEDOWN, Modifiers.None);
public Hotkey PreviousProductionTabKey = new Hotkey(Keycode.PAGEUP, Modifiers.None);
public Hotkey CycleProductionBuildingsKey = new Hotkey(Keycode.TAB, Modifiers.None);
public Hotkey ToggleStatusBarsKey = new Hotkey(Keycode.INSERT, Modifiers.None); public Hotkey ToggleStatusBarsKey = new Hotkey(Keycode.INSERT, Modifiers.None);

20
OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs Executable file → Normal file
View File

@@ -89,10 +89,12 @@ namespace OpenRA.Mods.Cnc.Widgets
paletteWidget = Lazy.New(() => Ui.Root.Get<ProductionPaletteWidget>(PaletteWidget)); paletteWidget = Lazy.New(() => Ui.Root.Get<ProductionPaletteWidget>(PaletteWidget));
} }
public void SelectNextTab(bool reverse) public bool SelectNextTab(bool reverse)
{ {
if (queueGroup == null) if (queueGroup == null)
return; return true;
Sound.PlayNotification(null, "Sounds", "ClickSound", null);
// Prioritize alerted queues // Prioritize alerted queues
var queues = Groups[queueGroup].Tabs.Select(t => t.Queue) var queues = Groups[queueGroup].Tabs.Select(t => t.Queue)
@@ -103,6 +105,8 @@ namespace OpenRA.Mods.Cnc.Widgets
CurrentQueue = queues.SkipWhile(q => q != CurrentQueue) CurrentQueue = queues.SkipWhile(q => q != CurrentQueue)
.Skip(1).FirstOrDefault() ?? queues.FirstOrDefault(); .Skip(1).FirstOrDefault() ?? queues.FirstOrDefault();
return true;
} }
public string QueueGroup public string QueueGroup
@@ -277,12 +281,12 @@ namespace OpenRA.Mods.Cnc.Widgets
if (e.Event != KeyInputEvent.Down) if (e.Event != KeyInputEvent.Down)
return false; return false;
if (Hotkey.FromKeyInput(e) == Game.Settings.Keys.CycleTabsKey) var hotkey = Hotkey.FromKeyInput(e);
{
Sound.PlayNotification(null, "Sounds", "ClickSound", null); if (hotkey == Game.Settings.Keys.NextProductionTabKey)
SelectNextTab(e.Modifiers.HasModifier(Modifiers.Shift)); return SelectNextTab(false);
return true; else if (hotkey == Game.Settings.Keys.PreviousProductionTabKey)
} return SelectNextTab(true);
return false; return false;
} }

View File

@@ -10,12 +10,21 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Mods.RA.Orders;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Mods.RA.Orders;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
{ {
static class PrimaryExts
{
public static bool IsPrimaryBuilding(this Actor a)
{
var pb = a.TraitOrDefault<PrimaryBuilding>();
return pb != null && pb.IsPrimary;
}
}
[Desc("Used together with ClassicProductionQueue.")] [Desc("Used together with ClassicProductionQueue.")]
class PrimaryBuildingInfo : TraitInfo<PrimaryBuilding> { } class PrimaryBuildingInfo : TraitInfo<PrimaryBuilding> { }
@@ -26,18 +35,18 @@ namespace OpenRA.Mods.RA
public IEnumerable<TagType> GetTags() public IEnumerable<TagType> GetTags()
{ {
yield return (isPrimary) ? TagType.Primary : TagType.None; yield return isPrimary ? TagType.Primary : TagType.None;
} }
public IEnumerable<IOrderTargeter> Orders public IEnumerable<IOrderTargeter> Orders
{ {
get { yield return new DeployOrderTargeter( "PrimaryProducer", 1 ); } get { yield return new DeployOrderTargeter("PrimaryProducer", 1); }
} }
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued ) public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
{ {
if( order.OrderID == "PrimaryProducer" ) if (order.OrderID == "PrimaryProducer")
return new Order( order.OrderID, self, false ); return new Order(order.OrderID, self, false);
return null; return null;
} }
@@ -63,7 +72,7 @@ namespace OpenRA.Mods.RA
.ActorsWithTrait<PrimaryBuilding>() .ActorsWithTrait<PrimaryBuilding>()
.Where(a => a.Actor.Owner == self.Owner) .Where(a => a.Actor.Owner == self.Owner)
.Where(x => x.Trait.IsPrimary .Where(x => x.Trait.IsPrimary
&& (x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains(p)))) && x.Actor.Info.Traits.Get<ProductionInfo>().Produces.Contains(p)))
b.Trait.SetPrimaryProducer(b.Actor, false); b.Trait.SetPrimaryProducer(b.Actor, false);
isPrimary = true; isPrimary = true;
@@ -71,13 +80,4 @@ namespace OpenRA.Mods.RA
Sound.PlayNotification(self.Owner, "Speech", "PrimaryBuildingSelected", self.Owner.Country.Race); Sound.PlayNotification(self.Owner, "Speech", "PrimaryBuildingSelected", self.Owner.Country.Race);
} }
} }
static class PrimaryExts
{
public static bool IsPrimaryBuilding(this Actor a)
{
var pb = a.TraitOrDefault<PrimaryBuilding>();
return pb != null && pb.IsPrimary;
}
}
} }

View File

@@ -149,11 +149,13 @@ namespace OpenRA.Mods.RA.Widgets
if (e.Event == KeyInputEvent.Up) if (e.Event == KeyInputEvent.Up)
return false; return false;
if (Hotkey.FromKeyInput(e) == Game.Settings.Keys.CycleTabsKey) var hotkey = Hotkey.FromKeyInput(e);
{
TabChange(e.Modifiers.HasModifier(Modifiers.Shift)); if (hotkey == Game.Settings.Keys.NextProductionTabKey)
return true; return ChangeTab(false);
} else if (hotkey == Game.Settings.Keys.PreviousProductionTabKey)
return ChangeTab(true);
return DoBuildingHotkey(e, world); return DoBuildingHotkey(e, world);
} }
@@ -164,15 +166,10 @@ namespace OpenRA.Mods.RA.Widgets
return true; return true;
if (mi.Button == MouseButton.WheelDown) if (mi.Button == MouseButton.WheelDown)
{ return ChangeTab(false);
TabChange(false);
return true;
}
if (mi.Button == MouseButton.WheelUp) if (mi.Button == MouseButton.WheelUp)
{ return ChangeTab(true);
TabChange(true);
return true;
}
var action = tabs.Where(a => a.First.Contains(mi.Location)) var action = tabs.Where(a => a.First.Contains(mi.Location))
.Select(a => a.Second).FirstOrDefault(); .Select(a => a.Second).FirstOrDefault();
@@ -515,14 +512,21 @@ namespace OpenRA.Mods.RA.Widgets
return false; return false;
} }
void TabChange(bool shift) // 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(null, "Sounds", "TabClick", null);
var queues = VisibleQueues.Concat(VisibleQueues); var queues = VisibleQueues.Concat(VisibleQueues);
if (shift) queues = queues.Reverse(); if (reverse)
queues = queues.Reverse();
var nextQueue = queues.SkipWhile(q => q != CurrentQueue) var nextQueue = queues.SkipWhile(q => q != CurrentQueue)
.ElementAtOrDefault(1); .ElementAtOrDefault(1);
if (nextQueue != null) if (nextQueue != null)
{
SetCurrentTab(nextQueue); SetCurrentTab(nextQueue);
return true;
}
return true;
} }
} }
} }

View File

@@ -257,9 +257,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{ "PowerDownKey", "Power-down mode" }, { "PowerDownKey", "Power-down mode" },
{ "RepairKey", "Repair mode" }, { "RepairKey", "Repair mode" },
{ "CycleTabsKey", "Cycle production tabs" }, { "NextProductionTabKey", "Next production tab" },
{ "PreviousProductionTabKey", "Previous production tab" },
{ "CycleProductionBuildingsKey", "Cycle production facilities" },
{ "ToggleStatusBarsKey", "Toggle status bars" } { "ToggleStatusBarsKey", "Toggle status bars" },
}; };
var unitHotkeys = new Dictionary<string, string>() var unitHotkeys = new Dictionary<string, string>()

View File

@@ -47,9 +47,13 @@ namespace OpenRA.Mods.RA.Widgets
{ {
var key = Hotkey.FromKeyInput(e); var key = Hotkey.FromKeyInput(e);
var ks = Game.Settings.Keys; var ks = Game.Settings.Keys;
if (key == ks.CycleBaseKey) if (key == ks.CycleBaseKey)
return CycleBases(); return CycleBases();
if (key == ks.CycleProductionBuildingsKey)
return CycleProductionBuildings();
if (key == ks.ToLastEventKey) if (key == ks.ToLastEventKey)
return ToLastEvent(); return ToLastEvent();
@@ -199,6 +203,30 @@ namespace OpenRA.Mods.RA.Widgets
return ToSelection(); return ToSelection();
} }
bool CycleProductionBuildings()
{
var facilities = world.ActorsWithTrait<Production>()
.Where(a => a.Actor.Owner == world.LocalPlayer && !a.Actor.HasTrait<BaseBuilding>())
.OrderBy(f => f.Actor.Info.Traits.Get<ProductionInfo>().Produces.First())
.ToArray();
if (!facilities.Any())
return true;
var next = facilities
.Select(b => b.Actor)
.SkipWhile(b => !world.Selection.Actors.Contains(b))
.Skip(1)
.FirstOrDefault();
if (next == null)
next = facilities.Select(b => b.Actor).First();
world.Selection.Combine(world, new Actor[] { next }, false, true);
return ToSelection();
}
bool ToLastEvent() bool ToLastEvent()
{ {
if (world.LocalPlayer == null) if (world.LocalPlayer == null)