diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index fa6d6941db..034dc789b9 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -156,6 +156,7 @@ + diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index 899d6ba3f3..3edcb4b08c 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -162,23 +162,4 @@ namespace OpenRA.Orders } } } - - public static class SelectableExts - { - public static int SelectionPriority(this ActorInfo a) - { - var selectableInfo = a.Traits.GetOrDefault(); - return selectableInfo != null ? selectableInfo.Priority : int.MinValue; - } - - public static Actor WithHighestSelectionPriority(this IEnumerable actors) - { - return actors.MaxByOrDefault(a => a.Info.SelectionPriority()); - } - - public static FrozenActor WithHighestSelectionPriority(this IEnumerable actors) - { - return actors.MaxByOrDefault(a => a.Info.SelectionPriority()); - } - } } diff --git a/OpenRA.Game/SelectableExts.cs b/OpenRA.Game/SelectableExts.cs new file mode 100644 index 0000000000..d762485870 --- /dev/null +++ b/OpenRA.Game/SelectableExts.cs @@ -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 System.Collections.Generic; +using System.Linq; + +namespace OpenRA.Traits +{ + public static class SelectableExts + { + public static int SelectionPriority(this ActorInfo a) + { + var selectableInfo = a.Traits.GetOrDefault(); + return selectableInfo != null ? selectableInfo.Priority : int.MinValue; + } + + const int PriorityRange = 30; + + public static int SelectionPriority(this Actor a) + { + var basePriority = a.Info.Traits.Get().Priority; + var lp = a.World.LocalPlayer; + + if (a.Owner == lp || lp == null) + return basePriority; + + switch (lp.Stances[a.Owner]) + { + case Stance.Ally: return basePriority - PriorityRange; + case Stance.Neutral: return basePriority - 2 * PriorityRange; + case Stance.Enemy: return basePriority - 3 * PriorityRange; + + default: + throw new InvalidOperationException(); + } + } + + public static Actor WithHighestSelectionPriority(this IEnumerable actors) + { + return actors.MaxByOrDefault(a => a.Info.SelectionPriority()); + } + + public static FrozenActor WithHighestSelectionPriority(this IEnumerable actors) + { + return actors.MaxByOrDefault(a => a.Info.SelectionPriority()); + } + + static readonly Actor[] NoActors = { }; + + public static IEnumerable SubsetWithHighestSelectionPriority(this IEnumerable actors) + { + return actors.GroupBy(x => x.SelectionPriority()) + .OrderByDescending(g => g.Key) + .Select(g => g.AsEnumerable()) + .DefaultIfEmpty(NoActors) + .FirstOrDefault(); + } + } +} diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index af381f97e5..d65f31a443 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -8,7 +8,6 @@ */ #endregion -using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -22,8 +21,6 @@ namespace OpenRA.Widgets { public class WorldInteractionControllerWidget : Widget { - static readonly Actor[] NoActors = { }; - protected readonly World World; readonly WorldRenderer worldRenderer; int2? dragStart, dragEnd; @@ -238,7 +235,7 @@ namespace OpenRA.Widgets else if (key == Game.Settings.Keys.SelectAllUnitsKey) { // Select actors on the screen which belong to the current player - var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, player); + var ownUnitsOnScreen = SelectActorsOnScreen(World, worldRenderer, null, player).SubsetWithHighestSelectionPriority(); World.Selection.Combine(World, ownUnitsOnScreen, false, false); } else if (key == Game.Settings.Keys.SelectUnitsByTypeKey) @@ -275,23 +272,24 @@ namespace OpenRA.Widgets static IEnumerable SelectActorsOnScreen(World world, WorldRenderer wr, IEnumerable selectionClasses, Player player) { - return SelectActorsByPlayerByClass(world.ScreenMap.ActorsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight), selectionClasses, player); + return SelectActorsByOwnerAndSelectionClass(world.ScreenMap.ActorsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight), player, selectionClasses); } static IEnumerable SelectActorsInWorld(World world, IEnumerable selectionClasses, Player player) { - return SelectActorsByPlayerByClass(world.ActorMap.ActorsInWorld(), selectionClasses, player); + return SelectActorsByOwnerAndSelectionClass(world.ActorMap.ActorsInWorld(), player, selectionClasses); } - static IEnumerable SelectActorsByPlayerByClass(IEnumerable actors, IEnumerable selectionClasses, Player player) + static IEnumerable SelectActorsByOwnerAndSelectionClass(IEnumerable actors, Player owner, IEnumerable selectionClasses) { return actors.Where(a => { - if (a.Owner != player) + if (a.Owner != owner) return false; + var s = a.TraitOrDefault(); - // sc == null means that units, that meet all other criteria, get selected + // selectionClasses == null means that units, that meet all other criteria, get selected return s != null && (selectionClasses == null || selectionClasses.Contains(s.Class)); }); } @@ -304,11 +302,7 @@ namespace OpenRA.Widgets return world.ScreenMap.ActorsInBox(a, b) .Where(x => x.HasTrait() && (x.Owner.IsAlliedWith(world.RenderPlayer) || !world.FogObscures(x))) - .GroupBy(x => x.GetSelectionPriority()) - .OrderByDescending(g => g.Key) - .Select(g => g.AsEnumerable()) - .DefaultIfEmpty(NoActors) - .FirstOrDefault(); + .SubsetWithHighestSelectionPriority(); } bool ToggleStatusBars() @@ -324,28 +318,4 @@ namespace OpenRA.Widgets return true; } } - - static class PriorityExts - { - const int PriorityRange = 30; - - public static int GetSelectionPriority(this Actor a) - { - var basePriority = a.Info.Traits.Get().Priority; - var lp = a.World.LocalPlayer; - - if (a.Owner == lp || lp == null) - return basePriority; - - switch (lp.Stances[a.Owner]) - { - case Stance.Ally: return basePriority - PriorityRange; - case Stance.Neutral: return basePriority - 2 * PriorityRange; - case Stance.Enemy: return basePriority - 3 * PriorityRange; - - default: - throw new InvalidOperationException(); - } - } - } } \ No newline at end of file