patterncsharpMinor
Hotkey detection for UI elements
Viewed 0 times
detectionelementsforhotkey
Problem
I have several UI elements that can be opened using hotkeys for example the settings menu's key is Escape. The problem is that I have the
And here's how I used to invoke them :
I didn't like the repetitive code in here so I decided to create a function which solves the problem:
```
CheckUIKeysCollection(Settings.Settings.KeysUIElementsWithButtonEvents);
CheckUIKeysCollection(Settings.Settings.KeysUIElementsWithActions);
private void CheckUIKeysCollection(Dictionary collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
Keycode stored in Dictionary along with an Action or a Button.ButtonClickedEvent here's how the two dictionaries are declared: public static readonly Dictionary KeysUIElementsWithButtonEvents = new Dictionary
{
{ KeyCode.P, SpellbookButton.onClick },
{ KeyCode.Escape, SettingsMenuButton.onClick },
};
public static readonly Dictionary KeysUIElementsWithActions = new Dictionary
{
{ KeyCode.LeftAlt, SwitchCursorState},
};And here's how I used to invoke them :
foreach (var item in Settings.Settings.KeysUIElementsWithButtonEvents)
{
if(Input.GetKeyDown(item.Key))
{
if(Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
item.Value.Invoke();
}
}
foreach (var item in Settings.Settings.KeysUIElementsWithActions)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
item.Value.Invoke();
}
}I didn't like the repetitive code in here so I decided to create a function which solves the problem:
```
CheckUIKeysCollection(Settings.Settings.KeysUIElementsWithButtonEvents);
CheckUIKeysCollection(Settings.Settings.KeysUIElementsWithActions);
private void CheckUIKeysCollection(Dictionary collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
Solution
The easiest way to solve this with one dictionary is to simply create an action for the
Can be one
Then this:
Becomes this:
No more generics, no more casting, no more inferences. Simply create an action that calls the
You could, also, create a method that does that for you:
Then make your dictionary:
This also means it's simpler to click buttons from anywhere in your code: simply call
Apart from that:
Using
Button.ButtonClickedEvent calls:public static readonly Dictionary KeysUIElementsWithButtonEvents = new Dictionary
{
{ KeyCode.P, SpellbookButton.onClick },
{ KeyCode.Escape, SettingsMenuButton.onClick },
};
public static readonly Dictionary KeysUIElementsWithActions = new Dictionary
{
{ KeyCode.LeftAlt, SwitchCursorState},
};Can be one
Dictionary:public static readonly Dictionary KeysUIElementsWithActions = new Dictionary
{
{ KeyCode.P, () => SpellbookButton.onClick.Invoke() },
{ KeyCode.Escape, () => SettingsMenuButton.onClick.Invoke() },
{ KeyCode.LeftAlt, SwitchCursorState }
}Then this:
private void CheckUIKeysCollection(Dictionary collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
if (item.Value is Action)
{
(item.Value as Action).Invoke();
continue;
}
(item.Value as Button.ButtonClickedEvent).Invoke();
}
}
}Becomes this:
private void CheckUIKeysCollection(Dictionary collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
item.Value.Invoke();
}
}
}No more generics, no more casting, no more inferences. Simply create an action that calls the
ButtonClickedEvent.Invoke() method for the appropriate Button.You could, also, create a method that does that for you:
public void ClickButton(Button button)
{
button.onClick.Invoke();
}Then make your dictionary:
public static readonly Dictionary KeysUIElementsWithActions = new Dictionary
{
{ KeyCode.P, ClickButton(SpellbookButton) },
{ KeyCode.Escape, ClickButton(SettingsMenuButton) },
{ KeyCode.LeftAlt, SwitchCursorState }
}This also means it's simpler to click buttons from anywhere in your code: simply call
ClickButton(Button), instead of Button.onClick.Invoke().Apart from that:
Using
is then as is not recommended, simply use as then check if it's null:var temp = value as string;
if (temp != null)
{
Console.WriteLine(temp.Length);
}Code Snippets
public static readonly Dictionary<KeyCode, Button.ButtonClickedEvent> KeysUIElementsWithButtonEvents = new Dictionary<KeyCode, Button.ButtonClickedEvent>
{
{ KeyCode.P, SpellbookButton.onClick },
{ KeyCode.Escape, SettingsMenuButton.onClick },
};
public static readonly Dictionary<KeyCode, Action> KeysUIElementsWithActions = new Dictionary<KeyCode, Action>
{
{ KeyCode.LeftAlt, SwitchCursorState},
};public static readonly Dictionary<KeyCode, Action> KeysUIElementsWithActions = new Dictionary<KeyCode, Action>
{
{ KeyCode.P, () => SpellbookButton.onClick.Invoke() },
{ KeyCode.Escape, () => SettingsMenuButton.onClick.Invoke() },
{ KeyCode.LeftAlt, SwitchCursorState }
}private void CheckUIKeysCollection<T>(Dictionary<KeyCode, T> collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
if (item.Value is Action)
{
(item.Value as Action).Invoke();
continue;
}
(item.Value as Button.ButtonClickedEvent).Invoke();
}
}
}private void CheckUIKeysCollection(Dictionary<KeyCode, Action> collection)
{
foreach (var item in collection)
{
if (Input.GetKeyDown(item.Key))
{
if (Cursor.lockState == CursorLockMode.Locked)
{
Settings.Settings.SwitchCursorState();
}
item.Value.Invoke();
}
}
}public void ClickButton(Button button)
{
button.onClick.Invoke();
}Context
StackExchange Code Review Q#135832, answer score: 5
Revisions (0)
No revisions yet.