From 7b46b763294df3f222f5ebcb31de74c5263e3cba Mon Sep 17 00:00:00 2001 From: Bynnar18 Date: Wed, 25 Feb 2015 19:28:32 -0600 Subject: [PATCH] Fixed left-click orders and implemented a selection deadzone. --- OpenRA.Game/Game.cs | 2 - OpenRA.Game/Input/InputHandler.cs | 2 - OpenRA.Game/Orders/UnitOrderGenerator.cs | 16 ++++- OpenRA.Game/Settings.cs | 2 + .../WorldInteractionControllerWidget.cs | 63 ++++++++++++------- OpenRA.Mods.Common/Traits/Guard.cs | 2 +- .../Widgets/WorldCommandWidget.cs | 2 +- OpenRA.Mods.RA/Traits/Minelayer.cs | 4 +- OpenRA.Mods.RA/Traits/PortableChrono.cs | 2 +- 9 files changed, 63 insertions(+), 32 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 7828e1181d..b0e86e3d11 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -27,8 +27,6 @@ namespace OpenRA { public static class Game { - public static MouseButtonPreference mouseButtonPreference = new MouseButtonPreference(); - public const int NetTickScale = 3; // 120 ms net tick for 40 ms local tick public const int Timestep = 40; public const int TimestepJankThreshold = 250; // Don't catch up for delays larger than 250ms diff --git a/OpenRA.Game/Input/InputHandler.cs b/OpenRA.Game/Input/InputHandler.cs index 68b5e92cd1..7923978688 100755 --- a/OpenRA.Game/Input/InputHandler.cs +++ b/OpenRA.Game/Input/InputHandler.cs @@ -52,7 +52,6 @@ namespace OpenRA public class MouseButtonPreference { - public MouseButton Action { get @@ -61,7 +60,6 @@ namespace OpenRA } } - public MouseButton Cancel { get diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index 2515ebce99..0a94727ec0 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -88,6 +88,20 @@ namespace OpenRA.Orders return cursorOrder != null ? cursorOrder.Cursor : (useSelect ? "select" : "default"); } + // Used for classic mouse orders, determines whether or not action at xy is move or select + public static bool InputOverridesSelection(World world, int2 xy, MouseInput mi) + { + var target = Target.FromActor(world.ScreenMap.ActorsAt(xy).WithHighestSelectionPriority()); + var underCursor = world.Selection.Actors.WithHighestSelectionPriority(); + + var o = OrderForUnit(underCursor, target, mi); + + if (o == null || o.Trait is IMove) + return true; + + return false; + } + static UnitOrderResult OrderForUnit(Actor self, Target target, MouseInput mi) { if (self.Owner != self.World.LocalPlayer) @@ -96,7 +110,7 @@ namespace OpenRA.Orders if (self.Destroyed || !target.IsValidFor(self)) return null; - if (mi.Button == Game.mouseButtonPreference.Action) + if (mi.Button == Game.Settings.Game.MouseButtonPreference.Action) { foreach (var o in self.TraitsImplementing() .SelectMany(trait => trait.Orders diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index 875a64ef5b..8e29368030 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -127,8 +127,10 @@ namespace OpenRA public bool ViewportEdgeScroll = true; public bool LockMouseWindow = false; public MouseScrollType MouseScroll = MouseScrollType.Standard; + public MouseButtonPreference MouseButtonPreference = new MouseButtonPreference(); public float ViewportEdgeScrollStep = 10f; public float UIScrollSpeed = 50f; + public int SelectionDeadzone = 24; public bool UseClassicMouseStyle = false; public bool AlwaysShowStatusBars = false; diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index d9b7c9d002..bd9f61814c 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -40,7 +40,7 @@ namespace OpenRA.Widgets { if (!IsDragging) { - foreach (var u in SelectActorsInBox(World, lastMousePosition, lastMousePosition, _ => true)) + foreach (var u in SelectActorsInBoxWithDeadzone(World, lastMousePosition, lastMousePosition, _ => true)) worldRenderer.DrawRollover(u); return; @@ -48,7 +48,7 @@ namespace OpenRA.Widgets var selbox = SelectionBox; Game.Renderer.WorldLineRenderer.DrawRect(selbox.Value.First.ToFloat2(), selbox.Value.Second.ToFloat2(), Color.White); - foreach (var u in SelectActorsInBox(World, selbox.Value.First, selbox.Value.Second, _ => true)) + foreach (var u in SelectActorsInBoxWithDeadzone(World, selbox.Value.First, selbox.Value.Second, _ => true)) worldRenderer.DrawRollover(u); } @@ -68,8 +68,8 @@ namespace OpenRA.Widgets dragStart = xy; - // place buildings - if(!useClassicMouseStyle) + // Place buildings + if (!useClassicMouseStyle || !World.Selection.Actors.Any()) ApplyOrders(World, xy, mi); } @@ -78,20 +78,26 @@ namespace OpenRA.Widgets if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up) { - if (useClassicMouseStyle && HasMouseFocus) - { - // order units around - if (!hasBox && World.Selection.Actors.Any() && !multiClick) - { - ApplyOrders(World, xy, mi); - YieldMouseFocus(mi); - return true; - } - } - - if (World.OrderGenerator is UnitOrderGenerator) { + if (useClassicMouseStyle && HasMouseFocus) + { + if (!hasBox && World.Selection.Actors.Any() && !multiClick) + { + if (!(World.ScreenMap.ActorsAt(xy).Where(x => x.HasTrait() && x.Trait().Info.Selectable && + (x.Owner.IsAlliedWith(World.RenderPlayer) || !World.FogObscures(x))).Any() && !mi.Modifiers.HasModifier(Modifiers.Ctrl) && + !mi.Modifiers.HasModifier(Modifiers.Alt) && UnitOrderGenerator.InputOverridesSelection(World, xy, mi))) + { + // Order units instead of selecting + ApplyOrders(World, xy, mi); + dragStart = dragEnd = null; + YieldMouseFocus(mi); + lastMousePosition = xy; + return true; + } + } + } + if (multiClick) { var unit = World.ScreenMap.ActorsAt(xy) @@ -104,10 +110,12 @@ namespace OpenRA.Widgets } else if (dragStart.HasValue) { - var newSelection = SelectActorsInBox(World, dragStart.Value, xy, _ => true); + var newSelection = SelectActorsInBoxWithDeadzone(World, dragStart.Value, xy, _ => true); World.Selection.Combine(World, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy); } } + else if (useClassicMouseStyle) + ApplyOrders(World, xy, mi); dragStart = dragEnd = null; YieldMouseFocus(mi); @@ -115,11 +123,14 @@ namespace OpenRA.Widgets if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down) { - if (useClassicMouseStyle) - World.Selection.Clear(); + // Don't do anything while selecting + if (!hasBox) + { + if (useClassicMouseStyle) + World.Selection.Clear(); - if (!hasBox) // don't issue orders while selecting ApplyOrders(World, xy, mi); + } } lastMousePosition = xy; @@ -131,7 +142,7 @@ namespace OpenRA.Widgets { get { - return dragStart.HasValue && dragEnd.HasValue; + return dragStart.HasValue && dragEnd.HasValue && (dragStart.Value - dragEnd.Value).Length > Game.Settings.Game.SelectionDeadzone; } } @@ -193,7 +204,7 @@ namespace OpenRA.Widgets var mi = new MouseInput { Location = screenPos, - Button = Game.mouseButtonPreference.Action, + Button = Game.Settings.Game.MouseButtonPreference.Action, Modifiers = Game.GetModifierKeys() }; @@ -245,6 +256,14 @@ namespace OpenRA.Widgets return false; } + static IEnumerable SelectActorsInBoxWithDeadzone(World world, int2 a, int2 b, Func cond) + { + if (a == b || (a - b).Length > Game.Settings.Game.SelectionDeadzone) + return SelectActorsInBox(world, a, b, cond); + else + return SelectActorsInBox(world, b, b, cond); + } + static IEnumerable SelectActorsInBox(World world, int2 a, int2 b, Func cond) { return world.ScreenMap.ActorsInBox(a, b) diff --git a/OpenRA.Mods.Common/Traits/Guard.cs b/OpenRA.Mods.Common/Traits/Guard.cs index b17be9ee3e..0c856daec6 100644 --- a/OpenRA.Mods.Common/Traits/Guard.cs +++ b/OpenRA.Mods.Common/Traits/Guard.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits public IEnumerable Order(World world, CPos xy, MouseInput mi) { - if (mi.Button == Game.mouseButtonPreference.Cancel) + if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) { world.CancelInputMode(); yield break; diff --git a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs index c1f7fbb2fb..b40633b46f 100644 --- a/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.Common/Widgets/WorldCommandWidget.cs @@ -98,7 +98,7 @@ namespace OpenRA.Mods.Common.Widgets if (actors.Any()) world.OrderGenerator = new GenericSelectTarget(actors, - "AttackMove", "attackmove", Game.mouseButtonPreference.Action); + "AttackMove", "attackmove", Game.Settings.Game.MouseButtonPreference.Action); return true; } diff --git a/OpenRA.Mods.RA/Traits/Minelayer.cs b/OpenRA.Mods.RA/Traits/Minelayer.cs index a1020e2f7f..706cebe9cc 100644 --- a/OpenRA.Mods.RA/Traits/Minelayer.cs +++ b/OpenRA.Mods.RA/Traits/Minelayer.cs @@ -146,7 +146,7 @@ namespace OpenRA.Mods.RA.Traits public IEnumerable Order(World world, CPos xy, MouseInput mi) { - if (mi.Button == Game.mouseButtonPreference.Cancel) + if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) { world.CancelInputMode(); yield break; @@ -157,7 +157,7 @@ namespace OpenRA.Mods.RA.Traits .MaxByOrDefault(a => a.Info.Traits.Contains() ? a.Info.Traits.Get().Priority : int.MinValue); - if (mi.Button == Game.mouseButtonPreference.Action && underCursor == null) + if (mi.Button == Game.Settings.Game.MouseButtonPreference.Action && underCursor == null) { minelayer.World.CancelInputMode(); yield return new Order("PlaceMinefield", minelayer, false) { TargetLocation = xy }; diff --git a/OpenRA.Mods.RA/Traits/PortableChrono.cs b/OpenRA.Mods.RA/Traits/PortableChrono.cs index ee845a03d7..510d74f8d5 100644 --- a/OpenRA.Mods.RA/Traits/PortableChrono.cs +++ b/OpenRA.Mods.RA/Traits/PortableChrono.cs @@ -153,7 +153,7 @@ namespace OpenRA.Mods.RA.Traits public IEnumerable Order(World world, CPos xy, MouseInput mi) { - if (mi.Button == Game.mouseButtonPreference.Cancel) + if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) { world.CancelInputMode(); yield break;