Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Keyboard.cs
浏览该文件的文档.
1#if ANDROID
2#pragma warning disable CA1416
3using System.Collections.Concurrent;
4using Android.App;
5using Android.Views;
6using Android.Widget;
7#elif BROWSER
9#else
10using Silk.NET.Input;
11#endif
12
13namespace Engine.Input {
14 public static class Keyboard {
15#if ANDROID
16 public struct KeyInfo {
17 public Key Key;
18 public bool Press;//true:按下,false: 抬起
19 public int? UnicodeChar;
20
21 public KeyInfo(Key key, bool press, int? unicodeChar) {
22 Key = key;
23 Press = press;
24 UnicodeChar = unicodeChar;
25 }
26 }
27
28 public static ConcurrentQueue<KeyInfo> m_cachedKeyEvents = [];
29#elif !BROWSER
30 public static IKeyboard m_keyboard;
31#endif
32
33 public static double m_keyFirstRepeatTime = 0.3;
34
35 public static double m_keyNextRepeatTime = 0.04;
36
37 static bool[] m_keysDownArray = new bool[Enum.GetValues<Key>().Length];
38
39 static bool[] m_keysDownOnceArray = new bool[Enum.GetValues<Key>().Length];
40
41 static double[] m_keysDownRepeatArray = new double[Enum.GetValues<Key>().Length];
42
43 static Key? m_lastKey;
44
45 static char? m_lastChar;
46
47 public static Key? LastKey => m_lastKey;
48
49 public static char? LastChar => m_lastChar;
50
51 public static bool IsKeyboardVisible { get; private set; }
52
53 public static bool BackButtonQuitsApp { get; set; }
54
55 public static event Action<Key> KeyDown;
56
57 public static event Action<Key> KeyUp;
58
59 public static event Action<char> CharacterEntered;
60
61 public static bool IsKeyDown(Key key) => m_keysDownArray[(int)key];
62
63 public static bool IsKeyDownOnce(Key key) => m_keysDownOnceArray[(int)key];
64
65 public static bool IsKeyDownRepeat(Key key) {
66 double num = m_keysDownRepeatArray[(int)key];
67 return num < 0.0 || (num != 0.0 && Time.FrameStartTime >= num);
68 }
69
70 public static void ShowKeyboard(string title,
71 string description,
72 string defaultText,
73 bool passwordMode,
74 Action<string> enter,
75 Action cancel) {
76 ArgumentNullException.ThrowIfNull(title);
77 ArgumentNullException.ThrowIfNull(description);
78 ArgumentNullException.ThrowIfNull(defaultText);
79 if (!IsKeyboardVisible) {
80 Clear();
81 Touch.Clear();
82 Mouse.Clear();
83 IsKeyboardVisible = true;
84 try {
86 title,
87 description,
88 defaultText,
89 passwordMode,
90 delegate(string text) {
92 delegate {
93 IsKeyboardVisible = false;
94 enter?.Invoke(text ?? string.Empty);
95 }
96 );
97 },
98 delegate {
100 delegate {
101 IsKeyboardVisible = false;
102 cancel?.Invoke();
103 }
104 );
105 }
106 );
107 }
108 catch {
109 IsKeyboardVisible = false;
110 throw;
111 }
112 }
113 }
114
115 public static void Clear() {
116 m_lastKey = null;
117 m_lastChar = null;
118 for (int i = 0; i < m_keysDownArray.Length; i++) {
119 m_keysDownArray[i] = false;
120 m_keysDownOnceArray[i] = false;
121 m_keysDownRepeatArray[i] = 0.0;
122 }
123 }
124
125 internal static void BeforeFrame() {
126#if ANDROID
127 while (!m_cachedKeyEvents.IsEmpty) {
128 if (m_cachedKeyEvents.TryDequeue(out KeyInfo keyInfo)) {
129 if (keyInfo.Press) {
130 if (keyInfo.Key != Key.Null) {
131 ProcessKeyDown(keyInfo.Key);
132 }
133 if (keyInfo.UnicodeChar.HasValue) {
134 ProcessCharacterEntered((char)keyInfo.UnicodeChar.Value);
135 }
136 }
137 else if (keyInfo.Key != Key.Null) {
138 ProcessKeyUp(keyInfo.Key);
139 }
140 }
141 else {
142 Thread.Yield();
143 }
144 }
145#endif
146 }
147
148 internal static void AfterFrame() {
149 if (BackButtonQuitsApp && (IsKeyDownOnce(Key.Back) || IsKeyDownOnce(Key.Escape))) {
150 Window.Close();
151 }
152 m_lastKey = null;
153 m_lastChar = null;
154 for (int i = 0; i < m_keysDownOnceArray.Length; i++) {
155 m_keysDownOnceArray[i] = false;
156 }
157 for (int j = 0; j < m_keysDownRepeatArray.Length; j++) {
158 if (m_keysDownArray[j]) {
159 if (m_keysDownRepeatArray[j] < 0.0) {
161 }
164 }
165 }
166 else {
167 m_keysDownRepeatArray[j] = 0.0;
168 }
169 }
170 }
171
172#if ANDROID
173 public static void EnqueueMouseButtonEvent(Key key, bool press, int? unicodeChar) {
174 m_cachedKeyEvents.Enqueue(new KeyInfo(key, press, unicodeChar));
175 }
176#endif
177
178 public static bool ProcessKeyDown(Key key) {
180 return false;
181 }
182 m_lastKey = key;
183 if (!m_keysDownArray[(int)key]) {
184 m_keysDownArray[(int)key] = true;
185 m_keysDownOnceArray[(int)key] = true;
186 m_keysDownRepeatArray[(int)key] = -1.0;
187 }
188 KeyDown?.Invoke(key);
189 return true;
190 }
191
192 public static bool ProcessKeyUp(Key key) {
194 return false;
195 }
196 if (m_keysDownArray[(int)key]) {
197 m_keysDownArray[(int)key] = false;
198 }
199 KeyUp?.Invoke(key);
200 return true;
201 }
202
203 public static bool ProcessCharacterEntered(char ch) {
205 return false;
206 }
207 m_lastChar = ch;
208 CharacterEntered?.Invoke(ch);
209 return true;
210 }
211
212 internal static void Initialize() {
213#if !MOBILE && !BROWSER
214 m_keyboard = Window.m_inputContext.Keyboards[0];
215 m_keyboard.KeyDown += KeyDownHandler;
216 m_keyboard.KeyUp += KeyUpHandler;
217 m_keyboard.KeyChar += KeyPressHandler;
218#endif
219 }
220
221 internal static void Dispose() { }
222#if ANDROID
223 public static void HandleKeyEvent(KeyEvent keyEvent) {
224 EnqueueMouseButtonEvent(TranslateKey(keyEvent.KeyCode), keyEvent.Action == KeyEventActions.Down, keyEvent.UnicodeChar);
225 }
226#elif !BROWSER
227 static void KeyDownHandler(IKeyboard keyboard, Silk.NET.Input.Key key, int scancode) {
228 if (scancode == 270
229 || key == Silk.NET.Input.Key.Delete) {
231 }
232 Key translatedKey = TranslateKey(key);
233 if (translatedKey != Key.Null) {
234 ProcessKeyDown(translatedKey);
235 }
236 else if (scancode == 270) {
237 ProcessKeyDown(Key.Back);
238 }
239 }
240
241 static void KeyUpHandler(IKeyboard keyboard, Silk.NET.Input.Key key, int scancode) {
242 Key translatedKey = TranslateKey(key);
243 if (translatedKey != Key.Null) {
244 ProcessKeyUp(translatedKey);
245 }
246 else if (scancode == 270) {
247 ProcessKeyUp(Key.Back);
248 }
249 }
250
251 static void KeyPressHandler(IKeyboard keyboard, char c) {
252 KeyboardInput.Chars.Add(c);
254 }
255#endif
256#if ANDROID
257 public static Key TranslateKey(Keycode keyCode) => keyCode switch {
258 Keycode.Home => Key.Home,
259 Keycode.Back => Key.Back,
260 Keycode.Num0 or Keycode.Numpad0 => Key.Number0,
261 Keycode.Num1 or Keycode.Numpad1 => Key.Number1,
262 Keycode.Num2 or Keycode.Numpad2 => Key.Number2,
263 Keycode.Num3 or Keycode.Numpad3 => Key.Number3,
264 Keycode.Num4 or Keycode.Numpad4 => Key.Number4,
265 Keycode.Num5 or Keycode.Numpad5 => Key.Number5,
266 Keycode.Num6 or Keycode.Numpad6 => Key.Number6,
267 Keycode.Num7 or Keycode.Numpad7 => Key.Number7,
268 Keycode.Num8 or Keycode.Numpad8 => Key.Number8,
269 Keycode.Num9 or Keycode.Numpad9 => Key.Number9,
270 Keycode.A => Key.A,
271 Keycode.B => Key.B,
272 Keycode.C => Key.C,
273 Keycode.D => Key.D,
274 Keycode.E => Key.E,
275 Keycode.F => Key.F,
276 Keycode.G => Key.G,
277 Keycode.H => Key.H,
278 Keycode.I => Key.I,
279 Keycode.J => Key.J,
280 Keycode.K => Key.K,
281 Keycode.L => Key.L,
282 Keycode.M => Key.M,
283 Keycode.N => Key.N,
284 Keycode.O => Key.O,
285 Keycode.P => Key.P,
286 Keycode.Q => Key.Q,
287 Keycode.R => Key.R,
288 Keycode.S => Key.S,
289 Keycode.T => Key.T,
290 Keycode.U => Key.U,
291 Keycode.V => Key.V,
292 Keycode.W => Key.W,
293 Keycode.X => Key.X,
294 Keycode.Y => Key.Y,
295 Keycode.Z => Key.Z,
296 Keycode.Comma => Key.Comma,
297 Keycode.Period or Keycode.NumpadDot => Key.Period,
298 Keycode.ShiftLeft or Keycode.ShiftRight => Key.Shift,
299 Keycode.Tab => Key.Tab,
300 Keycode.Space => Key.Space,
301 Keycode.Enter or Keycode.NumpadEnter => Key.Enter,
302 Keycode.Del => Key.Delete,
303 Keycode.Minus or Keycode.NumpadSubtract => Key.Minus,
304 Keycode.LeftBracket => Key.LeftBracket,
305 Keycode.RightBracket => Key.RightBracket,
306 Keycode.Semicolon => Key.Semicolon,
307 Keycode.Slash or Keycode.NumpadDivide => Key.Slash,
308 Keycode.Backslash => Key.BackSlash,
309 Keycode.Equals or Keycode.Plus => Key.Plus,
310 Keycode.PageUp => Key.PageUp,
311 Keycode.PageDown => Key.PageDown,
312 Keycode.Escape => Key.Escape,
313 Keycode.ForwardDel => Key.Delete,
314 Keycode.CtrlLeft or Keycode.CtrlRight => Key.Control,
315 Keycode.CapsLock => Key.CapsLock,
316 Keycode.Insert => Key.Insert,
317 Keycode.F1 => Key.F1,
318 Keycode.F2 => Key.F2,
319 Keycode.F3 => Key.F3,
320 Keycode.F4 => Key.F4,
321 Keycode.F5 => Key.F5,
322 Keycode.F6 => Key.F6,
323 Keycode.F7 => Key.F7,
324 Keycode.F8 => Key.F8,
325 Keycode.F9 => Key.F9,
326 Keycode.F10 => Key.F10,
327 Keycode.F11 => Key.F11,
328 Keycode.F12 => Key.F12,
329 Keycode.AltLeft or Keycode.AltRight => Key.Alt,
330 _ => Key.Null
331 };
332#elif BROWSER
333 public static Key TranslateKey(string code) => code switch {
334 "ShiftLeft" or "ShiftRight" => Key.Shift,
335 "ControlLeft" or "ControlRight" => Key.Control,
336 "F1" => Key.F1,
337 "F2" => Key.F2,
338 "F3" => Key.F3,
339 "F4" => Key.F4,
340 "F5" => Key.F5,
341 "F6" => Key.F6,
342 "F7" => Key.F7,
343 "F8" => Key.F8,
344 "F9" => Key.F9,
345 "F10" => Key.F10,
346 "F11" => Key.F11,
347 "F12" => Key.F12,
348 "ArrowLeft" => Key.LeftArrow,
349 "ArrowRight" => Key.RightArrow,
350 "ArrowUp" => Key.UpArrow,
351 "ArrowDown" => Key.DownArrow,
352 "Enter" or "NumpadEnter" => Key.Enter,
353 "Escape" => Key.Escape,
354 "Space" => Key.Space,
355 "Tab" => Key.Tab,
356 "Backspace" => Key.BackSpace,
357 "Insert" => Key.Insert,
358 "Delete" => Key.Delete,
359 "PageUp" => Key.PageUp,
360 "PageDown" => Key.PageDown,
361 "Home" => Key.Home,
362 "End" => Key.End,
363 "CapsLock" => Key.CapsLock,
364 "KeyA" => Key.A,
365 "KeyB" => Key.B,
366 "KeyC" => Key.C,
367 "KeyD" => Key.D,
368 "KeyE" => Key.E,
369 "KeyF" => Key.F,
370 "KeyG" => Key.G,
371 "KeyH" => Key.H,
372 "KeyI" => Key.I,
373 "KeyJ" => Key.J,
374 "KeyK" => Key.K,
375 "KeyL" => Key.L,
376 "KeyM" => Key.M,
377 "KeyN" => Key.N,
378 "KeyO" => Key.O,
379 "KeyP" => Key.P,
380 "KeyQ" => Key.Q,
381 "KeyR" => Key.R,
382 "KeyS" => Key.S,
383 "KeyT" => Key.T,
384 "KeyU" => Key.U,
385 "KeyV" => Key.V,
386 "KeyW" => Key.W,
387 "KeyX" => Key.X,
388 "KeyY" => Key.Y,
389 "KeyZ" => Key.Z,
390 "Numpad0" or "Digit0" => Key.Number0,
391 "Numpad1" or "Digit1" => Key.Number1,
392 "Numpad2" or "Digit2" => Key.Number2,
393 "Numpad3" or "Digit3" => Key.Number3,
394 "Numpad4" or "Digit4" => Key.Number4,
395 "Numpad5" or "Digit5" => Key.Number5,
396 "Numpad6" or "Digit6" => Key.Number6,
397 "Numpad7" or "Digit7" => Key.Number7,
398 "Numpad8" or "Digit8" => Key.Number8,
399 "Numpad9" or "Digit9" => Key.Number9,
400 "Backquote" => Key.Tilde,
401 "Minus" or "NumpadSubtract" => Key.Minus,
402 "Equal" or "NumpadAdd" => Key.Plus,
403 "BracketLeft" => Key.LeftBracket,
404 "BracketRight" => Key.RightBracket,
405 "Semicolon" => Key.Semicolon,
406 "Quote" => Key.Quote,
407 "Comma" => Key.Comma,
408 "Period" or "NumpadDecimal" => Key.Period,
409 "Slash" or "NumpadDivide" => Key.Slash,
410 "AltLeft" or "AltRight" => Key.Alt,
411 "Backslash" => Key.BackSlash,
412 _ => Key.Null
413 };
414#else
415 public static Key TranslateKey(Silk.NET.Input.Key key) => key switch {
416 Silk.NET.Input.Key.ShiftLeft or Silk.NET.Input.Key.ShiftRight => Key.Shift,
417 Silk.NET.Input.Key.ControlLeft or Silk.NET.Input.Key.ControlRight => Key.Control,
418 Silk.NET.Input.Key.F1 => Key.F1,
419 Silk.NET.Input.Key.F2 => Key.F2,
420 Silk.NET.Input.Key.F3 => Key.F3,
421 Silk.NET.Input.Key.F4 => Key.F4,
422 Silk.NET.Input.Key.F5 => Key.F5,
423 Silk.NET.Input.Key.F6 => Key.F6,
424 Silk.NET.Input.Key.F7 => Key.F7,
425 Silk.NET.Input.Key.F8 => Key.F8,
426 Silk.NET.Input.Key.F9 => Key.F9,
427 Silk.NET.Input.Key.F10 => Key.F10,
428 Silk.NET.Input.Key.F11 => Key.F11,
429 Silk.NET.Input.Key.F12 => Key.F12,
430 Silk.NET.Input.Key.Up => Key.UpArrow,
431 Silk.NET.Input.Key.Down => Key.DownArrow,
432 Silk.NET.Input.Key.Left => Key.LeftArrow,
433 Silk.NET.Input.Key.Right => Key.RightArrow,
434 Silk.NET.Input.Key.Enter or Silk.NET.Input.Key.KeypadEnter => Key.Enter,
435 Silk.NET.Input.Key.Escape => Key.Escape,
436 Silk.NET.Input.Key.Space => Key.Space,
437 Silk.NET.Input.Key.Tab => Key.Tab,
438 Silk.NET.Input.Key.Backspace => Key.BackSpace,
439 Silk.NET.Input.Key.Insert => Key.Insert,
440 Silk.NET.Input.Key.Delete => Key.Delete,
441 Silk.NET.Input.Key.PageUp => Key.PageUp,
442 Silk.NET.Input.Key.PageDown => Key.PageDown,
443 Silk.NET.Input.Key.Home => Key.Home,
444 Silk.NET.Input.Key.End => Key.End,
445 Silk.NET.Input.Key.CapsLock => Key.CapsLock,
446 Silk.NET.Input.Key.A => Key.A,
447 Silk.NET.Input.Key.B => Key.B,
448 Silk.NET.Input.Key.C => Key.C,
449 Silk.NET.Input.Key.D => Key.D,
450 Silk.NET.Input.Key.E => Key.E,
451 Silk.NET.Input.Key.F => Key.F,
452 Silk.NET.Input.Key.G => Key.G,
453 Silk.NET.Input.Key.H => Key.H,
454 Silk.NET.Input.Key.I => Key.I,
455 Silk.NET.Input.Key.J => Key.J,
456 Silk.NET.Input.Key.K => Key.K,
457 Silk.NET.Input.Key.L => Key.L,
458 Silk.NET.Input.Key.M => Key.M,
459 Silk.NET.Input.Key.N => Key.N,
460 Silk.NET.Input.Key.O => Key.O,
461 Silk.NET.Input.Key.P => Key.P,
462 Silk.NET.Input.Key.Q => Key.Q,
463 Silk.NET.Input.Key.R => Key.R,
464 Silk.NET.Input.Key.S => Key.S,
465 Silk.NET.Input.Key.T => Key.T,
466 Silk.NET.Input.Key.U => Key.U,
467 Silk.NET.Input.Key.V => Key.V,
468 Silk.NET.Input.Key.W => Key.W,
469 Silk.NET.Input.Key.X => Key.X,
470 Silk.NET.Input.Key.Y => Key.Y,
471 Silk.NET.Input.Key.Z => Key.Z,
472 Silk.NET.Input.Key.Number0 or Silk.NET.Input.Key.Keypad0 => Key.Number0,
473 Silk.NET.Input.Key.Number1 or Silk.NET.Input.Key.Keypad1 => Key.Number1,
474 Silk.NET.Input.Key.Number2 or Silk.NET.Input.Key.Keypad2 => Key.Number2,
475 Silk.NET.Input.Key.Number3 or Silk.NET.Input.Key.Keypad3 => Key.Number3,
476 Silk.NET.Input.Key.Number4 or Silk.NET.Input.Key.Keypad4 => Key.Number4,
477 Silk.NET.Input.Key.Number5 or Silk.NET.Input.Key.Keypad5 => Key.Number5,
478 Silk.NET.Input.Key.Number6 or Silk.NET.Input.Key.Keypad6 => Key.Number6,
479 Silk.NET.Input.Key.Number7 or Silk.NET.Input.Key.Keypad7 => Key.Number7,
480 Silk.NET.Input.Key.Number8 or Silk.NET.Input.Key.Keypad8 => Key.Number8,
481 Silk.NET.Input.Key.Number9 or Silk.NET.Input.Key.Keypad9 => Key.Number9,
482 Silk.NET.Input.Key.GraveAccent => Key.Tilde,
483 Silk.NET.Input.Key.Minus or Silk.NET.Input.Key.KeypadSubtract => Key.Minus,
484 Silk.NET.Input.Key.Equal or Silk.NET.Input.Key.KeypadAdd => Key.Plus,
485 Silk.NET.Input.Key.LeftBracket => Key.LeftBracket,
486 Silk.NET.Input.Key.RightBracket => Key.RightBracket,
487 Silk.NET.Input.Key.Semicolon => Key.Semicolon,
488 Silk.NET.Input.Key.Apostrophe => Key.Quote,
489 Silk.NET.Input.Key.Comma => Key.Comma,
490 Silk.NET.Input.Key.Period or Silk.NET.Input.Key.KeypadDecimal => Key.Period,
491 Silk.NET.Input.Key.Slash or Silk.NET.Input.Key.KeypadDivide => Key.Slash,
492 Silk.NET.Input.Key.BackSlash => Key.BackSlash,
493 Silk.NET.Input.Key.AltLeft or Silk.NET.Input.Key.AltRight => Key.Alt,
494 _ => Key.Null
495 };
496#endif
497 // ReSharper disable UnusedParameter.Local
498 public static void ShowKeyboardInternal(string title,
499 string description,
500 string defaultText,
501 bool passwordMode,
502 Action<string> enter,
503 Action cancel) {
504 // ReSharper restore UnusedParameter.Local
505#if ANDROID
506 AlertDialog.Builder builder = new(Window.Activity);
507 builder.SetTitle(title);
508 builder.SetMessage(description);
509 EditText editText = new(Window.Activity);
510 editText.Text = defaultText;
511 builder.SetView(editText);
512 builder.SetPositiveButton("Ok", delegate { enter(editText.Text); });
513 builder.SetNegativeButton("Cancel", delegate { cancel(); });
514 Window.Activity.RunOnUiThread(() => {
515 AlertDialog alertDialog = builder.Create();
516 if (alertDialog == null) {
517 return;
518 }
519 alertDialog.DismissEvent += delegate { cancel(); };
520 alertDialog.CancelEvent += delegate { cancel(); };
521 alertDialog.Window?.Attributes?.Gravity = GravityFlags.Center;
522 alertDialog.Show();
523 }
524 );
525#elif BROWSER
526 Task.Run(() => {
527 string input = BrowserInterop.ShowKeyboard(title, defaultText);
528 if (input == null) {
529 cancel();
530 }
531 else {
532 enter(input);
533 }
534 });
535#else
536 cancel();
537#endif
538 }
539 }
540}
static partial string ShowKeyboard(string title, string defaultText)
static void Dispatch(Action action, bool waitUntilCompleted=false)
static Key TranslateKey(Silk.NET.Input.Key key)
static bool[] m_keysDownOnceArray
static double m_keyFirstRepeatTime
static bool BackButtonQuitsApp
static void BeforeFrame()
static void ShowKeyboardInternal(string title, string description, string defaultText, bool passwordMode, Action< string > enter, Action cancel)
static bool ProcessKeyDown(Key key)
static Action< Key > KeyDown
static ? char m_lastChar
static bool ProcessCharacterEntered(char ch)
static double m_keyNextRepeatTime
static Action< char > CharacterEntered
static bool IsKeyDown(Key key)
static void ShowKeyboard(string title, string description, string defaultText, bool passwordMode, Action< string > enter, Action cancel)
static IKeyboard m_keyboard
static bool ProcessKeyUp(Key key)
static void KeyDownHandler(IKeyboard keyboard, Silk.NET.Input.Key key, int scancode)
static bool[] m_keysDownArray
static bool IsKeyDownRepeat(Key key)
static bool IsKeyDownOnce(Key key)
static void KeyPressHandler(IKeyboard keyboard, char c)
static void KeyUpHandler(IKeyboard keyboard, Silk.NET.Input.Key key, int scancode)
static double[] m_keysDownRepeatArray
static bool IsKeyboardVisible
static Action< Key > KeyUp
static void Clear()
static void Clear()
static double FrameStartTime
定义 Time.cs:42
static bool IsActive
static void Run(int width=0, int height=0, WindowMode windowMode=WindowMode.Resizable, string title="")
static void Close()
static IInputContext m_inputContext