slimecing

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

InputActionVisualizer.cs (12435B)


      1 using System;
      2 using System.Collections.Generic;
      3 
      4 ////TODO: support ProcessEventsManually
      5 ////TODO: add way to pick by player index
      6 
      7 // Some fields assigned through only through serialization.
      8 #pragma warning disable CS0649
      9 
     10 namespace UnityEngine.InputSystem.Samples
     11 {
     12     /// <summary>
     13     /// A component for debugging purposes that adds an on-screen display which shows
     14     /// activity on an input action over time (<see cref="InputActionVisualizer.Visualization.Interaction"/>)
     15     /// or an action's current value (<see cref="InputActionVisualizer.Visualization.Value"/>).
     16     /// </summary>
     17     /// <seealso cref="InputControlVisualizer"/>
     18     [AddComponentMenu("Input/Debug/Input Action Visualizer")]
     19     [ExecuteInEditMode]
     20     public class InputActionVisualizer : InputVisualizer
     21     {
     22         /// <summary>
     23         /// The action that is being visualized. May be null.
     24         /// </summary>
     25         public InputAction action => m_Action;
     26 
     27         protected void FixedUpdate()
     28         {
     29             if (m_Visualization != Visualization.Value || m_Action == null || m_Visualizer == null)
     30                 return;
     31             if (InputSystem.settings.updateMode != InputSettings.UpdateMode.ProcessEventsInFixedUpdate)
     32                 return;
     33             RecordValue(Time.fixedTime);
     34         }
     35 
     36         protected void Update()
     37         {
     38             if (m_Visualization != Visualization.Value || m_Action == null || m_Visualizer == null)
     39                 return;
     40             if (InputSystem.settings.updateMode != InputSettings.UpdateMode.ProcessEventsInDynamicUpdate)
     41                 return;
     42             RecordValue(Time.time);
     43         }
     44 
     45         protected new void OnEnable()
     46         {
     47             if (m_Visualization == Visualization.None)
     48                 return;
     49 
     50             base.OnEnable();
     51 
     52             ResolveAction();
     53             SetupVisualizer();
     54 
     55             if (s_EnabledInstances == null)
     56                 s_EnabledInstances = new List<InputActionVisualizer>();
     57             if (s_EnabledInstances.Count == 0)
     58                 InputSystem.onActionChange += OnActionChange;
     59             s_EnabledInstances.Add(this);
     60         }
     61 
     62         protected new void OnDisable()
     63         {
     64             base.OnDisable();
     65 
     66             s_EnabledInstances.Remove(this);
     67             if (s_EnabledInstances.Count == 0)
     68                 InputSystem.onActionChange -= OnActionChange;
     69 
     70             if (m_Visualization == Visualization.Interaction && m_Action != null)
     71             {
     72                 m_Action.started -= OnActionTriggered;
     73                 m_Action.performed -= OnActionTriggered;
     74                 m_Action.canceled -= OnActionTriggered;
     75             }
     76         }
     77 
     78         protected new void OnGUI()
     79         {
     80             if (m_Visualization == Visualization.None)
     81                 return;
     82 
     83             if (Event.current.type != EventType.Repaint)
     84                 return;
     85 
     86             base.OnGUI();
     87 
     88             if (m_ShowControlName && m_ActiveControlName != null)
     89                 VisualizationHelpers.DrawText(m_ActiveControlName, new Vector2(m_Rect.x, m_Rect.yMax),
     90                     VisualizationHelpers.ValueTextStyle);
     91         }
     92 
     93         private void RecordValue(double time)
     94         {
     95             Debug.Assert(m_Action != null);
     96             Debug.Assert(m_Visualizer != null);
     97 
     98             var value = m_Action.ReadValueAsObject();
     99             m_Visualizer.AddSample(value, time);
    100 
    101             if (m_ShowControlName)
    102                 RecordControlName();
    103         }
    104 
    105         private void RecordControlName()
    106         {
    107             var control = m_Action.activeControl;
    108             if (control == m_ActiveControl)
    109                 return;
    110 
    111             m_ActiveControl = control;
    112             m_ActiveControlName = control != null ? new GUIContent(control.path) : null;
    113         }
    114 
    115         private void ResolveAction()
    116         {
    117             // If we have a reference to an action, try that first.
    118             if (m_ActionReference != null)
    119                 m_Action = m_ActionReference.action;
    120 
    121             // If we didn't get an action from that but we have an action name,
    122             // just search through the currently enabled actions for one that
    123             // matches by name.
    124             if (m_Action == null && !string.IsNullOrEmpty(m_ActionName))
    125             {
    126                 var slashIndex = m_ActionName.IndexOf('/');
    127                 var mapName = slashIndex != -1 ? m_ActionName.Substring(0, slashIndex) : null;
    128                 var actionName = slashIndex != -1 ? m_ActionName.Substring(slashIndex + 1) : m_ActionName;
    129 
    130                 var enabledActions = InputSystem.ListEnabledActions();
    131                 foreach (var action in enabledActions)
    132                 {
    133                     if (string.Compare(actionName, action.name, StringComparison.InvariantCultureIgnoreCase) != 0)
    134                         continue;
    135 
    136                     if (mapName != null && action.actionMap != null && string.Compare(mapName, action.actionMap.name,
    137                         StringComparison.InvariantCultureIgnoreCase) != 0)
    138                         continue;
    139 
    140                     m_Action = action;
    141                     break;
    142                 }
    143             }
    144 
    145             // If we still don't have an action, there's nothing much for us to do.
    146             // The action may show up at a later point.
    147             if (m_Action == null)
    148                 return;
    149 
    150             if (m_Visualization == Visualization.Interaction)
    151             {
    152                 m_Action.performed += OnActionTriggered;
    153                 m_Action.started += OnActionTriggered;
    154                 m_Action.canceled += OnActionTriggered;
    155             }
    156         }
    157 
    158         private void SetupVisualizer()
    159         {
    160             m_Visualizer = null;
    161             if (m_Action == null)
    162                 return;
    163 
    164             switch (m_Visualization)
    165             {
    166                 case Visualization.Value:
    167                     switch (m_Action.type)
    168                     {
    169                         case InputActionType.Button:
    170                             m_Visualizer = new VisualizationHelpers.ScalarVisualizer<float>
    171                             {
    172                                 limitMax = 1
    173                             };
    174                             break;
    175 
    176                         case InputActionType.Value:
    177                         case InputActionType.PassThrough:
    178                             if (!string.IsNullOrEmpty(m_Action.expectedControlType))
    179                             {
    180                                 var layout = InputSystem.LoadLayout(m_Action.expectedControlType);
    181                                 if (layout != null)
    182                                 {
    183                                     var valueType = layout.GetValueType();
    184                                     if (valueType == typeof(float))
    185                                         m_Visualizer = new VisualizationHelpers.ScalarVisualizer<float>
    186                                         {
    187                                             limitMax = 1
    188                                         };
    189                                     else if (valueType == typeof(int))
    190                                         m_Visualizer = new VisualizationHelpers.ScalarVisualizer<int>
    191                                         {
    192                                             limitMax = 1
    193                                         };
    194                                     else if (valueType == typeof(Vector2))
    195                                         m_Visualizer = new VisualizationHelpers.Vector2Visualizer();
    196                                 }
    197                             }
    198                             break;
    199                     }
    200                     break;
    201 
    202                 case Visualization.Interaction:
    203                     // We don't really know which interactions are sitting on the action and its bindings
    204                     // and while we could do and perform work to find out, it's simpler to just wait until
    205                     // we get input and then whatever interactions we encounter as we go along. Also keeps
    206                     // the visualization a little less cluttered.
    207                     m_Visualizer = new VisualizationHelpers.TimelineVisualizer();
    208                     break;
    209             }
    210         }
    211 
    212         private void OnActionDisabled()
    213         {
    214         }
    215 
    216         private void OnActionTriggered(InputAction.CallbackContext context)
    217         {
    218             Debug.Assert(m_Visualization == Visualization.Interaction);
    219 
    220             var timelineName = "Default";
    221             var interaction = context.interaction;
    222             if (interaction != null)
    223             {
    224                 timelineName = interaction.GetType().Name;
    225                 if (timelineName.EndsWith("Interaction"))
    226                     timelineName = timelineName.Substring(0, timelineName.Length - "Interaction".Length);
    227             }
    228 
    229             var visualizer = (VisualizationHelpers.TimelineVisualizer)m_Visualizer;
    230             var timelineIndex = visualizer.GetTimeline(timelineName);
    231             if (timelineIndex == -1)
    232             {
    233                 Color color;
    234                 timelineIndex = visualizer.timelineCount;
    235                 if (timelineIndex < s_InteractionColors.Length)
    236                     color = s_InteractionColors[timelineIndex];
    237                 else
    238                     color = new Color(Random.value, Random.value, Random.value, 1);
    239 
    240                 visualizer.AddTimeline(timelineName, color);
    241                 if (timelineIndex > 0)
    242                     visualizer.showLegend = true;
    243             }
    244 
    245             var time = (float)context.time;
    246             switch (context.phase)
    247             {
    248                 case InputActionPhase.Canceled:
    249                     visualizer.AddSample(timelineIndex, 0f, time);
    250                     break;
    251 
    252                 case InputActionPhase.Performed:
    253                     visualizer.AddSample(timelineIndex, 1f, time);
    254                     visualizer.AddSample(timelineIndex, 0f, time);
    255                     break;
    256 
    257                 case InputActionPhase.Started:
    258                     visualizer.AddSample(timelineIndex, 0.5f, time);
    259                     break;
    260             }
    261 
    262             if (m_ShowControlName)
    263                 RecordControlName();
    264         }
    265 
    266         private static void OnActionChange(object actionOrMap, InputActionChange change)
    267         {
    268             switch (change)
    269             {
    270                 case InputActionChange.ActionEnabled:
    271                 case InputActionChange.ActionMapEnabled:
    272                     for (var i = 0; i < s_EnabledInstances.Count; ++i)
    273                         if (s_EnabledInstances[i].m_Action == null)
    274                         {
    275                             s_EnabledInstances[i].ResolveAction();
    276                             if (s_EnabledInstances[i].m_Action != null)
    277                                 s_EnabledInstances[i].SetupVisualizer();
    278                         }
    279                     break;
    280 
    281                 case InputActionChange.ActionDisabled:
    282                     for (var i = 0; i < s_EnabledInstances.Count; ++i)
    283                         if (actionOrMap == s_EnabledInstances[i].m_Action)
    284                             s_EnabledInstances[i].OnActionDisabled();
    285                     break;
    286 
    287                 case InputActionChange.ActionMapDisabled:
    288                     for (var i = 0; i < s_EnabledInstances.Count; ++i)
    289                         if (s_EnabledInstances[i].m_Action?.actionMap == actionOrMap)
    290                             s_EnabledInstances[i].OnActionDisabled();
    291                     break;
    292             }
    293         }
    294 
    295         [SerializeField] private Visualization m_Visualization;
    296         [SerializeField] private InputActionReference m_ActionReference;
    297         [SerializeField] private string m_ActionName;
    298         [SerializeField] private bool m_ShowControlName;
    299 
    300         [NonSerialized] private InputAction m_Action;
    301         [NonSerialized] private InputControl m_ActiveControl;
    302         [NonSerialized] private GUIContent m_ActiveControlName;
    303 
    304         private static List<InputActionVisualizer> s_EnabledInstances;
    305         private static readonly Color[] s_InteractionColors =
    306         {
    307             new Color(1, 0, 0, 1),
    308             new Color(0, 0, 1, 1),
    309             new Color(1, 1, 0, 1),
    310             new Color(1, 0, 1, 1),
    311             new Color(0, 1, 1, 1),
    312             new Color(0, 1, 0, 1),
    313         };
    314 
    315         public enum Visualization
    316         {
    317             None,
    318             Value,
    319             Interaction,
    320         }
    321     }
    322 }