#region CPL License /* Nuclex Framework Copyright (C) 2002-2010 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Nuclex.Input; using Nuclex.Input.Devices; namespace Nuclex.UserInterface.Input { /// Default implementation of an input capturer public class DefaultInputCapturer : IInputCapturer, IDisposable { #region class DummyInputReceiver /// Dummy receiver for input events private class DummyInputReceiver : IInputReceiver { /// Default instance of the dummy receiver public static readonly DummyInputReceiver Default = new DummyInputReceiver(); /// Injects an input command into the input receiver /// Input command to be injected public void InjectCommand(Command command) { } /// Called when a button on the gamepad has been pressed /// Button that has been pressed public void InjectButtonPress(Buttons button) { } /// Called when a button on the gamepad has been released /// Button that has been released public void InjectButtonRelease(Buttons button) { } /// Injects a mouse position update into the receiver /// New X coordinate of the mouse cursor on the screen /// New Y coordinate of the mouse cursor on the screen public void InjectMouseMove(float x, float y) { } /// Called when a mouse button has been pressed down /// Index of the button that has been pressed public void InjectMousePress(MouseButtons button) { } /// Called when a mouse button has been released again /// Index of the button that has been released public void InjectMouseRelease(MouseButtons button) { } /// Called when the mouse wheel has been rotated /// Number of ticks that the mouse wheel has been rotated public void InjectMouseWheel(float ticks) { } /// Called when a key on the keyboard has been pressed down /// Code of the key that was pressed public void InjectKeyPress(Keys keyCode) { } /// Called when a key on the keyboard has been released again /// Code of the key that was released public void InjectKeyRelease(Keys keyCode) { } /// Handle user text input by a physical or virtual keyboard /// Character that has been entered public void InjectCharacter(char character) { } } #endregion // class DummyInputReceiver /// /// Initializes a new input capturer, taking the input service from a service provider /// /// /// Service provider the input capturer will take the input service from /// public DefaultInputCapturer(IServiceProvider serviceProvider) : this(getInputService(serviceProvider)) { } /// /// Initializes a new input capturer using the specified input service /// /// /// Input service the capturer will subscribe to /// public DefaultInputCapturer(IInputService inputService) { this.inputService = inputService; this.inputReceiver = new DummyInputReceiver(); this.playerIndex = ExtendedPlayerIndex.One; this.keyPressedDelegate = new KeyDelegate(keyPressed); this.keyReleasedDelegate = new KeyDelegate(keyReleased); this.characterEnteredDelegate = new CharacterDelegate(characterEntered); this.mouseButtonPressedDelegate = new MouseButtonDelegate(mouseButtonPressed); this.mouseButtonReleasedDelegate = new MouseButtonDelegate(mouseButtonReleased); this.mouseMovedDelegate = new MouseMoveDelegate(mouseMoved); this.mouseWheelRotatedDelegate = new MouseWheelDelegate(mouseWheelRotated); this.buttonPressedDelegate = new GamePadButtonDelegate(buttonPressed); this.buttonReleasedDelegate = new GamePadButtonDelegate(buttonReleased); subscribeInputDevices(); } /// Immediately releases all resources owned by the instance public void Dispose() { if (this.inputService != null) { unsubscribeInputDevices(); this.inputService = null; } } /// Input receiver any captured input will be sent to public IInputReceiver InputReceiver { get { if (ReferenceEquals(this.inputReceiver, DummyInputReceiver.Default)) { return null; } else { return this.inputReceiver; } } set { if (value == null) { this.inputReceiver = DummyInputReceiver.Default; } else { this.inputReceiver = value; } } } /// Changes the controller which can interact with the GUI /// /// Index of the player whose controller will be allowed to interact with the GUI /// public void ChangePlayerIndex(PlayerIndex playerIndex) { ChangePlayerIndex((ExtendedPlayerIndex)playerIndex); } /// Changes the controller which can interact with the GUI /// /// Index of the player whose controller will be allowed to interact with the GUI /// public void ChangePlayerIndex(ExtendedPlayerIndex playerIndex) { unsubscribePlayerSpecificInputDevices(); this.playerIndex = playerIndex; subscribePlayerSpecificDevices(); } /// Subscribes to the events of all input devices private void subscribeInputDevices() { this.subscribedKeyboard = this.inputService.GetKeyboard(); this.subscribedKeyboard.KeyPressed += this.keyPressedDelegate; this.subscribedKeyboard.KeyReleased += this.keyReleasedDelegate; this.subscribedKeyboard.CharacterEntered += this.characterEnteredDelegate; this.subscribedMouse = this.inputService.GetMouse(); this.subscribedMouse.MouseButtonPressed += this.mouseButtonPressedDelegate; this.subscribedMouse.MouseButtonReleased += this.mouseButtonReleasedDelegate; this.subscribedMouse.MouseMoved += this.mouseMovedDelegate; this.subscribedMouse.MouseWheelRotated += this.mouseWheelRotatedDelegate; subscribePlayerSpecificDevices(); } /// Subscribes to the events of all player-specific input devices private void subscribePlayerSpecificDevices() { this.subscribedGamePad = this.inputService.GetGamePad(this.playerIndex); this.subscribedGamePad.ButtonPressed += this.buttonPressedDelegate; this.subscribedGamePad.ButtonReleased += this.buttonReleasedDelegate; if (this.playerIndex < ExtendedPlayerIndex.Five) { var standardPlayerIndex = (PlayerIndex)this.playerIndex; this.subscribedChatPad = this.inputService.GetKeyboard(standardPlayerIndex); this.subscribedChatPad.KeyPressed += this.keyPressedDelegate; this.subscribedChatPad.KeyReleased += this.keyReleasedDelegate; this.subscribedChatPad.CharacterEntered += this.characterEnteredDelegate; } } /// Unsubscribes from the events of all input devices private void unsubscribeInputDevices() { unsubscribePlayerSpecificInputDevices(); if (this.subscribedKeyboard != null) { this.subscribedKeyboard.CharacterEntered -= this.characterEnteredDelegate; this.subscribedKeyboard.KeyReleased -= this.keyReleasedDelegate; this.subscribedKeyboard.KeyPressed -= this.keyPressedDelegate; this.subscribedKeyboard = null; } if (this.subscribedMouse != null) { this.subscribedMouse.MouseWheelRotated -= this.mouseWheelRotatedDelegate; this.subscribedMouse.MouseMoved -= this.mouseMovedDelegate; this.subscribedMouse.MouseButtonReleased -= this.mouseButtonReleasedDelegate; this.subscribedMouse.MouseButtonPressed -= this.mouseButtonPressedDelegate; this.subscribedMouse = null; } } /// Unsubscribes from the events of all player-specific input devices private void unsubscribePlayerSpecificInputDevices() { if (this.subscribedChatPad != null) { this.subscribedChatPad.CharacterEntered -= this.characterEnteredDelegate; this.subscribedChatPad.KeyReleased -= this.keyReleasedDelegate; this.subscribedChatPad.KeyPressed -= this.keyPressedDelegate; this.subscribedChatPad = null; } if (this.subscribedGamePad != null) { this.subscribedGamePad.ButtonPressed -= this.buttonPressedDelegate; this.subscribedGamePad.ButtonReleased -= this.buttonReleasedDelegate; this.subscribedGamePad = null; } } /// Called when a button on the game pad has been released /// Button that has been released private void buttonReleased(Buttons buttons) { this.inputReceiver.InjectButtonRelease(buttons); } /// Called when a button on the game pad has been pressed /// Button that has been pressed private void buttonPressed(Buttons buttons) { if ((buttons & Buttons.DPadUp) != 0) { this.inputReceiver.InjectCommand(Command.Up); } else if ((buttons & Buttons.DPadDown) != 0) { this.inputReceiver.InjectCommand(Command.Down); } else if ((buttons & Buttons.DPadLeft) != 0) { this.inputReceiver.InjectCommand(Command.Left); } else if ((buttons & Buttons.DPadRight) != 0) { this.inputReceiver.InjectCommand(Command.Right); } else { this.inputReceiver.InjectButtonPress(buttons); } } /// Called when the mouse wheel has been rotated /// Number of ticks the wheel was rotated private void mouseWheelRotated(float ticks) { this.inputReceiver.InjectMouseWheel(ticks); } /// Called when the mouse cursor has been moved /// New X coordinate of the mouse cursor /// New Y coordinate of the mouse cursor private void mouseMoved(float x, float y) { this.inputReceiver.InjectMouseMove(x, y); } /// Called when a mouse button has been released /// Mouse button that has been released private void mouseButtonReleased(MouseButtons buttons) { this.inputReceiver.InjectMouseRelease(buttons); } /// Called when a mouse button has been pressed /// Mouse button that has been pressed private void mouseButtonPressed(MouseButtons buttons) { this.inputReceiver.InjectMousePress(buttons); } /// Called when a character has been entered on the keyboard /// Character that has been entered private void characterEntered(char character) { this.inputReceiver.InjectCharacter(character); } /// Called when a key has been released /// Key that was released private void keyReleased(Keys key) { this.inputReceiver.InjectKeyRelease(key); } /// Called when a key has been pressed /// Key that was pressed private void keyPressed(Keys key) { this.inputReceiver.InjectKeyPress(key); } /// Retrieves the input service from a service provider /// /// Service provider the service is taken from /// /// The input service stored in the service provider private static IInputService getInputService(IServiceProvider serviceProvider) { var inputService = (IInputService)serviceProvider.GetService( typeof(IInputService) ); if (inputService == null) { throw new InvalidOperationException( "Using the GUI with the DefaultInputCapturer requires the IInputService. " + "Please either add the IInputService to Game.Services by using the " + "Nuclex.Input.InputManager in your game or provide a custom IInputCapturer " + "implementation for the GUI and assign it before GuiManager.Initialize() " + "is called." ); } return inputService; } /// Player index this input capturer is working with private ExtendedPlayerIndex playerIndex; /// Current receiver of input events /// /// Always valid. If no input receiver is assigned, this field will be set /// to a dummy receiver. /// private IInputReceiver inputReceiver; /// Input service the capturer is currently subscribed to private IInputService inputService; /// Keyboard the input capturer is subscribed to private IKeyboard subscribedKeyboard; /// Mouse the input capturer is subscribed to private IMouse subscribedMouse; /// Game pad the input capturer is subscribed to private IGamePad subscribedGamePad; /// Chat pad the input capturer is subscribed to private IKeyboard subscribedChatPad; /// Delegate for the keyPressed() method private KeyDelegate keyPressedDelegate; /// Delegate for the keyReleased() method private KeyDelegate keyReleasedDelegate; /// Delegate for the characterEntered() method private CharacterDelegate characterEnteredDelegate; /// Delegate for the mouseButtonPressed() method private MouseButtonDelegate mouseButtonPressedDelegate; /// Delegate for the mouseButtonReleased() method private MouseButtonDelegate mouseButtonReleasedDelegate; /// Delegate for the mouseMoved() method private MouseMoveDelegate mouseMovedDelegate; /// Delegate for the mouseWheelRotated() method private MouseWheelDelegate mouseWheelRotatedDelegate; /// Delegate for the buttonPressed() method private GamePadButtonDelegate buttonPressedDelegate; /// Delegate for the buttonReleased() method private GamePadButtonDelegate buttonReleasedDelegate; } } // namespace Nuclex.UserInterface.Input