#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