Skip to content

Commit 2a51b10

Browse files
author
Dmytro Ivanov
authored
NEW: Improving state debugger to show live values, binary, etc (#1583)
1 parent 0356253 commit 2a51b10

1 file changed

Lines changed: 105 additions & 12 deletions

File tree

Packages/com.unity.inputsystem/InputSystem/Editor/Internal/InputStateWindow.cs

Lines changed: 105 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,21 @@ internal class InputStateWindow : EditorWindow
3030
private const int kHexDumpLineHeight = 25;
3131
private const int kOffsetLabelWidth = 30;
3232
private const int kHexGroupWidth = 25;
33+
private const int kBitGroupWidth = 75;
34+
35+
void Update()
36+
{
37+
if (m_PollControlState && m_Control != null)
38+
{
39+
PollBuffersFromControl(m_Control);
40+
Repaint();
41+
}
42+
}
3343

3444
public void InitializeWithEvent(InputEventPtr eventPtr, InputControl control)
3545
{
3646
m_Control = control;
47+
m_PollControlState = false;
3748
m_StateBuffers = new byte[1][];
3849
m_StateBuffers[0] = GetEventStateBuffer(eventPtr, control);
3950
m_SelectedStateBuffer = 0;
@@ -46,6 +57,7 @@ public void InitializeWithEvents(InputEventPtr[] eventPtrs, InputControl control
4657
var numEvents = eventPtrs.Length;
4758

4859
m_Control = control;
60+
m_PollControlState = false;
4961
m_StateBuffers = new byte[numEvents][];
5062
for (var i = 0; i < numEvents; ++i)
5163
m_StateBuffers[i] = GetEventStateBuffer(eventPtrs[i], control);
@@ -95,8 +107,16 @@ private unsafe byte[] GetEventStateBuffer(InputEventPtr eventPtr, InputControl c
95107
public unsafe void InitializeWithControl(InputControl control)
96108
{
97109
m_Control = control;
110+
m_PollControlState = true;
98111
m_SelectedStateBuffer = (int)BufferSelector.Default;
99112

113+
PollBuffersFromControl(control, selectBuffer: true);
114+
115+
titleContent = new GUIContent(control.displayName);
116+
}
117+
118+
private unsafe void PollBuffersFromControl(InputControl control, bool selectBuffer = false)
119+
{
100120
var bufferChoices = new List<GUIContent>();
101121
var bufferChoiceValues = new List<int>();
102122

@@ -119,7 +139,7 @@ public unsafe void InitializeWithControl(InputControl control)
119139
}
120140
m_StateBuffers[i] = buffer;
121141

122-
if (m_StateBuffers[m_SelectedStateBuffer] == null)
142+
if (selectBuffer && m_StateBuffers[m_SelectedStateBuffer] == null)
123143
m_SelectedStateBuffer = (int)selector;
124144

125145
bufferChoices.Add(Contents.bufferChoices[i]);
@@ -128,8 +148,6 @@ public unsafe void InitializeWithControl(InputControl control)
128148

129149
m_BufferChoices = bufferChoices.ToArray();
130150
m_BufferChoiceValues = bufferChoiceValues.ToArray();
131-
132-
titleContent = new GUIContent(control.displayName);
133151
}
134152

135153
private static unsafe void* TryGetDeviceState(InputDevice device, BufferSelector selector)
@@ -155,6 +173,10 @@ public unsafe void InitializeWithControl(InputControl control)
155173
if (manager.m_StateBuffers.m_EditorStateBuffers.valid)
156174
return manager.m_StateBuffers.m_EditorStateBuffers.GetBackBuffer(deviceIndex);
157175
break;
176+
case BufferSelector.NoiseMaskBuffer:
177+
return manager.m_StateBuffers.noiseMaskBuffer;
178+
case BufferSelector.ResetMaskBuffer:
179+
return manager.m_StateBuffers.resetMaskBuffer;
158180
}
159181

160182
return null;
@@ -173,9 +195,13 @@ public void OnGUI()
173195
}
174196

175197
GUILayout.BeginHorizontal(EditorStyles.toolbar);
198+
m_PollControlState = GUILayout.Toggle(m_PollControlState, Contents.live, EditorStyles.toolbarButton);
199+
176200
m_ShowRawBytes = GUILayout.Toggle(m_ShowRawBytes, Contents.showRawMemory, EditorStyles.toolbarButton,
177201
GUILayout.Width(150));
178202

203+
m_ShowAsBits = GUILayout.Toggle(m_ShowAsBits, Contents.showBits, EditorStyles.toolbarButton);
204+
179205
if (m_CompareStateBuffers)
180206
{
181207
var showDifferentOnly = GUILayout.Toggle(m_ShowDifferentOnly, Contents.showDifferentOnly,
@@ -233,12 +259,39 @@ public void OnGUI()
233259
}
234260
}
235261

262+
private byte[] TryGetBackBufferForCurrentlySelected()
263+
{
264+
if (m_StateBuffers.Length != (int)BufferSelector.COUNT)
265+
return null;
266+
267+
switch ((BufferSelector)m_SelectedStateBuffer)
268+
{
269+
case BufferSelector.PlayerUpdateFrontBuffer:
270+
return m_StateBuffers[(int)BufferSelector.PlayerUpdateBackBuffer];
271+
case BufferSelector.EditorUpdateFrontBuffer:
272+
return m_StateBuffers[(int)BufferSelector.EditorUpdateBackBuffer];
273+
default:
274+
return null;
275+
}
276+
}
277+
278+
private string FormatByte(byte value)
279+
{
280+
if (m_ShowAsBits)
281+
return Convert.ToString(value, 2).PadLeft(8, '0');
282+
else
283+
return value.ToString("X2");
284+
}
285+
236286
////TODO: support dumping multiple state side-by-side when comparing
237287
private void DrawHexDump()
238288
{
239289
m_HexDumpScrollPosition = EditorGUILayout.BeginScrollView(m_HexDumpScrollPosition);
240290

241291
var stateBuffer = m_StateBuffers[m_SelectedStateBuffer];
292+
var prevStateBuffer = TryGetBackBufferForCurrentlySelected();
293+
if (prevStateBuffer != null && prevStateBuffer.Length != stateBuffer.Length) // we assume they're same length, otherwise ignore prev buffer
294+
prevStateBuffer = null;
242295
var numBytes = stateBuffer.Length;
243296
var numHexGroups = numBytes / kBytesPerHexGroup + (numBytes % kBytesPerHexGroup > 0 ? 1 : 0);
244297
var numLines = numHexGroups / kHexGroupsPerLine + (numHexGroups % kHexGroupsPerLine > 0 ? 1 : 0);
@@ -262,26 +315,49 @@ private void DrawHexDump()
262315
// Draw hex groups.
263316
var hexGroupRect = offsetLabelRect;
264317
hexGroupRect.x += kOffsetLabelWidth + 10;
265-
hexGroupRect.width = kHexGroupWidth;
318+
hexGroupRect.width = m_ShowAsBits ? kBitGroupWidth : kHexGroupWidth;
266319
for (var group = 0;
267320
group < kHexGroupsPerLine && currentHexGroup < numHexGroups;
268321
++group, ++currentHexGroup)
269322
{
270323
// Convert bytes to hex.
271324
var hex = string.Empty;
272-
for (var i = 0; i < kBytesPerHexGroup; ++i)
325+
326+
for (var i = 0; i < kBytesPerHexGroup; ++i, ++currentByte)
273327
{
274328
if (currentByte >= numBytes)
275-
hex = " " + hex;
276-
else
277-
hex = stateBuffer[currentByte].ToString("X2") + hex;
278-
++currentByte;
329+
{
330+
hex += " ";
331+
continue;
332+
}
333+
334+
var current = FormatByte(stateBuffer[currentByte]);
335+
if (prevStateBuffer == null)
336+
{
337+
hex += current;
338+
continue;
339+
}
340+
341+
var prev = FormatByte(prevStateBuffer[currentByte]);
342+
if (prev.Length != current.Length)
343+
{
344+
hex += current;
345+
continue;
346+
}
347+
348+
for (var j = 0; j < current.Length; ++j)
349+
{
350+
if (current[j] != prev[j])
351+
hex += $"<color=#C84B31FF>{current[j]}</color>";
352+
else
353+
hex += current[j];
354+
}
279355
}
280356

281357
////TODO: draw alternating backgrounds for the hex groups
282358

283-
GUI.Label(hexGroupRect, hex);
284-
hexGroupRect.x += kHexGroupWidth;
359+
GUI.Label(hexGroupRect, hex, style: Styles.hexLabel);
360+
hexGroupRect.x += m_ShowAsBits ? kBitGroupWidth : kHexGroupWidth;
285361
}
286362

287363
currentLineRect.y += kHexDumpLineHeight;
@@ -299,6 +375,8 @@ private void DrawHexDump()
299375
[SerializeField] private bool m_CompareStateBuffers;
300376
[SerializeField] private bool m_ShowDifferentOnly;
301377
[SerializeField] private bool m_ShowRawBytes;
378+
[SerializeField] private bool m_ShowAsBits;
379+
[SerializeField] private bool m_PollControlState;
302380
[SerializeField] private TreeViewState m_ControlTreeState;
303381
[SerializeField] private MultiColumnHeaderState m_ControlTreeHeaderState;
304382
[SerializeField] private Vector2 m_HexDumpScrollPosition;
@@ -316,6 +394,8 @@ private enum BufferSelector
316394
PlayerUpdateBackBuffer,
317395
EditorUpdateFrontBuffer,
318396
EditorUpdateBackBuffer,
397+
NoiseMaskBuffer,
398+
ResetMaskBuffer,
319399
COUNT,
320400
Default = PlayerUpdateFrontBuffer
321401
}
@@ -330,18 +410,31 @@ private static class Styles
330410
fontSize = EditorStyles.boldFont.fontSize - 2,
331411
normal = new GUIStyleState { textColor = Color.black }
332412
};
413+
414+
public static GUIStyle hexLabel = new GUIStyle
415+
{
416+
fontStyle = FontStyle.Normal,
417+
font = EditorGUIUtility.Load("Fonts/RobotoMono/RobotoMono-Regular.ttf") as Font,
418+
fontSize = EditorStyles.label.fontSize + 2,
419+
normal = new GUIStyleState { textColor = Color.white },
420+
richText = true
421+
};
333422
}
334423

335424
private static class Contents
336425
{
426+
public static GUIContent live = new GUIContent("Live");
337427
public static GUIContent showRawMemory = new GUIContent("Display Raw Memory");
428+
public static GUIContent showBits = new GUIContent("Bits/Hex");
338429
public static GUIContent showDifferentOnly = new GUIContent("Show Only Differences");
339430
public static GUIContent[] bufferChoices =
340431
{
341432
new GUIContent("Player (Current)"),
342433
new GUIContent("Player (Previous)"),
343434
new GUIContent("Editor (Current)"),
344-
new GUIContent("Editor (Previous)")
435+
new GUIContent("Editor (Previous)"),
436+
new GUIContent("Noise Mask"),
437+
new GUIContent("Reset Mask")
345438
};
346439
}
347440
}

0 commit comments

Comments
 (0)