A game about forced loneliness, made by TACStudios
at master 4.7 kB view raw
1using System; 2using System.Collections; 3using System.Collections.Generic; 4using System.Runtime.InteropServices; 5using UnityEngine.InputSystem.Utilities; 6 7namespace UnityEngine.InputSystem.LowLevel 8{ 9 /// <summary> 10 /// A specialized event that contains the current IME Composition string, if IME is enabled and active. 11 /// This event contains the entire current string to date, and once a new composition is submitted will send a blank string event. 12 /// </summary> 13 [StructLayout(LayoutKind.Explicit, Size = InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize))] 14 public struct IMECompositionEvent : IInputEventTypeInfo 15 { 16 // These needs to match the native ImeCompositionStringInputEventData settings 17 internal const int kIMECharBufferSize = 64; 18 public const int Type = 0x494D4553; 19 20 [FieldOffset(0)] 21 public InputEvent baseEvent; 22 23 [FieldOffset(InputEvent.kBaseEventSize)] 24 public IMECompositionString compositionString; 25 26 public FourCC typeStatic => Type; 27 28 public static IMECompositionEvent Create(int deviceId, string compositionString, double time) 29 { 30 var inputEvent = new IMECompositionEvent(); 31 inputEvent.baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize), deviceId, time); 32 inputEvent.compositionString = new IMECompositionString(compositionString); 33 return inputEvent; 34 } 35 } 36 37 /// <summary> 38 /// A struct representing an string of characters generated by an IME for text input. 39 /// </summary> 40 /// <remarks> 41 /// This is the internal representation of character strings in the event stream. It is exposed to user content through the 42 /// <see cref="ITextInputReceiver.OnIMECompositionChanged"/> method. It can easily be converted to a normal C# string using 43 /// <see cref="ToString"/>, but is exposed as the raw struct to avoid allocating memory by default. 44 /// </remarks> 45 [StructLayout(LayoutKind.Explicit, Size = sizeof(int) + sizeof(char) * LowLevel.IMECompositionEvent.kIMECharBufferSize)] 46 public unsafe struct IMECompositionString : IEnumerable<char> 47 { 48 internal struct Enumerator : IEnumerator<char> 49 { 50 IMECompositionString m_CompositionString; 51 char m_CurrentCharacter; 52 int m_CurrentIndex; 53 54 public Enumerator(IMECompositionString compositionString) 55 { 56 m_CompositionString = compositionString; 57 m_CurrentCharacter = '\0'; 58 m_CurrentIndex = -1; 59 } 60 61 public bool MoveNext() 62 { 63 int size = m_CompositionString.Count; 64 65 m_CurrentIndex++; 66 67 if (m_CurrentIndex == size) 68 return false; 69 70 fixed(char* ptr = m_CompositionString.buffer) 71 { 72 m_CurrentCharacter = *(ptr + m_CurrentIndex); 73 } 74 75 return true; 76 } 77 78 public void Reset() 79 { 80 m_CurrentIndex = -1; 81 } 82 83 public void Dispose() 84 { 85 } 86 87 public char Current => m_CurrentCharacter; 88 89 object IEnumerator.Current => Current; 90 } 91 92 public int Count => size; 93 94 public char this[int index] 95 { 96 get 97 { 98 if (index >= Count || index < 0) 99 throw new ArgumentOutOfRangeException(nameof(index)); 100 101 fixed(char* ptr = buffer) 102 { 103 return *(ptr + index); 104 } 105 } 106 } 107 108 [FieldOffset(0)] 109 int size; 110 111 [FieldOffset(sizeof(int))] 112 fixed char buffer[IMECompositionEvent.kIMECharBufferSize]; 113 114 public IMECompositionString(string characters) 115 { 116 if (string.IsNullOrEmpty(characters)) 117 { 118 size = 0; 119 return; 120 } 121 122 Debug.Assert(characters.Length < IMECompositionEvent.kIMECharBufferSize); 123 size = characters.Length; 124 for (var i = 0; i < size; i++) 125 buffer[i] = characters[i]; 126 } 127 128 public override string ToString() 129 { 130 fixed(char* ptr = buffer) 131 { 132 return new string(ptr, 0, size); 133 } 134 } 135 136 public IEnumerator<char> GetEnumerator() 137 { 138 return new Enumerator(this); 139 } 140 141 IEnumerator IEnumerable.GetEnumerator() 142 { 143 return GetEnumerator(); 144 } 145 } 146}