Replace MouseButtonPreference with MouseActionType.

This commit is contained in:
Paul Chote
2025-12-15 20:30:26 +00:00
committed by Gustas Kažukauskas
parent c588c3ef8d
commit 962e7e911d
27 changed files with 212 additions and 246 deletions

View File

@@ -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;
}
}

View File

@@ -16,6 +16,7 @@ namespace OpenRA.Orders
{
public interface IOrderGenerator
{
MouseButton ActionButton { get; }
IEnumerable<Order> Order(World world, CPos cell, int2 worldPixel, MouseInput mi);
void Tick(World world);
IEnumerable<IRenderable> Render(WorldRenderer wr, World world);

View File

@@ -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

View File

@@ -35,7 +35,6 @@ namespace OpenRA
readonly List<IEffect> unpartitionedEffects = [];
readonly List<ISync> syncedEffects = [];
readonly GameSettings gameSettings;
readonly ModData modData;
readonly Queue<Action<World>> 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<T>() 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<GameSpeeds>();
var gameSpeedName = orderManager.LobbyInfo.GlobalSettings.OptionOrDefault("gamespeed", gameSpeeds.DefaultSpeed);

View File

@@ -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<Order> 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<PortableChrono>().CanTeleport && self.Owner.Shroud.IsExplored(cell))
{

View File

@@ -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<Order> 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

View File

@@ -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<Order> 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<Order> 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;

View File

@@ -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<Order> 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<IRenderable> Render(WorldRenderer wr, World world) { yield break; }

View File

@@ -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> 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);

View File

@@ -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<Order> 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<Order> OrderInner(World world, MouseInput mi)
protected override IEnumerable<Order> 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<T>()
.Any(IsValidTrait));
var underCursor = world.ScreenMap.ActorsAtMouse(mi)
.Select(a => a.Actor)
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.TraitsImplementing<T>()
.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<ToggleConditionOnOrder>
{
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<Sellable>
{
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<Sellable>())
.Where(t => !t.IsTraitDisabled)
.Select(si => si.Info.Cursor)

View File

@@ -20,27 +20,25 @@ namespace OpenRA.Mods.Common.Orders
{
readonly string orderName;
readonly string cursor;
readonly MouseButton expectedButton;
IEnumerable<Actor> subjects;
protected override MouseActionType ActionType => MouseActionType.ConfirmOrder;
public GuardOrderGenerator(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
public GuardOrderGenerator(World world, IEnumerable<Actor> subjects, string order, string cursor)
: base(world)
{
orderName = order;
this.cursor = cursor;
expectedButton = button;
this.subjects = subjects;
}
public override IEnumerable<Order> 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<Order> OrderInner(World world, MouseInput mi)
{
var target = FriendlyGuardableUnits(world, mi).FirstOrDefault();
if (target == null)
yield break;

View File

@@ -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> 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 [];
}

View File

@@ -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<PlaceBuildingInfo>();
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<VariantWrapper>()
@@ -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> 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;

View File

@@ -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<Order> OrderInner(World world, CPos cell, int2 worldPixel, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
world.CancelInputMode();
return OrderInner(world, mi);
}
static IEnumerable<Order> 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";
}
}

View File

@@ -22,6 +22,16 @@ namespace OpenRA.Mods.Common.Orders
{
readonly string worldSelectCursor = ChromeMetrics.Get<string>("WorldSelectCursor");
readonly string worldDefaultCursor = ChromeMetrics.Get<string>("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<ISelectableInfo>();
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.
/// </summary>
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)

View File

@@ -104,12 +104,11 @@ namespace OpenRA.Mods.Common.Traits
{
TraitPair<AttackMove>[] subjects;
readonly MouseButton expectedButton;
protected override MouseActionType ActionType => MouseActionType.ConfirmOrder;
public AttackMoveOrderGenerator(IEnumerable<Actor> subjects, MouseButton button)
public AttackMoveOrderGenerator(World world, IEnumerable<Actor> subjects)
: base(world)
{
expectedButton = button;
this.subjects = subjects.Where(a => !a.IsDead)
.SelectMany(a => a.TraitsImplementing<AttackMove>()
.Select(am => new TraitPair<AttackMove>(a, am)))
@@ -118,26 +117,21 @@ namespace OpenRA.Mods.Common.Traits
public override IEnumerable<Order> 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<Order> 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<Actor> selected)

View File

@@ -220,6 +220,8 @@ namespace OpenRA.Mods.Common.Traits
sealed class MinefieldOrderGenerator : OrderGenerator
{
protected override MouseActionType ActionType => MouseActionType.ConfirmOrder;
readonly List<Actor> 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<Order> 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<Actor> selected)

View File

@@ -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<Order> 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 };
}

View File

@@ -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;
}

View File

@@ -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<MouseAttachmentWidget>("MOUSE_ATTATCHMENT");
}
public MouseButton ActionButton => gameSettings.ResolveActionButton(MouseActionType.SupportPower);
public MouseButton CancelButton => gameSettings.ResolveCancelButton(MouseActionType.SupportPower);
IEnumerable<Order> 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)
{

View File

@@ -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<Order> 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 };
}

View File

@@ -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)

View File

@@ -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<Order> 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 };
}

View File

@@ -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);
};
}

View File

@@ -15,56 +15,41 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
public class SellOrderButtonLogic : ChromeLogic
public abstract class ChromeOrderButtonLogic<T> : 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<SellOrderGenerator>(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<RepairOrderGenerator>(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<PowerDownOrderGenerator>(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<BeaconOrderGenerator>(world, beacon, "beacon");
}
}
public static class OrderButtonsChromeUtils
{
public static void BindOrderButton<T>(World world, ButtonWidget w, string icon)
where T : IOrderGenerator, new()
{
w.OnClick = () => world.ToggleInputMode<T>();
w.IsHighlighted = () => world.OrderGenerator is T;
w.Get<ImageWidget>("ICON").GetImageName =
widget.Get<ImageWidget>("ICON").GetImageName =
() => world.OrderGenerator is T ? icon + "-active" : icon;
}
}
[method: ObjectCreator.UseCtor]
public class SellOrderButtonLogic(Widget widget, World world)
: ChromeOrderButtonLogic<SellOrderGenerator>(widget, world, "sell");
[method: ObjectCreator.UseCtor]
public class RepairOrderButtonLogic(Widget widget, World world)
: ChromeOrderButtonLogic<RepairOrderGenerator>(widget, world, "repair");
[method: ObjectCreator.UseCtor]
public class PowerdownOrderButtonLogic(Widget widget, World world)
: ChromeOrderButtonLogic<PowerDownOrderGenerator>(widget, world, "power");
[method: ObjectCreator.UseCtor]
public class BeaconOrderButtonLogic(Widget widget, World world)
: ChromeOrderButtonLogic<BeaconOrderGenerator>(widget, world, "beacon");
}

View File

@@ -36,6 +36,7 @@ namespace OpenRA.Mods.Common.Widgets
public Action AfterClose = () => { };
public Action<float> 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<string>("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<RadarPings>();
radarTerrainLayers = world.WorldActor.TraitsImplementing<IRadarTerrainLayer>().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,
};

View File

@@ -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<string>("ClickSound");
public readonly string ClickDisabledSound = ChromeMetrics.Get<string>("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()
};