slimecing

a fighting game featuring slimes and swords
Log | Files | Refs | README

InputRecorderInspector.cs (12092B)


      1 #if UNITY_EDITOR
      2 using UnityEditor;
      3 using UnityEngine.Events;
      4 
      5 ////TODO: add ability to inspect contents of event traces in a separate window
      6 
      7 namespace UnityEngine.InputSystem.Editor
      8 {
      9     /// <summary>
     10     /// A custom inspector for <see cref="InputRecorder"/>. Adds UI elements to store captures in files, to load them from
     11     /// there, and to initiate replays from within the editor. It also shows information for when captures or replays are
     12     /// in progress.
     13     /// </summary>
     14     [CustomEditor(typeof(InputRecorder))]
     15     internal class InputRecorderInspector : UnityEditor.Editor
     16     {
     17         protected void OnEnable()
     18         {
     19             m_DevicePathProperty = serializedObject.FindProperty("m_DevicePath");
     20             m_RecordButtonPath = serializedObject.FindProperty("m_RecordButtonPath");
     21             m_PlayButtonPathProperty = serializedObject.FindProperty("m_PlayButtonPath");
     22             m_RecordFramesProperty = serializedObject.FindProperty("m_RecordFrames");
     23             m_RecordStateEventsOnlyProperty = serializedObject.FindProperty("m_RecordStateEventsOnly");
     24             m_ReplayOnNewDevicesProperty = serializedObject.FindProperty("m_ReplayOnNewDevices");
     25             m_SimulateTimingOnReplayProperty = serializedObject.FindProperty("m_SimulateOriginalTimingOnReplay");
     26             m_CaptureMemoryDefaultSizeProperty = serializedObject.FindProperty("m_CaptureMemoryDefaultSize");
     27             m_CaptureMemoryMaxSizeProperty = serializedObject.FindProperty("m_CaptureMemoryMaxSize");
     28             m_StartRecordingWhenEnabledProperty = serializedObject.FindProperty("m_StartRecordingWhenEnabled");
     29 
     30             m_AllInput = string.IsNullOrEmpty(m_DevicePathProperty.stringValue);
     31 
     32             m_PlayText = EditorGUIUtility.TrIconContent("PlayButton", "Play the current input capture.");
     33             m_PauseText = EditorGUIUtility.TrIconContent("PauseButton", "Pause the current input playback.");
     34             m_ResumeText = EditorGUIUtility.TrIconContent("PauseButton On", "Resume the current input playback.");
     35             m_StepForwardText = EditorGUIUtility.TrIconContent("d_StepButton", "Play the next input event.");
     36             m_StepBackwardText = EditorGUIUtility.TrIconContent("d_StepLeftButton", "Play the previous input event.");
     37             m_StopText = EditorGUIUtility.TrIconContent("PlayButton On", "Stop the current input playback.");
     38             m_RecordText = EditorGUIUtility.TrIconContent("Animation.Record", "Start recording input.");
     39 
     40             var recorder = (InputRecorder)serializedObject.targetObject;
     41             m_OnRecordEvent = _ => Repaint();
     42             recorder.changeEvent.AddListener(m_OnRecordEvent);
     43         }
     44 
     45         protected void OnDisable()
     46         {
     47             var recorder = (InputRecorder)serializedObject.targetObject;
     48             recorder.changeEvent.RemoveListener(m_OnRecordEvent);
     49         }
     50 
     51         public override void OnInspectorGUI()
     52         {
     53             var recorder = (InputRecorder)serializedObject.targetObject;
     54 
     55             using (var scope = new EditorGUI.ChangeCheckScope())
     56             {
     57                 var newAllInput = EditorGUILayout.Toggle(m_AllInputText, m_AllInput);
     58                 if (!newAllInput)
     59                 {
     60                     using (new EditorGUI.IndentLevelScope())
     61                     {
     62                         EditorGUILayout.PropertyField(m_DevicePathProperty, m_DeviceText);
     63                     }
     64                 }
     65                 else if (newAllInput != m_AllInput)
     66                 {
     67                     m_DevicePathProperty.stringValue = string.Empty;
     68                 }
     69                 m_AllInput = newAllInput;
     70 
     71                 EditorGUILayout.PropertyField(m_RecordFramesProperty);
     72                 EditorGUILayout.PropertyField(m_RecordStateEventsOnlyProperty);
     73                 EditorGUILayout.PropertyField(m_ReplayOnNewDevicesProperty);
     74                 EditorGUILayout.PropertyField(m_SimulateTimingOnReplayProperty);
     75                 EditorGUILayout.PropertyField(m_StartRecordingWhenEnabledProperty, m_RecordWhenEnabledText);
     76 
     77                 var defaultSizeInMB = m_CaptureMemoryDefaultSizeProperty.intValue / (1024 * 1024);
     78                 var newDefaultSizeInMB = EditorGUILayout.IntSlider(m_DefaultSizeText, defaultSizeInMB, 1, 100);
     79                 if (newDefaultSizeInMB != defaultSizeInMB)
     80                     m_CaptureMemoryDefaultSizeProperty.intValue = newDefaultSizeInMB * 1024 * 1024;
     81 
     82                 var maxSizeInMB = m_CaptureMemoryMaxSizeProperty.intValue / (1024 * 1024);
     83                 var newMaxSizeInMB = maxSizeInMB < newDefaultSizeInMB
     84                     ? newDefaultSizeInMB
     85                     : EditorGUILayout.IntSlider(m_MaxSizeText, maxSizeInMB, 1, 100);
     86                 if (newMaxSizeInMB != maxSizeInMB)
     87                     m_CaptureMemoryMaxSizeProperty.intValue = newMaxSizeInMB * 1024 * 1024;
     88 
     89                 EditorGUILayout.PropertyField(m_RecordButtonPath, m_RecordButtonText);
     90                 EditorGUILayout.PropertyField(m_PlayButtonPathProperty, m_PlayButtonText);
     91 
     92                 if (scope.changed)
     93                     serializedObject.ApplyModifiedProperties();
     94             }
     95 
     96             EditorGUILayout.Space();
     97             using (new EditorGUILayout.HorizontalScope())
     98             {
     99                 ////TODO: go-to-next and go-to-previous button
    100                 // Play and pause buttons.
    101                 EditorGUI.BeginDisabledGroup(recorder.eventCount == 0 || recorder.captureIsRunning);
    102                 var oldIsPlaying = recorder.replayIsRunning;
    103                 var newIsPlaying = GUILayout.Toggle(oldIsPlaying, !oldIsPlaying ? m_PlayText : m_StopText, EditorStyles.miniButton,
    104                     GUILayout.Width(50));
    105                 if (oldIsPlaying != newIsPlaying)
    106                 {
    107                     if (newIsPlaying)
    108                         recorder.StartReplay();
    109                     else
    110                         recorder.StopReplay();
    111                 }
    112                 if (newIsPlaying && recorder.replay != null && GUILayout.Button(recorder.replay.paused ? m_ResumeText : m_PauseText, EditorStyles.miniButton,
    113                     GUILayout.Width(50)))
    114                 {
    115                     if (recorder.replay.paused)
    116                         recorder.StartReplay();
    117                     else
    118                         recorder.PauseReplay();
    119                 }
    120                 EditorGUI.EndDisabledGroup();
    121 
    122                 // Record button.
    123                 EditorGUI.BeginDisabledGroup(recorder.replayIsRunning);
    124                 var oldIsRecording = recorder.captureIsRunning;
    125                 var newIsRecording = GUILayout.Toggle(oldIsRecording, m_RecordText, EditorStyles.miniButton, GUILayout.Width(50));
    126                 if (oldIsRecording != newIsRecording)
    127                 {
    128                     if (newIsRecording)
    129                         recorder.StartCapture();
    130                     else
    131                         recorder.StopCapture();
    132                 }
    133                 EditorGUI.EndDisabledGroup();
    134 
    135                 // Load button.
    136                 EditorGUI.BeginDisabledGroup(recorder.replayIsRunning);
    137                 if (GUILayout.Button("Load"))
    138                 {
    139                     var filePath = EditorUtility.OpenFilePanel("Choose Input Event Trace to Load", string.Empty, "inputtrace");
    140                     if (!string.IsNullOrEmpty(filePath))
    141                         recorder.LoadCaptureFromFile(filePath);
    142                 }
    143                 EditorGUI.EndDisabledGroup();
    144 
    145                 // Save button.
    146                 EditorGUI.BeginDisabledGroup(recorder.eventCount == 0 || recorder.replayIsRunning);
    147                 if (GUILayout.Button("Save"))
    148                 {
    149                     var filePath = EditorUtility.SaveFilePanel("Choose Where to Save Input Event Trace", string.Empty, $"{recorder.gameObject.name}.inputtrace", "inputtrace");
    150                     if (!string.IsNullOrEmpty(filePath))
    151                         recorder.SaveCaptureToFile(filePath);
    152                 }
    153 
    154                 // Clear button.
    155                 if (GUILayout.Button("Clear"))
    156                 {
    157                     recorder.ClearCapture();
    158                     Repaint();
    159                 }
    160                 EditorGUI.EndDisabledGroup();
    161             }
    162 
    163             ////TODO: allow hotscrubbing
    164             // Play bar.
    165             EditorGUILayout.IntSlider(recorder.replayPosition, 0, (int)recorder.eventCount);
    166 
    167             EditorGUILayout.Space();
    168             using (new EditorGUI.DisabledScope())
    169             {
    170                 EditorGUILayout.LabelField(m_InfoText, EditorStyles.miniBoldLabel);
    171                 using (new EditorGUI.IndentLevelScope())
    172                 {
    173                     EditorGUILayout.LabelField($"{recorder.eventCount} events", EditorStyles.miniLabel);
    174                     EditorGUILayout.LabelField($"{recorder.totalEventSizeInBytes / 1024} kb captured", EditorStyles.miniLabel);
    175                     EditorGUILayout.LabelField($"{recorder.allocatedSizeInBytes / 1024} kb allocated", EditorStyles.miniLabel);
    176 
    177                     if (recorder.capture != null)
    178                     {
    179                         var devices = recorder.capture.deviceInfos;
    180                         if (devices.Count > 0)
    181                         {
    182                             EditorGUILayout.LabelField(m_DevicesText, EditorStyles.miniBoldLabel);
    183                             using (new EditorGUI.IndentLevelScope())
    184                             {
    185                                 foreach (var device in devices)
    186                                 {
    187                                     EditorGUILayout.LabelField(device.layout, EditorStyles.miniLabel);
    188                                 }
    189                             }
    190                         }
    191                     }
    192                 }
    193             }
    194         }
    195 
    196         private bool m_AllInput;
    197         private SerializedProperty m_DevicePathProperty;
    198         private SerializedProperty m_RecordButtonPath;
    199         private SerializedProperty m_PlayButtonPathProperty;
    200         private SerializedProperty m_RecordFramesProperty;
    201         private SerializedProperty m_RecordStateEventsOnlyProperty;
    202         private SerializedProperty m_ReplayOnNewDevicesProperty;
    203         private SerializedProperty m_SimulateTimingOnReplayProperty;
    204         private SerializedProperty m_CaptureMemoryDefaultSizeProperty;
    205         private SerializedProperty m_CaptureMemoryMaxSizeProperty;
    206         private SerializedProperty m_StartRecordingWhenEnabledProperty;
    207         private UnityAction<InputRecorder.Change> m_OnRecordEvent;
    208 
    209         private GUIContent m_RecordButtonText = new GUIContent("Record Button", "If set, this button will start and stop capture in play mode.");
    210         private GUIContent m_PlayButtonText = new GUIContent("Play Button", "If set, this button will start and stop replay of the current capture in play mode.");
    211         private GUIContent m_RecordWhenEnabledText = new GUIContent("Capture When Enabled", "If true, recording will start immediately when the component is enabled in play mode.");
    212         private GUIContent m_DevicesText = new GUIContent("Devices");
    213         private GUIContent m_AllInputText = new GUIContent("All Input", "Whether to record input from all devices or from just specific devices.");
    214         private GUIContent m_DeviceText = new GUIContent("Device", "Type of device to record input from.");
    215         private GUIContent m_InfoText = new GUIContent("Info:");
    216         private GUIContent m_DefaultSizeText = new GUIContent("Default Size (MB)", "Memory allocate for capture by default. Will automatically grow up to max memory.");
    217         private GUIContent m_MaxSizeText = new GUIContent("Max Size (MB)", "Maximum memory allocated for capture. Once a capture reaches this limit, new events will start overwriting old ones.");
    218         private GUIContent m_PlayText;
    219         private GUIContent m_PauseText;
    220         private GUIContent m_ResumeText;
    221         private GUIContent m_StepForwardText;
    222         private GUIContent m_StepBackwardText;
    223         private GUIContent m_StopText;
    224         private GUIContent m_RecordText;
    225     }
    226 }
    227 #endif