暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

InputEventStream.cs 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using Unity.Collections;
  2. using Unity.Collections.LowLevel.Unsafe;
  3. namespace UnityEngine.InputSystem.LowLevel
  4. {
  5. /// <summary>
  6. /// The input event stream is a combination of the input event buffer passed from native code and an
  7. /// append buffer that is owned by the managed side. Events queued during update are added to the
  8. /// append buffer. To calling code, the two buffers look like a single coherent stream of events.
  9. /// Calling Advance will first step through the events from the native side, followed by any events
  10. /// that have been appended.
  11. /// </summary>
  12. internal unsafe struct InputEventStream
  13. {
  14. public bool isOpen => m_IsOpen;
  15. public int remainingEventCount => m_RemainingNativeEventCount + m_RemainingAppendEventCount;
  16. /// <summary>
  17. /// How many events were left in the native buffer during reading.
  18. /// </summary>
  19. public int numEventsRetainedInBuffer => m_NumEventsRetainedInBuffer;
  20. public InputEvent* currentEventPtr => m_RemainingNativeEventCount > 0
  21. ? m_CurrentNativeEventReadPtr
  22. : (m_RemainingAppendEventCount > 0 ? m_CurrentAppendEventReadPtr : null);
  23. public uint numBytesRetainedInBuffer =>
  24. (uint)((byte*)m_CurrentNativeEventWritePtr -
  25. (byte*)NativeArrayUnsafeUtility
  26. .GetUnsafeBufferPointerWithoutChecks(m_NativeBuffer.data));
  27. public InputEventStream(ref InputEventBuffer eventBuffer, int maxAppendedEvents)
  28. {
  29. m_CurrentNativeEventWritePtr = m_CurrentNativeEventReadPtr =
  30. (InputEvent*)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(eventBuffer.data);
  31. m_NativeBuffer = eventBuffer;
  32. m_RemainingNativeEventCount = m_NativeBuffer.eventCount;
  33. m_NumEventsRetainedInBuffer = 0;
  34. m_CurrentAppendEventReadPtr = m_CurrentAppendEventWritePtr = default;
  35. m_AppendBuffer = default;
  36. m_RemainingAppendEventCount = 0;
  37. m_MaxAppendedEvents = maxAppendedEvents;
  38. m_IsOpen = true;
  39. }
  40. public void Close(ref InputEventBuffer eventBuffer)
  41. {
  42. // If we have retained events, update event count and buffer size. If not, just reset.
  43. if (m_NumEventsRetainedInBuffer > 0)
  44. {
  45. var bufferPtr = NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_NativeBuffer.data);
  46. Debug.Assert((byte*)m_CurrentNativeEventWritePtr > (byte*)bufferPtr);
  47. var newBufferSize = (byte*)m_CurrentNativeEventWritePtr - (byte*)bufferPtr;
  48. m_NativeBuffer = new InputEventBuffer((InputEvent*)bufferPtr, m_NumEventsRetainedInBuffer, (int)newBufferSize,
  49. (int)m_NativeBuffer.capacityInBytes);
  50. }
  51. else
  52. {
  53. m_NativeBuffer.Reset();
  54. }
  55. if (m_AppendBuffer.data.IsCreated)
  56. m_AppendBuffer.Dispose();
  57. eventBuffer = m_NativeBuffer;
  58. m_IsOpen = false;
  59. }
  60. public void CleanUpAfterException()
  61. {
  62. if (!isOpen)
  63. return;
  64. m_NativeBuffer.Reset();
  65. if (m_AppendBuffer.data.IsCreated)
  66. m_AppendBuffer.Dispose();
  67. m_IsOpen = false;
  68. }
  69. public void Write(InputEvent* eventPtr)
  70. {
  71. if (m_AppendBuffer.eventCount >= m_MaxAppendedEvents)
  72. {
  73. Debug.LogError($"Maximum number of queued events exceeded. Set the '{nameof(InputSettings.maxQueuedEventsPerUpdate)}' " +
  74. $"setting to a higher value if you need to queue more events than this. " +
  75. $"Current limit is '{m_MaxAppendedEvents}'.");
  76. return;
  77. }
  78. var wasAlreadyCreated = m_AppendBuffer.data.IsCreated;
  79. var oldBufferPtr = (byte*)m_AppendBuffer.bufferPtr.data;
  80. m_AppendBuffer.AppendEvent(eventPtr, allocator: Allocator.Temp);
  81. if (!wasAlreadyCreated)
  82. {
  83. m_CurrentAppendEventWritePtr = m_CurrentAppendEventReadPtr =
  84. (InputEvent*)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_AppendBuffer.data);
  85. }
  86. else
  87. {
  88. // AppendEvent can reallocate the buffer if it needs more space, so make sure the read and write pointers
  89. // point to the equivalent places in the new buffer.
  90. var newBufferPtr = (byte*)m_AppendBuffer.bufferPtr.data;
  91. if (oldBufferPtr != newBufferPtr)
  92. {
  93. var currentWriteOffset = (byte*)m_CurrentAppendEventWritePtr - oldBufferPtr;
  94. var currentReadOffset = (byte*)m_CurrentAppendEventReadPtr - oldBufferPtr;
  95. m_CurrentAppendEventWritePtr = (InputEvent*)(newBufferPtr + currentWriteOffset);
  96. m_CurrentAppendEventReadPtr = (InputEvent*)(newBufferPtr + currentReadOffset);
  97. }
  98. }
  99. m_RemainingAppendEventCount++;
  100. }
  101. public InputEvent* Advance(bool leaveEventInBuffer)
  102. {
  103. if (m_RemainingNativeEventCount > 0)
  104. {
  105. m_NativeBuffer.AdvanceToNextEvent(ref m_CurrentNativeEventReadPtr, ref m_CurrentNativeEventWritePtr,
  106. ref m_NumEventsRetainedInBuffer, ref m_RemainingNativeEventCount, leaveEventInBuffer);
  107. }
  108. else if (m_RemainingAppendEventCount > 0)
  109. {
  110. var numEventRetained = 0;
  111. m_AppendBuffer.AdvanceToNextEvent(ref m_CurrentAppendEventReadPtr, ref m_CurrentAppendEventWritePtr,
  112. ref numEventRetained, ref m_RemainingAppendEventCount, false);
  113. }
  114. return currentEventPtr;
  115. }
  116. /// <summary>
  117. /// Peeks next event in the stream
  118. /// </summary>
  119. public InputEvent* Peek()
  120. {
  121. // Advance will go to next event in m_NativeBuffer
  122. if (m_RemainingNativeEventCount > 1)
  123. return InputEvent.GetNextInMemory(m_CurrentNativeEventReadPtr);
  124. // Advance will decrement m_RemainingNativeEventCount to 0
  125. // and currentEventPtr will point to m_CurrentAppendEventReadPtr if any
  126. if (m_RemainingNativeEventCount == 1)
  127. return m_RemainingAppendEventCount > 0 ? m_CurrentAppendEventReadPtr : null;
  128. // Advance will go to next event in m_AppendBuffer
  129. if (m_RemainingAppendEventCount > 1)
  130. return InputEvent.GetNextInMemory(m_CurrentAppendEventReadPtr);
  131. // No next event
  132. return null;
  133. }
  134. private InputEventBuffer m_NativeBuffer;
  135. private InputEvent* m_CurrentNativeEventReadPtr;
  136. private InputEvent* m_CurrentNativeEventWritePtr;
  137. private int m_RemainingNativeEventCount;
  138. private readonly int m_MaxAppendedEvents;
  139. // During Update, new events that are queued will be added to the append buffer
  140. private InputEventBuffer m_AppendBuffer;
  141. private InputEvent* m_CurrentAppendEventReadPtr;
  142. private InputEvent* m_CurrentAppendEventWritePtr;
  143. private int m_RemainingAppendEventCount;
  144. // When timeslicing events or in before-render updates, we may be leaving events in the buffer
  145. // for later processing. We do this by compacting the event buffer and moving events down such
  146. // that the events we leave in the buffer form one contiguous chunk of memory at the beginning
  147. // of the buffer.
  148. private int m_NumEventsRetainedInBuffer;
  149. private bool m_IsOpen;
  150. }
  151. }