diff --git a/OpenRA.Game/Input/InputHandler.cs b/OpenRA.Game/Input/InputHandler.cs index 8de70e96a9..8f20a27fb4 100644 --- a/OpenRA.Game/Input/InputHandler.cs +++ b/OpenRA.Game/Input/InputHandler.cs @@ -50,11 +50,4 @@ namespace OpenRA Sync.RunUnsynced(world, () => Ui.HandleInput(input)); } } - - public class MouseButtonPreference - { - public MouseButton Action => Game.Settings.Game.UseClassicMouseStyle ? MouseButton.Left : MouseButton.Right; - - public MouseButton Cancel => Game.Settings.Game.UseClassicMouseStyle ? MouseButton.Right : MouseButton.Left; - } } diff --git a/OpenRA.Game/Orders/IOrderGenerator.cs b/OpenRA.Game/Orders/IOrderGenerator.cs index d3d69d0ace..b351eace54 100644 --- a/OpenRA.Game/Orders/IOrderGenerator.cs +++ b/OpenRA.Game/Orders/IOrderGenerator.cs @@ -16,6 +16,7 @@ namespace OpenRA.Orders { public interface IOrderGenerator { + MouseButton ActionButton { get; } IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi); void Tick(World world); IEnumerable Render(WorldRenderer wr, World world); diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index fd0f7b20af..e07e375775 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -23,6 +23,8 @@ namespace OpenRA public enum StatusBarsType { Standard, DamageShow, AlwaysShow } public enum TargetLinesType { Disabled, Manual, Automatic } + public enum MouseActionType { Contextual, ConfirmOrder, GlobalCommand, SupportPower, PlaceBuilding } + [Flags] public enum MPGameFilters { @@ -270,7 +272,6 @@ namespace OpenRA public bool LockMouseWindow = false; public MouseScrollType MouseScroll = MouseScrollType.Joystick; - public MouseButtonPreference MouseButtonPreference = new(); public float ViewportEdgeScrollStep = 30f; public float UIScrollSpeed = 50f; public float ZoomSpeed = 0.04f; @@ -306,6 +307,22 @@ namespace OpenRA public bool EnableDiscordService = true; public TextNotificationPoolFilters TextNotificationPoolFilters = TextNotificationPoolFilters.Feedback | TextNotificationPoolFilters.Transients; + + public MouseButton ResolveActionButton(MouseActionType actionType) + { + switch (actionType) + { + case MouseActionType.ConfirmOrder: + case MouseActionType.Contextual: + return UseClassicMouseStyle ? MouseButton.Left : MouseButton.Right; + default: return MouseButton.Left; + } + } + + public MouseButton ResolveCancelButton(MouseActionType actionType) + { + return ResolveActionButton(actionType) == MouseButton.Left ? MouseButton.Right : MouseButton.Left; + } } public class Settings diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 6f584042b0..320c476288 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -35,7 +35,6 @@ namespace OpenRA readonly List unpartitionedEffects = []; readonly List syncedEffects = []; readonly GameSettings gameSettings; - readonly ModData modData; readonly Queue> frameEndActions = []; @@ -169,21 +168,7 @@ namespace OpenRA public readonly ISelection Selection; public readonly IControlGroups ControlGroups; - public void CancelInputMode() { OrderGenerator = (IOrderGenerator)modData.ObjectCreator.CreateBasic(defaultOrderGeneratorType); } - - public bool ToggleInputMode() where T : IOrderGenerator, new() - { - if (OrderGenerator is T) - { - CancelInputMode(); - return false; - } - else - { - OrderGenerator = new T(); - return true; - } - } + public void CancelInputMode() { OrderGenerator = (IOrderGenerator)defaultOrderGeneratorType.GetConstructor([typeof(World)])?.Invoke([this]); } public bool RulesContainTemporaryBlocker { get; } @@ -191,7 +176,6 @@ namespace OpenRA internal World(Map map, ModData modData, OrderManager orderManager, WorldType type) { - this.modData = modData; Type = type; OrderManager = orderManager; Map = map; @@ -203,7 +187,7 @@ namespace OpenRA if (defaultOrderGeneratorType == null) throw new InvalidDataException($"{modData.Manifest.DefaultOrderGenerator} is not a valid DefaultOrderGenerator"); - orderGenerator = (IOrderGenerator)modData.ObjectCreator.CreateBasic(defaultOrderGeneratorType); + orderGenerator = (IOrderGenerator)defaultOrderGeneratorType.GetConstructor([typeof(World)])?.Invoke([this]); var gameSpeeds = modData.GetOrCreate(); var gameSpeedName = orderManager.LobbyInfo.GlobalSettings.OptionOrDefault("gamespeed", gameSpeeds.DefaultSpeed); diff --git a/OpenRA.Mods.Cnc/Traits/PortableChrono.cs b/OpenRA.Mods.Cnc/Traits/PortableChrono.cs index 8a39ceccfe..fbb00fd544 100644 --- a/OpenRA.Mods.Cnc/Traits/PortableChrono.cs +++ b/OpenRA.Mods.Cnc/Traits/PortableChrono.cs @@ -216,7 +216,10 @@ namespace OpenRA.Mods.Cnc.Traits readonly PortableChrono portableChrono; readonly PortableChronoInfo info; + protected override MouseActionType ActionType => MouseActionType.ConfirmOrder; + public PortableChronoOrderGenerator(Actor self, PortableChrono portableChrono) + : base(self.World, false) { this.self = self; this.portableChrono = portableChrono; @@ -225,12 +228,6 @@ namespace OpenRA.Mods.Cnc.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) - { - world.CancelInputMode(); - yield break; - } - if (self.IsInWorld && self.Location != cell && self.Trait().CanTeleport && self.Owner.Shroud.IsExplored(cell)) { diff --git a/OpenRA.Mods.Cnc/Traits/SupportPowers/AttackOrderPower.cs b/OpenRA.Mods.Cnc/Traits/SupportPowers/AttackOrderPower.cs index c069637167..46e8b0aba3 100644 --- a/OpenRA.Mods.Cnc/Traits/SupportPowers/AttackOrderPower.cs +++ b/OpenRA.Mods.Cnc/Traits/SupportPowers/AttackOrderPower.cs @@ -50,7 +50,7 @@ namespace OpenRA.Mods.Cnc.Traits public override void SelectTarget(Actor self, string order, SupportPowerManager manager) { - self.World.OrderGenerator = new SelectAttackPowerTarget(self, order, manager, info.Cursor, MouseButton.Left, attack); + self.World.OrderGenerator = new SelectAttackPowerTarget(self, order, manager, info.Cursor, attack); } public override void Activate(Actor self, Order order, SupportPowerManager manager) @@ -81,20 +81,17 @@ namespace OpenRA.Mods.Cnc.Traits readonly string order; readonly string cursor; readonly string cursorBlocked; - readonly MouseButton expectedButton; readonly AttackBase attack; - public SelectAttackPowerTarget(Actor self, string order, SupportPowerManager manager, string cursor, MouseButton button, AttackBase attack) - { - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) - manager.Self.World.Selection.Clear(); + protected override MouseActionType ActionType => MouseActionType.SupportPower; + public SelectAttackPowerTarget(Actor self, string order, SupportPowerManager manager, string cursor, AttackBase attack) + : base(self.World) + { instance = manager.GetPowersForActor(self).FirstOrDefault(); this.manager = manager; this.order = order; this.cursor = cursor; - expectedButton = button; this.attack = attack; cursorBlocked = cursor + "-blocked"; } @@ -110,7 +107,7 @@ namespace OpenRA.Mods.Cnc.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - if (mi.Button == expectedButton && IsValidTarget(world, cell)) + if (IsValidTarget(world, cell)) yield return new Order(order, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true diff --git a/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs index ac6e9222eb..c4bd2e7abd 100644 --- a/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.Cnc/Traits/SupportPowers/ChronoshiftPower.cs @@ -150,12 +150,11 @@ namespace OpenRA.Mods.Cnc.Traits readonly SupportPowerManager manager; readonly string order; - public SelectChronoshiftTarget(World world, string order, SupportPowerManager manager, ChronoshiftPower power) - { - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) - manager.Self.World.Selection.Clear(); + protected override MouseActionType ActionType => MouseActionType.SupportPower; + public SelectChronoshiftTarget(World world, string order, SupportPowerManager manager, ChronoshiftPower power) + : base(world) + { this.manager = manager; this.order = order; this.power = power; @@ -171,9 +170,7 @@ namespace OpenRA.Mods.Cnc.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - if (mi.Button == MouseButton.Left) - world.OrderGenerator = new SelectDestination(world, order, manager, power, cell); - + world.OrderGenerator = new SelectDestination(world, order, manager, power, cell); yield break; } @@ -230,7 +227,10 @@ namespace OpenRA.Mods.Cnc.Traits readonly SupportPowerManager manager; readonly string order; + protected override MouseActionType ActionType => MouseActionType.SupportPower; + public SelectDestination(World world, string order, SupportPowerManager manager, ChronoshiftPower power, CPos sourceLocation) + : base(world) { this.manager = manager; this.order = order; @@ -267,12 +267,6 @@ namespace OpenRA.Mods.Cnc.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == MouseButton.Right) - { - world.CancelInputMode(); - yield break; - } - var ret = OrderInner(cell).FirstOrDefault(); if (ret == null) yield break; diff --git a/OpenRA.Mods.Common/Orders/BeaconOrderGenerator.cs b/OpenRA.Mods.Common/Orders/BeaconOrderGenerator.cs index 59cc4b7f4f..5d1e6c5105 100644 --- a/OpenRA.Mods.Common/Orders/BeaconOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/BeaconOrderGenerator.cs @@ -17,12 +17,15 @@ namespace OpenRA.Mods.Common.Orders { public class BeaconOrderGenerator : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.PlaceBuilding; + + public BeaconOrderGenerator(World world) + : base(world) { } + protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - - if (mi.Button == MouseButton.Left) - yield return new Order("PlaceBeacon", world.LocalPlayer.PlayerActor, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; + yield return new Order("PlaceBeacon", world.LocalPlayer.PlayerActor, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; } protected override IEnumerable Render(WorldRenderer wr, World world) { yield break; } diff --git a/OpenRA.Mods.Common/Orders/ForceModifiersOrderGenerator.cs b/OpenRA.Mods.Common/Orders/ForceModifiersOrderGenerator.cs index 9d2b580548..f86b6bf2aa 100644 --- a/OpenRA.Mods.Common/Orders/ForceModifiersOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/ForceModifiersOrderGenerator.cs @@ -15,10 +15,12 @@ namespace OpenRA.Mods.Common.Orders { public class ForceModifiersOrderGenerator : UnitOrderGenerator { + protected override MouseActionType ActionType => MouseActionType.ConfirmOrder; public readonly Modifiers Modifiers; readonly bool cancelOnFirstUse; - public ForceModifiersOrderGenerator(Modifiers modifiers, bool cancelOnFirstUse) + public ForceModifiersOrderGenerator(World world, Modifiers modifiers, bool cancelOnFirstUse) + : base(world) { Modifiers = modifiers; this.cancelOnFirstUse = cancelOnFirstUse; @@ -27,8 +29,7 @@ namespace OpenRA.Mods.Common.Orders public override IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { mi.Modifiers |= Modifiers; - - if (cancelOnFirstUse) + if ((cancelOnFirstUse && !mi.Modifiers.HasModifier(Modifiers.Shift)) || mi.Button == CancelButton) world.CancelInputMode(); return base.Order(world, cell, worldPixel, mi); diff --git a/OpenRA.Mods.Common/Orders/GlobalButtonOrderGenerator.cs b/OpenRA.Mods.Common/Orders/GlobalButtonOrderGenerator.cs index 4213b1555e..a11a7bedd8 100644 --- a/OpenRA.Mods.Common/Orders/GlobalButtonOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/GlobalButtonOrderGenerator.cs @@ -20,38 +20,30 @@ namespace OpenRA.Mods.Common.Orders { readonly string order; - protected GlobalButtonOrderGenerator(string order) + protected override MouseActionType ActionType => MouseActionType.GlobalCommand; + + protected GlobalButtonOrderGenerator(World world, string order) + : base(world) { this.order = order; } - protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) - { - if (mi.Button == MouseButton.Right) - world.CancelInputMode(); - - return OrderInner(world, mi); - } - protected virtual bool IsValidTrait(T t) { return t.IsTraitEnabled(); } - protected IEnumerable OrderInner(World world, MouseInput mi) + protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == MouseButton.Left) - { - var underCursor = world.ScreenMap.ActorsAtMouse(mi) - .Select(a => a.Actor) - .FirstOrDefault(a => a.Owner == world.LocalPlayer && a.TraitsImplementing() - .Any(IsValidTrait)); + var underCursor = world.ScreenMap.ActorsAtMouse(mi) + .Select(a => a.Actor) + .FirstOrDefault(a => a.Owner == world.LocalPlayer && a.TraitsImplementing() + .Any(IsValidTrait)); - if (underCursor == null) - yield break; + if (underCursor == null) + yield break; - yield return new Order(order, underCursor, false); - } + yield return new Order(order, underCursor, false); } protected override void Tick(World world) @@ -70,8 +62,8 @@ namespace OpenRA.Mods.Common.Orders public class PowerDownOrderGenerator : GlobalButtonOrderGenerator { - public PowerDownOrderGenerator() - : base("PowerDown") { } + public PowerDownOrderGenerator(World world) + : base(world, "PowerDown") { } protected override bool IsValidTrait(ToggleConditionOnOrder t) { @@ -80,21 +72,18 @@ namespace OpenRA.Mods.Common.Orders protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) { - mi.Button = MouseButton.Left; - return OrderInner(world, mi).Any() ? "powerdown" : "powerdown-blocked"; + return OrderInner(world, cell, worldPixel, mi).Any() ? "powerdown" : "powerdown-blocked"; } } public class SellOrderGenerator : GlobalButtonOrderGenerator { - public SellOrderGenerator() - : base("Sell") { } + public SellOrderGenerator(World world) + : base(world, "Sell") { } protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) { - mi.Button = MouseButton.Left; - - var cursor = OrderInner(world, mi) + var cursor = OrderInner(world, cell, worldPixel, mi) .SelectMany(o => o.Subject.TraitsImplementing()) .Where(t => !t.IsTraitDisabled) .Select(si => si.Info.Cursor) diff --git a/OpenRA.Mods.Common/Orders/GuardOrderGenerator.cs b/OpenRA.Mods.Common/Orders/GuardOrderGenerator.cs index 2ac444a66c..af16ade443 100644 --- a/OpenRA.Mods.Common/Orders/GuardOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/GuardOrderGenerator.cs @@ -20,27 +20,25 @@ namespace OpenRA.Mods.Common.Orders { readonly string orderName; readonly string cursor; - readonly MouseButton expectedButton; IEnumerable subjects; + protected override MouseActionType ActionType => MouseActionType.ConfirmOrder; - public GuardOrderGenerator(IEnumerable subjects, string order, string cursor, MouseButton button) + public GuardOrderGenerator(World world, IEnumerable subjects, string order, string cursor) + : base(world) { orderName = order; this.cursor = cursor; - expectedButton = button; this.subjects = subjects; } public override IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button != expectedButton) + if (mi.Button != ActionButton) + { world.CancelInputMode(); + yield break; + } - return OrderInner(world, mi); - } - - IEnumerable OrderInner(World world, MouseInput mi) - { var target = FriendlyGuardableUnits(world, mi).FirstOrDefault(); if (target == null) yield break; diff --git a/OpenRA.Mods.Common/Orders/OrderGenerator.cs b/OpenRA.Mods.Common/Orders/OrderGenerator.cs index ae6a62e068..9265a3bb63 100644 --- a/OpenRA.Mods.Common/Orders/OrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/OrderGenerator.cs @@ -17,11 +17,27 @@ namespace OpenRA.Mods.Common.Orders { public abstract class OrderGenerator : IOrderGenerator { + protected abstract MouseActionType ActionType { get; } + readonly GameSettings gameSettings; + + protected OrderGenerator(World world, bool classicClearSelection = true) + { + gameSettings = Game.Settings.Game; + if (classicClearSelection && gameSettings.UseClassicMouseStyle) + world.Selection.Clear(); + } + + public MouseButton ActionButton => gameSettings.ResolveActionButton(ActionType); + public MouseButton CancelButton => gameSettings.ResolveCancelButton(ActionType); + public virtual IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if ((mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down) || (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Up)) + if (mi.Button == ActionButton && mi.Event == MouseInputEvent.Down) return OrderInner(world, cell, worldPixel, mi); + if (mi.Button == CancelButton && mi.Event == MouseInputEvent.Up) + world.CancelInputMode(); + return []; } diff --git a/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs index 78cc5a7a22..7ebba10871 100644 --- a/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/PlaceBuildingOrderGenerator.cs @@ -90,6 +90,7 @@ namespace OpenRA.Mods.Common.Orders readonly PlaceBuildingInfo placeBuildingInfo; readonly Viewport viewport; readonly VariantWrapper[] variants; + readonly GameSettings gameSettings; int variant; public PlaceBuildingOrderGenerator(ProductionQueue queue, string name, WorldRenderer worldRenderer) @@ -98,9 +99,9 @@ namespace OpenRA.Mods.Common.Orders world = queue.Actor.World; placeBuildingInfo = queue.Actor.Owner.PlayerActor.Info.TraitInfo(); viewport = worldRenderer.Viewport; + gameSettings = Game.Settings.Game; - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) + if (gameSettings.UseClassicMouseStyle) world.Selection.Clear(); var variants = new List() @@ -115,6 +116,8 @@ namespace OpenRA.Mods.Common.Orders this.variants = variants.ToArray(); } + public MouseButton ActionButton => gameSettings.ResolveActionButton(MouseActionType.PlaceBuilding); + static PlaceBuildingCellType MakeCellType(bool valid, bool lineBuild = false) { var cell = valid ? PlaceBuildingCellType.Valid : PlaceBuildingCellType.Invalid; @@ -126,9 +129,11 @@ namespace OpenRA.Mods.Common.Orders public IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if ((mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down) || (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Up)) + var actionButton = gameSettings.ResolveActionButton(MouseActionType.PlaceBuilding); + var cancelButton = gameSettings.ResolveCancelButton(MouseActionType.PlaceBuilding); + if ((mi.Button == actionButton && mi.Event == MouseInputEvent.Down) || (mi.Button == cancelButton && mi.Event == MouseInputEvent.Up)) { - if (mi.Button == MouseButton.Right) + if (mi.Button == cancelButton) world.CancelInputMode(); var ret = InnerOrder(world, cell, mi).ToArray(); @@ -168,7 +173,7 @@ namespace OpenRA.Mods.Common.Orders var bi = variants[variant].BuildingInfo; var notification = Queue.Info.CannotPlaceAudio ?? placeBuildingInfo.CannotPlaceNotification; - if (mi.Button == MouseButton.Left) + if (mi.Button == ActionButton) { var orderType = "PlaceBuilding"; var topLeft = TopLeft; diff --git a/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs b/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs index 9a50f35744..d7c6744303 100644 --- a/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/RepairOrderGenerator.cs @@ -19,19 +19,13 @@ namespace OpenRA.Mods.Common.Orders { public class RepairOrderGenerator : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.GlobalCommand; + + public RepairOrderGenerator(World world) + : base(world) { } + protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == MouseButton.Right) - world.CancelInputMode(); - - return OrderInner(world, mi); - } - - static IEnumerable OrderInner(World world, MouseInput mi) - { - if (mi.Button != MouseButton.Left) - yield break; - var underCursor = world.ScreenMap.ActorsAtMouse(mi) .Select(a => a.Actor) .FirstOrDefault(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && !world.FogObscures(a)); @@ -86,8 +80,7 @@ namespace OpenRA.Mods.Common.Orders protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) { - mi.Button = MouseButton.Left; - return OrderInner(world, mi).Any() + return OrderInner(world, cell, worldPixel, mi).Any() ? "repair" : "repair-blocked"; } } diff --git a/OpenRA.Mods.Common/Orders/UnitOrderGenerator.cs b/OpenRA.Mods.Common/Orders/UnitOrderGenerator.cs index ee5e4a5bae..0a216a80b0 100644 --- a/OpenRA.Mods.Common/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Mods.Common/Orders/UnitOrderGenerator.cs @@ -22,6 +22,16 @@ namespace OpenRA.Mods.Common.Orders { readonly string worldSelectCursor = ChromeMetrics.Get("WorldSelectCursor"); readonly string worldDefaultCursor = ChromeMetrics.Get("WorldDefaultCursor"); + readonly GameSettings gameSettings; + + protected virtual MouseActionType ActionType => MouseActionType.Contextual; + public MouseButton ActionButton => gameSettings.ResolveActionButton(ActionType); + public MouseButton CancelButton => gameSettings.ResolveCancelButton(ActionType); + + public UnitOrderGenerator(World world) + { + gameSettings = Game.Settings.Game; + } protected static Target TargetForInput(World world, CPos cell, int2 worldPixel, MouseInput mi) { @@ -72,7 +82,7 @@ namespace OpenRA.Mods.Common.Orders var target = TargetForInput(world, cell, worldPixel, mi); bool useSelect; - if (Game.Settings.Game.UseClassicMouseStyle && !InputOverridesSelection(world, worldPixel, mi)) + if (gameSettings.UseClassicMouseStyle && !InputOverridesSelection(world, worldPixel, mi)) useSelect = target.Type == TargetType.Actor && target.Actor.Info.HasTraitInfo(); else { @@ -137,9 +147,9 @@ namespace OpenRA.Mods.Common.Orders /// First priority is given to orders that interact with the given actors. /// Second priority is given to actors in the given cell. /// - protected static UnitOrderResult OrderForUnit(Actor self, Target target, CPos xy, MouseInput mi) + protected UnitOrderResult OrderForUnit(Actor self, Target target, CPos xy, MouseInput mi) { - if (mi.Button != Game.Settings.Game.MouseButtonPreference.Action) + if (mi.Button != ActionButton) return null; if (self.Owner != self.World.LocalPlayer) diff --git a/OpenRA.Mods.Common/Traits/AttackMove.cs b/OpenRA.Mods.Common/Traits/AttackMove.cs index 628b221c13..b06e1e72eb 100644 --- a/OpenRA.Mods.Common/Traits/AttackMove.cs +++ b/OpenRA.Mods.Common/Traits/AttackMove.cs @@ -104,12 +104,11 @@ namespace OpenRA.Mods.Common.Traits { TraitPair[] subjects; - readonly MouseButton expectedButton; + protected override MouseActionType ActionType => MouseActionType.ConfirmOrder; - public AttackMoveOrderGenerator(IEnumerable subjects, MouseButton button) + public AttackMoveOrderGenerator(World world, IEnumerable subjects) + : base(world) { - expectedButton = button; - this.subjects = subjects.Where(a => !a.IsDead) .SelectMany(a => a.TraitsImplementing() .Select(am => new TraitPair(a, am))) @@ -118,26 +117,21 @@ namespace OpenRA.Mods.Common.Traits public override IEnumerable Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button != expectedButton) + if (mi.Button != ActionButton) + { + world.CancelInputMode(); + yield break; + } + + var queued = mi.Modifiers.HasModifier(Modifiers.Shift); + if (!queued) world.CancelInputMode(); - return OrderInner(world, cell, mi); - } + var orderName = mi.Modifiers.HasModifier(Modifiers.Ctrl) ? "AssaultMove" : "AttackMove"; - protected virtual IEnumerable OrderInner(World world, CPos cell, MouseInput mi) - { - if (mi.Button == expectedButton) - { - var queued = mi.Modifiers.HasModifier(Modifiers.Shift); - if (!queued) - world.CancelInputMode(); - - var orderName = mi.Modifiers.HasModifier(Modifiers.Ctrl) ? "AssaultMove" : "AttackMove"; - - // Cells outside the playable area should be clamped to the edge for consistency with move orders - cell = world.Map.Clamp(cell); - yield return new Order(orderName, null, Target.FromCell(world, cell), queued, null, subjects.Select(s => s.Actor).ToArray()); - } + // Cells outside the playable area should be clamped to the edge for consistency with move orders + cell = world.Map.Clamp(cell); + yield return new Order(orderName, null, Target.FromCell(world, cell), queued, null, subjects.Select(s => s.Actor).ToArray()); } public override void SelectionChanged(World world, IEnumerable selected) diff --git a/OpenRA.Mods.Common/Traits/Minelayer.cs b/OpenRA.Mods.Common/Traits/Minelayer.cs index e07ed5b340..b085875caf 100644 --- a/OpenRA.Mods.Common/Traits/Minelayer.cs +++ b/OpenRA.Mods.Common/Traits/Minelayer.cs @@ -220,6 +220,8 @@ namespace OpenRA.Mods.Common.Traits sealed class MinefieldOrderGenerator : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.ConfirmOrder; + readonly List minelayers; readonly Minelayer minelayer; readonly Sprite validTile, unknownTile, blockedTile; @@ -229,6 +231,7 @@ namespace OpenRA.Mods.Common.Traits readonly string cursor; public MinefieldOrderGenerator(Actor a, CPos xy, bool queued) + : base(a.World, false) { minelayers = [a]; minefieldStart = xy; @@ -286,18 +289,9 @@ namespace OpenRA.Mods.Common.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) - { - world.CancelInputMode(); - yield break; - } - - if (mi.Button == Game.Settings.Game.MouseButtonPreference.Action) - { - minelayers[0].World.CancelInputMode(); - foreach (var minelayer in minelayers) - yield return new Order("PlaceMinefield", minelayer, Target.FromCell(world, cell), queued) { ExtraLocation = minefieldStart }; - } + world.CancelInputMode(); + foreach (var minelayer in minelayers) + yield return new Order("PlaceMinefield", minelayer, Target.FromCell(world, cell), queued) { ExtraLocation = minefieldStart }; } protected override void SelectionChanged(World world, IEnumerable selected) diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs index f159baa795..97ccb4a1ce 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/GrantExternalConditionPower.cs @@ -109,6 +109,7 @@ namespace OpenRA.Mods.Common.Traits sealed class SelectConditionTarget : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.SupportPower; readonly GrantExternalConditionPower power; readonly char[] footprint; readonly CVec dimensions; @@ -118,11 +119,8 @@ namespace OpenRA.Mods.Common.Traits readonly string order; public SelectConditionTarget(World world, string order, SupportPowerManager manager, GrantExternalConditionPower power) + : base(world) { - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) - manager.Self.World.Selection.Clear(); - this.manager = manager; this.order = order; this.power = power; @@ -137,7 +135,7 @@ namespace OpenRA.Mods.Common.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - if (mi.Button == MouseButton.Left && power.UnitsInRange(cell).Any()) + if (power.UnitsInRange(cell).Any()) yield return new Order(order, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/NukePower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/NukePower.cs index 3245bea728..e53b4763c9 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/NukePower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/NukePower.cs @@ -210,7 +210,7 @@ namespace OpenRA.Mods.Common.Traits public override void SelectTarget(Actor self, string order, SupportPowerManager manager) { - self.World.OrderGenerator = new SelectNukePowerTarget(order, manager, info, MouseButton.Left); + self.World.OrderGenerator = new SelectNukePowerTarget(order, manager, info); } } @@ -218,8 +218,8 @@ namespace OpenRA.Mods.Common.Traits { readonly NukePowerInfo info; - public SelectNukePowerTarget(string order, SupportPowerManager manager, NukePowerInfo info, MouseButton button) - : base(order, manager, info, button) + public SelectNukePowerTarget(string order, SupportPowerManager manager, NukePowerInfo info) + : base(order, manager, info) { this.info = info; } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SelectDirectionalTarget.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SelectDirectionalTarget.cs index e82400d4b1..6d6508ce19 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SelectDirectionalTarget.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SelectDirectionalTarget.cs @@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Traits readonly string order; readonly SupportPowerManager manager; + readonly GameSettings gameSettings; readonly Arrow[] directionArrows; @@ -43,20 +44,24 @@ namespace OpenRA.Mods.Common.Traits this.order = order; this.manager = manager; this.info = info; + gameSettings = Game.Settings.Game; directionArrows = LoadArrows(info.DirectionArrowAnimation, world, info.Arrows.Length); mouseAttachment = Ui.Root.Get("MOUSE_ATTATCHMENT"); } + public MouseButton ActionButton => gameSettings.ResolveActionButton(MouseActionType.SupportPower); + public MouseButton CancelButton => gameSettings.ResolveCancelButton(MouseActionType.SupportPower); + IEnumerable IOrderGenerator.Order(World world, CPos cell, int2 worldPixel, MouseInput mi) { - if (mi.Button == MouseButton.Right) + if (mi.Button == CancelButton) { world.CancelInputMode(); yield break; } - if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down) + if (mi.Button == ActionButton && mi.Event == MouseInputEvent.Down) { if (!activated && world.Map.Contains(cell)) { @@ -86,7 +91,7 @@ namespace OpenRA.Mods.Common.Traits dragStarted = true; } - if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up) + if (mi.Button == ActionButton && mi.Event == MouseInputEvent.Up) { yield return new Order(order, manager.Self, Target.FromCell(manager.Self.World, targetCell), false) { diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs index 4cce7db477..459380f801 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SpawnActorPower.cs @@ -102,7 +102,7 @@ namespace OpenRA.Mods.Common.Traits TextNotificationsManager.AddTransientLine(manager.Self.Owner, Info.SelectTargetTextNotification); - self.World.OrderGenerator = new SelectSpawnActorPowerTarget(order, manager, this, MouseButton.Left); + self.World.OrderGenerator = new SelectSpawnActorPowerTarget(order, manager, this); } public bool Validate(World world, SpawnActorPowerInfo info, CPos cell) @@ -122,23 +122,19 @@ namespace OpenRA.Mods.Common.Traits public class SelectSpawnActorPowerTarget : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.SupportPower; readonly SpawnActorPower power; readonly SpawnActorPowerInfo info; readonly SupportPowerManager manager; - readonly MouseButton expectedButton; public string OrderKey { get; } - public SelectSpawnActorPowerTarget(string order, SupportPowerManager manager, SpawnActorPower power, MouseButton button) + public SelectSpawnActorPowerTarget(string order, SupportPowerManager manager, SpawnActorPower power) + : base(manager.Self.World) { - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) - manager.Self.World.Selection.Clear(); - this.manager = manager; this.power = power; OrderKey = order; - expectedButton = button; info = (SpawnActorPowerInfo)power.Info; } @@ -146,11 +142,7 @@ namespace OpenRA.Mods.Common.Traits protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - - if (!power.Validate(world, info, cell)) - yield break; - - if (mi.Button == expectedButton) + if (power.Validate(world, info, cell)) yield return new Order(OrderKey, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; } diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs index d16d5d8b65..dc0d165dbf 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPower.cs @@ -213,7 +213,7 @@ namespace OpenRA.Mods.Common.Traits public virtual void SelectTarget(Actor self, string order, SupportPowerManager manager) { - self.World.OrderGenerator = new SelectGenericPowerTarget(order, manager, info, MouseButton.Left); + self.World.OrderGenerator = new SelectGenericPowerTarget(order, manager, info); } public virtual void Activate(Actor self, Order order, SupportPowerManager manager) diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs index 00d281121e..19ec9c768e 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/SupportPowerManager.cs @@ -282,28 +282,24 @@ namespace OpenRA.Mods.Common.Traits public class SelectGenericPowerTarget : OrderGenerator { + protected override MouseActionType ActionType => MouseActionType.SupportPower; readonly SupportPowerManager manager; readonly SupportPowerInfo info; - readonly MouseButton expectedButton; public string OrderKey { get; } - public SelectGenericPowerTarget(string order, SupportPowerManager manager, SupportPowerInfo info, MouseButton button) + public SelectGenericPowerTarget(string order, SupportPowerManager manager, SupportPowerInfo info) + : base(manager.Self.World) { - // Clear selection if using Left-Click Orders - if (Game.Settings.Game.UseClassicMouseStyle) - manager.Self.World.Selection.Clear(); - this.manager = manager; OrderKey = order; this.info = info; - expectedButton = button; } protected override IEnumerable OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi) { world.CancelInputMode(); - if (mi.Button == expectedButton && world.Map.Contains(cell)) + if (world.Map.Contains(cell)) yield return new Order(OrderKey, manager.Self, Target.FromCell(world, cell), false) { SuppressVisualFeedback = true }; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs index 7f060026be..f82d750a40 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/CommandBarLogic.cs @@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Widgets world.CancelInputMode(); } else - world.OrderGenerator = new AttackMoveOrderGenerator(selectedActors, Game.Settings.Game.MouseButtonPreference.Action); + world.OrderGenerator = new AttackMoveOrderGenerator(world, selectedActors); } attackMoveButton.OnClick = () => Toggle(true); @@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Widgets if (forceMoveButton.IsHighlighted()) world.CancelInputMode(); else - world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Alt, true); + world.OrderGenerator = new ForceModifiersOrderGenerator(world, Modifiers.Alt, true); }; } @@ -102,7 +102,7 @@ namespace OpenRA.Mods.Common.Widgets if (forceAttackButton.IsHighlighted()) world.CancelInputMode(); else - world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Ctrl, true); + world.OrderGenerator = new ForceModifiersOrderGenerator(world, Modifiers.Ctrl, true); }; } @@ -122,8 +122,7 @@ namespace OpenRA.Mods.Common.Widgets world.CancelInputMode(); } else - world.OrderGenerator = new GuardOrderGenerator(selectedActors, - "Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action); + world.OrderGenerator = new GuardOrderGenerator(world, selectedActors, "Guard", "guard"); } guardButton.OnClick = () => Toggle(true); @@ -205,7 +204,7 @@ namespace OpenRA.Mods.Common.Widgets if (queueOrdersButton.IsHighlighted()) world.CancelInputMode(); else - world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Shift, false); + world.OrderGenerator = new ForceModifiersOrderGenerator(world, Modifiers.Shift, false); }; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/OrderButtonsChromeLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/OrderButtonsChromeLogic.cs index 4f57c7f502..5cac2e9327 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/OrderButtonsChromeLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/OrderButtonsChromeLogic.cs @@ -15,56 +15,41 @@ using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets.Logic { - public class SellOrderButtonLogic : ChromeLogic + public abstract class ChromeOrderButtonLogic : ChromeLogic where T : IOrderGenerator { - [ObjectCreator.UseCtor] - public SellOrderButtonLogic(Widget widget, World world) + protected ChromeOrderButtonLogic(Widget w, World world, string icon) { - if (widget is ButtonWidget sell) - OrderButtonsChromeUtils.BindOrderButton(world, sell, "sell"); - } - } + if (w is not ButtonWidget widget) + return; - public class RepairOrderButtonLogic : ChromeLogic - { - [ObjectCreator.UseCtor] - public RepairOrderButtonLogic(Widget widget, World world) - { - if (widget is ButtonWidget repair) - OrderButtonsChromeUtils.BindOrderButton(world, repair, "repair"); - } - } + widget.OnClick = () => + { + if (world.OrderGenerator is T) + world.CancelInputMode(); + else + world.OrderGenerator = (IOrderGenerator)typeof(T).GetConstructor([typeof(World)])?.Invoke([world]); + }; - public class PowerdownOrderButtonLogic : ChromeLogic - { - [ObjectCreator.UseCtor] - public PowerdownOrderButtonLogic(Widget widget, World world) - { - if (widget is ButtonWidget power) - OrderButtonsChromeUtils.BindOrderButton(world, power, "power"); - } - } + widget.IsHighlighted = () => world.OrderGenerator is T; - public class BeaconOrderButtonLogic : ChromeLogic - { - [ObjectCreator.UseCtor] - public BeaconOrderButtonLogic(Widget widget, World world) - { - if (widget is ButtonWidget beacon) - OrderButtonsChromeUtils.BindOrderButton(world, beacon, "beacon"); - } - } - - public static class OrderButtonsChromeUtils - { - public static void BindOrderButton(World world, ButtonWidget w, string icon) - where T : IOrderGenerator, new() - { - w.OnClick = () => world.ToggleInputMode(); - w.IsHighlighted = () => world.OrderGenerator is T; - - w.Get("ICON").GetImageName = + widget.Get("ICON").GetImageName = () => world.OrderGenerator is T ? icon + "-active" : icon; } } + + [method: ObjectCreator.UseCtor] + public class SellOrderButtonLogic(Widget widget, World world) + : ChromeOrderButtonLogic(widget, world, "sell"); + + [method: ObjectCreator.UseCtor] + public class RepairOrderButtonLogic(Widget widget, World world) + : ChromeOrderButtonLogic(widget, world, "repair"); + + [method: ObjectCreator.UseCtor] + public class PowerdownOrderButtonLogic(Widget widget, World world) + : ChromeOrderButtonLogic(widget, world, "power"); + + [method: ObjectCreator.UseCtor] + public class BeaconOrderButtonLogic(Widget widget, World world) + : ChromeOrderButtonLogic(widget, world, "beacon"); } diff --git a/OpenRA.Mods.Common/Widgets/RadarWidget.cs b/OpenRA.Mods.Common/Widgets/RadarWidget.cs index 66e55b9814..9758056249 100644 --- a/OpenRA.Mods.Common/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.Common/Widgets/RadarWidget.cs @@ -36,6 +36,7 @@ namespace OpenRA.Mods.Common.Widgets public Action AfterClose = () => { }; public Action Animating = _ => { }; + readonly ModData modData; readonly World world; readonly WorldRenderer worldRenderer; readonly RadarPings radarPings; @@ -45,6 +46,7 @@ namespace OpenRA.Mods.Common.Widgets readonly int previewWidth; readonly int previewHeight; readonly string worldDefaultCursor = ChromeMetrics.Get("WorldDefaultCursor"); + readonly GameSettings gameSettings; float radarMinimapHeight; int frame; @@ -66,10 +68,12 @@ namespace OpenRA.Mods.Common.Widgets Player currentPlayer; [ObjectCreator.UseCtor] - public RadarWidget(World world, WorldRenderer worldRenderer) + public RadarWidget(ModData modData, World world, WorldRenderer worldRenderer) { + this.modData = modData; this.world = world; this.worldRenderer = worldRenderer; + gameSettings = Game.Settings.Game; radarPings = world.WorldActor.TraitOrDefault(); radarTerrainLayers = world.WorldActor.TraitsImplementing().ToArray(); @@ -294,7 +298,7 @@ namespace OpenRA.Mods.Common.Widgets var mi = new MouseInput { Location = location, - Button = Game.Settings.Game.MouseButtonPreference.Action, + Button = world.OrderGenerator.ActionButton, Modifiers = Game.GetModifierKeys() }; @@ -302,7 +306,7 @@ namespace OpenRA.Mods.Common.Widgets if (cursor == null) return worldDefaultCursor; - return Game.ModData.Cursors.ContainsKey(cursor + "-minimap") ? cursor + "-minimap" : cursor; + return modData.Cursors.ContainsKey(cursor + "-minimap") ? cursor + "-minimap" : cursor; } public override bool HandleMouseInput(MouseInput mi) @@ -315,12 +319,12 @@ namespace OpenRA.Mods.Common.Widgets var worldCoords = MinimapPixelToWorldCoords(mi.Location); if ((mi.Event == MouseInputEvent.Down || mi.Event == MouseInputEvent.Move) - && mi.Button == Game.Settings.Game.MouseButtonPreference.Cancel) + && mi.Button == gameSettings.ResolveCancelButton(MouseActionType.Contextual)) { worldRenderer.Viewport.Center(worldCoords); } - if (mi.Event == MouseInputEvent.Down && mi.Button == Game.Settings.Game.MouseButtonPreference.Action && WorldInteractionController != null) + if (mi.Event == MouseInputEvent.Down && mi.Button == gameSettings.ResolveActionButton(MouseActionType.Contextual) && WorldInteractionController != null) { var worldPos = worldCoords.ToInt2(); var wpos = new WPos(worldPos.X, worldPos.Y, 0); @@ -330,7 +334,7 @@ namespace OpenRA.Mods.Common.Widgets var fakemi = new MouseInput { Event = MouseInputEvent.Down, - Button = Game.Settings.Game.MouseButtonPreference.Action, + Button = mi.Button, Modifiers = mi.Modifiers, Location = location, }; diff --git a/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs index ea41f5ff8a..9c87778c0b 100644 --- a/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/WorldInteractionControllerWidget.cs @@ -27,6 +27,7 @@ namespace OpenRA.Mods.Common.Widgets readonly Color normalSelectionColor; readonly Color altSelectionColor; readonly Color ctrlSelectionColor; + readonly GameSettings gameSettings; public readonly string ClickSound = ChromeMetrics.Get("ClickSound"); public readonly string ClickDisabledSound = ChromeMetrics.Get("ClickDisabledSound"); @@ -40,6 +41,7 @@ namespace OpenRA.Mods.Common.Widgets public WorldInteractionControllerWidget(World world, WorldRenderer worldRenderer) { World = world; + gameSettings = Game.Settings.Game; this.worldRenderer = worldRenderer; if (!ChromeMetrics.TryGet("AltSelectionColor", out altSelectionColor)) altSelectionColor = Color.White; @@ -84,8 +86,7 @@ namespace OpenRA.Mods.Common.Widgets { mousePos = worldRenderer.Viewport.ViewToWorldPx(mi.Location); - var useClassicMouseStyle = Game.Settings.Game.UseClassicMouseStyle; - + var useClassicMouseStyle = gameSettings.UseClassicMouseStyle; var multiClick = mi.MultiTapCount >= 2; if (World.OrderGenerator is not UnitOrderGenerator uog) @@ -218,7 +219,7 @@ namespace OpenRA.Mods.Common.Widgets var mi = new MouseInput { Location = screenPos, - Button = Game.Settings.Game.MouseButtonPreference.Action, + Button = World.OrderGenerator.ActionButton, Modifiers = Game.GetModifierKeys() };