mirror of
https://github.com/FriendshipIsEpic/FiE-Game.git
synced 2025-02-20 12:24:22 +01:00
3241 lines
No EOL
152 KiB
C#
3241 lines
No EOL
152 KiB
C#
// Copyright (c) 2015 Augie R. Maddox, Guavaman Enterprises. All rights reserved.
|
|
#pragma warning disable 0219
|
|
#pragma warning disable 0618
|
|
#pragma warning disable 0649
|
|
|
|
namespace Rewired.UI.ControlMapper {
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.Events;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.EventSystems;
|
|
using Rewired;
|
|
using Rewired.Utils;
|
|
|
|
[AddComponentMenu("")]
|
|
public partial class ControlMapper : MonoBehaviour {
|
|
|
|
#region Consts
|
|
|
|
private const float blockInputOnFocusTimeout = 0.1f; // a small delay after main screen receives focus to filter out button down events during new assignments
|
|
|
|
private const string buttonIdentifier_playerSelection = "PlayerSelection";
|
|
private const string buttonIdentifier_removeController = "RemoveController";
|
|
private const string buttonIdentifier_assignController = "AssignController";
|
|
private const string buttonIdentifier_calibrateController = "CalibrateController";
|
|
private const string buttonIdentifier_editInputBehaviors = "EditInputBehaviors";
|
|
private const string buttonIdentifier_mapCategorySelection = "MapCategorySelection";
|
|
private const string buttonIdentifier_assignedControllerSelection = "AssignedControllerSelection";
|
|
private const string buttonIdentifier_done = "Done";
|
|
private const string buttonIdentifier_restoreDefaults = "RestoreDefaults";
|
|
|
|
#endregion
|
|
|
|
#region Inspector Vars
|
|
|
|
[SerializeField]
|
|
[Tooltip("Must be assigned a Rewired Input Manager scene object or prefab.")]
|
|
private InputManager _rewiredInputManager;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Set to True to prevent the Game Object from being destroyed when a new scene is loaded.\n\nNOTE: Changing this value from True to False at runtime will have no effect because Object.DontDestroyOnLoad cannot be undone once set.")]
|
|
private bool _dontDestroyOnLoad;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Open the control mapping screen immediately on start. Mainly used for testing.")]
|
|
private bool _openOnStart = false;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The Layout of the Keyboard Maps to be displayed.")]
|
|
private int _keyboardMapDefaultLayout = 0;
|
|
[SerializeField]
|
|
[Tooltip("The Layout of the Mouse Maps to be displayed.")]
|
|
private int _mouseMapDefaultLayout = 0;
|
|
[SerializeField]
|
|
[Tooltip("The Layout of the Mouse Maps to be displayed.")]
|
|
private int _joystickMapDefaultLayout = 0;
|
|
|
|
[SerializeField]
|
|
private MappingSet[] _mappingSets = new MappingSet[1] { MappingSet.Default };
|
|
|
|
[SerializeField]
|
|
[Tooltip("Display a selectable list of Players. If your game only supports 1 player, you can disable this.")]
|
|
private bool _showPlayers = true;
|
|
[SerializeField]
|
|
[Tooltip("Display the Controller column for input mapping.")]
|
|
private bool _showControllers = true;
|
|
[SerializeField]
|
|
[Tooltip("Display the Keyboard column for input mapping.")]
|
|
private bool _showKeyboard = true;
|
|
[SerializeField]
|
|
[Tooltip("Display the Mouse column for input mapping.")]
|
|
private bool _showMouse = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip(
|
|
"The maximum number of controllers allowed to be assigned to a Player. " +
|
|
"If set to any value other than 1, a selectable list of currently-assigned controller will be displayed to the user. " +
|
|
"[0 = infinite]"
|
|
)]
|
|
private int _maxControllersPerPlayer = 1;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Display section labels for each Action Category in the input field grid. Only applies if Action Categories are used to display the Action list.")]
|
|
private bool _showActionCategoryLabels = false;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The number of input fields to display for the keyboard. If you want to support alternate mappings on the same device, set this to 2 or more.")]
|
|
private int _keyboardInputFieldCount = 2;
|
|
[SerializeField]
|
|
[Tooltip("The number of input fields to display for the mouse. If you want to support alternate mappings on the same device, set this to 2 or more.")]
|
|
private int _mouseInputFieldCount = 1;
|
|
[SerializeField]
|
|
[Tooltip("The number of input fields to display for joysticks. If you want to support alternate mappings on the same device, set this to 2 or more.")]
|
|
private int _controllerInputFieldCount = 1;
|
|
|
|
[SerializeField]
|
|
[Tooltip(
|
|
"Display a full-axis input assignment field for every axis-type Action in the input field grid. Also displays an invert toggle for the user " +
|
|
" to invert the full-axis assignment direction." +
|
|
"\n\n*IMPORTANT*: This field is required if you have made any full-axis assignments in the Rewired Input Manager or in saved XML user data. " +
|
|
"Disabling this field when you have full-axis assignments will result in the inability for the user to view, remove, or modify these " +
|
|
"full-axis assignments. In addition, these assignments may cause conflicts when trying to remap the same axes to Actions."
|
|
)]
|
|
private bool _showFullAxisInputFields = true;
|
|
[SerializeField]
|
|
[Tooltip(
|
|
"Display a positive and negative input assignment field for every axis-type Action in the input field grid." +
|
|
"\n\n*IMPORTANT*: These fields are required to assign buttons, keyboard keys, and hat or D-Pad directions to axis-type Actions. " +
|
|
"If you have made any split-axis assignments or button/key/D-pad assignments to axis-type Actions in the Rewired Input Manager or " +
|
|
"in saved XML user data, disabling these fields will result in the inability for the user to view, remove, or modify these assignments. " +
|
|
"In addition, these assignments may cause conflicts when trying to remap the same elements to Actions."
|
|
)]
|
|
private bool _showSplitAxisInputFields = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip("If enabled, when an element assignment conflict is found, an option will be displayed that allows the user to make the conflicting assignment anyway.")]
|
|
private bool _allowElementAssignmentConflicts = false;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of the Action label column.")]
|
|
private int _actionLabelWidth = 200;
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of the Keyboard column.")]
|
|
private int _keyboardColMaxWidth = 360;
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of the Mouse column.")]
|
|
private int _mouseColMaxWidth = 200;
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of the Controller column.")]
|
|
private int _controllerColMaxWidth = 200;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The height in relative pixels of the input grid button rows.")]
|
|
private int _inputRowHeight = 40;
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of spacing between columns.")]
|
|
private int _inputColumnSpacing = 40;
|
|
[SerializeField]
|
|
[Tooltip("The height in relative pixels of the space between Action Category sections. Only applicable if Show Action Category Labels is checked.")]
|
|
private int _inputRowCategorySpacing = 20;
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of the invert toggle buttons.")]
|
|
private int _invertToggleWidth = 40;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The width in relative pixels of generated popup windows.")]
|
|
private int _defaultWindowWidth = 500;
|
|
[SerializeField]
|
|
[Tooltip("The height in relative pixels of generated popup windows.")]
|
|
private int _defaultWindowHeight = 400;
|
|
|
|
[SerializeField]
|
|
[Tooltip("The time in seconds the user has to press an element on a controller when assigning a controller to a Player. If this time elapses with no user input a controller, the assignment will be canceled.")]
|
|
private float _controllerAssignmentTimeout = 5.0f;
|
|
[SerializeField]
|
|
[Tooltip("The time in seconds the user has to press an element on a controller while waiting for axes to be centered before assigning input.")]
|
|
private float _preInputAssignmentTimeout = 5.0f;
|
|
[SerializeField]
|
|
[Tooltip("The time in seconds the user has to press an element on a controller when assigning input. If this time elapses with no user input on the target controller, the assignment will be canceled.")]
|
|
private float _inputAssignmentTimeout = 5.0f;
|
|
[SerializeField]
|
|
[Tooltip("The time in seconds the user has to press an element on a controller during calibration.")]
|
|
private float _axisCalibrationTimeout = 5.0f;
|
|
|
|
[SerializeField]
|
|
[Tooltip("If checked, mouse X-axis movement will always be ignored during input assignment. Check this if you don't want the horizontal mouse axis to be user-assignable to any Actions.")]
|
|
private bool _ignoreMouseXAxisAssignment = true;
|
|
[SerializeField]
|
|
[Tooltip("If checked, mouse Y-axis movement will always be ignored during input assignment. Check this if you don't want the vertical mouse axis to be user-assignable to any Actions.")]
|
|
private bool _ignoreMouseYAxisAssignment = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip("An Action that when activated will alternately close or open the main screen as long as no popup windows are open.")]
|
|
private int _screenToggleAction = -1;
|
|
[SerializeField]
|
|
[Tooltip("An Action that when activated will open the main screen if it is closed.")]
|
|
private int _screenOpenAction = -1;
|
|
[SerializeField]
|
|
[Tooltip("An Action that when activated will close the main screen as long as no popup windows are open.")]
|
|
private int _screenCloseAction = -1;
|
|
[SerializeField]
|
|
[Tooltip("An Action that when activated will cancel and close any open popup window. Use with care because the element assigned to this Action can never be mapped by the user (because it would just cancel his assignment).")]
|
|
private int _universalCancelAction = -1;
|
|
[SerializeField]
|
|
[Tooltip("If enabled, Universal Cancel will also close the main screen if pressed when no windows are open.")]
|
|
private bool _universalCancelClosesScreen = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip("If checked, controls will be displayed which will allow the user to customize certain Input Behavior settings.")]
|
|
private bool _showInputBehaviorSettings;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Customizable settings for user-modifiable Input Behaviors. This can be used for settings like Mouse Look Sensitivity.")]
|
|
private InputBehaviorSettings[] _inputBehaviorSettings;
|
|
|
|
[SerializeField]
|
|
[Tooltip("If enabled, UI elements will be themed based on the settings in Theme Settings.")]
|
|
private bool _useThemeSettings = true;
|
|
[SerializeField]
|
|
[Tooltip("Must be assigned a ThemeSettings object. Used to theme UI elements.")]
|
|
private ThemeSettings _themeSettings;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Must be assigned a LanguageData object. Used to retrieve language entries for UI elements.")]
|
|
private UI.ControlMapper.LanguageData _language;
|
|
|
|
[SerializeField]
|
|
[Tooltip("A list of prefabs. You should not have to modify this.")]
|
|
private Prefabs prefabs;
|
|
[SerializeField]
|
|
[Tooltip("A list of references to elements in the hierarchy. You should not have to modify this.")]
|
|
private References references;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the Players button group?")]
|
|
private bool _showPlayersGroupLabel = true;
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the Controller button group?")]
|
|
private bool _showControllerGroupLabel = true;
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the Assigned Controllers button group?")]
|
|
private bool _showAssignedControllersGroupLabel = true;
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the Settings button group?")]
|
|
private bool _showSettingsGroupLabel = true;
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the Map Categories button group?")]
|
|
private bool _showMapCategoriesGroupLabel = true;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Show the label for the current controller name?")]
|
|
private bool _showControllerNameLabel = true;
|
|
[SerializeField]
|
|
[Tooltip("Show the Assigned Controllers group? If joystick auto-assignment is enabled in the Rewired Input Manager and the max joysticks per player is set to any value other than 1, the Assigned Controllers group will always be displayed.")]
|
|
private bool _showAssignedControllers = true;
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
// .NET events
|
|
|
|
private System.Action _ScreenClosedEvent;
|
|
private System.Action _ScreenOpenedEvent;
|
|
private System.Action _PopupWindowOpenedEvent;
|
|
private System.Action _PopupWindowClosedEvent;
|
|
private System.Action _InputPollingStartedEvent;
|
|
private System.Action _InputPollingEndedEvent;
|
|
|
|
/// <summary>
|
|
/// Event sent when the UI is closed.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onScreenClosed event.
|
|
/// </summary>
|
|
public event System.Action ScreenClosedEvent {
|
|
add {
|
|
_ScreenClosedEvent += value;
|
|
}
|
|
remove {
|
|
_ScreenClosedEvent -= value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event sent when the UI is opened.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onScreenOpened event.
|
|
/// </summary>
|
|
public event System.Action ScreenOpenedEvent {
|
|
add {
|
|
_ScreenOpenedEvent += value;
|
|
}
|
|
remove {
|
|
_ScreenOpenedEvent -= value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event sent when a popup window is closed.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onPopupWindowClosed event.
|
|
/// </summary>
|
|
public event System.Action PopupWindowClosedEvent {
|
|
add {
|
|
_PopupWindowClosedEvent += value;
|
|
}
|
|
remove {
|
|
_PopupWindowClosedEvent -= value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event sent when a popup window is opened.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onPopupWindowOpened event.
|
|
/// </summary>
|
|
public event System.Action PopupWindowOpenedEvent {
|
|
add {
|
|
_PopupWindowOpenedEvent += value;
|
|
}
|
|
remove {
|
|
_PopupWindowOpenedEvent -= value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event sent when polling for input has started.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onInputPollingStarted event.
|
|
/// </summary>
|
|
public event System.Action InputPollingStartedEvent {
|
|
add {
|
|
_InputPollingStartedEvent += value;
|
|
}
|
|
remove {
|
|
_InputPollingStartedEvent -= value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event sent when polling for input has ended.
|
|
/// This is a .NET event. If you are using Unity Events,
|
|
/// use the onInputPollingStopped event.
|
|
/// </summary>
|
|
public event System.Action InputPollingEndedEvent {
|
|
add {
|
|
_InputPollingEndedEvent += value;
|
|
}
|
|
remove {
|
|
_InputPollingEndedEvent -= value;
|
|
}
|
|
}
|
|
|
|
// Unity events
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when the UI is closed.")]
|
|
private UnityEvent _onScreenClosed;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when the UI is opened.")]
|
|
private UnityEvent _onScreenOpened;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when a popup window is closed.")]
|
|
private UnityEvent _onPopupWindowClosed;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when a popup window is opened.")]
|
|
private UnityEvent _onPopupWindowOpened;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when polling for input has started.")]
|
|
private UnityEvent _onInputPollingStarted;
|
|
|
|
[SerializeField]
|
|
[Tooltip("Event sent when polling for input has ended.")]
|
|
private UnityEvent _onInputPollingEnded;
|
|
|
|
/// <summary>
|
|
/// Unity event sent when the UI is closed.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use ScreenClosedEvent.
|
|
/// </summary>
|
|
public event UnityAction onScreenClosed {
|
|
add {
|
|
_onScreenClosed.AddListener(value);
|
|
}
|
|
remove {
|
|
_onScreenClosed.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity event sent when the UI is opened.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use ScreenOpenedEvent.
|
|
/// </summary>
|
|
public event UnityAction onScreenOpened {
|
|
add {
|
|
_onScreenOpened.AddListener(value);
|
|
}
|
|
remove {
|
|
_onScreenOpened.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity event sent when a popup window is closed.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use PopupWindowClosedEvent.
|
|
/// </summary>
|
|
public event UnityAction onPopupWindowClosed {
|
|
add {
|
|
_onPopupWindowClosed.AddListener(value);
|
|
}
|
|
remove {
|
|
_onPopupWindowClosed.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity event sent when a popup window is opened.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use PopupWindowOpenedEvent.
|
|
/// </summary>
|
|
public event UnityAction onPopupWindowOpened {
|
|
add {
|
|
_onPopupWindowOpened.AddListener(value);
|
|
}
|
|
remove {
|
|
_onPopupWindowOpened.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity event sent when polling for input has started.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use InputPollingStartedEvent.
|
|
/// </summary>
|
|
public event UnityAction onInputPollingStarted {
|
|
add {
|
|
_onInputPollingStarted.AddListener(value);
|
|
}
|
|
remove {
|
|
_onInputPollingStarted.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unity event sent when polling for input has ended.
|
|
/// This is a Unity event. For the .NET event,
|
|
/// use InputPollingEndedEvent.
|
|
/// </summary>
|
|
public event UnityAction onInputPollingEnded {
|
|
add {
|
|
_onInputPollingEnded.AddListener(value);
|
|
}
|
|
remove {
|
|
_onInputPollingEnded.RemoveListener(value);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Working vars
|
|
|
|
private static ControlMapper Instance;
|
|
|
|
private bool initialized;
|
|
private int playerCount;
|
|
|
|
private InputGrid inputGrid;
|
|
private WindowManager windowManager;
|
|
private int currentPlayerId;
|
|
private int currentMapCategoryId;
|
|
private List<GUIButton> playerButtons;
|
|
private List<GUIButton> mapCategoryButtons;
|
|
private List<GUIButton> assignedControllerButtons;
|
|
private GUIButton assignedControllerButtonsPlaceholder;
|
|
private List<GameObject> miscInstantiatedObjects;
|
|
private GameObject canvas;
|
|
private GameObject lastUISelection;
|
|
private int currentJoystickId = -1;
|
|
private float blockInputOnFocusEndTime;
|
|
private bool isPollingForInput;
|
|
|
|
private InputMapping pendingInputMapping;
|
|
private AxisCalibrator pendingAxisCalibration;
|
|
|
|
private System.Action<InputFieldInfo> inputFieldActivatedDelegate;
|
|
private System.Action<ToggleInfo, bool> inputFieldInvertToggleStateChangedDelegate;
|
|
|
|
private System.Action _restoreDefaultsDelegate;
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
#region Inspector Properties
|
|
|
|
// Public access to certain settings which can be changed at runtime before initialization or after initialization provided Reset() is called afterwards.
|
|
// This is useful if you want to show only certain settings based on the current platform.
|
|
// Not all properties are runtime modifiable.
|
|
|
|
public InputManager rewiredInputManager { get { return _rewiredInputManager; } set { _rewiredInputManager = value; InspectorPropertyChanged(true); } }
|
|
public bool dontDestroyOnLoad { get { return _dontDestroyOnLoad; } set { if(value != _dontDestroyOnLoad) { if(value) DontDestroyOnLoad(transform.gameObject); } _dontDestroyOnLoad = value; } }
|
|
public int keyboardMapDefaultLayout { get { return _keyboardMapDefaultLayout; } set { _keyboardMapDefaultLayout = value; InspectorPropertyChanged(true); } }
|
|
public int mouseMapDefaultLayout { get { return _mouseMapDefaultLayout; } set { _mouseMapDefaultLayout = value; InspectorPropertyChanged(true); } }
|
|
public int joystickMapDefaultLayout { get { return _joystickMapDefaultLayout; } set { _joystickMapDefaultLayout = value; InspectorPropertyChanged(true); } }
|
|
//public MappingSet[] mappingSets { get { return _mappingSets; } set { _mappingSets = value; InspectorPropertyChanged(); } }
|
|
public bool showPlayers { get { return _showPlayers && ReInput.players.playerCount > 1; } set { _showPlayers = value; InspectorPropertyChanged(true); } }
|
|
public bool showControllers { get { return _showControllers; } set { _showControllers = value; InspectorPropertyChanged(true); } }
|
|
public bool showKeyboard { get { return _showKeyboard; } set { _showKeyboard = value; InspectorPropertyChanged(true); } }
|
|
public bool showMouse { get { return _showMouse; } set { _showMouse = value; InspectorPropertyChanged(true); } }
|
|
public int maxControllersPerPlayer { get { return _maxControllersPerPlayer; } set { _maxControllersPerPlayer = value; InspectorPropertyChanged(true); } }
|
|
public bool showActionCategoryLabels { get { return _showActionCategoryLabels; } set { _showActionCategoryLabels = value; InspectorPropertyChanged(true); } }
|
|
public int keyboardInputFieldCount { get { return _keyboardInputFieldCount; } set { _keyboardInputFieldCount = value; InspectorPropertyChanged(true); } }
|
|
public int mouseInputFieldCount { get { return _mouseInputFieldCount; } set { _mouseInputFieldCount = value; InspectorPropertyChanged(true); } }
|
|
public int controllerInputFieldCount { get { return _controllerInputFieldCount; } set { _controllerInputFieldCount = value; InspectorPropertyChanged(true); } }
|
|
public bool showFullAxisInputFields { get { return _showFullAxisInputFields; } set { _showFullAxisInputFields = value; InspectorPropertyChanged(true); } }
|
|
public bool showSplitAxisInputFields { get { return _showSplitAxisInputFields; } set { _showSplitAxisInputFields = value; InspectorPropertyChanged(true); } }
|
|
public bool allowElementAssignmentConflicts { get { return _allowElementAssignmentConflicts; } set { _allowElementAssignmentConflicts = value; InspectorPropertyChanged(); } }
|
|
public int actionLabelWidth { get { return _actionLabelWidth; } set { _actionLabelWidth = value; InspectorPropertyChanged(true); } }
|
|
public int keyboardColMaxWidth { get { return _keyboardColMaxWidth; } set { _keyboardColMaxWidth = value; InspectorPropertyChanged(true); } }
|
|
public int mouseColMaxWidth { get { return _mouseColMaxWidth; } set { _mouseColMaxWidth = value; InspectorPropertyChanged(true); } }
|
|
public int controllerColMaxWidth { get { return _controllerColMaxWidth; } set { _controllerColMaxWidth = value; InspectorPropertyChanged(true); } }
|
|
public int inputRowHeight { get { return _inputRowHeight; } set { _inputRowHeight = value; InspectorPropertyChanged(true); } }
|
|
public int inputColumnSpacing { get { return _inputColumnSpacing; } set { _inputColumnSpacing = value; InspectorPropertyChanged(true); } }
|
|
public int inputRowCategorySpacing { get { return _inputRowCategorySpacing; } set { _inputRowCategorySpacing = value; InspectorPropertyChanged(true); } }
|
|
public int invertToggleWidth { get { return _invertToggleWidth; } set { _invertToggleWidth = value; InspectorPropertyChanged(true); } }
|
|
public int defaultWindowWidth { get { return _defaultWindowWidth; } set { _defaultWindowWidth = value; InspectorPropertyChanged(true); } }
|
|
public int defaultWindowHeight { get { return _defaultWindowHeight; } set { _defaultWindowHeight = value; InspectorPropertyChanged(true); } }
|
|
public float controllerAssignmentTimeout { get { return _controllerAssignmentTimeout; } set { _controllerAssignmentTimeout = value; InspectorPropertyChanged(); } }
|
|
public float preInputAssignmentTimeout { get { return _preInputAssignmentTimeout; } set { _preInputAssignmentTimeout = value; InspectorPropertyChanged(); } }
|
|
public float inputAssignmentTimeout { get { return _inputAssignmentTimeout; } set { _inputAssignmentTimeout = value; InspectorPropertyChanged(); } }
|
|
public float axisCalibrationTimeout { get { return _axisCalibrationTimeout; } set { _axisCalibrationTimeout = value; InspectorPropertyChanged(); } }
|
|
public bool ignoreMouseXAxisAssignment { get { return _ignoreMouseXAxisAssignment; } set { _ignoreMouseXAxisAssignment = value; InspectorPropertyChanged(); } }
|
|
public bool ignoreMouseYAxisAssignment { get { return _ignoreMouseYAxisAssignment; } set { _ignoreMouseYAxisAssignment = value; InspectorPropertyChanged(); } }
|
|
//public int screenToggleAction { get { return _screenToggleAction; } set { _screenToggleAction = value; InspectorPropertyChanged(); } }
|
|
//public int screenOpenAction { get { return _screenOpenAction; } set { _screenOpenAction = value; InspectorPropertyChanged(); } }
|
|
//public int screenCloseAction { get { return _screenCloseAction; } set { _screenCloseAction = value; InspectorPropertyChanged(); } }
|
|
//public int universalCancelAction { get { return _universalCancelAction; } set { _universalCancelAction = value; InspectorPropertyChanged(); } }
|
|
public bool universalCancelClosesScreen { get { return _universalCancelClosesScreen; } set { _universalCancelClosesScreen = value; InspectorPropertyChanged(); } }
|
|
public bool showInputBehaviorSettings { get { return _showInputBehaviorSettings; } set { _showInputBehaviorSettings = value; InspectorPropertyChanged(true); } }
|
|
public bool useThemeSettings { get { return _useThemeSettings; } set { _useThemeSettings = value; InspectorPropertyChanged(true); } }
|
|
public LanguageData language { get { return _language; } set { _language = value; if(_language != null) _language.Initialize(); InspectorPropertyChanged(true); } }
|
|
|
|
public bool showPlayersGroupLabel { get { return _showPlayersGroupLabel; } set { _showPlayersGroupLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showControllerGroupLabel { get { return _showControllerGroupLabel; } set { _showControllerGroupLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showAssignedControllersGroupLabel { get { return _showAssignedControllersGroupLabel; } set { _showAssignedControllersGroupLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showSettingsGroupLabel { get { return _showSettingsGroupLabel; } set { _showSettingsGroupLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showMapCategoriesGroupLabel { get { return _showMapCategoriesGroupLabel; } set { _showMapCategoriesGroupLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showControllerNameLabel { get { return _showControllerNameLabel; } set { _showControllerNameLabel = value; InspectorPropertyChanged(true); } }
|
|
public bool showAssignedControllers { get { return _showAssignedControllers; } set { _showAssignedControllers = value; InspectorPropertyChanged(true); } }
|
|
|
|
public System.Action restoreDefaultsDelegate { get { return _restoreDefaultsDelegate; } set { _restoreDefaultsDelegate = value; } }
|
|
|
|
#endregion
|
|
|
|
public bool isOpen {
|
|
get {
|
|
if(!initialized) return references.canvas != null ? references.canvas.gameObject.activeInHierarchy : false;
|
|
return canvas.activeInHierarchy;
|
|
}
|
|
}
|
|
|
|
private bool isFocused {
|
|
get {
|
|
if(!initialized) return false;
|
|
return !windowManager.isWindowOpen;
|
|
}
|
|
}
|
|
|
|
private bool inputAllowed {
|
|
get {
|
|
if(blockInputOnFocusEndTime > Time.unscaledTime) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private int inputGridColumnCount {
|
|
get {
|
|
int count = 1; // action label is always displayed
|
|
if(_showKeyboard) count++;
|
|
if(_showMouse) count++;
|
|
if(_showControllers) count++;
|
|
return count;
|
|
}
|
|
}
|
|
|
|
private int inputGridWidth => _actionLabelWidth + (_showKeyboard ? _keyboardColMaxWidth : 0) + (_showMouse ? _mouseColMaxWidth : 0) + (_showControllers ? _controllerColMaxWidth : 0) + ((inputGridColumnCount - 1) * _inputColumnSpacing);
|
|
|
|
private Player currentPlayer => ReInput.players.GetPlayer(currentPlayerId);
|
|
|
|
private InputCategory currentMapCategory => ReInput.mapping.GetMapCategory(currentMapCategoryId);
|
|
|
|
private MappingSet currentMappingSet {
|
|
get {
|
|
if(currentMapCategoryId < 0) return null;
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
if(_mappingSets[i].mapCategoryId == currentMapCategoryId) return _mappingSets[i];
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private Joystick currentJoystick => ReInput.controllers.GetJoystick(currentJoystickId);
|
|
|
|
private bool isJoystickSelected => currentJoystickId >= 0;
|
|
|
|
private GameObject currentUISelection => EventSystem.current != null ? EventSystem.current.currentSelectedGameObject : null;
|
|
|
|
private bool showSettings => _showInputBehaviorSettings && _inputBehaviorSettings.Length > 0;
|
|
|
|
private bool showMapCategories {
|
|
get {
|
|
if(_mappingSets == null) return false;
|
|
if(_mappingSets.Length <= 1) return false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MonoBehaviour Events
|
|
|
|
void Awake() {
|
|
if(_dontDestroyOnLoad) {
|
|
DontDestroyOnLoad(transform.gameObject);
|
|
}
|
|
|
|
PreInitialize();
|
|
|
|
// Open immediately if instantiated with canvas active
|
|
if(isOpen) {
|
|
Initialize();
|
|
Open(true);
|
|
}
|
|
}
|
|
|
|
void Start() {
|
|
if(_openOnStart) Open(false);
|
|
}
|
|
|
|
void Update() {
|
|
#if UNITY_EDITOR
|
|
CheckEditorRecompile();
|
|
#endif
|
|
|
|
if(!isOpen) return;
|
|
if(!initialized) return;
|
|
|
|
// Make sure the selection is never totally lost for joystick only users
|
|
CheckUISelection();
|
|
}
|
|
|
|
void OnDestroy() {
|
|
// Remove all events
|
|
ReInput.ControllerConnectedEvent -= OnJoystickConnected;
|
|
ReInput.ControllerDisconnectedEvent -= OnJoystickDisconnected;
|
|
ReInput.ControllerPreDisconnectEvent -= OnJoystickPreDisconnect;
|
|
#if UNITY_EDITOR
|
|
ReInput.EditorRecompileEvent -= OnEditorRecompile;
|
|
#endif
|
|
UnsubscribeMenuControlInputEvents();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Initialization
|
|
|
|
private void PreInitialize() {
|
|
if(!ReInput.isReady) {
|
|
Debug.LogError("Rewired Control Mapper: Rewired has not been initialized! Are you missing a Rewired Input Manager in your scene?");
|
|
return;
|
|
}
|
|
|
|
// Set up menu control input events
|
|
SubscribeMenuControlInputEvents();
|
|
}
|
|
|
|
private void Initialize() {
|
|
if(initialized) return;
|
|
if(!ReInput.isReady) return;
|
|
|
|
if(_rewiredInputManager == null) {
|
|
_rewiredInputManager = Object.FindObjectOfType<Rewired.InputManager>();
|
|
if(_rewiredInputManager == null) {
|
|
Debug.LogError("Rewired Control Mapper: A Rewired Input Manager was not assigned in the inspector or found in the current scene! Control Mapper will not function.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Set up singleton
|
|
if(ControlMapper.Instance != null) {
|
|
Debug.LogError("Rewired Control Mapper: Only one ControlMapper can exist at one time!");
|
|
return;
|
|
}
|
|
ControlMapper.Instance = this;
|
|
|
|
// Check inspector vars
|
|
if(prefabs == null || !prefabs.Check()) {
|
|
Debug.LogError("Rewired Control Mapper: All prefabs must be assigned in the inspector!");
|
|
return;
|
|
}
|
|
if(references == null || !references.Check()) {
|
|
Debug.LogError("Rewired Control Mapper: All references must be assigned in the inspector!");
|
|
return;
|
|
}
|
|
references.inputGridLayoutElement = references.inputGridContainer.GetComponent<LayoutElement>();
|
|
if(references.inputGridLayoutElement == null) {
|
|
Debug.LogError("Rewired Control Mapper: InputGridContainer is missing LayoutElement component!");
|
|
return;
|
|
}
|
|
|
|
if(_showKeyboard && _keyboardInputFieldCount < 1) {
|
|
Debug.LogWarning("Rewired Control Mapper: Keyboard Input Fields must be at least 1!");
|
|
_keyboardInputFieldCount = 1;
|
|
}
|
|
if(_showMouse && _mouseInputFieldCount < 1) {
|
|
Debug.LogWarning("Rewired Control Mapper: Mouse Input Fields must be at least 1!");
|
|
_mouseInputFieldCount = 1;
|
|
}
|
|
if(_showControllers && _controllerInputFieldCount < 1) {
|
|
Debug.LogWarning("Rewired Control Mapper: Controller Input Fields must be at least 1!");
|
|
_controllerInputFieldCount = 1;
|
|
}
|
|
if(_maxControllersPerPlayer < 0) {
|
|
Debug.LogWarning("Rewired Control Mapper: Max Controllers Per Player must be at least 0 (no limit)!");
|
|
_maxControllersPerPlayer = 0;
|
|
}
|
|
if(_useThemeSettings && _themeSettings == null) {
|
|
Debug.LogWarning("Rewired Control Mapper: To use theming, Theme Settings must be set in the inspector! Theming has been disabled.");
|
|
_useThemeSettings = false;
|
|
}
|
|
if(_language == null) {
|
|
Debug.LogError("Rawired UI: Language must be set in the inspector!");
|
|
return;
|
|
}
|
|
|
|
// Initialize objects
|
|
_language.Initialize();
|
|
|
|
// Create delegates
|
|
inputFieldActivatedDelegate = OnInputFieldActivated;
|
|
inputFieldInvertToggleStateChangedDelegate = OnInputFieldInvertToggleStateChanged;
|
|
|
|
// Register for events
|
|
ReInput.ControllerConnectedEvent += OnJoystickConnected;
|
|
ReInput.ControllerDisconnectedEvent += OnJoystickDisconnected;
|
|
ReInput.ControllerPreDisconnectEvent += OnJoystickPreDisconnect;
|
|
#if UNITY_EDITOR
|
|
ReInput.EditorRecompileEvent += OnEditorRecompile;
|
|
#endif
|
|
|
|
// Get the number of players
|
|
playerCount = ReInput.players.playerCount;
|
|
|
|
// Store references
|
|
canvas = references.canvas.gameObject;
|
|
|
|
// Create objects
|
|
windowManager = new WindowManager(prefabs.window, prefabs.fader, references.canvas.transform);
|
|
playerButtons = new List<GUIButton>();
|
|
mapCategoryButtons = new List<GUIButton>();
|
|
assignedControllerButtons = new List<GUIButton>();
|
|
miscInstantiatedObjects = new List<GameObject>();
|
|
|
|
// Set default values
|
|
currentMapCategoryId = _mappingSets[0].mapCategoryId;
|
|
|
|
// Draw generated UI items
|
|
Draw();
|
|
|
|
// Create input grid
|
|
CreateInputGrid();
|
|
|
|
// Create the layout
|
|
CreateLayout();
|
|
|
|
// Set up events in fixed UI elements
|
|
SubscribeFixedUISelectionEvents();
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Controller Connect / Disconnect Event Handlers
|
|
|
|
private void OnJoystickConnected(ControllerStatusChangedEventArgs args) {
|
|
if(!initialized) return;
|
|
if(!_showControllers) return;
|
|
ClearVarsOnJoystickChange();
|
|
ForceRefresh();
|
|
}
|
|
|
|
private void OnJoystickDisconnected(ControllerStatusChangedEventArgs args) {
|
|
if(!initialized) return;
|
|
if(!_showControllers) return;
|
|
ClearVarsOnJoystickChange();
|
|
ForceRefresh();
|
|
}
|
|
|
|
private void OnJoystickPreDisconnect(ControllerStatusChangedEventArgs args) {
|
|
if(!initialized) return;
|
|
if(!_showControllers) return;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Main Window Event Handlers
|
|
|
|
// Public - UI Buttons reference and call these directly
|
|
|
|
public void OnButtonActivated(ButtonInfo buttonInfo) {
|
|
if(!initialized) return;
|
|
if(!inputAllowed) return;
|
|
|
|
switch(buttonInfo.identifier) {
|
|
case buttonIdentifier_playerSelection: // player selection
|
|
OnPlayerSelected(buttonInfo.intData, true);
|
|
break;
|
|
case buttonIdentifier_assignedControllerSelection:
|
|
OnControllerSelected(buttonInfo.intData);
|
|
break;
|
|
case buttonIdentifier_removeController:
|
|
OnRemoveCurrentController();
|
|
break;
|
|
case buttonIdentifier_assignController:
|
|
ShowAssignControllerWindow();
|
|
break;
|
|
case buttonIdentifier_calibrateController:
|
|
ShowCalibrateControllerWindow();
|
|
break;
|
|
case buttonIdentifier_editInputBehaviors:
|
|
ShowEditInputBehaviorsWindow();
|
|
break;
|
|
case buttonIdentifier_mapCategorySelection:
|
|
OnMapCategorySelected(buttonInfo.intData, true);
|
|
break;
|
|
case buttonIdentifier_done:
|
|
Close(true);
|
|
break;
|
|
case buttonIdentifier_restoreDefaults:
|
|
OnRestoreDefaults();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void OnInputFieldActivated(InputFieldInfo fieldInfo) {
|
|
if(!initialized) return;
|
|
if(!inputAllowed) return;
|
|
if(currentPlayer == null) return;
|
|
|
|
InputAction action = ReInput.mapping.GetAction(fieldInfo.actionId);
|
|
if(action == null) return;
|
|
|
|
string actionName;
|
|
if(action.type == InputActionType.Button) {
|
|
actionName = action.descriptiveName;
|
|
} else if(action.type == InputActionType.Axis) {
|
|
if(fieldInfo.axisRange == AxisRange.Full) actionName = action.descriptiveName;
|
|
else if(fieldInfo.axisRange == AxisRange.Positive) {
|
|
if(string.IsNullOrEmpty(action.positiveDescriptiveName)) actionName = action.descriptiveName + " +";
|
|
else actionName = action.positiveDescriptiveName;
|
|
} else if(fieldInfo.axisRange == AxisRange.Negative) {
|
|
if(string.IsNullOrEmpty(action.negativeDescriptiveName)) actionName = action.descriptiveName + " -";
|
|
else actionName = action.negativeDescriptiveName;
|
|
} else throw new System.NotImplementedException();
|
|
} else throw new System.NotImplementedException();
|
|
|
|
ControllerMap map = GetControllerMap(fieldInfo.controllerType);
|
|
if(map == null) return;
|
|
|
|
ActionElementMap aem = fieldInfo.actionElementMapId >= 0 ? map.GetElementMap(fieldInfo.actionElementMapId) : null;
|
|
|
|
if(aem != null) { // element replacement dialog
|
|
ShowBeginElementAssignmentReplacementWindow(fieldInfo, action, map, aem, actionName);
|
|
} else { // create new element dialog
|
|
ShowCreateNewElementAssignmentWindow(fieldInfo, action, map, actionName);
|
|
}
|
|
}
|
|
|
|
public void OnInputFieldInvertToggleStateChanged(ToggleInfo toggleInfo, bool newState) {
|
|
if(!initialized) return;
|
|
if(!inputAllowed) return;
|
|
|
|
SetActionAxisInverted(newState, toggleInfo.controllerType, toggleInfo.actionElementMapId);
|
|
}
|
|
|
|
// Private
|
|
|
|
private void OnPlayerSelected(int playerId, bool redraw) {
|
|
if(!initialized) return;
|
|
currentPlayerId = playerId;
|
|
ClearVarsOnPlayerChange();
|
|
if(redraw) Redraw(true, true);
|
|
}
|
|
|
|
private void OnControllerSelected(int joystickId) {
|
|
if(!initialized) return;
|
|
|
|
currentJoystickId = joystickId;
|
|
Redraw(true, true);
|
|
}
|
|
|
|
private void OnRemoveCurrentController() {
|
|
if(currentPlayer == null) return;
|
|
if(currentJoystickId < 0) return;
|
|
RemoveController(currentPlayer, currentJoystickId);
|
|
ClearVarsOnJoystickChange();
|
|
Redraw(false, false);
|
|
}
|
|
|
|
private void OnMapCategorySelected(int id, bool redraw) {
|
|
if(!initialized) return;
|
|
currentMapCategoryId = id;
|
|
if(redraw) Redraw(true, true);
|
|
}
|
|
|
|
private void OnRestoreDefaults() {
|
|
if(!initialized) return;
|
|
ShowRestoreDefaultsWindow();
|
|
}
|
|
|
|
private void OnScreenToggleActionPressed(InputActionEventData data) {
|
|
if(!isOpen) { // mapper is not open, open it
|
|
Open();
|
|
return;
|
|
}
|
|
|
|
if(!initialized) return;
|
|
|
|
if(!isFocused) return; // a window is open, so do nothing
|
|
Close(true); // no window is open, close the mapper
|
|
}
|
|
|
|
private void OnScreenOpenActionPressed(InputActionEventData data) {
|
|
Open();
|
|
}
|
|
|
|
private void OnScreenCloseActionPressed(InputActionEventData data) {
|
|
if(!initialized) return;
|
|
if(!isOpen) return;
|
|
if(!isFocused) return; // a window is open, so do nothing
|
|
Close(true); // no window is open, close the mapper
|
|
}
|
|
|
|
private void OnUniversalCancelActionPressed(InputActionEventData data) {
|
|
if(!initialized) return;
|
|
if(!isOpen) return;
|
|
if(_universalCancelClosesScreen) {
|
|
if(isFocused) {
|
|
Close(true); // close the main screen
|
|
return;
|
|
}
|
|
} else if(isFocused) { // no window is open, so do nothing
|
|
return;
|
|
}
|
|
CloseAllWindows();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Popup Window Button Callbacks
|
|
|
|
private void OnWindowCancel(int windowId) {
|
|
if(!initialized) return;
|
|
if(windowId < 0) return;
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnRemoveElementAssignment(int windowId, ControllerMap map, ActionElementMap aem) {
|
|
if(map == null || aem == null) return;
|
|
map.DeleteElementMap(aem.id);
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnBeginElementAssignment(InputFieldInfo fieldInfo, ControllerMap map, ActionElementMap aem, string actionName) {
|
|
if(fieldInfo == null || map == null) return;
|
|
|
|
// Store the mapping information
|
|
pendingInputMapping = new InputMapping(actionName, fieldInfo, map, aem, fieldInfo.controllerType, fieldInfo.controllerId);
|
|
|
|
switch(fieldInfo.controllerType) {
|
|
case ControllerType.Joystick:
|
|
ShowElementAssignmentPrePollingWindow();
|
|
break;
|
|
case ControllerType.Keyboard:
|
|
ShowElementAssignmentPollingWindow();
|
|
break;
|
|
case ControllerType.Mouse:
|
|
ShowElementAssignmentPollingWindow();
|
|
break;
|
|
default: throw new System.NotImplementedException();
|
|
}
|
|
}
|
|
|
|
private void OnControllerAssignmentConfirmed(int windowId, Player player, int controllerId) {
|
|
if(windowId < 0 || player == null || controllerId < 0) return;
|
|
|
|
// Assign the joystick
|
|
AssignController(player, controllerId);
|
|
|
|
// Close the window
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnMouseAssignmentConfirmed(int windowId, Player player) {
|
|
if(windowId < 0 || player == null) return;
|
|
|
|
// Remove mouse from all normal Players
|
|
IList<Player> playes = ReInput.players.Players;
|
|
for(int i = 0; i < playes.Count; i++) {
|
|
if(playes[i] == player) continue; // skip self
|
|
playes[i].controllers.hasMouse = false;
|
|
}
|
|
|
|
// Assign the controller
|
|
player.controllers.hasMouse = true;
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnElementAssignmentConflictReplaceConfirmed(int windowId, InputMapping mapping, ElementAssignment assignment, bool skipOtherPlayers) {
|
|
if(currentPlayer == null || mapping == null) return;
|
|
ElementAssignmentConflictCheck conflictCheck;
|
|
if(!CreateConflictCheck(mapping, assignment, out conflictCheck)) {
|
|
Debug.LogError("Rewired Control Mapper: Error creating conflict check!");
|
|
CloseWindow(windowId);
|
|
return;
|
|
}
|
|
|
|
// Remove conflicting mappings
|
|
if(skipOtherPlayers) { // skip other players, only remove from system and self
|
|
ReInput.players.SystemPlayer.controllers.conflictChecking.RemoveElementAssignmentConflicts(conflictCheck);
|
|
currentPlayer.controllers.conflictChecking.RemoveElementAssignmentConflicts(conflictCheck);
|
|
} else { // remove from all players
|
|
ReInput.controllers.conflictChecking.RemoveElementAssignmentConflicts(conflictCheck);
|
|
}
|
|
|
|
// Create the new mapping or replace existing
|
|
mapping.map.ReplaceOrCreateElementMap(assignment);
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnElementAssignmentAddConfirmed(int windowId, InputMapping mapping, ElementAssignment assignment) {
|
|
if(currentPlayer == null || mapping == null) return;
|
|
|
|
// Create the new mapping or replace existing
|
|
mapping.map.ReplaceOrCreateElementMap(assignment);
|
|
CloseWindow(windowId);
|
|
}
|
|
|
|
private void OnRestoreDefaultsConfirmed(int windowId) {
|
|
if(_restoreDefaultsDelegate == null) {
|
|
IList<Player> players = ReInput.players.Players;
|
|
for(int i = 0; i < players.Count; i++) {
|
|
Player player = players[i];
|
|
if(_showControllers) player.controllers.maps.LoadDefaultMaps(ControllerType.Joystick);
|
|
if(_showKeyboard) player.controllers.maps.LoadDefaultMaps(ControllerType.Keyboard);
|
|
if(_showMouse) player.controllers.maps.LoadDefaultMaps(ControllerType.Mouse);
|
|
}
|
|
}
|
|
CloseWindow(windowId);
|
|
if(_restoreDefaultsDelegate != null) {
|
|
_restoreDefaultsDelegate();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Popup Window Update Callbacks
|
|
|
|
private void OnAssignControllerWindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
InputPollingStopped();
|
|
CloseWindow(windowId); // close the window
|
|
return;
|
|
}
|
|
|
|
// Poll for controller element down
|
|
ControllerPollingInfo info = ReInput.controllers.polling.PollAllControllersOfTypeForFirstElementDown(ControllerType.Joystick);
|
|
if(info.success) {
|
|
|
|
InputPollingStopped();
|
|
|
|
// Check if another Player has this controller already
|
|
if(ReInput.controllers.IsControllerAssigned(ControllerType.Joystick, info.controllerId) &&
|
|
!currentPlayer.controllers.ContainsController(ControllerType.Joystick, info.controllerId)) { // another player has the controller
|
|
ShowControllerAssignmentConflictWindow(info.controllerId);
|
|
return;
|
|
}
|
|
|
|
// Assign the controller to this Player
|
|
OnControllerAssignmentConfirmed(windowId, currentPlayer, info.controllerId);
|
|
return;
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
}
|
|
|
|
private void OnElementAssignmentPrePollingWindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingInputMapping == null) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
goto Success; // when timer expires, go to next step to support no-button controllers like pedals
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
|
|
ControllerPollingInfo pollingInfo;
|
|
|
|
switch(pendingInputMapping.controllerType) {
|
|
case ControllerType.Joystick:
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
pollingInfo = ReInput.controllers.polling.PollControllerForFirstButtonDown(pendingInputMapping.controllerType, currentJoystick.id);
|
|
break;
|
|
case ControllerType.Keyboard:
|
|
case ControllerType.Mouse:
|
|
pollingInfo = ReInput.controllers.polling.PollControllerForFirstButtonDown(pendingInputMapping.controllerType, 0);
|
|
break;
|
|
default: throw new System.NotImplementedException();
|
|
}
|
|
|
|
if(!pollingInfo.success) return;
|
|
|
|
Success:
|
|
ShowElementAssignmentPollingWindow();
|
|
}
|
|
|
|
private void OnJoystickElementAssignmentPollingWindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingInputMapping == null) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
InputPollingStopped();
|
|
CloseWindow(windowId); // close the window
|
|
return;
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
|
|
ControllerPollingInfo pollingInfo = ReInput.controllers.polling.PollControllerForFirstElementDown(ControllerType.Joystick, currentJoystick.id);
|
|
if(!pollingInfo.success) return;
|
|
|
|
// Verify that this assignment is allowed
|
|
if(!IsAllowedAssignment(pendingInputMapping, pollingInfo)) return;
|
|
|
|
ElementAssignment assignment = pendingInputMapping.ToElementAssignment(pollingInfo);
|
|
|
|
if(!HasElementAssignmentConflicts(currentPlayer, pendingInputMapping, assignment, false)) {
|
|
pendingInputMapping.map.ReplaceOrCreateElementMap(assignment);
|
|
InputPollingStopped();
|
|
CloseWindow(windowId);
|
|
} else {
|
|
InputPollingStopped();
|
|
ShowElementAssignmentConflictWindow(assignment, false);
|
|
}
|
|
}
|
|
|
|
private void OnKeyboardElementAssignmentPollingWindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingInputMapping == null) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
InputPollingStopped();
|
|
CloseWindow(windowId); // close the window
|
|
return;
|
|
}
|
|
|
|
ControllerPollingInfo pollingInfo;
|
|
ModifierKeyFlags modifierFlags;
|
|
bool modifierKeyPressed;
|
|
string label;
|
|
|
|
PollKeyboardForAssignment(out pollingInfo, out modifierKeyPressed, out modifierFlags, out label);
|
|
|
|
if(modifierKeyPressed) window.timer.Start(_inputAssignmentTimeout); // reset close timer if a modifier key is pressed
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(modifierKeyPressed ? string.Empty : Mathf.CeilToInt(window.timer.remaining).ToString(), 2);
|
|
|
|
// Show the modifier key label
|
|
window.SetContentText(label, 1);
|
|
|
|
if(!pollingInfo.success) return;
|
|
|
|
// Verify that this assignment is allowed
|
|
if(!IsAllowedAssignment(pendingInputMapping, pollingInfo)) return;
|
|
|
|
ElementAssignment assignment = pendingInputMapping.ToElementAssignment(pollingInfo, modifierFlags);
|
|
|
|
if(!HasElementAssignmentConflicts(currentPlayer, pendingInputMapping, assignment, false)) {
|
|
pendingInputMapping.map.ReplaceOrCreateElementMap(assignment);
|
|
InputPollingStopped();
|
|
CloseWindow(windowId);
|
|
} else {
|
|
InputPollingStopped();
|
|
ShowElementAssignmentConflictWindow(assignment, false);
|
|
}
|
|
}
|
|
|
|
private void OnMouseElementAssignmentPollingWindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingInputMapping == null) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
InputPollingStopped();
|
|
CloseWindow(windowId); // close the window
|
|
return;
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
|
|
ControllerPollingInfo pollingInfo;
|
|
|
|
if(_ignoreMouseXAxisAssignment || _ignoreMouseYAxisAssignment) {
|
|
pollingInfo = new ControllerPollingInfo();
|
|
foreach(ControllerPollingInfo p in ReInput.controllers.polling.PollControllerForAllElementsDown(ControllerType.Mouse, 0)) {
|
|
if(p.elementType == ControllerElementType.Axis) {
|
|
if(_ignoreMouseXAxisAssignment && p.elementIndex == 0) continue; // skip X
|
|
else if(_ignoreMouseYAxisAssignment && p.elementIndex == 1) continue; // skip Y
|
|
}
|
|
pollingInfo = p;
|
|
break;
|
|
}
|
|
} else {
|
|
pollingInfo = ReInput.controllers.polling.PollControllerForFirstElementDown(ControllerType.Mouse, 0);
|
|
}
|
|
if(!pollingInfo.success) return;
|
|
|
|
// Verify that the assignment is allowed
|
|
if(!IsAllowedAssignment(pendingInputMapping, pollingInfo)) return;
|
|
|
|
ElementAssignment assignment = pendingInputMapping.ToElementAssignment(pollingInfo);
|
|
|
|
if(!HasElementAssignmentConflicts(currentPlayer, pendingInputMapping, assignment, true)) {
|
|
pendingInputMapping.map.ReplaceOrCreateElementMap(assignment);
|
|
InputPollingStopped();
|
|
CloseWindow(windowId);
|
|
} else {
|
|
InputPollingStopped();
|
|
ShowElementAssignmentConflictWindow(assignment, true);
|
|
}
|
|
}
|
|
|
|
private void OnCalibrateAxisStep1WindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingAxisCalibration == null || !pendingAxisCalibration.isValid) return;
|
|
|
|
InputPollingStarted();
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
goto Success; // when timer expires, go to next step to support no-button controllers like pedals
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
|
|
// Poll for button press for confirmation
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
ControllerPollingInfo pollingInfo = pendingAxisCalibration.joystick.PollForFirstButtonDown();
|
|
|
|
if(!pollingInfo.success) return;
|
|
|
|
Success:
|
|
pendingAxisCalibration.RecordZero(); // record zero value
|
|
CloseWindow(windowId); // close this window
|
|
ShowCalibrateAxisStep2Window();
|
|
}
|
|
|
|
private void OnCalibrateAxisStep2WindowUpdate(int windowId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = windowManager.GetWindow(windowId);
|
|
if(windowId < 0) return;
|
|
|
|
if(pendingAxisCalibration == null || !pendingAxisCalibration.isValid) return;
|
|
|
|
// Check the close window timer
|
|
if(window.timer.finished) { // timer expired
|
|
goto Success; // when timer expires, go to next step to support no-button controllers like pedals
|
|
}
|
|
|
|
// Show the window close timer
|
|
window.SetContentText(Mathf.CeilToInt(window.timer.remaining).ToString(), 1);
|
|
|
|
// Record min/max values as user moves the axis
|
|
pendingAxisCalibration.RecordMinMax();
|
|
|
|
// Poll for button press for confirmation
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
ControllerPollingInfo pollingInfo = pendingAxisCalibration.joystick.PollForFirstButtonDown();
|
|
|
|
if(!pollingInfo.success) return;
|
|
|
|
Success:
|
|
EndAxisCalibration(); // commit the calibration
|
|
InputPollingStopped();
|
|
CloseWindow(windowId); // close this window
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Show Specific Popup Windows
|
|
|
|
private void ShowAssignControllerWindow() {
|
|
if(currentPlayer == null) return;
|
|
if(ReInput.controllers.joystickCount == 0) return;
|
|
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
window.SetUpdateCallback(OnAssignControllerWindowUpdate);
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.assignControllerWindowTitle);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.assignControllerWindowMessage);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.timer.Start(_controllerAssignmentTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowControllerAssignmentConflictWindow(int controllerId) {
|
|
if(currentPlayer == null) return;
|
|
if(ReInput.controllers.joystickCount == 0) return;
|
|
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
string otherPlayer = string.Empty;
|
|
IList<Player> players = ReInput.players.Players;
|
|
for(int i = 0; i < players.Count; i++) {
|
|
if(players[i] == currentPlayer) continue; // skip self
|
|
if(!players[i].controllers.ContainsController(ControllerType.Joystick, controllerId)) continue;
|
|
otherPlayer = players[i].descriptiveName;
|
|
break;
|
|
}
|
|
|
|
Joystick joystick = ReInput.controllers.GetJoystick(controllerId);
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.controllerAssignmentConflictWindowTitle);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.GetControllerAssignmentConflictWindowMessage(joystick.name, otherPlayer, currentPlayer.descriptiveName));
|
|
UnityAction cancelCallback = () => { OnWindowCancel(window.id); };
|
|
window.cancelCallback = cancelCallback;
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomLeft, UI.UIAnchor.BottomLeft, Vector2.zero, _language.yes, () => { OnControllerAssignmentConfirmed(window.id, currentPlayer, controllerId); }, cancelCallback, true);
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomRight, UI.UIAnchor.BottomRight, Vector2.zero, _language.no, cancelCallback, cancelCallback, false);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowBeginElementAssignmentReplacementWindow(InputFieldInfo fieldInfo, InputAction action, ControllerMap map, ActionElementMap aem, string actionName) {
|
|
GUIInputField field = inputGrid.GetGUIInputField(currentMapCategoryId, action.id, fieldInfo.axisRange, fieldInfo.controllerType, fieldInfo.intData);
|
|
if(field == null) return;
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, actionName);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), field.GetLabel());
|
|
UnityAction cancelCallback = () => { OnWindowCancel(window.id); };
|
|
window.cancelCallback = cancelCallback;
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomLeft, UI.UIAnchor.BottomLeft, Vector2.zero, _language.replace, () => { OnBeginElementAssignment(fieldInfo, map, aem, actionName); }, cancelCallback, true);
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, Vector2.zero, _language.remove, () => { OnRemoveElementAssignment(window.id, map, aem); }, cancelCallback, false);
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomRight, UI.UIAnchor.BottomRight, Vector2.zero, _language.cancel, cancelCallback, cancelCallback, false);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowCreateNewElementAssignmentWindow(InputFieldInfo fieldInfo, InputAction action, ControllerMap map, string actionName) {
|
|
GUIInputField field = inputGrid.GetGUIInputField(currentMapCategoryId, action.id, fieldInfo.axisRange, fieldInfo.controllerType, fieldInfo.intData);
|
|
if(field == null) return;
|
|
OnBeginElementAssignment(fieldInfo, map, null, actionName);
|
|
}
|
|
|
|
private void ShowElementAssignmentPrePollingWindow() {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, pendingInputMapping.actionName);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.elementAssignmentPrePollingWindowMessage);
|
|
if(prefabs.centerStickGraphic != null) window.AddContentImage(prefabs.centerStickGraphic, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, new Vector2(0, 40));
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnElementAssignmentPrePollingWindowUpdate);
|
|
window.timer.Start(_preInputAssignmentTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowElementAssignmentPollingWindow() {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
switch(pendingInputMapping.controllerType) {
|
|
case ControllerType.Joystick:
|
|
ShowJoystickElementAssignmentPollingWindow();
|
|
break;
|
|
case ControllerType.Keyboard:
|
|
ShowKeyboardElementAssignmentPollingWindow();
|
|
break;
|
|
case ControllerType.Mouse:
|
|
if(currentPlayer.controllers.hasMouse) ShowMouseElementAssignmentPollingWindow();
|
|
else ShowMouseAssignmentConflictWindow();
|
|
break;
|
|
default: throw new System.NotImplementedException();
|
|
}
|
|
}
|
|
|
|
private void ShowJoystickElementAssignmentPollingWindow() {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
string message = pendingInputMapping.axisRange == AxisRange.Full && _showFullAxisInputFields && !_showSplitAxisInputFields ?
|
|
_language.GetJoystickElementAssignmentPollingWindowMessage_FullAxisFieldOnly(pendingInputMapping.actionName) :
|
|
_language.GetJoystickElementAssignmentPollingWindowMessage(pendingInputMapping.actionName);
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, pendingInputMapping.actionName);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), message);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnJoystickElementAssignmentPollingWindowUpdate);
|
|
window.timer.Start(_inputAssignmentTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowKeyboardElementAssignmentPollingWindow() {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, pendingInputMapping.actionName);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.GetKeyboardElementAssignmentPollingWindowMessage(pendingInputMapping.actionName));
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -(window.GetContentTextHeight(0) + 50.0f)), "");
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnKeyboardElementAssignmentPollingWindowUpdate);
|
|
window.timer.Start(_inputAssignmentTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowMouseElementAssignmentPollingWindow() {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
string message = pendingInputMapping.axisRange == AxisRange.Full && _showFullAxisInputFields && !_showSplitAxisInputFields ?
|
|
_language.GetMouseElementAssignmentPollingWindowMessage_FullAxisFieldOnly(pendingInputMapping.actionName) :
|
|
_language.GetMouseElementAssignmentPollingWindowMessage(pendingInputMapping.actionName);
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, pendingInputMapping.actionName);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), message);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnMouseElementAssignmentPollingWindowUpdate);
|
|
window.timer.Start(_inputAssignmentTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowElementAssignmentConflictWindow(ElementAssignment assignment, bool skipOtherPlayers) {
|
|
if(pendingInputMapping == null) return;
|
|
|
|
// Determine what kind of conflict we had
|
|
bool blocked = IsBlockingAssignmentConflict(pendingInputMapping, assignment, skipOtherPlayers);
|
|
|
|
string message = blocked ?
|
|
_language.GetElementAlreadyInUseBlocked(pendingInputMapping.elementName) :
|
|
_language.GetElementAlreadyInUseCanReplace(pendingInputMapping.elementName, _allowElementAssignmentConflicts);
|
|
|
|
// Open window and set properties
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.elementAssignmentConflictWindowMessage);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), message);
|
|
|
|
UnityAction cancelCallback = () => { OnWindowCancel(window.id); };
|
|
window.cancelCallback = cancelCallback;
|
|
|
|
if(blocked) {
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, Vector2.zero, _language.okay, cancelCallback, cancelCallback, true);
|
|
} else {
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomLeft, UI.UIAnchor.BottomLeft, Vector2.zero, _language.replace, () => { OnElementAssignmentConflictReplaceConfirmed(window.id, pendingInputMapping, assignment, skipOtherPlayers); }, cancelCallback, true);
|
|
|
|
if(_allowElementAssignmentConflicts) {
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, Vector2.zero, _language.add, () => { OnElementAssignmentAddConfirmed(window.id, pendingInputMapping, assignment); }, cancelCallback, false);
|
|
}
|
|
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomRight, UI.UIAnchor.BottomRight, Vector2.zero, _language.cancel, cancelCallback, cancelCallback, false);
|
|
}
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowMouseAssignmentConflictWindow() {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = OpenWindow(true);
|
|
if(window == null) return;
|
|
|
|
string otherPlayer = string.Empty;
|
|
IList<Player> players = ReInput.players.Players;
|
|
for(int i = 0; i < players.Count; i++) {
|
|
if(players[i] == currentPlayer) continue; // skip self
|
|
if(!players[i].controllers.hasMouse) continue;
|
|
otherPlayer = players[i].descriptiveName;
|
|
break;
|
|
}
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.mouseAssignmentConflictWindowTitle);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.GetMouseAssignmentConflictWindowMessage(otherPlayer, currentPlayer.descriptiveName));
|
|
UnityAction cancelCallback = () => { OnWindowCancel(window.id); };
|
|
window.cancelCallback = cancelCallback;
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomLeft, UI.UIAnchor.BottomLeft, Vector2.zero, _language.yes, () => { OnMouseAssignmentConfirmed(window.id, currentPlayer); }, cancelCallback, true);
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomRight, UI.UIAnchor.BottomRight, Vector2.zero, _language.no, cancelCallback, cancelCallback, false);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowCalibrateControllerWindow() {
|
|
if(currentPlayer == null) return;
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
|
|
CalibrationWindow window = OpenWindow(prefabs.calibrationWindow, "CalibrationWindow", true) as CalibrationWindow;
|
|
if(window == null) return;
|
|
|
|
Joystick joystick = currentJoystick;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.calibrateControllerWindowTitle);
|
|
window.SetJoystick(currentPlayer.id, joystick);
|
|
window.SetButtonCallback(CalibrationWindow.ButtonIdentifier.Done, CloseWindow);
|
|
window.SetButtonCallback(CalibrationWindow.ButtonIdentifier.Calibrate, StartAxisCalibration);
|
|
window.SetButtonCallback(CalibrationWindow.ButtonIdentifier.Cancel, CloseWindow);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowCalibrateAxisStep1Window() {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = OpenWindow(false);
|
|
if(window == null) return;
|
|
|
|
if(pendingAxisCalibration == null) return;
|
|
|
|
Joystick joystick = pendingAxisCalibration.joystick;
|
|
if(joystick.axisCount == 0) return;
|
|
|
|
int axisIndex = pendingAxisCalibration.axisIndex;
|
|
if(axisIndex < 0 || axisIndex >= joystick.axisCount) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.calibrateAxisStep1WindowTitle);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.GetCalibrateAxisStep1WindowMessage(joystick.AxisElementIdentifiers[axisIndex].name));
|
|
if(prefabs.centerStickGraphic != null) window.AddContentImage(prefabs.centerStickGraphic, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, new Vector2(0, 40));
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnCalibrateAxisStep1WindowUpdate);
|
|
window.timer.Start(_axisCalibrationTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowCalibrateAxisStep2Window() {
|
|
if(currentPlayer == null) return;
|
|
|
|
Window window = OpenWindow(false);
|
|
if(window == null) return;
|
|
|
|
if(pendingAxisCalibration == null) return;
|
|
|
|
Joystick joystick = pendingAxisCalibration.joystick;
|
|
if(joystick.axisCount == 0) return;
|
|
|
|
int axisIndex = pendingAxisCalibration.axisIndex;
|
|
if(axisIndex < 0 || axisIndex >= joystick.axisCount) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.calibrateAxisStep2WindowTitle);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), _language.GetCalibrateAxisStep2WindowMessage(joystick.AxisElementIdentifiers[axisIndex].name));
|
|
if(prefabs.moveStickGraphic != null) window.AddContentImage(prefabs.moveStickGraphic, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomCenter, new Vector2(0, 40));
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.BottomCenter, UI.UIAnchor.BottomHStretch, Vector2.zero, "");
|
|
window.SetUpdateCallback(OnCalibrateAxisStep2WindowUpdate);
|
|
window.timer.Start(_axisCalibrationTimeout);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowEditInputBehaviorsWindow() {
|
|
if(currentPlayer == null) return;
|
|
if(_inputBehaviorSettings == null) return;
|
|
|
|
InputBehaviorWindow window = OpenWindow(prefabs.inputBehaviorsWindow, "EditInputBehaviorsWindow", true) as InputBehaviorWindow;
|
|
if(window == null) return;
|
|
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, _language.inputBehaviorSettingsWindowTitle);
|
|
window.SetData(currentPlayer.id, _inputBehaviorSettings);
|
|
window.SetButtonCallback(InputBehaviorWindow.ButtonIdentifier.Done, CloseWindow);
|
|
window.SetButtonCallback(InputBehaviorWindow.ButtonIdentifier.Cancel, CloseWindow);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void ShowRestoreDefaultsWindow() {
|
|
if(currentPlayer == null) return;
|
|
OpenModal(
|
|
_language.restoreDefaultsWindowTitle,
|
|
_language.restoreDefaultsWindowMessage,
|
|
_language.yes,
|
|
OnRestoreDefaultsConfirmed,
|
|
_language.no,
|
|
OnWindowCancel,
|
|
true
|
|
);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Input Field Grid
|
|
|
|
private void CreateInputGrid() {
|
|
InitializeInputGrid();
|
|
|
|
// Create the column groups
|
|
CreateHeaderLabels();
|
|
CreateActionLabelColumn();
|
|
CreateKeyboardInputFieldColumn();
|
|
CreateMouseInputFieldColumn();
|
|
CreateControllerInputFieldColumn();
|
|
|
|
// Create GUI Elements
|
|
CreateInputActionLabels();
|
|
CreateInputFields();
|
|
|
|
// Disable all GUI elements initially
|
|
inputGrid.HideAll();
|
|
|
|
// Fix Unity scroll bar bug
|
|
ResetInputGridScrollBar();
|
|
}
|
|
|
|
private void InitializeInputGrid() {
|
|
if(inputGrid == null) inputGrid = new InputGrid();
|
|
else inputGrid.ClearAll();
|
|
|
|
// Add all user-assignable actions to the grid
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
MappingSet set = _mappingSets[i];
|
|
if(set == null || !set.isValid) continue;
|
|
|
|
InputMapCategory mapCat = ReInput.mapping.GetMapCategory(set.mapCategoryId);
|
|
if(mapCat == null) continue;
|
|
if(!mapCat.userAssignable) continue;
|
|
|
|
inputGrid.AddMapCategory(set.mapCategoryId);
|
|
|
|
if(set.actionListMode == MappingSet.ActionListMode.ActionCategory) { // list actions in action categories
|
|
|
|
IList<int> actionCategoryIds = set.actionCategoryIds;
|
|
for(int j = 0; j < actionCategoryIds.Count; j++) {
|
|
int actionCatId = actionCategoryIds[j];
|
|
InputCategory actionCat = ReInput.mapping.GetActionCategory(actionCatId);
|
|
if(actionCat == null) continue;
|
|
if(!actionCat.userAssignable) continue;
|
|
|
|
inputGrid.AddActionCategory(set.mapCategoryId, actionCatId); // add the action category
|
|
|
|
foreach(InputAction action in ReInput.mapping.UserAssignableActionsInCategory(actionCatId)) {
|
|
if(action.type == InputActionType.Axis) {
|
|
if(_showFullAxisInputFields) inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Full);
|
|
if(_showSplitAxisInputFields) {
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Positive);
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Negative);
|
|
}
|
|
} else if(action.type == InputActionType.Button) {
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Positive);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} else { // list individual user-assigned actions
|
|
|
|
IList<int> actionIds = set.actionIds;
|
|
for(int j = 0; j < actionIds.Count; j++) {
|
|
InputAction action = ReInput.mapping.GetAction(actionIds[j]);
|
|
if(action == null) continue;
|
|
|
|
if(action.type == InputActionType.Axis) {
|
|
if(_showFullAxisInputFields) inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Full);
|
|
if(_showSplitAxisInputFields) {
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Positive);
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Negative);
|
|
}
|
|
} else if(action.type == InputActionType.Button) {
|
|
inputGrid.AddAction(set.mapCategoryId, action, AxisRange.Positive);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set column H-spacing
|
|
references.inputGridInnerGroup.GetComponent<HorizontalLayoutGroup>().spacing = _inputColumnSpacing;
|
|
|
|
// Set grid layout width
|
|
references.inputGridLayoutElement.flexibleWidth = 0; // disable flexible width
|
|
references.inputGridLayoutElement.preferredWidth = inputGridWidth;
|
|
}
|
|
|
|
private void RefreshInputGridStructure() {
|
|
if(currentMappingSet == null) return;
|
|
inputGrid.HideAll();
|
|
inputGrid.Show(currentMappingSet.mapCategoryId);
|
|
// Resize the main container to fit the elements
|
|
references.inputGridInnerGroup.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, inputGrid.GetColumnHeight(currentMappingSet.mapCategoryId));
|
|
}
|
|
|
|
// Layout
|
|
|
|
private void CreateHeaderLabels() {
|
|
GUILabel label;
|
|
|
|
// Actions column header
|
|
references.inputGridHeader1 = CreateNewColumnGroup("ActionsHeader", references.inputGridHeadersGroup, _actionLabelWidth).transform;
|
|
CreateLabel(prefabs.inputGridHeaderLabel, _language.actionColumnLabel, references.inputGridHeader1, Vector2.zero);
|
|
|
|
// Keyboard column header
|
|
if(_showKeyboard) {
|
|
references.inputGridHeader2 = CreateNewColumnGroup("KeybordHeader", references.inputGridHeadersGroup, _keyboardColMaxWidth).transform;
|
|
label = CreateLabel(prefabs.inputGridHeaderLabel, _language.keyboardColumnLabel, references.inputGridHeader2, Vector2.zero);
|
|
label.SetTextAlignment(TextAnchor.MiddleCenter);
|
|
}
|
|
|
|
// Mouse column header
|
|
if(_showMouse) {
|
|
references.inputGridHeader3 = CreateNewColumnGroup("MouseHeader", references.inputGridHeadersGroup, _mouseColMaxWidth).transform;
|
|
label = CreateLabel(prefabs.inputGridHeaderLabel, _language.mouseColumnLabel, references.inputGridHeader3, Vector2.zero);
|
|
label.SetTextAlignment(TextAnchor.MiddleCenter);
|
|
}
|
|
|
|
// Controller column header
|
|
if(_showControllers) {
|
|
references.inputGridHeader4 = CreateNewColumnGroup("ControllerHeader", references.inputGridHeadersGroup, _controllerColMaxWidth).transform;
|
|
label = CreateLabel(prefabs.inputGridHeaderLabel, _language.controllerColumnLabel, references.inputGridHeader4, Vector2.zero);
|
|
label.SetTextAlignment(TextAnchor.MiddleCenter);
|
|
}
|
|
}
|
|
|
|
private void CreateActionLabelColumn() {
|
|
Transform columnXform = CreateNewColumnGroup("ActionLabelColumn", references.inputGridInnerGroup, _actionLabelWidth).transform;
|
|
references.inputGridActionColumn = columnXform;
|
|
}
|
|
|
|
private void CreateKeyboardInputFieldColumn() {
|
|
if(!_showKeyboard) return;
|
|
CreateInputFieldColumn("KeyboardColumn", ControllerType.Keyboard, _keyboardColMaxWidth, _keyboardInputFieldCount, true);
|
|
}
|
|
|
|
private void CreateMouseInputFieldColumn() {
|
|
if(!_showMouse) return;
|
|
CreateInputFieldColumn("MouseColumn", ControllerType.Mouse, _mouseColMaxWidth, _mouseInputFieldCount, false);
|
|
}
|
|
|
|
private void CreateControllerInputFieldColumn() {
|
|
if(!_showControllers) return;
|
|
CreateInputFieldColumn("ControllerColumn", ControllerType.Joystick, _controllerColMaxWidth, _controllerInputFieldCount, false);
|
|
}
|
|
|
|
private void CreateInputFieldColumn(string name, ControllerType controllerType, int maxWidth, int cols, bool disableFullAxis) {
|
|
Transform columnXform = CreateNewColumnGroup(name, references.inputGridInnerGroup, maxWidth).transform;
|
|
switch(controllerType) {
|
|
case ControllerType.Joystick:
|
|
references.inputGridControllerColumn = columnXform;
|
|
break;
|
|
case ControllerType.Keyboard:
|
|
references.inputGridKeyboardColumn = columnXform;
|
|
break;
|
|
case ControllerType.Mouse:
|
|
references.inputGridMouseColumn = columnXform;
|
|
break;
|
|
default: throw new System.NotImplementedException();
|
|
}
|
|
}
|
|
|
|
// Create the individual elements
|
|
|
|
private void CreateInputActionLabels() {
|
|
|
|
Transform columnXform = references.inputGridActionColumn;
|
|
|
|
for(int mappingSetIndex = 0; mappingSetIndex < _mappingSets.Length; mappingSetIndex++) {
|
|
MappingSet set = _mappingSets[mappingSetIndex];
|
|
if(set == null || !set.isValid) continue;
|
|
|
|
int yPos = 0;
|
|
|
|
// Create the labels
|
|
if(set.actionListMode == MappingSet.ActionListMode.ActionCategory) { // list all actions in categories
|
|
|
|
int categoryCount = 0;
|
|
IList<int> actionCategoryIds = set.actionCategoryIds;
|
|
|
|
for(int i = 0; i < actionCategoryIds.Count; i++) {
|
|
InputCategory category = ReInput.mapping.GetActionCategory(actionCategoryIds[i]);
|
|
if(category == null) continue;
|
|
if(!category.userAssignable) continue; // action category isn't user assignable
|
|
|
|
// Count actions first
|
|
int count = CountIEnumerable<InputAction>(ReInput.mapping.UserAssignableActionsInCategory(category.id));
|
|
if(count == 0) continue; // no actions so skip category
|
|
|
|
// Draw category label
|
|
if(_showActionCategoryLabels) {
|
|
if(categoryCount > 0) yPos -= _inputRowCategorySpacing; // extra space above category
|
|
GUILabel label = CreateLabel(category.descriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.SetFontStyle(FontStyle.Bold);
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionCategoryLabel(set.mapCategoryId, category.id, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
// Draw Action labels
|
|
foreach(InputAction action in ReInput.mapping.UserAssignableActionsInCategory(category.id, true)) {
|
|
|
|
GUILabel label;
|
|
if(action.type == InputActionType.Axis) {
|
|
|
|
if(_showFullAxisInputFields) {
|
|
label = CreateLabel(action.descriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Full, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
if(_showSplitAxisInputFields) {
|
|
string positiveDescriptiveName = !string.IsNullOrEmpty(action.positiveDescriptiveName) ? action.positiveDescriptiveName : action.descriptiveName + " +";
|
|
label = CreateLabel(positiveDescriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Positive, label);
|
|
yPos -= _inputRowHeight;
|
|
|
|
string negativeDescriptiveName = !string.IsNullOrEmpty(action.negativeDescriptiveName) ? action.negativeDescriptiveName : action.descriptiveName + " -";
|
|
label = CreateLabel(negativeDescriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Negative, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
} else if(action.type == InputActionType.Button) {
|
|
label = CreateLabel(action.descriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Positive, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
}
|
|
categoryCount++;
|
|
}
|
|
|
|
} else { // list only individual actions defined by the user
|
|
|
|
IList<int> actionIds = set.actionIds;
|
|
|
|
for(int i = 0; i < actionIds.Count; i++) {
|
|
InputAction action = ReInput.mapping.GetAction(actionIds[i]);
|
|
if(action == null) continue;
|
|
if(!action.userAssignable) continue; // action isn't user assignable
|
|
|
|
InputCategory category = ReInput.mapping.GetActionCategory(action.categoryId);
|
|
if(category == null) continue;
|
|
if(!category.userAssignable) continue; // action category isn't user assignable
|
|
|
|
// Draw Action labels
|
|
GUILabel label;
|
|
if(action.type == InputActionType.Axis) {
|
|
|
|
if(_showFullAxisInputFields) {
|
|
label = CreateLabel(action.descriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Full, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
if(_showSplitAxisInputFields) {
|
|
label = CreateLabel(action.positiveDescriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Positive, label);
|
|
yPos -= _inputRowHeight;
|
|
|
|
label = CreateLabel(action.negativeDescriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Negative, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
} else if(action.type == InputActionType.Button) {
|
|
label = CreateLabel(action.descriptiveName, columnXform, new Vector2(0, yPos));
|
|
label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
inputGrid.AddActionLabel(set.mapCategoryId, action.id, AxisRange.Positive, label);
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
}
|
|
}
|
|
|
|
inputGrid.SetColumnHeight(set.mapCategoryId, -yPos); // store the column height for this map category
|
|
}
|
|
}
|
|
|
|
private void CreateInputFields() {
|
|
if(_showControllers) CreateInputFields(references.inputGridControllerColumn, ControllerType.Joystick, _controllerColMaxWidth, _controllerInputFieldCount, false);
|
|
if(_showKeyboard) CreateInputFields(references.inputGridKeyboardColumn, ControllerType.Keyboard, _keyboardColMaxWidth, _keyboardInputFieldCount, true);
|
|
if(_showMouse) CreateInputFields(references.inputGridMouseColumn, ControllerType.Mouse, _mouseColMaxWidth, _mouseInputFieldCount, false);
|
|
}
|
|
|
|
private void CreateInputFields(Transform columnXform, ControllerType controllerType, int maxWidth, int cols, bool disableFullAxis) {
|
|
for(int mappingSetIndex = 0; mappingSetIndex < _mappingSets.Length; mappingSetIndex++) {
|
|
MappingSet set = _mappingSets[mappingSetIndex];
|
|
if(set == null || !set.isValid) continue;
|
|
|
|
// Create input field buttons
|
|
int fieldWidth = maxWidth / cols;
|
|
int yPos = 0;
|
|
int categoryCount = 0;
|
|
|
|
// Create the labels
|
|
if(set.actionListMode == MappingSet.ActionListMode.ActionCategory) { // list all actions in categories
|
|
|
|
IList<int> actionCategoryIds = set.actionCategoryIds;
|
|
for(int i = 0; i < actionCategoryIds.Count; i++) {
|
|
InputCategory category = ReInput.mapping.GetActionCategory(actionCategoryIds[i]);
|
|
if(category == null) continue;
|
|
if(!category.userAssignable) continue; // action category isn't user assignable
|
|
|
|
// Count actions first
|
|
int count = CountIEnumerable<InputAction>(ReInput.mapping.UserAssignableActionsInCategory(category.id));
|
|
if(count == 0) continue; // no actions so skip category
|
|
|
|
// Add spaces for category labels
|
|
if(_showActionCategoryLabels) {
|
|
yPos -= categoryCount > 0 ? _inputRowHeight + _inputRowCategorySpacing : _inputRowHeight;
|
|
}
|
|
|
|
// Draw input field buttons
|
|
foreach(InputAction action in ReInput.mapping.UserAssignableActionsInCategory(category.id, true)) {
|
|
|
|
if(action.type == InputActionType.Axis) {
|
|
if(_showFullAxisInputFields) CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Full, controllerType, cols, fieldWidth, ref yPos, disableFullAxis);
|
|
if(_showSplitAxisInputFields) {
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Positive, controllerType, cols, fieldWidth, ref yPos, false);
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Negative, controllerType, cols, fieldWidth, ref yPos, false);
|
|
}
|
|
} else if(action.type == InputActionType.Button) {
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Positive, controllerType, cols, fieldWidth, ref yPos, false);
|
|
}
|
|
|
|
categoryCount++;
|
|
}
|
|
}
|
|
|
|
} else { // list only individual actins defined by the user
|
|
|
|
IList<int> actionIds = set.actionIds;
|
|
for(int i = 0; i < actionIds.Count; i++) {
|
|
InputAction action = ReInput.mapping.GetAction(actionIds[i]);
|
|
if(action == null) continue;
|
|
if(!action.userAssignable) continue;
|
|
|
|
InputCategory category = ReInput.mapping.GetActionCategory(action.categoryId);
|
|
if(category == null) continue;
|
|
if(!category.userAssignable) continue; // action category isn't user assignable
|
|
|
|
// Draw input field buttons
|
|
if(action.type == InputActionType.Axis) {
|
|
if(_showFullAxisInputFields) CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Full, controllerType, cols, fieldWidth, ref yPos, disableFullAxis);
|
|
if(_showSplitAxisInputFields) {
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Positive, controllerType, cols, fieldWidth, ref yPos, false);
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Negative, controllerType, cols, fieldWidth, ref yPos, false);
|
|
}
|
|
} else if(action.type == InputActionType.Button) {
|
|
CreateInputFieldSet(columnXform, set.mapCategoryId, action, AxisRange.Positive, controllerType, cols, fieldWidth, ref yPos, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateInputFieldSet(Transform parent, int mapCategoryId, InputAction action, AxisRange axisRange, ControllerType controllerType, int cols, int fieldWidth, ref int yPos, bool disableFullAxis) {
|
|
// Create horizontal layout group to hold fields
|
|
GameObject layoutGroup = CreateNewGUIObject("FieldLayoutGroup", parent, new Vector2(0, yPos));
|
|
HorizontalLayoutGroup hLayoutGroup = layoutGroup.AddComponent<HorizontalLayoutGroup>();
|
|
RectTransform rt = layoutGroup.GetComponent<RectTransform>();
|
|
rt.anchorMin = new Vector2(0, 1);
|
|
rt.anchorMax = new Vector2(1, 1);
|
|
rt.pivot = new Vector2(0, 1);
|
|
rt.sizeDelta = Vector2.zero;
|
|
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _inputRowHeight);
|
|
|
|
// Create the field set
|
|
inputGrid.AddInputFieldSet(mapCategoryId, action, axisRange, controllerType, layoutGroup);
|
|
|
|
// Create the fields
|
|
for(int fieldIndex = 0; fieldIndex < cols; fieldIndex++) {
|
|
int toggleWidth = axisRange == AxisRange.Full ? _invertToggleWidth : 0;
|
|
|
|
GUIInputField field = CreateInputField(hLayoutGroup.transform, Vector2.zero, "", action.id, axisRange, controllerType, fieldIndex);
|
|
field.SetFirstChildObjectWidth(LayoutElementSizeType.PreferredSize, fieldWidth - toggleWidth); // set max width so buttons will stay equal widths
|
|
inputGrid.AddInputField(mapCategoryId, action, axisRange, controllerType, fieldIndex, field); // add to the system
|
|
|
|
if(axisRange == AxisRange.Full) {
|
|
// Create invert toggle field
|
|
if(!disableFullAxis) {
|
|
GUIToggle toggle = CreateToggle(prefabs.inputGridFieldInvertToggle, hLayoutGroup.transform, Vector2.zero, "", action.id, axisRange, controllerType, fieldIndex);
|
|
toggle.SetFirstChildObjectWidth(LayoutElementSizeType.MinSize, toggleWidth); // set max width so buttons will stay equal widths
|
|
field.AddToggle(toggle);
|
|
} else {
|
|
field.SetInteractible(false, false, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
yPos -= _inputRowHeight;
|
|
}
|
|
|
|
private void PopulateInputFields() {
|
|
|
|
// Clear
|
|
inputGrid.InitializeFields(currentMapCategoryId);
|
|
|
|
// Get the player
|
|
if(currentPlayer == null) return;
|
|
|
|
inputGrid.SetFieldsActive(currentMapCategoryId, true);
|
|
|
|
foreach(InputActionSet actionSet in inputGrid.GetActionSets(currentMapCategoryId)) {
|
|
|
|
ControllerType controllerType;
|
|
int controllerId;
|
|
int layoutId;
|
|
int fieldCount;
|
|
|
|
// Draw keyboard and mouse fields
|
|
if(_showKeyboard) {
|
|
controllerType = ControllerType.Keyboard;
|
|
controllerId = 0;
|
|
layoutId = _keyboardMapDefaultLayout;
|
|
fieldCount = _keyboardInputFieldCount;
|
|
ControllerMap map = GetControllerMapOrCreateNew(controllerType, controllerId, layoutId);
|
|
PopulateInputFieldGroup(actionSet, map, controllerType, controllerId, fieldCount);
|
|
}
|
|
|
|
if(_showMouse) {
|
|
controllerType = ControllerType.Mouse;
|
|
controllerId = 0;
|
|
layoutId = _mouseMapDefaultLayout;
|
|
fieldCount = _mouseInputFieldCount;
|
|
ControllerMap map = GetControllerMapOrCreateNew(controllerType, controllerId, layoutId);
|
|
if(currentPlayer.controllers.hasMouse) PopulateInputFieldGroup(actionSet, map, controllerType, controllerId, fieldCount); // only populate if mouse is assigned, hide maps if not
|
|
// Do not disable fields if player doesn't have mouse so player can assign it by clicking on the fields
|
|
}
|
|
|
|
// Draw joystick fields
|
|
if(isJoystickSelected && currentPlayer.controllers.joystickCount > 0) {
|
|
controllerType = ControllerType.Joystick;
|
|
controllerId = currentJoystick.id;
|
|
layoutId = _joystickMapDefaultLayout;
|
|
fieldCount = _controllerInputFieldCount;
|
|
ControllerMap map = GetControllerMapOrCreateNew(controllerType, controllerId, layoutId);
|
|
PopulateInputFieldGroup(actionSet, map, controllerType, controllerId, fieldCount);
|
|
} else { // no controller assigned to this player
|
|
DisableInputFieldGroup(actionSet, ControllerType.Joystick, _controllerInputFieldCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PopulateInputFieldGroup(InputActionSet actionSet, ControllerMap controllerMap, ControllerType controllerType, int controllerId, int maxFields) {
|
|
if(controllerMap == null) return;
|
|
|
|
int count = 0;
|
|
|
|
// First populate fixed data in all fields including blanks
|
|
inputGrid.SetFixedFieldData(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, controllerId);
|
|
|
|
// Populate data in fields that have an ActionElementMap
|
|
foreach(ActionElementMap aem in controllerMap.ElementMapsWithAction(actionSet.actionId)) {
|
|
|
|
if(aem.elementType == ControllerElementType.Button) {
|
|
|
|
if(actionSet.axisRange == AxisRange.Full) {
|
|
|
|
// Not implemented
|
|
continue;
|
|
|
|
} else if(actionSet.axisRange == AxisRange.Positive) {
|
|
|
|
if(aem.axisContribution == Pole.Negative) continue;
|
|
|
|
} else if(actionSet.axisRange == AxisRange.Negative) {
|
|
|
|
if(aem.axisContribution == Pole.Positive) continue;
|
|
|
|
}
|
|
|
|
inputGrid.PopulateField(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, controllerId, count, aem.id, aem.elementIdentifierName, false);
|
|
|
|
} else if(aem.elementType == ControllerElementType.Axis) {
|
|
|
|
if(actionSet.axisRange == AxisRange.Full) {
|
|
if(aem.axisRange != AxisRange.Full) continue;
|
|
|
|
inputGrid.PopulateField(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, controllerId, count, aem.id, aem.elementIdentifierName, aem.invert);
|
|
|
|
} else if(actionSet.axisRange == AxisRange.Positive) {
|
|
if(aem.axisRange == AxisRange.Full) continue;
|
|
if(aem.axisContribution == Pole.Negative) continue;
|
|
|
|
inputGrid.PopulateField(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, controllerId, count, aem.id, aem.elementIdentifierName, false);
|
|
|
|
} else if(actionSet.axisRange == AxisRange.Negative) {
|
|
if(aem.axisRange == AxisRange.Full) continue;
|
|
if(aem.axisContribution == Pole.Positive) continue;
|
|
|
|
inputGrid.PopulateField(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, controllerId, count, aem.id, aem.elementIdentifierName, false);
|
|
}
|
|
}
|
|
|
|
count++;
|
|
if(count > maxFields) break; // no more room
|
|
}
|
|
}
|
|
|
|
private void DisableInputFieldGroup(InputActionSet actionSet, ControllerType controllerType, int fieldCount) {
|
|
// Disable the fields
|
|
for(int i = 0; i < fieldCount; i++) {
|
|
GUIInputField field = inputGrid.GetGUIInputField(currentMapCategoryId, actionSet.actionId, actionSet.axisRange, controllerType, i);
|
|
if(field == null) continue;
|
|
field.SetInteractible(false, false);
|
|
}
|
|
}
|
|
|
|
private void ResetInputGridScrollBar() {
|
|
references.inputGridInnerGroup.GetComponent<RectTransform>().anchoredPosition = Vector2.zero; // fix Unity scrollbar bug
|
|
references.inputGridVScrollbar.value = 1.0f;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Drawing (UI Layout)
|
|
|
|
// Draw the layout initially
|
|
|
|
private void CreateLayout() {
|
|
|
|
// Enable all groups that are used by the current settings.
|
|
|
|
// Player section
|
|
references.playersGroup.gameObject.SetActive(showPlayers);
|
|
|
|
// Controller section
|
|
references.controllerGroup.gameObject.SetActive(_showControllers);
|
|
references.assignedControllersGroup.gameObject.SetActive(_showControllers && ShowAssignedControllers());
|
|
|
|
// Settings and Map Categories section
|
|
|
|
references.settingsAndMapCategoriesGroup.gameObject.SetActive(showSettings || showMapCategories);
|
|
|
|
// Settings section
|
|
references.settingsGroup.gameObject.SetActive(showSettings);
|
|
|
|
// Map categories section
|
|
references.mapCategoriesGroup.gameObject.SetActive(showMapCategories);
|
|
}
|
|
|
|
private void Draw() {
|
|
DrawPlayersGroup();
|
|
DrawControllersGroup();
|
|
DrawSettingsGroup();
|
|
DrawMapCategoriesGroup();
|
|
DrawWindowButtonsGroup();
|
|
}
|
|
|
|
private void DrawPlayersGroup() {
|
|
if(!showPlayers) return;
|
|
|
|
// Set label
|
|
references.playersGroup.labelText = _language.playersGroupLabel;
|
|
references.playersGroup.SetLabelActive(_showPlayersGroupLabel);
|
|
|
|
for(int i = 0; i < playerCount; i++) {
|
|
Player player = ReInput.players.GetPlayer(i);
|
|
if(player == null) continue;
|
|
GameObject instance = UI.ControlMapper.UITools.InstantiateGUIObject<ButtonInfo>(prefabs.button, references.playersGroup.content, "Player" + i + "Button");
|
|
GUIButton button = new GUIButton(instance);
|
|
button.SetLabel(player.descriptiveName);
|
|
button.SetButtonInfoData(buttonIdentifier_playerSelection, player.id);
|
|
button.SetOnClickCallback(OnButtonActivated);
|
|
button.buttonInfo.OnSelectedEvent += OnUIElementSelected;
|
|
playerButtons.Add(button);
|
|
}
|
|
}
|
|
|
|
private void DrawControllersGroup() {
|
|
if(!_showControllers) return;
|
|
|
|
// Set group labels
|
|
references.controllerSettingsGroup.labelText = _language.controllerSettingsGroupLabel;
|
|
references.controllerSettingsGroup.SetLabelActive(_showControllerGroupLabel);
|
|
references.controllerNameLabel.gameObject.SetActive(_showControllerNameLabel);
|
|
references.controllerGroupLabelGroup.gameObject.SetActive(_showControllerGroupLabel || _showControllerNameLabel);
|
|
if(ShowAssignedControllers()) {
|
|
references.assignedControllersGroup.labelText = _language.assignedControllersGroupLabel;
|
|
references.assignedControllersGroup.SetLabelActive(_showAssignedControllersGroupLabel);
|
|
}
|
|
|
|
ButtonInfo buttonInfo;
|
|
|
|
// Set up button labels in static buttons
|
|
buttonInfo = references.removeControllerButton.GetComponent<ButtonInfo>();
|
|
buttonInfo.text.text = _language.removeControllerButtonLabel;
|
|
|
|
buttonInfo = references.calibrateControllerButton.GetComponent<ButtonInfo>();
|
|
buttonInfo.text.text = _language.calibrateControllerButtonLabel;
|
|
|
|
buttonInfo = references.assignControllerButton.GetComponent<ButtonInfo>();
|
|
buttonInfo.text.text = _language.assignControllerButtonLabel;
|
|
|
|
// Create None placeholder button
|
|
GUIButton guiButton = CreateButton(_language.none, references.assignedControllersGroup.content, Vector2.zero);
|
|
guiButton.SetInteractible(false, false, true);
|
|
assignedControllerButtonsPlaceholder = guiButton;
|
|
}
|
|
|
|
private void DrawSettingsGroup() {
|
|
if(!showSettings) return;
|
|
|
|
// Set label on group
|
|
references.settingsGroup.labelText = _language.settingsGroupLabel;
|
|
references.settingsGroup.SetLabelActive(_showSettingsGroupLabel);
|
|
|
|
// Create Input Behavior Settings button
|
|
GUIButton button = CreateButton(_language.inputBehaviorSettingsButtonLabel, references.settingsGroup.content, Vector2.zero);
|
|
miscInstantiatedObjects.Add(button.gameObject);
|
|
button.buttonInfo.OnSelectedEvent += OnUIElementSelected;
|
|
button.SetButtonInfoData(buttonIdentifier_editInputBehaviors, 0);
|
|
button.SetOnClickCallback(OnButtonActivated);
|
|
}
|
|
|
|
private void DrawMapCategoriesGroup() {
|
|
if(!showMapCategories) return;
|
|
if(_mappingSets == null) return;
|
|
|
|
// Set label on group
|
|
references.mapCategoriesGroup.labelText = _language.mapCategoriesGroupLabel;
|
|
references.mapCategoriesGroup.SetLabelActive(_showMapCategoriesGroupLabel);
|
|
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
MappingSet set = _mappingSets[i];
|
|
if(set == null) continue;
|
|
InputMapCategory cat = ReInput.mapping.GetMapCategory(set.mapCategoryId);
|
|
if(cat == null) continue; // invalid map category id
|
|
|
|
GameObject instance = UI.ControlMapper.UITools.InstantiateGUIObject<ButtonInfo>(prefabs.button, references.mapCategoriesGroup.content, cat.name + "Button");
|
|
GUIButton button = new GUIButton(instance);
|
|
button.SetLabel(cat.descriptiveName);
|
|
button.SetButtonInfoData(buttonIdentifier_mapCategorySelection, cat.id);
|
|
button.SetOnClickCallback(OnButtonActivated);
|
|
button.buttonInfo.OnSelectedEvent += OnUIElementSelected;
|
|
mapCategoryButtons.Add(button);
|
|
}
|
|
}
|
|
|
|
private void DrawWindowButtonsGroup() {
|
|
references.doneButton.GetComponent<ButtonInfo>().text.text = _language.doneButtonLabel;
|
|
references.restoreDefaultsButton.GetComponent<ButtonInfo>().text.text = _language.restoreDefaultsButtonLabel;
|
|
}
|
|
|
|
// Redraw / Refresh the layout
|
|
|
|
private void Redraw(bool listsChanged, bool playTransitions) {
|
|
RedrawPlayerGroup(playTransitions);
|
|
RedrawControllerGroup();
|
|
RedrawMapCategoriesGroup(playTransitions);
|
|
RedrawInputGrid(listsChanged);
|
|
|
|
// Make sure something is always selected so UI navigation is never lost with only joysticks
|
|
if(currentUISelection == null || !currentUISelection.activeInHierarchy) RestoreLastUISelection();
|
|
}
|
|
|
|
private void RedrawPlayerGroup(bool playTransitions) {
|
|
if(!showPlayers) return;
|
|
|
|
for(int i = 0; i < playerButtons.Count; i++) {
|
|
bool state = currentPlayerId != playerButtons[i].buttonInfo.intData;
|
|
playerButtons[i].SetInteractible(state, playTransitions);
|
|
}
|
|
}
|
|
|
|
private void RedrawControllerGroup() {
|
|
|
|
int prevSelectedButtonJoyId = -1;
|
|
|
|
// Reset config group
|
|
references.controllerNameLabel.text = _language.none;
|
|
UI.ControlMapper.UITools.SetInteractable(references.removeControllerButton, false, false);
|
|
UI.ControlMapper.UITools.SetInteractable(references.assignControllerButton, false, false);
|
|
UI.ControlMapper.UITools.SetInteractable(references.calibrateControllerButton, false, false);
|
|
|
|
// Reset assigned controllers group
|
|
if(ShowAssignedControllers()) {
|
|
|
|
// Clear assigned controller buttons
|
|
foreach(GUIButton button in assignedControllerButtons) {
|
|
if(button.gameObject == null) continue;
|
|
if(currentUISelection == button.gameObject) prevSelectedButtonJoyId = button.buttonInfo.intData; // store selection if this was the active UI element
|
|
Object.Destroy(button.gameObject);
|
|
}
|
|
assignedControllerButtons.Clear();
|
|
|
|
// Enable placeholder
|
|
assignedControllerButtonsPlaceholder.SetActive(true);
|
|
}
|
|
|
|
// Get the current player
|
|
Player player = ReInput.players.GetPlayer(currentPlayerId);
|
|
if(player == null) return;
|
|
|
|
// Assigned controller buttons
|
|
if(ShowAssignedControllers()) {
|
|
|
|
if(player.controllers.joystickCount > 0) assignedControllerButtonsPlaceholder.SetActive(false); // disable the None placeholder
|
|
|
|
// Create buttons for the assigned controllers
|
|
foreach(Joystick joystick in player.controllers.Joysticks) {
|
|
GUIButton button = CreateButton(joystick.name, references.assignedControllersGroup.content, Vector2.zero);
|
|
button.SetButtonInfoData(buttonIdentifier_assignedControllerSelection, joystick.id);
|
|
button.SetOnClickCallback(OnButtonActivated);
|
|
button.buttonInfo.OnSelectedEvent += OnUIElementSelected;
|
|
assignedControllerButtons.Add(button);
|
|
if(joystick.id == currentJoystickId) button.SetInteractible(false, true); // disable the selected joystick
|
|
}
|
|
|
|
// Auto-select the first controller if none selected
|
|
if(player.controllers.joystickCount > 0 && !isJoystickSelected) {
|
|
currentJoystickId = player.controllers.Joysticks[0].id;
|
|
assignedControllerButtons[0].SetInteractible(false, false);
|
|
}
|
|
|
|
// Restore UI selection if selected button was destroyed
|
|
if(prevSelectedButtonJoyId >= 0) {
|
|
foreach(GUIButton button in assignedControllerButtons) {
|
|
if(button.buttonInfo.intData == prevSelectedButtonJoyId) {
|
|
SetUISelection(button.gameObject);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else { // just one controller per player
|
|
|
|
// Auto-select the first controller if none selected
|
|
if(player.controllers.joystickCount > 0 && !isJoystickSelected) {
|
|
currentJoystickId = player.controllers.Joysticks[0].id;
|
|
}
|
|
}
|
|
|
|
// Set ineractible on controller config buttons if a controller is selected/assigned
|
|
if(isJoystickSelected && player.controllers.joystickCount > 0) {
|
|
|
|
// Remove Controller button
|
|
references.removeControllerButton.interactable = true;
|
|
|
|
// Controller name label
|
|
references.controllerNameLabel.text = currentJoystick.name;
|
|
|
|
// Calibrate Controller button
|
|
if(currentJoystick.axisCount > 0) references.calibrateControllerButton.interactable = true;
|
|
}
|
|
|
|
// Assign Controller button
|
|
int playerJoystickCount = player.controllers.joystickCount;
|
|
int totalJoystickCount = ReInput.controllers.joystickCount;
|
|
int maxJoysticksPerPlayer = GetMaxControllersPerPlayer();
|
|
bool infiniteJoysticksPerPlayer = maxJoysticksPerPlayer == 0;
|
|
|
|
if(totalJoystickCount > 0 &&
|
|
playerJoystickCount < totalJoystickCount &&
|
|
(maxJoysticksPerPlayer == 1 || infiniteJoysticksPerPlayer || playerJoystickCount < maxJoysticksPerPlayer)
|
|
) {
|
|
UI.ControlMapper.UITools.SetInteractable(references.assignControllerButton, true, false);
|
|
}
|
|
}
|
|
|
|
private void RedrawMapCategoriesGroup(bool playTransitions) {
|
|
if(!showMapCategories) return;
|
|
|
|
for(int i = 0; i < mapCategoryButtons.Count; i++) {
|
|
bool state = currentMapCategoryId != mapCategoryButtons[i].buttonInfo.intData;
|
|
mapCategoryButtons[i].SetInteractible(state, playTransitions);
|
|
}
|
|
}
|
|
|
|
private void RedrawInputGrid(bool listsChanged) {
|
|
if(listsChanged) RefreshInputGridStructure();
|
|
PopulateInputFields();
|
|
if(listsChanged) ResetInputGridScrollBar();
|
|
}
|
|
|
|
private void ForceRefresh() {
|
|
if(windowManager.isWindowOpen) CloseAllWindows();
|
|
else Redraw(false, false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Create UI Objects
|
|
|
|
private void CreateInputCategoryRow(ref int rowCount, InputCategory category) {
|
|
CreateLabel(category.descriptiveName, references.inputGridActionColumn, new Vector2(0, rowCount * _inputRowHeight * -1.0f));
|
|
rowCount++;
|
|
}
|
|
|
|
private GUILabel CreateLabel(string labelText, Transform parent, Vector2 offset) {
|
|
return CreateLabel(prefabs.inputGridLabel, labelText, parent, offset);
|
|
}
|
|
private GUILabel CreateLabel(GameObject prefab, string labelText, Transform parent, Vector2 offset) {
|
|
GameObject instance = InstantiateGUIObject(prefab, parent, offset);
|
|
Text text = UnityTools.GetComponentInSelfOrChildren<Text>(instance);
|
|
if(text == null) {
|
|
Debug.LogError("Rewired Control Mapper: Label prefab is missing Text component!");
|
|
return null;
|
|
}
|
|
text.text = labelText;
|
|
return new GUILabel(instance);
|
|
}
|
|
|
|
private GUIButton CreateButton(string labelText, Transform parent, Vector2 offset) {
|
|
GUIButton button = new GUIButton(InstantiateGUIObject(prefabs.button, parent, offset));
|
|
button.SetLabel(labelText);
|
|
return button;
|
|
}
|
|
|
|
private GUIButton CreateFitButton(string labelText, Transform parent, Vector2 offset) {
|
|
GUIButton button = new GUIButton(InstantiateGUIObject(prefabs.fitButton, parent, offset));
|
|
button.SetLabel(labelText);
|
|
return button;
|
|
}
|
|
|
|
private GUIInputField CreateInputField(Transform parent, Vector2 offset, string label, int actionId, AxisRange axisRange, ControllerType controllerType, int fieldIndex) {
|
|
GUIInputField field = CreateInputField(parent, offset);
|
|
field.SetLabel("");
|
|
field.SetFieldInfoData(actionId, axisRange, controllerType, fieldIndex);
|
|
field.SetOnClickCallback(inputFieldActivatedDelegate);
|
|
field.fieldInfo.OnSelectedEvent += OnUIElementSelected;
|
|
return field;
|
|
}
|
|
private GUIInputField CreateInputField(Transform parent, Vector2 offset) {
|
|
return new GUIInputField(InstantiateGUIObject(prefabs.inputGridFieldButton, parent, offset));
|
|
}
|
|
|
|
private GUIToggle CreateToggle(GameObject prefab, Transform parent, Vector2 offset, string label, int actionId, AxisRange axisRange, ControllerType controllerType, int fieldIndex) {
|
|
GUIToggle toggle = CreateToggle(prefab, parent, offset);
|
|
toggle.SetToggleInfoData(actionId, axisRange, controllerType, fieldIndex);
|
|
toggle.SetOnSubmitCallback(inputFieldInvertToggleStateChangedDelegate);
|
|
toggle.toggleInfo.OnSelectedEvent += OnUIElementSelected;
|
|
return toggle;
|
|
}
|
|
private GUIToggle CreateToggle(GameObject prefab, Transform parent, Vector2 offset) {
|
|
return new GUIToggle(InstantiateGUIObject(prefab, parent, offset));
|
|
}
|
|
|
|
private GameObject InstantiateGUIObject(GameObject prefab, Transform parent, Vector2 offset) {
|
|
if(prefab == null) {
|
|
Debug.LogError("Rewired Control Mapper: Prefab is null!");
|
|
return null;
|
|
}
|
|
GameObject instance = (GameObject)Object.Instantiate(prefab);
|
|
return InitializeNewGUIGameObject(instance, parent, offset);
|
|
}
|
|
|
|
private GameObject CreateNewGUIObject(string name, Transform parent, Vector2 offset) {
|
|
GameObject instance = new GameObject();
|
|
instance.name = name;
|
|
instance.AddComponent<RectTransform>();
|
|
return InitializeNewGUIGameObject(instance, parent, offset);
|
|
}
|
|
|
|
private GameObject InitializeNewGUIGameObject(GameObject gameObject, Transform parent, Vector2 offset) {
|
|
if(gameObject == null) {
|
|
Debug.LogError("Rewired Control Mapper: GameObject is null!");
|
|
return null;
|
|
}
|
|
|
|
RectTransform instanceXform = gameObject.GetComponent<RectTransform>();
|
|
if(instanceXform == null) {
|
|
Debug.LogError("Rewired Control Mapper: GameObject does not have a RectTransform component!");
|
|
return gameObject;
|
|
}
|
|
if(parent != null) {
|
|
instanceXform.SetParent(parent, false);
|
|
}
|
|
//instanceXform.localScale = Vector3.one;
|
|
//instanceXform.localPosition = Vector3.zero;
|
|
instanceXform.anchoredPosition = offset;
|
|
return gameObject;
|
|
}
|
|
|
|
private GameObject CreateNewColumnGroup(string name, Transform parent, int maxWidth) {
|
|
GameObject group = CreateNewGUIObject(name, parent, Vector2.zero);
|
|
inputGrid.AddGroup(group);
|
|
LayoutElement layout = group.AddComponent<LayoutElement>();
|
|
if(maxWidth >= 0) layout.preferredWidth = maxWidth;
|
|
RectTransform rectXForm = group.GetComponent<RectTransform>();
|
|
rectXForm.anchorMin = new Vector2(0, 0);
|
|
rectXForm.anchorMax = new Vector2(1, 0);
|
|
return group;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Popup Window Management
|
|
|
|
private Window OpenWindow(bool closeOthers) {
|
|
return OpenWindow(string.Empty, closeOthers);
|
|
}
|
|
private Window OpenWindow(string name, bool closeOthers) {
|
|
if(closeOthers) windowManager.CancelAll();
|
|
Window window = windowManager.OpenWindow(name, _defaultWindowWidth, _defaultWindowHeight);
|
|
if(window == null) return null;
|
|
ChildWindowOpened();
|
|
return window;
|
|
}
|
|
private Window OpenWindow(GameObject windowPrefab, bool closeOthers) {
|
|
return OpenWindow(windowPrefab, string.Empty, closeOthers);
|
|
}
|
|
private Window OpenWindow(GameObject windowPrefab, string name, bool closeOthers) {
|
|
if(closeOthers) windowManager.CancelAll();
|
|
Window window = windowManager.OpenWindow(windowPrefab, name);
|
|
if(window == null) return null;
|
|
ChildWindowOpened();
|
|
return window;
|
|
}
|
|
|
|
private void OpenModal(string title, string message, string confirmText, System.Action<int> confirmAction, string cancelText, System.Action<int> cancelAction, bool closeOthers) {
|
|
Window window = OpenWindow(closeOthers);
|
|
if(window == null) return;
|
|
window.CreateTitleText(prefabs.windowTitleText, Vector2.zero, title);
|
|
window.AddContentText(prefabs.windowContentText, UI.UIPivot.TopCenter, UI.UIAnchor.TopHStretch, new Vector2(0, -100), message);
|
|
UnityAction cancelCallback = () => { OnWindowCancel(window.id); };
|
|
window.cancelCallback = cancelCallback;
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomLeft, UI.UIAnchor.BottomLeft, Vector2.zero, confirmText, () => { OnRestoreDefaultsConfirmed(window.id); }, cancelCallback, false);
|
|
window.CreateButton(prefabs.fitButton, UI.UIPivot.BottomRight, UI.UIAnchor.BottomRight, Vector2.zero, cancelText, cancelCallback, cancelCallback, true);
|
|
windowManager.Focus(window);
|
|
}
|
|
|
|
private void CloseWindow(int windowId) {
|
|
if(!windowManager.isWindowOpen) return;
|
|
windowManager.CloseWindow(windowId);
|
|
ChildWindowClosed();
|
|
}
|
|
|
|
private void CloseTopWindow() {
|
|
if(!windowManager.isWindowOpen) return;
|
|
windowManager.CloseTop();
|
|
ChildWindowClosed();
|
|
}
|
|
|
|
private void CloseAllWindows() {
|
|
if(!windowManager.isWindowOpen) return;
|
|
windowManager.CancelAll();
|
|
ChildWindowClosed();
|
|
InputPollingStopped();
|
|
}
|
|
|
|
private void ChildWindowOpened() {
|
|
if(!windowManager.isWindowOpen) return; // do nothing if a window is not open
|
|
SetIsFocused(false);
|
|
if(_PopupWindowOpenedEvent != null) _PopupWindowOpenedEvent();
|
|
if(_onPopupWindowOpened != null) _onPopupWindowOpened.Invoke();
|
|
}
|
|
|
|
private void ChildWindowClosed() {
|
|
if(windowManager.isWindowOpen) return; // do nothing if a window is still open
|
|
SetIsFocused(true);
|
|
if(_PopupWindowClosedEvent != null) _PopupWindowClosedEvent();
|
|
if(_onPopupWindowClosed != null) _onPopupWindowClosed.Invoke();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Element Assignment
|
|
|
|
private bool HasElementAssignmentConflicts(Player player, InputMapping mapping, ElementAssignment assignment, bool skipOtherPlayers) {
|
|
if(player == null || mapping == null) return false;
|
|
|
|
ElementAssignmentConflictCheck conflictCheck;
|
|
if(!CreateConflictCheck(mapping, assignment, out conflictCheck)) return false;
|
|
|
|
if(skipOtherPlayers) { // skip other players, only check system and self
|
|
if(ReInput.players.SystemPlayer.controllers.conflictChecking.DoesElementAssignmentConflict(conflictCheck)) return true;
|
|
if(player.controllers.conflictChecking.DoesElementAssignmentConflict(conflictCheck)) return true;
|
|
return false;
|
|
} else { // check all players
|
|
return ReInput.controllers.conflictChecking.DoesElementAssignmentConflict(conflictCheck);
|
|
}
|
|
}
|
|
|
|
private bool IsBlockingAssignmentConflict(InputMapping mapping, ElementAssignment assignment, bool skipOtherPlayers) {
|
|
ElementAssignmentConflictCheck conflictCheck;
|
|
if(!CreateConflictCheck(mapping, assignment, out conflictCheck)) return false;
|
|
|
|
if(skipOtherPlayers) { // skip other players, only check system and self
|
|
foreach(ElementAssignmentConflictInfo conflict in ReInput.players.SystemPlayer.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) return true;
|
|
}
|
|
foreach(ElementAssignmentConflictInfo conflict in currentPlayer.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) return true;
|
|
}
|
|
} else { // check all players
|
|
foreach(ElementAssignmentConflictInfo conflict in ReInput.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private IEnumerable<ElementAssignmentConflictInfo> ElementAssignmentConflicts(Player player, InputMapping mapping, ElementAssignment assignment, bool skipOtherPlayers) {
|
|
if(player == null || mapping == null) yield break;
|
|
|
|
ElementAssignmentConflictCheck conflictCheck;
|
|
if(!CreateConflictCheck(mapping, assignment, out conflictCheck)) yield break;
|
|
|
|
if(skipOtherPlayers) { // skip other players, only check system and self
|
|
foreach(ElementAssignmentConflictInfo conflict in ReInput.players.SystemPlayer.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) yield return conflict;
|
|
}
|
|
foreach(ElementAssignmentConflictInfo conflict in player.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) yield return conflict;
|
|
}
|
|
} else { // check all players
|
|
foreach(ElementAssignmentConflictInfo conflict in ReInput.controllers.conflictChecking.ElementAssignmentConflicts(conflictCheck)) {
|
|
if(!conflict.isUserAssignable) yield return conflict;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool CreateConflictCheck(InputMapping mapping, ElementAssignment assignment, out ElementAssignmentConflictCheck conflictCheck) {
|
|
if(mapping == null || currentPlayer == null) {
|
|
conflictCheck = new ElementAssignmentConflictCheck();
|
|
return false;
|
|
}
|
|
|
|
conflictCheck = assignment.ToElementAssignmentConflictCheck();
|
|
conflictCheck.playerId = currentPlayer.id;
|
|
conflictCheck.controllerType = mapping.controllerType;
|
|
conflictCheck.controllerId = mapping.controllerId;
|
|
conflictCheck.controllerMapId = mapping.map.id;
|
|
conflictCheck.controllerMapCategoryId = mapping.map.categoryId;
|
|
if(mapping.aem != null) conflictCheck.elementMapId = mapping.aem.id;
|
|
|
|
return true;
|
|
}
|
|
|
|
private void PollKeyboardForAssignment(out ControllerPollingInfo pollingInfo, out bool modifierKeyPressed, out ModifierKeyFlags modifierFlags, out string label) {
|
|
pollingInfo = new ControllerPollingInfo();
|
|
label = string.Empty;
|
|
modifierKeyPressed = false;
|
|
modifierFlags = ModifierKeyFlags.None;
|
|
|
|
int modifierPressedCount = 0; // the number of modifier keys being pressed this cycle
|
|
ControllerPollingInfo nonModifierKeyInfo = new ControllerPollingInfo();
|
|
ControllerPollingInfo firstModifierKeyInfo = new ControllerPollingInfo();
|
|
ModifierKeyFlags curModifiers = ModifierKeyFlags.None;
|
|
|
|
// Check all keys being pressed at present so we can handle modifier keys
|
|
foreach(ControllerPollingInfo info in ReInput.controllers.Keyboard.PollForAllKeys()) {
|
|
KeyCode key = info.keyboardKey;
|
|
if(key == KeyCode.AltGr) continue; // skip AltGr key because it gets fired when alt and control are held on some keyboards
|
|
|
|
// determine if a modifier key is being pressed
|
|
if(Keyboard.IsModifierKey(info.keyboardKey)) { // a modifier key is pressed
|
|
if(modifierPressedCount == 0) firstModifierKeyInfo = info; // store the polling info for the first modifier key pressed in case its the only key pressed
|
|
|
|
curModifiers |= Keyboard.KeyCodeToModifierKeyFlags(key); // add the key to the current modifier flags
|
|
modifierPressedCount += 1; // count how many modifier keys are pressed
|
|
|
|
} else { // this is not a modifier key
|
|
|
|
if(nonModifierKeyInfo.keyboardKey != KeyCode.None) continue; // skip after the first one detected, we only need one non-modifier key press
|
|
nonModifierKeyInfo = info; // store the polling info
|
|
}
|
|
|
|
}
|
|
|
|
// Commit immediately if a non-modifier key was pressed
|
|
if(nonModifierKeyInfo.keyboardKey != KeyCode.None) { // a regular key was pressed
|
|
|
|
// Make sure the primary button is in a down state or else we'll get immediate confirmation if using the keyboard to navigate
|
|
if(!ReInput.controllers.Keyboard.GetKeyDown(nonModifierKeyInfo.keyboardKey)) return; // fail because key is not in a down state
|
|
|
|
if(modifierPressedCount == 0) { // only the regular key was pressed
|
|
pollingInfo = nonModifierKeyInfo; // copy polling info into entry
|
|
return;
|
|
|
|
} else { // one more more modifier keys was pressed too
|
|
|
|
pollingInfo = nonModifierKeyInfo; // copy polling info into entry
|
|
modifierFlags = curModifiers; // set the modifier key flags
|
|
return;
|
|
|
|
}
|
|
|
|
} else if(modifierPressedCount > 0) { // one or more modifier keys were pressed, but no regular keys
|
|
modifierKeyPressed = true;
|
|
|
|
if(modifierPressedCount == 1) { // only one modifier is pressed, allow assigning just the modifier key
|
|
|
|
// Assign the modifier key as the main key if the user holds it for 1 second
|
|
if(ReInput.controllers.Keyboard.GetKeyTimePressed(firstModifierKeyInfo.keyboardKey) > 1.0f) { // key was pressed for one second
|
|
pollingInfo = firstModifierKeyInfo; // copy polling info into entry
|
|
return;
|
|
}
|
|
|
|
// Show the key that is being pressed
|
|
label = Keyboard.GetKeyName(firstModifierKeyInfo.keyboardKey);
|
|
|
|
} else { // more than one modifier key is pressed
|
|
// do nothing because we don't want to assign modified modifier key presses such as Control + Alt, but you could if you wanted to.
|
|
|
|
// Show the modifier keys being held
|
|
label = Keyboard.ModifierKeyFlagsToString(curModifiers);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Controller Calibration
|
|
|
|
private void StartAxisCalibration(int axisIndex) {
|
|
if(currentPlayer == null) return;
|
|
if(currentPlayer.controllers.joystickCount == 0) return;
|
|
Joystick joystick = currentJoystick;
|
|
if(axisIndex < 0 || axisIndex >= joystick.axisCount) return;
|
|
|
|
pendingAxisCalibration = new AxisCalibrator(joystick, axisIndex);
|
|
ShowCalibrateAxisStep1Window();
|
|
}
|
|
|
|
private void EndAxisCalibration() {
|
|
if(pendingAxisCalibration == null) return;
|
|
pendingAxisCalibration.Commit();
|
|
pendingAxisCalibration = null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UI Selection
|
|
|
|
private void SetUISelection(GameObject selection) {
|
|
if(EventSystem.current == null) return;
|
|
EventSystem.current.SetSelectedGameObject(selection);
|
|
}
|
|
|
|
private void RestoreLastUISelection() {
|
|
if(lastUISelection == null || !lastUISelection.activeInHierarchy) {
|
|
SetDefaultUISelection();
|
|
return;
|
|
}
|
|
SetUISelection(lastUISelection);
|
|
}
|
|
|
|
private void SetDefaultUISelection() {
|
|
if(!isOpen) return;
|
|
if(references.defaultSelection == null) SetUISelection(null);
|
|
else SetUISelection(references.defaultSelection.gameObject);
|
|
}
|
|
|
|
private void SelectDefaultMapCategory(bool redraw) {
|
|
currentMapCategoryId = GetDefaultMapCategoryId();
|
|
OnMapCategorySelected(currentMapCategoryId, redraw);
|
|
|
|
if(!showMapCategories) return;
|
|
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
InputMapCategory cat = ReInput.mapping.GetMapCategory(_mappingSets[i].mapCategoryId);
|
|
if(cat == null) continue;
|
|
currentMapCategoryId = _mappingSets[i].mapCategoryId;
|
|
break;
|
|
}
|
|
if(currentMapCategoryId < 0) return; // invalid, no map cats found
|
|
|
|
// Disable the selected button and enable others
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
bool state = _mappingSets[i].mapCategoryId == currentMapCategoryId ? false : true;
|
|
mapCategoryButtons[i].SetInteractible(state, false);
|
|
}
|
|
}
|
|
|
|
private void CheckUISelection() {
|
|
if(!isFocused) return;
|
|
if(currentUISelection == null) RestoreLastUISelection();
|
|
}
|
|
|
|
private void OnUIElementSelected(GameObject selectedObject) {
|
|
lastUISelection = selectedObject; // record the last selected UI element
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Main Page
|
|
|
|
private void SetIsFocused(bool state) {
|
|
// Set interactible state on main page controls
|
|
references.mainCanvasGroup.interactable = state;
|
|
|
|
if(state) { // just received focus
|
|
Redraw(false, false);
|
|
RestoreLastUISelection();
|
|
// Block input for a short time to prevent immediate button-down events when making a new assignment or assigning a controller
|
|
blockInputOnFocusEndTime = Time.unscaledTime + blockInputOnFocusTimeout;
|
|
}
|
|
}
|
|
|
|
public void Toggle() {
|
|
if(isOpen) Close(true);
|
|
else Open();
|
|
}
|
|
|
|
public void Open() {
|
|
Open(false);
|
|
}
|
|
private void Open(bool force) {
|
|
if(!initialized) Initialize();
|
|
if(!initialized) return; // failed to init
|
|
if(!force && isOpen) return;
|
|
Clear();
|
|
canvas.SetActive(true);
|
|
OnPlayerSelected(0, false);
|
|
SelectDefaultMapCategory(false);
|
|
SetDefaultUISelection();
|
|
Redraw(true, false);
|
|
if(_ScreenOpenedEvent != null) _ScreenOpenedEvent();
|
|
if(_onScreenOpened != null) _onScreenOpened.Invoke();
|
|
}
|
|
|
|
public void Close(bool save) {
|
|
if(!initialized) return;
|
|
if(!isOpen) return;
|
|
if(save) { // save data before closing
|
|
if(ReInput.userDataStore != null) ReInput.userDataStore.Save();
|
|
}
|
|
Clear();
|
|
canvas.SetActive(false);
|
|
SetUISelection(null); // deselect
|
|
if(_ScreenClosedEvent != null) _ScreenClosedEvent();
|
|
if(_onScreenClosed != null) _onScreenClosed.Invoke();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Clear / Reset
|
|
|
|
private void Clear() {
|
|
windowManager.CancelAll();
|
|
lastUISelection = null;
|
|
pendingInputMapping = null;
|
|
pendingAxisCalibration = null;
|
|
InputPollingStopped();
|
|
}
|
|
|
|
private void ClearCompletely() {
|
|
ClearSpawnedObjects();
|
|
ClearAllVars();
|
|
}
|
|
|
|
private void ClearSpawnedObjects() {
|
|
|
|
windowManager.ClearCompletely();
|
|
inputGrid.ClearAll();
|
|
|
|
foreach(GUIButton item in playerButtons) {
|
|
Object.Destroy(item.gameObject);
|
|
}
|
|
playerButtons.Clear();
|
|
foreach(GUIButton item in mapCategoryButtons) {
|
|
Object.Destroy(item.gameObject);
|
|
}
|
|
mapCategoryButtons.Clear();
|
|
foreach(GUIButton item in assignedControllerButtons) {
|
|
Object.Destroy(item.gameObject);
|
|
}
|
|
assignedControllerButtons.Clear();
|
|
|
|
if(assignedControllerButtonsPlaceholder != null) {
|
|
Object.Destroy(assignedControllerButtonsPlaceholder.gameObject);
|
|
assignedControllerButtonsPlaceholder = null;
|
|
}
|
|
|
|
foreach(GameObject item in miscInstantiatedObjects) {
|
|
Object.Destroy(item);
|
|
}
|
|
miscInstantiatedObjects.Clear();
|
|
}
|
|
|
|
private void ClearVarsOnPlayerChange() {
|
|
currentJoystickId = -1;
|
|
}
|
|
|
|
private void ClearVarsOnJoystickChange() {
|
|
currentJoystickId = -1;
|
|
}
|
|
|
|
private void ClearAllVars() {
|
|
initialized = false;
|
|
Instance = null; // clear singleton instance
|
|
playerCount = 0;
|
|
|
|
inputGrid = null;
|
|
windowManager = null;
|
|
currentPlayerId = -1;
|
|
currentMapCategoryId = -1;
|
|
playerButtons = null;
|
|
mapCategoryButtons = null;
|
|
miscInstantiatedObjects = null;
|
|
canvas = null;
|
|
lastUISelection = null;
|
|
currentJoystickId = -1;
|
|
|
|
pendingInputMapping = null;
|
|
pendingAxisCalibration = null;
|
|
|
|
inputFieldActivatedDelegate = null;
|
|
inputFieldInvertToggleStateChangedDelegate = null;
|
|
|
|
isPollingForInput = false;
|
|
}
|
|
|
|
public void Reset() {
|
|
if(!initialized) return;
|
|
ClearCompletely();
|
|
Initialize();
|
|
if(isOpen) Open(true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Misc
|
|
|
|
private void SetActionAxisInverted(bool state, ControllerType controllerType, int actionElementMapId) {
|
|
if(currentPlayer == null) return;
|
|
|
|
ControllerMapWithAxes map = GetControllerMap(controllerType) as ControllerMapWithAxes;
|
|
if(map == null) return;
|
|
|
|
ActionElementMap aem = map.GetElementMap(actionElementMapId);
|
|
if(aem == null) return;
|
|
|
|
aem.invert = state;
|
|
}
|
|
|
|
private ControllerMap GetControllerMap(ControllerType type) {
|
|
if(currentPlayer == null) return null;
|
|
int controllerId = 0;
|
|
switch(type) {
|
|
case ControllerType.Keyboard:
|
|
break;
|
|
case ControllerType.Mouse:
|
|
break;
|
|
case ControllerType.Joystick:
|
|
if(currentPlayer.controllers.joystickCount > 0) controllerId = currentJoystick.id;
|
|
else return null;
|
|
break;
|
|
default: throw new System.NotImplementedException();
|
|
}
|
|
|
|
// We cannot support multiple layouts in the same category in this system, so just get the first map in the category we find
|
|
return currentPlayer.controllers.maps.GetFirstMapInCategory(type, controllerId, currentMapCategoryId);
|
|
}
|
|
|
|
private ControllerMap GetControllerMapOrCreateNew(ControllerType controllerType, int controllerId, int layoutId) {
|
|
ControllerMap map = GetControllerMap(controllerType);
|
|
if(map == null) {
|
|
currentPlayer.controllers.maps.AddEmptyMap(controllerType, controllerId, currentMapCategoryId, layoutId);
|
|
map = currentPlayer.controllers.maps.GetMap(controllerType, controllerId, currentMapCategoryId, layoutId);
|
|
}
|
|
return map;
|
|
}
|
|
|
|
private int CountIEnumerable<T>(IEnumerable<T> enumerable) {
|
|
if(enumerable == null) return 0;
|
|
IEnumerator<T> enumerator = enumerable.GetEnumerator();
|
|
if(enumerator == null) return 0;
|
|
int count = 0;
|
|
while(enumerator.MoveNext()) {
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
private int GetDefaultMapCategoryId() {
|
|
if(_mappingSets.Length == 0) return 0; // use Default
|
|
|
|
// Get the first valid map category id we find
|
|
for(int i = 0; i < _mappingSets.Length; i++) {
|
|
if(ReInput.mapping.GetMapCategory(_mappingSets[i].mapCategoryId) == null) continue;
|
|
return _mappingSets[i].mapCategoryId;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private void SubscribeFixedUISelectionEvents() {
|
|
if(references.fixedSelectableUIElements == null) return;
|
|
foreach(GameObject go in references.fixedSelectableUIElements) {
|
|
UIElementInfo elementInfo = UnityTools.GetComponent<UIElementInfo>(go);
|
|
if(elementInfo == null) continue;
|
|
elementInfo.OnSelectedEvent += OnUIElementSelected;
|
|
}
|
|
}
|
|
|
|
private void SubscribeMenuControlInputEvents() {
|
|
|
|
// Set up menu toggle event
|
|
SubscribeRewiredInputEventAllPlayers(_screenToggleAction, OnScreenToggleActionPressed);
|
|
|
|
// Set up player menu open event
|
|
SubscribeRewiredInputEventAllPlayers(_screenOpenAction, OnScreenOpenActionPressed);
|
|
|
|
// Set up player menu close event
|
|
SubscribeRewiredInputEventAllPlayers(_screenCloseAction, OnScreenCloseActionPressed);
|
|
|
|
// Set up universal cancel event
|
|
SubscribeRewiredInputEventAllPlayers(_universalCancelAction, OnUniversalCancelActionPressed);
|
|
}
|
|
|
|
private void UnsubscribeMenuControlInputEvents() {
|
|
|
|
// Remove menu toggle event
|
|
UnsubscribeRewiredInputEventAllPlayers(_screenToggleAction, OnScreenToggleActionPressed);
|
|
|
|
// Remove player menu open event
|
|
UnsubscribeRewiredInputEventAllPlayers(_screenOpenAction, OnScreenOpenActionPressed);
|
|
|
|
// Remove player menu close event
|
|
UnsubscribeRewiredInputEventAllPlayers(_screenCloseAction, OnScreenCloseActionPressed);
|
|
|
|
// Remove universal cancel event
|
|
UnsubscribeRewiredInputEventAllPlayers(_universalCancelAction, OnUniversalCancelActionPressed);
|
|
}
|
|
|
|
private void SubscribeRewiredInputEventAllPlayers(int actionId, System.Action<InputActionEventData> callback) {
|
|
if(actionId < 0 || callback == null) return;
|
|
|
|
if(ReInput.mapping.GetAction(actionId) == null) {
|
|
Debug.LogWarning("Rewired Control Mapper: " + actionId + " is not a valid Action id!");
|
|
return;
|
|
}
|
|
|
|
// Allow control by all players including system
|
|
foreach(Player p in ReInput.players.AllPlayers) {
|
|
p.AddInputEventDelegate(callback, UpdateLoopType.Update, InputActionEventType.ButtonJustPressed, actionId);
|
|
}
|
|
}
|
|
|
|
private void UnsubscribeRewiredInputEventAllPlayers(int actionId, System.Action<InputActionEventData> callback) {
|
|
if(actionId < 0 || callback == null) return;
|
|
if(!Rewired.ReInput.isReady) return; // Rewired may have been destroyed already
|
|
|
|
if(ReInput.mapping.GetAction(actionId) == null) {
|
|
Debug.LogWarning("Rewired Control Mapper: " + actionId + " is not a valid Action id!");
|
|
return;
|
|
}
|
|
|
|
// Allow control by all players including system
|
|
foreach(Player p in ReInput.players.AllPlayers) {
|
|
p.RemoveInputEventDelegate(callback, UpdateLoopType.Update, InputActionEventType.ButtonJustPressed, actionId);
|
|
}
|
|
}
|
|
|
|
private int GetMaxControllersPerPlayer() {
|
|
if(_rewiredInputManager.userData.ConfigVars.autoAssignJoysticks) return _rewiredInputManager.userData.ConfigVars.maxJoysticksPerPlayer;
|
|
return _maxControllersPerPlayer;
|
|
}
|
|
|
|
private bool ShowAssignedControllers() {
|
|
if(!_showControllers) return false;
|
|
if(_showAssignedControllers) return true;
|
|
if(GetMaxControllersPerPlayer() != 1) return true; // force display if Player can have more than 1 controller
|
|
return false;
|
|
}
|
|
|
|
private void InspectorPropertyChanged(bool reset = false) {
|
|
if(reset) Reset();
|
|
}
|
|
|
|
private void AssignController(Player player, int controllerId) {
|
|
if(player == null) return;
|
|
if(player.controllers.ContainsController(ControllerType.Joystick, controllerId)) return; // already assigned to this player
|
|
|
|
// Remove any controllers first if player only allowed 1 at a time
|
|
if(GetMaxControllersPerPlayer() == 1) {
|
|
RemoveAllControllers(player);
|
|
ClearVarsOnJoystickChange(); // redraw
|
|
}
|
|
|
|
// Manually remove the controller from all other Players first so the configs can be saved
|
|
foreach(Player p in ReInput.players.Players) {
|
|
if(p == player) continue; // skip self
|
|
RemoveController(p, controllerId);
|
|
}
|
|
|
|
// Assign the controller to the Player
|
|
player.controllers.AddController(ControllerType.Joystick, controllerId, false);
|
|
|
|
// Load the controller data in case the user customized this controller before
|
|
if(ReInput.userDataStore != null) ReInput.userDataStore.LoadControllerData(player.id, ControllerType.Joystick, controllerId);
|
|
}
|
|
|
|
private void RemoveAllControllers(Player player) {
|
|
if(player == null) return;
|
|
|
|
// Clear controllers from the Player manually so we can save them first
|
|
IList<Joystick> joysticks = player.controllers.Joysticks;
|
|
for(int i = joysticks.Count - 1; i >= 0; i--) {
|
|
RemoveController(player, joysticks[i].id);
|
|
}
|
|
}
|
|
|
|
private void RemoveController(Player player, int controllerId) {
|
|
if(player == null) return;
|
|
if(!player.controllers.ContainsController(ControllerType.Joystick, controllerId)) return;
|
|
|
|
// Save the controller data before unassigning it
|
|
if(ReInput.userDataStore != null) ReInput.userDataStore.SaveControllerData(player.id, ControllerType.Joystick, controllerId);
|
|
|
|
// Unassign the controller
|
|
player.controllers.RemoveController(ControllerType.Joystick, controllerId);
|
|
}
|
|
|
|
private bool IsAllowedAssignment(InputMapping pendingInputMapping, ControllerPollingInfo pollingInfo) {
|
|
if(pendingInputMapping == null) return false;
|
|
|
|
// Determine if user settings prevent this potential assignment
|
|
|
|
// Handle user disabling of split-axis assignment fields
|
|
if(pendingInputMapping.axisRange == AxisRange.Full) { // this is a full-axis assignment
|
|
|
|
// If the user has disabled the split-axis fields, do not allow button or key assignments
|
|
if(!_showSplitAxisInputFields && pollingInfo.elementType == ControllerElementType.Button) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private void InputPollingStarted() {
|
|
bool prev = isPollingForInput;
|
|
isPollingForInput = true;
|
|
if(!prev) {
|
|
if(_InputPollingStartedEvent != null) _InputPollingStartedEvent();
|
|
if(_onInputPollingStarted != null) _onInputPollingStarted.Invoke();
|
|
}
|
|
}
|
|
|
|
private void InputPollingStopped() {
|
|
bool prev = isPollingForInput;
|
|
isPollingForInput = false;
|
|
if(prev) {
|
|
if(_InputPollingEndedEvent != null) _InputPollingEndedEvent();
|
|
if(_onInputPollingEnded != null) _onInputPollingEnded.Invoke();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Editor Recompile
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
private bool recompiling;
|
|
|
|
private void CheckEditorRecompile() {
|
|
if(!recompiling) return;
|
|
if(!ReInput.isReady) return;
|
|
recompiling = false;
|
|
PreInitialize();
|
|
Initialize();
|
|
}
|
|
|
|
private void OnEditorRecompile() {
|
|
recompiling = true;
|
|
if(!initialized) return;
|
|
Close(false);
|
|
ClearCompletely();
|
|
}
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
#region Static Methods
|
|
|
|
public static void ApplyTheme(ThemedElement.ElementInfo[] elementInfo) {
|
|
if(Instance == null) return;
|
|
if(Instance._themeSettings == null) return;
|
|
if(!Instance._useThemeSettings) return; // themeing not allowed
|
|
Instance._themeSettings.Apply(elementInfo);
|
|
}
|
|
|
|
public static UI.ControlMapper.LanguageData GetLanguage() {
|
|
if(Instance == null) return null;
|
|
return Instance._language;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |