#if UNITY_EDITOR using System; using System.Linq; using UnityEditor; using UnityEngine.InputSystem.Users; namespace UnityEngine.InputSystem.Editor { /// /// Custom inspector for . /// [CustomEditor(typeof(PlayerInputManager))] internal class PlayerInputManagerEditor : UnityEditor.Editor { public void OnEnable() { InputUser.onChange += OnUserChange; } public void OnDisable() { new InputComponentEditorAnalytic(InputSystemComponent.PlayerInputManager).Send(); new PlayerInputManagerEditorAnalytic(this).Send(); } public void OnDestroy() { InputUser.onChange -= OnUserChange; } private void OnUserChange(InputUser user, InputUserChange change, InputDevice device) { Repaint(); } public override void OnInspectorGUI() { ////TODO: cache properties EditorGUI.BeginChangeCheck(); DoNotificationSectionUI(); EditorGUILayout.Space(); DoJoinSectionUI(); EditorGUILayout.Space(); DoSplitScreenSectionUI(); if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties(); if (EditorApplication.isPlaying) DoDebugUI(); } private void DoNotificationSectionUI() { var notificationBehaviorProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_NotificationBehavior)); EditorGUILayout.PropertyField(notificationBehaviorProperty); switch ((PlayerNotifications)notificationBehaviorProperty.intValue) { case PlayerNotifications.SendMessages: if (m_SendMessagesHelpText == null) m_SendMessagesHelpText = EditorGUIUtility.TrTextContent( $"Will SendMessage() to GameObject: " + string.Join(",", PlayerInputManager.messages)); EditorGUILayout.HelpBox(m_SendMessagesHelpText); break; case PlayerNotifications.BroadcastMessages: if (m_BroadcastMessagesHelpText == null) m_BroadcastMessagesHelpText = EditorGUIUtility.TrTextContent( $"Will BroadcastMessage() to GameObject: " + string.Join(",", PlayerInputManager.messages)); EditorGUILayout.HelpBox(m_BroadcastMessagesHelpText); break; case PlayerNotifications.InvokeUnityEvents: m_EventsExpanded = EditorGUILayout.Foldout(m_EventsExpanded, m_EventsLabel, toggleOnLabelClick: true); if (m_EventsExpanded) { var playerJoinedEventProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerJoinedEvent)); var playerLeftEventProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerLeftEvent)); EditorGUILayout.PropertyField(playerJoinedEventProperty); EditorGUILayout.PropertyField(playerLeftEventProperty); } break; } } private void DoJoinSectionUI() { EditorGUILayout.LabelField(m_JoiningGroupLabel, EditorStyles.boldLabel); // Join behavior var joinBehaviorProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_JoinBehavior)); EditorGUILayout.PropertyField(joinBehaviorProperty); if ((PlayerJoinBehavior)joinBehaviorProperty.intValue != PlayerJoinBehavior.JoinPlayersManually) { ++EditorGUI.indentLevel; // Join action. if ((PlayerJoinBehavior)joinBehaviorProperty.intValue == PlayerJoinBehavior.JoinPlayersWhenJoinActionIsTriggered) { var joinActionProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_JoinAction)); EditorGUILayout.PropertyField(joinActionProperty); } // Player prefab. var playerPrefabProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_PlayerPrefab)); EditorGUILayout.PropertyField(playerPrefabProperty); ValidatePlayerPrefab(joinBehaviorProperty, playerPrefabProperty); --EditorGUI.indentLevel; } // Enabled-by-default. var allowJoiningProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_AllowJoining)); if (m_AllowingJoiningLabel == null) m_AllowingJoiningLabel = new GUIContent("Joining Enabled By Default", allowJoiningProperty.GetTooltip()); EditorGUILayout.PropertyField(allowJoiningProperty, m_AllowingJoiningLabel); // Max player count. var maxPlayerCountProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_MaxPlayerCount)); if (m_EnableMaxPlayerCountLabel == null) m_EnableMaxPlayerCountLabel = EditorGUIUtility.TrTextContent("Limit Number of Players", maxPlayerCountProperty.GetTooltip()); if (maxPlayerCountProperty.intValue > 0) m_MaxPlayerCountEnabled = true; m_MaxPlayerCountEnabled = EditorGUILayout.Toggle(m_EnableMaxPlayerCountLabel, m_MaxPlayerCountEnabled); if (m_MaxPlayerCountEnabled) { ++EditorGUI.indentLevel; if (maxPlayerCountProperty.intValue < 0) maxPlayerCountProperty.intValue = 1; EditorGUILayout.PropertyField(maxPlayerCountProperty); --EditorGUI.indentLevel; } else maxPlayerCountProperty.intValue = -1; } private static void ValidatePlayerPrefab(SerializedProperty joinBehaviorProperty, SerializedProperty playerPrefabProperty) { if ((PlayerJoinBehavior)joinBehaviorProperty.intValue != PlayerJoinBehavior.JoinPlayersWhenButtonIsPressed) return; if (playerPrefabProperty.objectReferenceValue == null) return; var playerInput = ((GameObject)playerPrefabProperty.objectReferenceValue) .GetComponentInChildren(); if (playerInput == null) { EditorGUILayout.HelpBox("No PlayerInput component found in player prefab.", MessageType.Info); return; } if (playerInput.actions == null) { EditorGUILayout.HelpBox("PlayerInput component has no input action asset assigned.", MessageType.Info); return; } if (playerInput.actions.controlSchemes.Any(c => c.deviceRequirements.Count > 0) == false) EditorGUILayout.HelpBox("Join Players When Button Is Pressed behavior will not work when the Input Action Asset " + "assigned to the PlayerInput component has no required devices in any control scheme.", MessageType.Info); } private void DoSplitScreenSectionUI() { EditorGUILayout.LabelField(m_SplitScreenGroupLabel, EditorStyles.boldLabel); // Split-screen toggle. var splitScreenProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_SplitScreen)); if (m_SplitScreenLabel == null) m_SplitScreenLabel = new GUIContent("Enable Split-Screen", splitScreenProperty.GetTooltip()); EditorGUILayout.PropertyField(splitScreenProperty, m_SplitScreenLabel); if (!splitScreenProperty.boolValue) return; ++EditorGUI.indentLevel; // Maintain-aspect-ratio toggle. var maintainAspectRatioProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_MaintainAspectRatioInSplitScreen)); if (m_MaintainAspectRatioLabel == null) m_MaintainAspectRatioLabel = new GUIContent("Maintain Aspect Ratio", maintainAspectRatioProperty.GetTooltip()); EditorGUILayout.PropertyField(maintainAspectRatioProperty, m_MaintainAspectRatioLabel); // Fixed-number toggle. var fixedNumberProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_FixedNumberOfSplitScreens)); if (m_EnableFixedNumberOfSplitScreensLabel == null) m_EnableFixedNumberOfSplitScreensLabel = EditorGUIUtility.TrTextContent("Set Fixed Number", fixedNumberProperty.GetTooltip()); if (fixedNumberProperty.intValue > 0) m_FixedNumberOfSplitScreensEnabled = true; m_FixedNumberOfSplitScreensEnabled = EditorGUILayout.Toggle(m_EnableFixedNumberOfSplitScreensLabel, m_FixedNumberOfSplitScreensEnabled); if (m_FixedNumberOfSplitScreensEnabled) { ++EditorGUI.indentLevel; if (fixedNumberProperty.intValue < 0) fixedNumberProperty.intValue = 4; if (m_FixedNumberOfSplitScreensLabel == null) m_FixedNumberOfSplitScreensLabel = EditorGUIUtility.TrTextContent("Number of Screens", fixedNumberProperty.tooltip); EditorGUILayout.PropertyField(fixedNumberProperty, m_FixedNumberOfSplitScreensLabel); --EditorGUI.indentLevel; } else { fixedNumberProperty.intValue = -1; } // Split-screen area. var splitScreenAreaProperty = serializedObject.FindProperty(nameof(PlayerInputManager.m_SplitScreenRect)); if (m_SplitScreenAreaLabel == null) m_SplitScreenAreaLabel = new GUIContent("Screen Rectangle", splitScreenAreaProperty.GetTooltip()); EditorGUILayout.PropertyField(splitScreenAreaProperty, m_SplitScreenAreaLabel); --EditorGUI.indentLevel; } private void DoDebugUI() { EditorGUILayout.Space(); EditorGUILayout.LabelField(m_DebugLabel, EditorStyles.boldLabel); EditorGUI.BeginDisabledGroup(true); var players = PlayerInput.all; if (players.Count == 0) { EditorGUILayout.LabelField("No Players"); } else { foreach (var player in players) { var str = player.gameObject.name; if (player.splitScreenIndex != -1) str += $" (Screen #{player.splitScreenIndex})"; EditorGUILayout.LabelField("Player #" + player.playerIndex, str); } } EditorGUI.EndDisabledGroup(); } [SerializeField] private bool m_EventsExpanded; [SerializeField] private bool m_MaxPlayerCountEnabled; [SerializeField] private bool m_FixedNumberOfSplitScreensEnabled; [NonSerialized] private readonly GUIContent m_JoiningGroupLabel = EditorGUIUtility.TrTextContent("Joining"); [NonSerialized] private readonly GUIContent m_SplitScreenGroupLabel = EditorGUIUtility.TrTextContent("Split-Screen"); [NonSerialized] private readonly GUIContent m_EventsLabel = EditorGUIUtility.TrTextContent("Events"); [NonSerialized] private readonly GUIContent m_DebugLabel = EditorGUIUtility.TrTextContent("Debug"); [NonSerialized] private GUIContent m_SendMessagesHelpText; [NonSerialized] private GUIContent m_BroadcastMessagesHelpText; [NonSerialized] private GUIContent m_AllowingJoiningLabel; [NonSerialized] private GUIContent m_SplitScreenLabel; [NonSerialized] private GUIContent m_MaintainAspectRatioLabel; [NonSerialized] private GUIContent m_SplitScreenAreaLabel; [NonSerialized] private GUIContent m_FixedNumberOfSplitScreensLabel; [NonSerialized] private GUIContent m_EnableMaxPlayerCountLabel; [NonSerialized] private GUIContent m_EnableFixedNumberOfSplitScreensLabel; } } #endif // UNITY_EDITOR