IndieGame/client/Packages/com.unity.inputsystem@1.7.0/InputSystem/Events/IMECompositionEvent.cs

147 lines
4.6 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine.InputSystem.Utilities;
namespace UnityEngine.InputSystem.LowLevel
{
/// <summary>
/// A specialized event that contains the current IME Composition string, if IME is enabled and active.
/// This event contains the entire current string to date, and once a new composition is submitted will send a blank string event.
/// </summary>
[StructLayout(LayoutKind.Explicit, Size = InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize))]
public struct IMECompositionEvent : IInputEventTypeInfo
{
// These needs to match the native ImeCompositionStringInputEventData settings
internal const int kIMECharBufferSize = 64;
public const int Type = 0x494D4553;
[FieldOffset(0)]
public InputEvent baseEvent;
[FieldOffset(InputEvent.kBaseEventSize)]
public IMECompositionString compositionString;
public FourCC typeStatic => Type;
public static IMECompositionEvent Create(int deviceId, string compositionString, double time)
{
var inputEvent = new IMECompositionEvent();
inputEvent.baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize), deviceId, time);
inputEvent.compositionString = new IMECompositionString(compositionString);
return inputEvent;
}
}
/// <summary>
/// A struct representing an string of characters generated by an IME for text input.
/// </summary>
/// <remarks>
/// This is the internal representation of character strings in the event stream. It is exposed to user content through the
/// <see cref="ITextInputReceiver.OnIMECompositionChanged"/> method. It can easily be converted to a normal C# string using
/// <see cref="ToString"/>, but is exposed as the raw struct to avoid allocating memory by default.
/// </remarks>
[StructLayout(LayoutKind.Explicit, Size = sizeof(int) + sizeof(char) * LowLevel.IMECompositionEvent.kIMECharBufferSize)]
public unsafe struct IMECompositionString : IEnumerable<char>
{
internal struct Enumerator : IEnumerator<char>
{
IMECompositionString m_CompositionString;
char m_CurrentCharacter;
int m_CurrentIndex;
public Enumerator(IMECompositionString compositionString)
{
m_CompositionString = compositionString;
m_CurrentCharacter = '\0';
m_CurrentIndex = -1;
}
public bool MoveNext()
{
int size = m_CompositionString.Count;
m_CurrentIndex++;
if (m_CurrentIndex == size)
return false;
fixed(char* ptr = m_CompositionString.buffer)
{
m_CurrentCharacter = *(ptr + m_CurrentIndex);
}
return true;
}
public void Reset()
{
m_CurrentIndex = -1;
}
public void Dispose()
{
}
public char Current => m_CurrentCharacter;
object IEnumerator.Current => Current;
}
public int Count => size;
public char this[int index]
{
get
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException(nameof(index));
fixed(char* ptr = buffer)
{
return *(ptr + index);
}
}
}
[FieldOffset(0)]
int size;
[FieldOffset(sizeof(int))]
fixed char buffer[IMECompositionEvent.kIMECharBufferSize];
public IMECompositionString(string characters)
{
if (string.IsNullOrEmpty(characters))
{
size = 0;
return;
}
Debug.Assert(characters.Length < IMECompositionEvent.kIMECharBufferSize);
size = characters.Length;
for (var i = 0; i < size; i++)
buffer[i] = characters[i];
}
public override string ToString()
{
fixed(char* ptr = buffer)
{
return new string(ptr, 0, size);
}
}
public IEnumerator<char> GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}