diff --git a/OpenRa.Game/Controller.cs b/OpenRa.Game/Controller.cs index 62b0e6047d..a7f649ef5c 100644 --- a/OpenRa.Game/Controller.cs +++ b/OpenRa.Game/Controller.cs @@ -13,6 +13,7 @@ namespace OpenRa public class Controller : IHandleInput { public IOrderGenerator orderGenerator; + public Selection selection = new Selection(); readonly Func GetModifierKeys; @@ -22,10 +23,7 @@ namespace OpenRa CancelInputMode(); } - public void CancelInputMode() - { - orderGenerator = new UnitOrderGenerator(new Actor[] { }); - } + public void CancelInputMode() { orderGenerator = new UnitOrderGenerator(); } public bool ToggleInputMode() where T : IOrderGenerator, new() { @@ -83,7 +81,7 @@ namespace OpenRa if (orderGenerator is UnitOrderGenerator) { var newSelection = world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy); - CombineSelection(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy); + selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy); } dragStart = dragEnd = xy; @@ -98,29 +96,6 @@ namespace OpenRa return true; } - void CombineSelection(World world, IEnumerable newSelection, bool isCombine, bool isClick) - { - var oldSelection = (orderGenerator is UnitOrderGenerator) - ? (orderGenerator as UnitOrderGenerator).selection : new Actor[] { }.AsEnumerable(); - - if (isClick) - { - var adjNewSelection = newSelection.Take(1); /* todo: select BEST, not FIRST */ - orderGenerator = new UnitOrderGenerator(isCombine - ? oldSelection.SymmetricDifference(adjNewSelection) : adjNewSelection); - } - else - orderGenerator = new UnitOrderGenerator(isCombine - ? oldSelection.Union(newSelection) : newSelection); - - var voicedUnit = ((UnitOrderGenerator)orderGenerator).selection - .Where(a => a.traits.Contains() - && a.Owner == world.LocalPlayer) - .FirstOrDefault(); - - Sound.PlayVoice("Select", voicedUnit); - } - public Pair? SelectionBox { get @@ -158,20 +133,17 @@ namespace OpenRa public void DoControlGroup(World world, int group, Modifiers mods) { - var uog = orderGenerator as UnitOrderGenerator; - if (uog == null) return; - if (mods.HasModifier(Modifiers.Ctrl)) { - if (!uog.selection.Any()) + if (!selection.Actors.Any()) return; controlGroups[group].Clear(); for (var i = 0; i < 10; i++) /* all control groups */ - controlGroups[i].RemoveAll(a => uog.selection.Contains(a)); + controlGroups[i].RemoveAll(a => selection.Actors.Contains(a)); - controlGroups[group].AddRange(uog.selection); + controlGroups[group].AddRange(selection.Actors); return; } @@ -181,7 +153,8 @@ namespace OpenRa return; } - CombineSelection(world, controlGroups[group], mods.HasModifier(Modifiers.Shift), false); + selection.Combine(world, controlGroups[group], + mods.HasModifier(Modifiers.Shift), false); } public int? GetControlGroupForActor(Actor a) @@ -191,4 +164,33 @@ namespace OpenRa .FirstOrDefault(); } } + + public class Selection + { + List actors = new List(); + + public void Combine(World world, IEnumerable newSelection, bool isCombine, bool isClick) + { + var oldSelection = actors.AsEnumerable(); + + if (isClick) + { + var adjNewSelection = newSelection.Take(1); /* todo: select BEST, not FIRST */ + actors = (isCombine ? oldSelection.SymmetricDifference(adjNewSelection) : adjNewSelection).ToList(); + } + else + actors = (isCombine ? oldSelection.Union(newSelection) : newSelection).ToList(); + + var voicedUnit = actors.FirstOrDefault(a => a.traits.Contains() && a.Owner == world.LocalPlayer); + Sound.PlayVoice("Select", voicedUnit); + } + + public IEnumerable Actors { get { return actors; } } + public void Clear() { actors = new List(); } + + public void Tick(World world) + { + actors.RemoveAll(a => !a.IsInWorld); + } + } } diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index ef20f79fff..a669919d12 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -153,9 +153,9 @@ namespace OpenRa if (orderManager.IsReadyForNextFrame) { - orderManager.Tick( world ); - if (controller.orderGenerator != null) - controller.orderGenerator.Tick( world ); + orderManager.Tick(world); + controller.orderGenerator.Tick(world); + controller.selection.Tick(world); world.Tick(); } diff --git a/OpenRa.Game/Orders/UnitOrderGenerator.cs b/OpenRa.Game/Orders/UnitOrderGenerator.cs index 2821664a0a..ccc4ae3d97 100644 --- a/OpenRa.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRa.Game/Orders/UnitOrderGenerator.cs @@ -8,16 +8,9 @@ namespace OpenRa.Orders { class UnitOrderGenerator : IOrderGenerator { - public readonly List selection; - - public UnitOrderGenerator( IEnumerable selected ) - { - selection = selected.ToList(); - } - public IEnumerable Order( World world, int2 xy, MouseInput mi ) { - foreach( var unit in selection ) + foreach( var unit in Game.controller.selection.Actors ) { var ret = unit.Order( xy, mi ); if( ret != null ) @@ -25,14 +18,11 @@ namespace OpenRa.Orders } } - public void Tick( World world ) - { - selection.RemoveAll(a => !a.IsInWorld); - } + public void Tick( World world ) {} public void Render( World world ) { - foreach( var a in selection ) + foreach( var a in Game.controller.selection.Actors ) world.WorldRenderer.DrawSelectionBox( a, Color.White, true ); } diff --git a/OpenRa.Game/Traits/RallyPoint.cs b/OpenRa.Game/Traits/RallyPoint.cs index 3978b98d48..15870ff06a 100644 --- a/OpenRa.Game/Traits/RallyPoint.cs +++ b/OpenRa.Game/Traits/RallyPoint.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using OpenRa.Graphics; using OpenRa.Orders; @@ -27,8 +28,7 @@ namespace OpenRa.Traits public IEnumerable Render(Actor self) { - var uog = Game.controller.orderGenerator as UnitOrderGenerator; - if (uog != null && self.Owner == self.World.LocalPlayer && uog.selection.Contains(self)) + if (self.Owner == self.World.LocalPlayer && Game.controller.selection.Actors.Contains(self)) yield return Util.Centered(self, anim.Image, Util.CenterOfCell(rallyPoint)); }