A game about forced loneliness, made by TACStudios
1#if UNITY_EDITOR 2using System; 3using System.Linq; 4using UnityEditor; 5using UnityEngine.InputSystem.Users; 6 7namespace UnityEngine.InputSystem.Editor 8{ 9 /// <summary> 10 /// Custom inspector for <see cref="PlayerInputManager"/>. 11 /// </summary> 12 [CustomEditor(typeof(PlayerInputManager))] 13 internal class PlayerInputManagerEditor : UnityEditor.Editor 14 { 15 public void OnEnable() 16 { 17 InputUser.onChange += OnUserChange; 18 } 19 20 public void OnDisable() 21 { 22 new InputComponentEditorAnalytic(InputSystemComponent.PlayerInputManager).Send(); 23 new PlayerInputManagerEditorAnalytic(this).Send(); 24 } 25 26 public void OnDestroy() 27 { 28 InputUser.onChange -= OnUserChange; 29 } 30 31 private void OnUserChange(InputUser user, InputUserChange change, InputDevice device) 32 { 33 Repaint(); 34 } 35 36 public override void OnInspectorGUI() 37 { 38 ////TODO: cache properties 39 40 EditorGUI.BeginChangeCheck(); 41 42 DoNotificationSectionUI(); 43 EditorGUILayout.Space(); 44 DoJoinSectionUI(); 45 EditorGUILayout.Space(); 46 DoSplitScreenSectionUI(); 47 48 if (EditorGUI.EndChangeCheck()) 49 serializedObject.ApplyModifiedProperties(); 50 51 if (EditorApplication.isPlaying) 52 DoDebugUI(); 53 } 54 55 private void DoNotificationSectionUI() 56 { 57 var notificationBehaviorProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_NotificationBehavior)); 58 EditorGUILayout.PropertyField(notificationBehaviorProperty); 59 switch ((PlayerNotifications)notificationBehaviorProperty.intValue) 60 { 61 case PlayerNotifications.SendMessages: 62 if (m_SendMessagesHelpText == null) 63 m_SendMessagesHelpText = EditorGUIUtility.TrTextContent( 64 $"Will SendMessage() to GameObject: " + string.Join(",", PlayerInputManager.messages)); 65 EditorGUILayout.HelpBox(m_SendMessagesHelpText); 66 break; 67 68 case PlayerNotifications.BroadcastMessages: 69 if (m_BroadcastMessagesHelpText == null) 70 m_BroadcastMessagesHelpText = EditorGUIUtility.TrTextContent( 71 $"Will BroadcastMessage() to GameObject: " + string.Join(",", PlayerInputManager.messages)); 72 EditorGUILayout.HelpBox(m_BroadcastMessagesHelpText); 73 break; 74 75 case PlayerNotifications.InvokeUnityEvents: 76 m_EventsExpanded = EditorGUILayout.Foldout(m_EventsExpanded, m_EventsLabel, toggleOnLabelClick: true); 77 if (m_EventsExpanded) 78 { 79 var playerJoinedEventProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerJoinedEvent)); 80 var playerLeftEventProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerLeftEvent)); 81 82 EditorGUILayout.PropertyField(playerJoinedEventProperty); 83 EditorGUILayout.PropertyField(playerLeftEventProperty); 84 } 85 break; 86 } 87 } 88 89 private void DoJoinSectionUI() 90 { 91 EditorGUILayout.LabelField(m_JoiningGroupLabel, EditorStyles.boldLabel); 92 93 // Join behavior 94 var joinBehaviorProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_JoinBehavior)); 95 EditorGUILayout.PropertyField(joinBehaviorProperty); 96 if ((PlayerJoinBehavior)joinBehaviorProperty.intValue != PlayerJoinBehavior.JoinPlayersManually) 97 { 98 ++EditorGUI.indentLevel; 99 100 // Join action. 101 if ((PlayerJoinBehavior)joinBehaviorProperty.intValue == 102 PlayerJoinBehavior.JoinPlayersWhenJoinActionIsTriggered) 103 { 104 var joinActionProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_JoinAction)); 105 EditorGUILayout.PropertyField(joinActionProperty); 106 } 107 108 // Player prefab. 109 var playerPrefabProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerPrefab)); 110 EditorGUILayout.PropertyField(playerPrefabProperty); 111 112 ValidatePlayerPrefab(joinBehaviorProperty, playerPrefabProperty); 113 114 --EditorGUI.indentLevel; 115 } 116 117 // Enabled-by-default. 118 var allowJoiningProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_AllowJoining)); 119 if (m_AllowingJoiningLabel == null) 120 m_AllowingJoiningLabel = new GUIContent("Joining Enabled By Default", allowJoiningProperty.GetTooltip()); 121 EditorGUILayout.PropertyField(allowJoiningProperty, m_AllowingJoiningLabel); 122 123 // Max player count. 124 var maxPlayerCountProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_MaxPlayerCount)); 125 if (m_EnableMaxPlayerCountLabel == null) 126 m_EnableMaxPlayerCountLabel = EditorGUIUtility.TrTextContent("Limit Number of Players", maxPlayerCountProperty.GetTooltip()); 127 if (maxPlayerCountProperty.intValue > 0) 128 m_MaxPlayerCountEnabled = true; 129 m_MaxPlayerCountEnabled = EditorGUILayout.Toggle(m_EnableMaxPlayerCountLabel, m_MaxPlayerCountEnabled); 130 if (m_MaxPlayerCountEnabled) 131 { 132 ++EditorGUI.indentLevel; 133 if (maxPlayerCountProperty.intValue < 0) 134 maxPlayerCountProperty.intValue = 1; 135 EditorGUILayout.PropertyField(maxPlayerCountProperty); 136 --EditorGUI.indentLevel; 137 } 138 else 139 maxPlayerCountProperty.intValue = -1; 140 } 141 142 private static void ValidatePlayerPrefab(SerializedProperty joinBehaviorProperty, 143 SerializedProperty playerPrefabProperty) 144 { 145 if ((PlayerJoinBehavior)joinBehaviorProperty.intValue != PlayerJoinBehavior.JoinPlayersWhenButtonIsPressed) 146 return; 147 148 if (playerPrefabProperty.objectReferenceValue == null) 149 return; 150 151 var playerInput = ((GameObject)playerPrefabProperty.objectReferenceValue) 152 .GetComponentInChildren<PlayerInput>(); 153 154 if (playerInput == null) 155 { 156 EditorGUILayout.HelpBox("No PlayerInput component found in player prefab.", MessageType.Info); 157 return; 158 } 159 160 if (playerInput.actions == null) 161 { 162 EditorGUILayout.HelpBox("PlayerInput component has no input action asset assigned.", MessageType.Info); 163 return; 164 } 165 166 if (playerInput.actions.controlSchemes.Any(c => c.deviceRequirements.Count > 0) == false) 167 EditorGUILayout.HelpBox("Join Players When Button Is Pressed behavior will not work when the Input Action Asset " + 168 "assigned to the PlayerInput component has no required devices in any control scheme.", 169 MessageType.Info); 170 } 171 172 private void DoSplitScreenSectionUI() 173 { 174 EditorGUILayout.LabelField(m_SplitScreenGroupLabel, EditorStyles.boldLabel); 175 176 // Split-screen toggle. 177 var splitScreenProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_SplitScreen)); 178 if (m_SplitScreenLabel == null) 179 m_SplitScreenLabel = new GUIContent("Enable Split-Screen", splitScreenProperty.GetTooltip()); 180 EditorGUILayout.PropertyField(splitScreenProperty, m_SplitScreenLabel); 181 if (!splitScreenProperty.boolValue) 182 return; 183 184 ++EditorGUI.indentLevel; 185 186 // Maintain-aspect-ratio toggle. 187 var maintainAspectRatioProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_MaintainAspectRatioInSplitScreen)); 188 if (m_MaintainAspectRatioLabel == null) 189 m_MaintainAspectRatioLabel = 190 new GUIContent("Maintain Aspect Ratio", maintainAspectRatioProperty.GetTooltip()); 191 EditorGUILayout.PropertyField(maintainAspectRatioProperty, m_MaintainAspectRatioLabel); 192 193 // Fixed-number toggle. 194 var fixedNumberProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_FixedNumberOfSplitScreens)); 195 if (m_EnableFixedNumberOfSplitScreensLabel == null) 196 m_EnableFixedNumberOfSplitScreensLabel = EditorGUIUtility.TrTextContent("Set Fixed Number", fixedNumberProperty.GetTooltip()); 197 if (fixedNumberProperty.intValue > 0) 198 m_FixedNumberOfSplitScreensEnabled = true; 199 m_FixedNumberOfSplitScreensEnabled = EditorGUILayout.Toggle(m_EnableFixedNumberOfSplitScreensLabel, 200 m_FixedNumberOfSplitScreensEnabled); 201 if (m_FixedNumberOfSplitScreensEnabled) 202 { 203 ++EditorGUI.indentLevel; 204 if (fixedNumberProperty.intValue < 0) 205 fixedNumberProperty.intValue = 4; 206 if (m_FixedNumberOfSplitScreensLabel == null) 207 m_FixedNumberOfSplitScreensLabel = EditorGUIUtility.TrTextContent("Number of Screens", 208 fixedNumberProperty.tooltip); 209 EditorGUILayout.PropertyField(fixedNumberProperty, m_FixedNumberOfSplitScreensLabel); 210 --EditorGUI.indentLevel; 211 } 212 else 213 { 214 fixedNumberProperty.intValue = -1; 215 } 216 217 // Split-screen area. 218 var splitScreenAreaProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_SplitScreenRect)); 219 if (m_SplitScreenAreaLabel == null) 220 m_SplitScreenAreaLabel = new GUIContent("Screen Rectangle", splitScreenAreaProperty.GetTooltip()); 221 EditorGUILayout.PropertyField(splitScreenAreaProperty, m_SplitScreenAreaLabel); 222 223 --EditorGUI.indentLevel; 224 } 225 226 private void DoDebugUI() 227 { 228 EditorGUILayout.Space(); 229 EditorGUILayout.LabelField(m_DebugLabel, EditorStyles.boldLabel); 230 EditorGUI.BeginDisabledGroup(true); 231 232 var players = PlayerInput.all; 233 if (players.Count == 0) 234 { 235 EditorGUILayout.LabelField("No Players"); 236 } 237 else 238 { 239 foreach (var player in players) 240 { 241 var str = player.gameObject.name; 242 if (player.splitScreenIndex != -1) 243 str += $" (Screen #{player.splitScreenIndex})"; 244 EditorGUILayout.LabelField("Player #" + player.playerIndex, str); 245 } 246 } 247 EditorGUI.EndDisabledGroup(); 248 } 249 250 [SerializeField] private bool m_EventsExpanded; 251 [SerializeField] private bool m_MaxPlayerCountEnabled; 252 [SerializeField] private bool m_FixedNumberOfSplitScreensEnabled; 253 254 [NonSerialized] private readonly GUIContent m_JoiningGroupLabel = EditorGUIUtility.TrTextContent("Joining"); 255 [NonSerialized] private readonly GUIContent m_SplitScreenGroupLabel = EditorGUIUtility.TrTextContent("Split-Screen"); 256 [NonSerialized] private readonly GUIContent m_EventsLabel = EditorGUIUtility.TrTextContent("Events"); 257 [NonSerialized] private readonly GUIContent m_DebugLabel = EditorGUIUtility.TrTextContent("Debug"); 258 [NonSerialized] private GUIContent m_SendMessagesHelpText; 259 [NonSerialized] private GUIContent m_BroadcastMessagesHelpText; 260 [NonSerialized] private GUIContent m_AllowingJoiningLabel; 261 [NonSerialized] private GUIContent m_SplitScreenLabel; 262 [NonSerialized] private GUIContent m_MaintainAspectRatioLabel; 263 [NonSerialized] private GUIContent m_SplitScreenAreaLabel; 264 [NonSerialized] private GUIContent m_FixedNumberOfSplitScreensLabel; 265 [NonSerialized] private GUIContent m_EnableMaxPlayerCountLabel; 266 [NonSerialized] private GUIContent m_EnableFixedNumberOfSplitScreensLabel; 267 } 268} 269#endif // UNITY_EDITOR