/// <summary> /// The OpenXR plug-in uses extensions to expose all possible data, which might be surfaced through multiple input devices. /// This method is overridden to account for multiple input devices and reuse MRTK controllers if a match is found. /// </summary> protected override GenericXRSDKController GetOrAddController(InputDevice inputDevice) { using (GetOrAddControllerPerfMarker.Auto()) { // If this is a new input device, search if an existing input device has matching characteristics if (!ActiveControllers.ContainsKey(inputDevice)) { foreach (InputDevice device in ActiveControllers.Keys) { if (((device.characteristics.HasFlag(InputDeviceCharacteristics.Controller) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Controller)) || (device.characteristics.HasFlag(InputDeviceCharacteristics.HandTracking) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.HandTracking))) && ((device.characteristics.HasFlag(InputDeviceCharacteristics.Left) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left)) || (device.characteristics.HasFlag(InputDeviceCharacteristics.Right) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right)))) { ActiveControllers.Add(inputDevice, ActiveControllers[device]); break; } } } if (inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.HandTracking) && inputDevice.TryGetFeatureValue(CommonUsages.isTracked, out bool isTracked) && !isTracked) { // If this is an input device from the Microsoft Hand Interaction profile, it doesn't go invalid but instead goes untracked. Ignore it if untracked. return(null); } return(base.GetOrAddController(inputDevice)); } }
/// <summary> /// The OpenXR plug-in uses extensions to expose all possible data, which might be surfaced through multiple input devices. /// This method is overridden to account for multiple input devices and reuse MRTK controllers if a match is found. /// </summary> protected override void RemoveController(InputDevice inputDevice) { using (RemoveControllerPerfMarker.Auto()) { foreach (InputDevice device in ActiveControllers.Keys) { if (device != inputDevice && ((device.characteristics.HasFlag(InputDeviceCharacteristics.Controller) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Controller)) || (device.characteristics.HasFlag(InputDeviceCharacteristics.HandTracking) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.HandTracking))) && ((device.characteristics.HasFlag(InputDeviceCharacteristics.Left) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Left)) || (device.characteristics.HasFlag(InputDeviceCharacteristics.Right) && inputDevice.characteristics.HasFlag(InputDeviceCharacteristics.Right)))) { ActiveControllers.Remove(inputDevice); // Since an additional device exists, return so a lost source isn't reported return; } } base.RemoveController(inputDevice); } }
public void HandleMessage(object sender, Message message) { if (message.Kind == Message.MessageType.InputMessage) { // Pass input messages to the respective ball controllers InputMessage msg = (InputMessage)message; // When using turn mode in hot-seat, direct all input messages to the active player if (Session.UsePlayerTurns && msg.Player != null && msg.Player.IsLocal && Session.ActivePlayer != null && ActiveControllers.ContainsKey(Session.ActivePlayer)) { ActiveControllers[Session.ActivePlayer]?.HandleMessage(sender, msg); } // Otherwise, redirect input messages to the player given by msg.Player else if (msg.Player != null && msg.Player.IsLocal && ActiveControllers.ContainsKey(msg.Player) && ActiveControllers.ContainsKey(msg.Player)) { ActiveControllers[msg.Player]?.HandleMessage(sender, msg); } } if (message.Kind == Message.MessageType.LogicMessage) { LogicMessage msg = (LogicMessage)message; if (msg.Kind == LogicMessage.MessageType.GameMessage) { Enabled = !Enabled; if (Enabled && Game.Match.State != SessionState.Finished) { Game.Match.State = SessionState.Running; } else { Ballz.The().Services.GetService <SoundControl>().PlaySound(SoundControl.DeclineSound); Game.Match.State = SessionState.Paused; } } } }
/// <inheritdoc /> protected override GenericUnityController GetOrAddController(string joystickName) { // If a device is already registered with the ID provided, just return it. if (ActiveControllers.ContainsKey(joystickName)) { var controller = ActiveControllers[joystickName]; Debug.Assert(controller != null); return(controller); } Handedness controllingHand; if (joystickName.Contains("Left")) { controllingHand = Handedness.Left; } else if (joystickName.Contains("Right")) { controllingHand = Handedness.Right; } else { controllingHand = Handedness.None; } var currentControllerType = GetCurrentControllerType(joystickName); Type controllerType; switch (currentControllerType) { case SupportedControllerType.GenericOpenVR: controllerType = typeof(GenericOpenVRController); break; case SupportedControllerType.ViveWand: controllerType = typeof(ViveWandController); break; case SupportedControllerType.ViveKnuckles: controllerType = typeof(ViveKnucklesController); break; case SupportedControllerType.OculusTouch: controllerType = typeof(OculusTouchController); break; case SupportedControllerType.OculusRemote: controllerType = typeof(OculusRemoteController); break; case SupportedControllerType.WindowsMixedReality: controllerType = typeof(WindowsMixedRealityOpenVRMotionController); break; default: return(null); } var pointers = RequestPointers(controllerType, controllingHand); var inputSource = InputSystem?.RequestNewGenericInputSource($"{currentControllerType} Controller {controllingHand}", pointers); var detectedController = Activator.CreateInstance(controllerType, TrackingState.NotTracked, controllingHand, inputSource, null) as GenericOpenVRController; if (detectedController == null) { Debug.LogError($"Failed to create {controllerType.Name} controller"); return(null); } if (!detectedController.SetupConfiguration(controllerType)) { // Controller failed to be setup correctly. Debug.LogError($"Failed to Setup {controllerType.Name} controller"); // Return null so we don't raise the source detected. return(null); } for (int i = 0; i < detectedController.InputSource?.Pointers?.Length; i++) { detectedController.InputSource.Pointers[i].Controller = detectedController; } ActiveControllers.Add(joystickName, detectedController); return(detectedController); }
public override void Update(GameTime time) { var elapsedSeconds = (float)time.ElapsedGameTime.TotalSeconds; Session.GameTime += elapsedSeconds; Session.FocussedEntity = null; // Remove finished graphics events var graphicsEffects = Session.World.GraphicsEvents.Where(e => e.End < Session.GameTime).ToArray(); foreach (var e in graphicsEffects) { Session.World.GraphicsEvents.Remove(e); } if (Session.UsePlayerTurns) { if (Session.ActivePlayer == null) { Session.ActivePlayer = Session.Players[0]; } Session.TurnTime += elapsedSeconds; if (Session.TurnTime > Session.SecondsPerTurn && Session.TurnState == TurnState.Running) { EndTurn(); } // End the turn if the turn is over and MinSecondsBetweenTurns have passed. // Wait for all entities to stand still, but at most MaxSecondsBetweenTurns. if (Session.TurnState == TurnState.WaitingForEnd && (Session.TurnTime > Session.MaxSecondsBetweenTurns || (Session.TurnTime > Session.MinSecondsBetweenTurns && !Session.World.IsSomethingMoving)) ) { StartNextTurn(); } } var worldState = Session.World; if (Game.Match.State == SessionState.Running && !Session.IsRemoteControlled) { // Update all active balls var currentControllers = ActiveControllers.Values.ToArray(); foreach (var controller in currentControllers) { if (controller != null && controller.Ball.Player.IsLocal && (controller.Ball.Player == Session.ActivePlayer || !Session.UsePlayerTurns)) { var playerMadeAction = controller.Update(elapsedSeconds, worldState); if (playerMadeAction) { EndTurn(); } } } // Check for dead balls List <Player> alivePlayers = new List <Player>(); Player winner = null; var ballControllers = BallControllers.Values.ToArray(); foreach (var controller in ballControllers) { if (controller.Ball.Disposed || !controller.Ball.IsAlive) { controller.Ball.Player.OwnedBalls.Remove(controller.Ball); if (controller.Ball.Player == Session.ActivePlayer) { StartNextTurn(); } ActiveControllers.Remove(controller.Ball.Player); BallControllers.Remove(controller.Ball); } else if (controller.Ball.IsAlive) { if (!alivePlayers.Contains(controller.Ball.Player)) { alivePlayers.Add(controller.Ball.Player); } winner = controller.Ball.Player; } } //TODO: find proper game finished condition, this one is not always correct if (alivePlayers.Count < 2) { Game.Match.State = SessionState.Finished; //TODO: find proper condition to determine the winner, this one is not always correct if (alivePlayers.Count == 1) { Game.Match.Winner = winner; Game.Services.GetService <Sound.SoundControl>().PlaySound(Sound.SoundControl.WinnerSounds[winner.TeamName]); } } } }