// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. using System; using System.Collections.Generic; using UnityEngine; namespace HoloToolkit.Unity.InputModule { /// <summary> /// Xbox Controller support. /// <remarks>Only supports one connected device at a time.</remarks> /// <remarks>Make sure to enable the <see cref="HumanInterfaceDevice"/> capability before using when targeting HoloLens device.</remarks> /// </summary> public class XboxControllerInputSource : GamePadInputSource { [Serializable] private class MappingEntry { public XboxControllerMappingTypes Type = XboxControllerMappingTypes.None; public string Value = string.Empty; } private readonly Dictionary<uint, XboxControllerData> gamePadInputDatas = new Dictionary<uint, XboxControllerData>(0); private XboxControllerData controllerData; public XboxControllerMappingTypes HorizontalAxis { get { return horizontalAxis; } } public XboxControllerMappingTypes VerticalAxis { get { return verticalAxis; } } public XboxControllerMappingTypes CancelButton { get { return cancelButton; } } public XboxControllerMappingTypes SubmitButton { get { return submitButton; } } [SerializeField] private XboxControllerMappingTypes horizontalAxis = XboxControllerMappingTypes.XboxDpadHorizontal; [SerializeField] private XboxControllerMappingTypes verticalAxis = XboxControllerMappingTypes.XboxDpadVertical; [SerializeField] private XboxControllerMappingTypes submitButton = XboxControllerMappingTypes.XboxA; [SerializeField] private XboxControllerMappingTypes cancelButton = XboxControllerMappingTypes.XboxB; [SerializeField] private MappingEntry[] mapping = null; private int motionControllerCount = 0; protected override void Awake() { base.Awake(); if (mapping != null) { for (var i = 0; i < Enum.GetNames(typeof(XboxControllerMappingTypes)).Length; i++) { XboxControllerMapping.SetMapping((XboxControllerMappingTypes)i, mapping[i].Value); } } PreviousForceActiveState = InputModule.forceModuleActive; PreviousHorizontalAxis = InputModule.horizontalAxis; PreviousVerticalAxis = InputModule.verticalAxis; PreviousSubmitButton = InputModule.submitButton; PreviousCancelButton = InputModule.cancelButton; } protected override void Update() { base.Update(); // We will only register the first device we find. Input is taken from joystick 1. // If we have motion controllers connected we will not process Xbox controller input. if (gamePadInputDatas.Count != 1 || motionControllerCount > 0) { return; } controllerData.XboxLeftStickHorizontalAxis = Input.GetAxis(XboxControllerMapping.XboxLeftStickHorizontal); controllerData.XboxLeftStickVerticalAxis = Input.GetAxis(XboxControllerMapping.XboxLeftStickVertical); controllerData.XboxRightStickHorizontalAxis = Input.GetAxis(XboxControllerMapping.XboxRightStickHorizontal); controllerData.XboxRightStickVerticalAxis = Input.GetAxis(XboxControllerMapping.XboxRightStickVertical); controllerData.XboxDpadHorizontalAxis = Input.GetAxis(XboxControllerMapping.XboxDpadHorizontal); controllerData.XboxDpadVerticalAxis = Input.GetAxis(XboxControllerMapping.XboxDpadVertical); controllerData.XboxLeftTriggerAxis = Input.GetAxis(XboxControllerMapping.XboxLeftTrigger); controllerData.XboxRightTriggerAxis = Input.GetAxis(XboxControllerMapping.XboxRightTrigger); controllerData.XboxSharedTriggerAxis = Input.GetAxis(XboxControllerMapping.XboxSharedTrigger); controllerData.XboxA_Down = Input.GetButtonDown(XboxControllerMapping.XboxA); controllerData.XboxB_Down = Input.GetButtonDown(XboxControllerMapping.XboxB); controllerData.XboxX_Down = Input.GetButtonDown(XboxControllerMapping.XboxX); controllerData.XboxY_Down = Input.GetButtonDown(XboxControllerMapping.XboxY); controllerData.XboxView_Down = Input.GetButtonDown(XboxControllerMapping.XboxView); controllerData.XboxMenu_Down = Input.GetButtonDown(XboxControllerMapping.XboxMenu); controllerData.XboxLeftBumper_Down = Input.GetButtonDown(XboxControllerMapping.XboxLeftBumper); controllerData.XboxRightBumper_Down = Input.GetButtonDown(XboxControllerMapping.XboxRightBumper); controllerData.XboxLeftStick_Down = Input.GetButtonDown(XboxControllerMapping.XboxLeftStickClick); controllerData.XboxRightStick_Down = Input.GetButtonDown(XboxControllerMapping.XboxRightStickClick); controllerData.XboxA_Pressed = Input.GetButton(XboxControllerMapping.XboxA); controllerData.XboxB_Pressed = Input.GetButton(XboxControllerMapping.XboxB); controllerData.XboxX_Pressed = Input.GetButton(XboxControllerMapping.XboxX); controllerData.XboxY_Pressed = Input.GetButton(XboxControllerMapping.XboxY); controllerData.XboxView_Pressed = Input.GetButton(XboxControllerMapping.XboxView); controllerData.XboxMenu_Pressed = Input.GetButton(XboxControllerMapping.XboxMenu); controllerData.XboxLeftBumper_Pressed = Input.GetButton(XboxControllerMapping.XboxLeftBumper); controllerData.XboxRightBumper_Pressed = Input.GetButton(XboxControllerMapping.XboxRightBumper); controllerData.XboxLeftStick_Pressed = Input.GetButton(XboxControllerMapping.XboxLeftStickClick); controllerData.XboxRightStick_Pressed = Input.GetButton(XboxControllerMapping.XboxRightStickClick); controllerData.XboxA_Up = Input.GetButtonUp(XboxControllerMapping.XboxA); controllerData.XboxB_Up = Input.GetButtonUp(XboxControllerMapping.XboxB); controllerData.XboxX_Up = Input.GetButtonUp(XboxControllerMapping.XboxX); controllerData.XboxY_Up = Input.GetButtonUp(XboxControllerMapping.XboxY); controllerData.XboxView_Up = Input.GetButtonUp(XboxControllerMapping.XboxView); controllerData.XboxMenu_Up = Input.GetButtonUp(XboxControllerMapping.XboxMenu); controllerData.XboxLeftBumper_Up = Input.GetButtonUp(XboxControllerMapping.XboxLeftBumper); controllerData.XboxRightBumper_Up = Input.GetButtonUp(XboxControllerMapping.XboxRightBumper); controllerData.XboxLeftStick_Up = Input.GetButtonUp(XboxControllerMapping.XboxLeftStickClick); controllerData.XboxRightStick_Up = Input.GetButtonUp(XboxControllerMapping.XboxRightStickClick); InputManager.Instance.RaiseXboxInputUpdate(this, SourceId, controllerData); } protected override void RefreshDevices() { var joystickNames = Input.GetJoystickNames(); if (joystickNames.Length <= 0) { return; } bool devicesChanged = LastDeviceList == null; if (LastDeviceList != null && joystickNames.Length == LastDeviceList.Length) { for (int i = 0; i < LastDeviceList.Length; i++) { if (!joystickNames[i].Equals(LastDeviceList[i])) { devicesChanged = true; if (LastDeviceList == null) { LastDeviceList = joystickNames; } } } } if (LastDeviceList != null && devicesChanged) { foreach (var gamePadInputSource in gamePadInputDatas) { InputManager.Instance.RaiseSourceLost(this, gamePadInputSource.Key); } gamePadInputDatas.Clear(); if (gamePadInputDatas.Count == 0) { // Reset our input module to it's previous state. InputModule.forceModuleActive = PreviousForceActiveState; InputModule.verticalAxis = PreviousVerticalAxis; InputModule.horizontalAxis = PreviousHorizontalAxis; InputModule.submitButton = PreviousSubmitButton; InputModule.cancelButton = PreviousCancelButton; } } motionControllerCount = 0; for (var i = 0; i < joystickNames.Length; i++) { if (joystickNames[i].Contains(MotionControllerLeft) || joystickNames[i].Contains(MotionControllerRight)) { // If we don't have any matching joystick types, continue. // If we have motion controllers connected we override the xbox input. motionControllerCount++; continue; } if (joystickNames[i].Contains(XboxController) || joystickNames[i].Contains(XboxOneForWindows) || joystickNames[i].Contains(XboxBluetoothGamePad) || joystickNames[i].Contains(XboxWirelessController)) { // We will only register the first device we find. Input is taken from all joysticks. if (gamePadInputDatas.Count != 0) { return; } SourceId = (uint)i; controllerData = new XboxControllerData { GamePadName = joystickNames[i] }; gamePadInputDatas.Add(SourceId, controllerData); InputManager.Instance.RaiseSourceDetected(this, SourceId); // Setup the Input Module to use our custom axis settings. InputModule.forceModuleActive = true; if (verticalAxis != XboxControllerMappingTypes.None) { InputModule.verticalAxis = XboxControllerMapping.GetMapping(verticalAxis); } if (horizontalAxis != XboxControllerMappingTypes.None) { InputModule.horizontalAxis = XboxControllerMapping.GetMapping(horizontalAxis); } if (submitButton != XboxControllerMappingTypes.None) { InputModule.submitButton = XboxControllerMapping.GetMapping(submitButton); } if (cancelButton != XboxControllerMappingTypes.None) { InputModule.cancelButton = XboxControllerMapping.GetMapping(cancelButton); } } } LastDeviceList = joystickNames; LastDeviceUpdateCount = joystickNames.Length; } } }