diff --git a/AUTHORS b/AUTHORS index 04b4c0bccf..4a88044ee7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,6 +37,7 @@ Also thanks to: * Raymond Martineau (mart0258) * Riderr3 * Tim Mylemans (gecko) + * Tirili Past developers included: * Paul Chote (pchote) diff --git a/OpenRA.Game/GameRules/Settings.cs b/OpenRA.Game/GameRules/Settings.cs index e270d78d49..bb8d3fc0ed 100644 --- a/OpenRA.Game/GameRules/Settings.cs +++ b/OpenRA.Game/GameRules/Settings.cs @@ -120,6 +120,26 @@ namespace OpenRA.GameRules public string ConnectTo = ""; } + public class KeySettings + { + public string PauseKey = "f3"; + + public string CycleBaseKey = "backspace"; + public string GotoLastEventKey = "space"; + public string SellKey = "v"; + public string PowerDownKey = "b"; + public string RepairKey = "n"; + + public string AttackMoveKey = "a"; + public string StopKey = "s"; + public string ScatterKey = "x"; + public string StanceCycleKey = "z"; + public string DeployKey = "f"; + + public string CycleTabsKey = "tab"; + } + + public class Settings { string SettingsFile; @@ -130,6 +150,7 @@ namespace OpenRA.GameRules public GraphicSettings Graphics = new GraphicSettings(); public ServerSettings Server = new ServerSettings(); public DebugSettings Debug = new DebugSettings(); + public KeySettings Keys = new KeySettings(); public Dictionary Sections; @@ -144,6 +165,7 @@ namespace OpenRA.GameRules {"Graphics", Graphics}, {"Server", Server}, {"Debug", Debug}, + {"Keys", Keys}, }; // Override fieldloader to ignore invalid entries diff --git a/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs b/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs index 95f31484ba..c9459eba05 100755 --- a/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs +++ b/OpenRA.Mods.Cnc/Widgets/ProductionTabsWidget.cs @@ -266,7 +266,7 @@ namespace OpenRA.Mods.Cnc.Widgets public override bool HandleKeyPress(KeyInput e) { if (e.Event != KeyInputEvent.Down) return false; - if (e.KeyName == "tab") + if (e.KeyName == Game.Settings.Keys.CycleTabsKey) { Sound.PlayNotification(null, "Sounds", "ClickSound", null); SelectNextTab(e.Modifiers.HasModifier(Modifiers.Shift)); diff --git a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs index f0cdaa6517..0ec408ecf6 100755 --- a/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs +++ b/OpenRA.Mods.RA/Widgets/BuildPaletteWidget.cs @@ -145,7 +145,7 @@ namespace OpenRA.Mods.RA.Widgets public override bool HandleKeyPress(KeyInput e) { if (e.Event == KeyInputEvent.Up) return false; - if (e.KeyName == "tab") + if (e.KeyName == Game.Settings.Keys.CycleTabsKey) { TabChange(e.Modifiers.HasModifier(Modifiers.Shift)); return true; diff --git a/OpenRA.Mods.RA/Widgets/Logic/SettingsMenuLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/SettingsMenuLogic.cs index d6b4b847f4..f3552f2987 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/SettingsMenuLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/SettingsMenuLogic.cs @@ -30,6 +30,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic tabs.Get("GENERAL").OnClick = () => FlipToTab("GENERAL_PANE"); tabs.Get("AUDIO").OnClick = () => FlipToTab("AUDIO_PANE"); tabs.Get("DISPLAY").OnClick = () => FlipToTab("DISPLAY_PANE"); + tabs.Get("KEYS").OnClick = () => FlipToTab("KEYS_PANE"); tabs.Get("DEBUG").OnClick = () => FlipToTab("DEBUG_PANE"); FlipToTab("GENERAL_PANE"); @@ -120,6 +121,82 @@ namespace OpenRA.Mods.RA.Widgets.Logic Game.viewport.Zoom = gs.PixelDouble ? 2 : 1; }; + // Keys + var keys = bg.Get("KEYS_PANE"); + var keyConfig = Game.Settings.Keys; + + var specialHotkeyList = keys.Get("SPECIALHOTKEY_LIST"); + var specialHotkeyTemplate = specialHotkeyList.Get("SPECIALHOTKEY_TEMPLATE"); + + var pauseKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + pauseKey.Get("FUNCTION").GetText = () => "Pause the game:"; + SetupKeyBinding(pauseKey.Get("HOTKEY"), + () => keyConfig.PauseKey, k => keyConfig.PauseKey = k); + specialHotkeyList.AddChild(pauseKey); + + var viewportToBase = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + viewportToBase.Get("FUNCTION").GetText = () => "Move Viewport to Base:"; + SetupKeyBinding(viewportToBase.Get("HOTKEY"), + () => keyConfig.CycleBaseKey, k => keyConfig.CycleBaseKey = k); + specialHotkeyList.AddChild(viewportToBase); + + var lastEventKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + lastEventKey.Get("FUNCTION").GetText = () => "Move Viewport to Last Event:"; + SetupKeyBinding(lastEventKey.Get("HOTKEY"), + () => keyConfig.GotoLastEventKey, k => keyConfig.GotoLastEventKey = k); + specialHotkeyList.AddChild(lastEventKey); + + var sellKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + sellKey.Get("FUNCTION").GetText = () => "Switch to Sell-Cursor:"; + SetupKeyBinding(sellKey.Get("HOTKEY"), + () => keyConfig.SellKey, k => keyConfig.SellKey = k); + specialHotkeyList.AddChild(sellKey); + + var powerDownKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + powerDownKey.Get("FUNCTION").GetText = () => "Switch to Power-Down-Cursor:"; + SetupKeyBinding(powerDownKey.Get("HOTKEY"), + () => keyConfig.PowerDownKey, k => keyConfig.PowerDownKey = k); + specialHotkeyList.AddChild(powerDownKey); + + var repairKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {}); + repairKey.Get("FUNCTION").GetText = () => "Switch to Repair-Cursor:"; + SetupKeyBinding(repairKey.Get("HOTKEY"), + () => keyConfig.RepairKey, k => keyConfig.RepairKey = k); + specialHotkeyList.AddChild(repairKey); + + var unitCommandHotkeyList = keys.Get("UNITCOMMANDHOTKEY_LIST"); + var unitCommandHotkeyTemplate = unitCommandHotkeyList.Get("UNITCOMMANDHOTKEY_TEMPLATE"); + + var attackKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {}); + attackKey.Get("FUNCTION").GetText = () => "Attack Move:"; + SetupKeyBinding(attackKey.Get("HOTKEY"), + () => keyConfig.AttackMoveKey, k => keyConfig.AttackMoveKey = k); + unitCommandHotkeyList.AddChild(attackKey); + + var stopKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {}); + stopKey.Get("FUNCTION").GetText = () => "Stop:"; + SetupKeyBinding(stopKey.Get("HOTKEY"), + () => keyConfig.StopKey, k => keyConfig.StopKey = k); + unitCommandHotkeyList.AddChild(stopKey); + + var scatterKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {}); + scatterKey.Get("FUNCTION").GetText = () => "Scatter:"; + SetupKeyBinding(scatterKey.Get("HOTKEY"), + () => keyConfig.ScatterKey, k => keyConfig.ScatterKey = k); + unitCommandHotkeyList.AddChild(scatterKey); + + var stanceCycleKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {}); + stanceCycleKey.Get("FUNCTION").GetText = () => "Cycle Stance:"; + SetupKeyBinding(stanceCycleKey.Get("HOTKEY"), + () => keyConfig.StanceCycleKey, k => keyConfig.StanceCycleKey = k); + unitCommandHotkeyList.AddChild(stanceCycleKey); + + var deployKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {}); + deployKey.Get("FUNCTION").GetText = () => "Deploy:"; + SetupKeyBinding(deployKey.Get("HOTKEY"), + () => keyConfig.DeployKey, k => keyConfig.DeployKey = k); + unitCommandHotkeyList.AddChild(deployKey); + // Debug var debug = bg.Get("DEBUG_PANE"); @@ -199,6 +276,22 @@ namespace OpenRA.Mods.RA.Widgets.Logic return true; } + void SetupKeyBinding(TextFieldWidget textBox, Func getValue, Action setValue) + { + textBox.Text = getValue(); + + textBox.OnLoseFocus = () => + { + textBox.Text.Trim(); + if (textBox.Text.Length == 0) + textBox.Text = getValue(); + else + setValue(textBox.Text); + }; + + textBox.OnEnterKey = () => { textBox.LoseFocus(); return true; }; + } + public static bool ShowRendererDropdown(DropDownButtonWidget dropdown, GraphicSettings s) { var options = new Dictionary() diff --git a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs index 3c1262e4a6..753529834d 100644 --- a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs @@ -16,6 +16,7 @@ using OpenRA.Graphics; using OpenRA.Network; using OpenRA.Orders; using OpenRA.Widgets; +using OpenRA.Mods.RA.Orders; namespace OpenRA.Mods.RA.Widgets { @@ -23,14 +24,6 @@ namespace OpenRA.Mods.RA.Widgets { public World World { get { return OrderManager.world; } } - public string AttackMoveKey = "a"; - public string StopKey = "s"; - public string ScatterKey = "x"; - public string DeployKey = "f"; - public string StanceCycleKey = "z"; - public string BaseCycleKey = "backspace"; - public string GotoLastEventKey = "space"; - public readonly OrderManager OrderManager; [ObjectCreator.UseCtor] @@ -51,28 +44,37 @@ namespace OpenRA.Mods.RA.Widgets { if (e.Modifiers == Modifiers.None && e.Event == KeyInputEvent.Down) { - if (e.KeyName == BaseCycleKey) + if (e.KeyName == Game.Settings.Keys.CycleBaseKey) return CycleBases(); - if (e.KeyName == GotoLastEventKey) + if (e.KeyName == Game.Settings.Keys.GotoLastEventKey) return GotoLastEvent(); - if (!World.Selection.Actors.Any()) + if (e.KeyName == Game.Settings.Keys.SellKey) + return PerformSwitchToSellMode(); + + if (e.KeyName == Game.Settings.Keys.PowerDownKey) + return PerformSwitchToPowerDownMode(); + + if (e.KeyName == Game.Settings.Keys.RepairKey) + return PerformSwitchToRepairMode(); + + if (!World.Selection.Actors.Any()) // Put all functions, that are no unit-functions, before this line! return false; - if (e.KeyName == AttackMoveKey) + if (e.KeyName == Game.Settings.Keys.AttackMoveKey) return PerformAttackMove(); - if (e.KeyName == StopKey) + if (e.KeyName == Game.Settings.Keys.StopKey) return PerformStop(); - if (e.KeyName == ScatterKey) + if (e.KeyName == Game.Settings.Keys.ScatterKey) return PerformScatter(); - if (e.KeyName == DeployKey) + if (e.KeyName == Game.Settings.Keys.DeployKey) return PerformDeploy(); - if (e.KeyName == StanceCycleKey) + if (e.KeyName == Game.Settings.Keys.StanceCycleKey) return PerformStanceCycle(); } @@ -115,10 +117,11 @@ namespace OpenRA.Mods.RA.Widgets bool PerformDeploy() { - /* hack: three orders here -- ReturnToBase, DeployTransform, Unload. */ + /* hack: multiple orders here */ PerformKeyboardOrderOnSelection(a => new Order("ReturnToBase", a, false)); PerformKeyboardOrderOnSelection(a => new Order("DeployTransform", a, false)); PerformKeyboardOrderOnSelection(a => new Order("Unload", a, false)); + PerformKeyboardOrderOnSelection(a => new Order("DemoDeploy", a, false)); return true; } @@ -184,5 +187,23 @@ namespace OpenRA.Mods.RA.Widgets Game.viewport.Center(eventNotifier.lastAttackLocation.ToFloat2()); return true; } + + private bool PerformSwitchToSellMode () + { + World.ToggleInputMode (); + return true; + } + + private bool PerformSwitchToPowerDownMode () + { + World.ToggleInputMode (); + return true; + } + + private bool PerformSwitchToRepairMode () + { + World.ToggleInputMode(); + return true; + } } } diff --git a/mods/ra/chrome/settings.yaml b/mods/ra/chrome/settings.yaml index 22e831761f..b9113b01c9 100644 --- a/mods/ra/chrome/settings.yaml +++ b/mods/ra/chrome/settings.yaml @@ -2,13 +2,13 @@ Background@SETTINGS_MENU: Logic:SettingsMenuLogic X:(WINDOW_RIGHT - WIDTH)/2 Y:(WINDOW_BOTTOM- HEIGHT)/2 - Width: 450 - Height: 350 + Width: 540 + Height: 400 Children: Label@SETTINGS_LABEL_TITLE: X:0 Y:20 - Width:450 + Width:540 Height:25 Text:Settings Align:Center @@ -48,11 +48,18 @@ Background@SETTINGS_MENU: Height:25 Text:Display Font:Bold - Button@DEBUG: + Button@KEYS: X:315 Y:0 Width:90 Height:25 + Text:Keys + Font:Bold + Button@DEBUG: + X:405 + Y:0 + Width:90 + Height:25 Text:Debug Font:Bold Container@GENERAL_PANE: @@ -228,6 +235,67 @@ Background@SETTINGS_MENU: Height:20 Font:Regular Text:Enable Pixel Doubling + Container@KEYS_PANE: + X:37 + Y:100 + Width:PARENT_RIGHT - 37 + Height:PARENT_BOTTOM - 100 + Visible: false + Children: + Label@KEYS_SPECIALHOTKEYSHEADLINE: + X:0 + Y:0 + Text: Special Hotkeys: + Font:Bold + ScrollPanel@SPECIALHOTKEY_LIST: + X:0 + Y:20 + Width:449 + Height:85 + Children: + ScrollItem@SPECIALHOTKEY_TEMPLATE: + Width:PARENT_RIGHT-27 + Height:25 + X:2 + Y:0 + Visible:false + Children: + Label@FUNCTION: + X:10 + Width:200 + Height:25 + TextField@HOTKEY: + X:250 + Width:139 + Height:25 + MaxLength:16 + Label@KEYS_UNITCOMMANDSHEADLINE: + X:0 + Y:130 + Text: Hotkeys for Unit Commands: + Font:Bold + ScrollPanel@UNITCOMMANDHOTKEY_LIST: + X:0 + Y:150 + Width:449 + Height:85 + Children: + ScrollItem@UNITCOMMANDHOTKEY_TEMPLATE: + Width:PARENT_RIGHT-27 + Height:25 + X:2 + Y:0 + Visible:false + Children: + Label@FUNCTION: + X:10 + Width:200 + Height:25 + TextField@HOTKEY: + X:250 + Width:139 + Height:25 + MaxLength:16 Container@DEBUG_PANE: X:37 Y:100