make hotkey user-configurable via in-game settings

This commit is contained in:
Matthias Mailänder
2013-02-09 14:08:36 +01:00
parent e71135b511
commit 1f99b1ec8e
7 changed files with 228 additions and 23 deletions

View File

@@ -37,6 +37,7 @@ Also thanks to:
* Raymond Martineau (mart0258)
* Riderr3
* Tim Mylemans (gecko)
* Tirili
Past developers included:
* Paul Chote (pchote)

View File

@@ -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<string, object> Sections;
@@ -144,6 +165,7 @@ namespace OpenRA.GameRules
{"Graphics", Graphics},
{"Server", Server},
{"Debug", Debug},
{"Keys", Keys},
};
// Override fieldloader to ignore invalid entries

View File

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

View File

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

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
tabs.Get<ButtonWidget>("GENERAL").OnClick = () => FlipToTab("GENERAL_PANE");
tabs.Get<ButtonWidget>("AUDIO").OnClick = () => FlipToTab("AUDIO_PANE");
tabs.Get<ButtonWidget>("DISPLAY").OnClick = () => FlipToTab("DISPLAY_PANE");
tabs.Get<ButtonWidget>("KEYS").OnClick = () => FlipToTab("KEYS_PANE");
tabs.Get<ButtonWidget>("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<ScrollPanelWidget>("SPECIALHOTKEY_LIST");
var specialHotkeyTemplate = specialHotkeyList.Get<ScrollItemWidget>("SPECIALHOTKEY_TEMPLATE");
var pauseKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
pauseKey.Get<LabelWidget>("FUNCTION").GetText = () => "Pause the game:";
SetupKeyBinding(pauseKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.PauseKey, k => keyConfig.PauseKey = k);
specialHotkeyList.AddChild(pauseKey);
var viewportToBase = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
viewportToBase.Get<LabelWidget>("FUNCTION").GetText = () => "Move Viewport to Base:";
SetupKeyBinding(viewportToBase.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.CycleBaseKey, k => keyConfig.CycleBaseKey = k);
specialHotkeyList.AddChild(viewportToBase);
var lastEventKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
lastEventKey.Get<LabelWidget>("FUNCTION").GetText = () => "Move Viewport to Last Event:";
SetupKeyBinding(lastEventKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.GotoLastEventKey, k => keyConfig.GotoLastEventKey = k);
specialHotkeyList.AddChild(lastEventKey);
var sellKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
sellKey.Get<LabelWidget>("FUNCTION").GetText = () => "Switch to Sell-Cursor:";
SetupKeyBinding(sellKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.SellKey, k => keyConfig.SellKey = k);
specialHotkeyList.AddChild(sellKey);
var powerDownKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
powerDownKey.Get<LabelWidget>("FUNCTION").GetText = () => "Switch to Power-Down-Cursor:";
SetupKeyBinding(powerDownKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.PowerDownKey, k => keyConfig.PowerDownKey = k);
specialHotkeyList.AddChild(powerDownKey);
var repairKey = ScrollItemWidget.Setup(specialHotkeyTemplate, () => false, () => {});
repairKey.Get<LabelWidget>("FUNCTION").GetText = () => "Switch to Repair-Cursor:";
SetupKeyBinding(repairKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.RepairKey, k => keyConfig.RepairKey = k);
specialHotkeyList.AddChild(repairKey);
var unitCommandHotkeyList = keys.Get<ScrollPanelWidget>("UNITCOMMANDHOTKEY_LIST");
var unitCommandHotkeyTemplate = unitCommandHotkeyList.Get<ScrollItemWidget>("UNITCOMMANDHOTKEY_TEMPLATE");
var attackKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {});
attackKey.Get<LabelWidget>("FUNCTION").GetText = () => "Attack Move:";
SetupKeyBinding(attackKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.AttackMoveKey, k => keyConfig.AttackMoveKey = k);
unitCommandHotkeyList.AddChild(attackKey);
var stopKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {});
stopKey.Get<LabelWidget>("FUNCTION").GetText = () => "Stop:";
SetupKeyBinding(stopKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.StopKey, k => keyConfig.StopKey = k);
unitCommandHotkeyList.AddChild(stopKey);
var scatterKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {});
scatterKey.Get<LabelWidget>("FUNCTION").GetText = () => "Scatter:";
SetupKeyBinding(scatterKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.ScatterKey, k => keyConfig.ScatterKey = k);
unitCommandHotkeyList.AddChild(scatterKey);
var stanceCycleKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {});
stanceCycleKey.Get<LabelWidget>("FUNCTION").GetText = () => "Cycle Stance:";
SetupKeyBinding(stanceCycleKey.Get<TextFieldWidget>("HOTKEY"),
() => keyConfig.StanceCycleKey, k => keyConfig.StanceCycleKey = k);
unitCommandHotkeyList.AddChild(stanceCycleKey);
var deployKey = ScrollItemWidget.Setup(unitCommandHotkeyTemplate, () => false, () => {});
deployKey.Get<LabelWidget>("FUNCTION").GetText = () => "Deploy:";
SetupKeyBinding(deployKey.Get<TextFieldWidget>("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<string> getValue, Action<string> 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<string, string>()

View File

@@ -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<SellOrderGenerator> ();
return true;
}
private bool PerformSwitchToPowerDownMode ()
{
World.ToggleInputMode<PowerDownOrderGenerator> ();
return true;
}
private bool PerformSwitchToRepairMode ()
{
World.ToggleInputMode<RepairOrderGenerator>();
return true;
}
}
}

View File

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