A game about forced loneliness, made by TACStudios
1using System.Globalization;
2using UnityEngine.InputSystem.LowLevel;
3using UnityEngine.Scripting;
4
5namespace UnityEngine.InputSystem.Controls
6{
7 /// <summary>
8 /// A key on a <see cref="Keyboard"/>.
9 /// </summary>
10 /// <remarks>
11 /// This is an extended button control which adds various features to account for the fact that keys
12 /// have symbols associated with them which may change depending on keyboard layout as well as in combination
13 /// with other keys.
14 ///
15 /// Note:
16 /// Unity input system key codes and input manager key codes are designed with game controls in mind.
17 ///
18 /// This means the way they are assigned is intended to preserve the location of keys on keyboards,
19 /// so that pressing a key in the same location on different keyboards should result in the same action
20 /// regardless of what is printed on a key or what current system language is set.
21 ///
22 /// This means, for example, that <see cref="Key.A"/> is always the key to the right of <see cref="Key.CapsLock"/>,
23 /// regardless of which key (if any) produces the "a" character on the current keyboard layout.
24 ///
25 /// Unity relies on physical hardware in the keyboards to report same USB HID "usage" for the keys in
26 /// the same location.This puts a practical limit on what can be achieved, because different keyboards
27 /// might report different data, and this is outside of Unity's control.
28 ///
29 /// For this reason, you should not use key codes to read text input.
30 /// Instead, you should use the <see cref="Keyboard.onTextInput"/> callback.
31 /// The `onTextInput` callback provides you with the actual text characters which correspond
32 /// to the symbols printed on a keyboard, based on the end user's current system language layout.
33 ///
34 /// To find the text character (if any) generated by a key according to the currently active keyboard
35 /// layout, use the <see cref="InputControl.displayName"/> property of <see cref="KeyControl"/>.
36 /// </remarks>
37 public class KeyControl : ButtonControl
38 {
39 /// <summary>
40 /// The code used in Unity to identify the key.
41 /// </summary>
42 /// <remarks>
43 /// This property must be initialized by <see cref="InputControl.FinishSetup"/> of
44 /// the device owning the control.
45 /// You should not use `keyCode` to read text input. For more information, <see cref="KeyControl"/>
46 /// </remarks>
47 public Key keyCode { get; set; }
48
49 ////REVIEW: rename this to something like platformKeyCode? We're not really dealing with scan code here.
50 /// <summary>
51 /// The code that the underlying platform uses to identify the key.
52 /// </summary>
53 public int scanCode
54 {
55 get
56 {
57 RefreshConfigurationIfNeeded();
58 return m_ScanCode;
59 }
60 }
61
62 protected override void RefreshConfiguration()
63 {
64 // Wipe our last cached set of data (if any).
65 displayName = null;
66 m_ScanCode = 0;
67
68 var command = QueryKeyNameCommand.Create(keyCode);
69 if (device.ExecuteCommand(ref command) > 0)
70 {
71 m_ScanCode = command.scanOrKeyCode;
72
73 var rawKeyName = command.ReadKeyName();
74 if (string.IsNullOrEmpty(rawKeyName))
75 {
76 displayName = rawKeyName;
77 return;
78 }
79
80 var textInfo = CultureInfo.InvariantCulture.TextInfo;
81 // We need to lower case first because ToTitleCase preserves upper casing.
82 // For example on Swedish Windows layout right shift display name is "HÖGER SKIFT".
83 // Just passing it to ToTitleCase won't change anything. But passing "höger skift" will return "Höger Skift".
84 var keyNameLowerCase = textInfo.ToLower(rawKeyName);
85 if (string.IsNullOrEmpty(keyNameLowerCase))
86 {
87 displayName = rawKeyName;
88 return;
89 }
90
91 displayName = textInfo.ToTitleCase(keyNameLowerCase);
92 }
93 }
94
95 // Cached configuration data for the key. We fetch this from the
96 // device on demand.
97 private int m_ScanCode;
98 }
99}