using System; using System.Collections.Generic; using Chernobyl.Collections.Generic.Event; using Chernobyl.Dependency; using Chernobyl.Input.Controls; using Chernobyl.Input.Xna.Controls.Gamepad; using Chernobyl.Input.Xna.Controls.Keyboard; using Chernobyl.Input.Xna.Controls.Mouse; using Chernobyl.Plugin; using Chernobyl.Update; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using IUpdateable = Chernobyl.Update.IUpdateable; namespace Chernobyl.Input.Xna { /// /// Configures and holds information about Chernobyl.Input.Xna. /// public class XnaInputPlugin : Updateable, IPlugin { /// /// Constructor. /// /// The /// instance that gives and takes services. public XnaInputPlugin(IEventCollection services) { _xnaGamepads = new SortedList(); Services = services; services.Inject(this); } /// /// The services provided by this plug-in or null if no services are /// provided. /// public IEventCollection Services { get; private set; } /// /// The used to update the controls. /// [Inject(Type = typeof(IRootUpdateable))] public IUpdateable Updateable { get { return _updateable; } set { IUpdateable previousValue = _updateable; _updateable = value; if(previousValue != null) Chernobyl.Update.Updateable.SeparateParentChild(previousValue, this); if(_updateable != null) Chernobyl.Update.Updateable.MakeParentChild(_updateable, this); } } /// /// Provides the main mouse in the application. /// [Provide] public IMouse Mouse { get { if (_mouse == null) { _mouse = new XnaMouse(Services); Chernobyl.Update.Updateable.MakeParentChild(this, _mouse); } return _mouse; } } /// /// Provides the main keyboard in the application. /// [Provide] public IKeyboard Keyboard { get { if (_keyboard == null) { _keyboard = new XnaKeyboard(Services); Chernobyl.Update.Updateable.MakeParentChild(this, _keyboard); } return _keyboard; } } /// /// The instances currently plugged into the /// device and are available for use. The /// and /// can be used to know /// when a device has been connected or disconnected from the machine. /// [Inject(typeof(InputPlugin))] public IEventCollection Gamepads { get { return _gamepads; } set { IEventCollection previousValue = _gamepads; _gamepads = value; if(previousValue != null) { // Remove the XNA gamepads from the old gamepad list. foreach (KeyValuePair gamepadPair in _xnaGamepads) previousValue.Remove(gamepadPair.Value); } if (_gamepads != null) { // Give the currently existing gamepads to the incoming list. foreach (KeyValuePair gamepadPair in _xnaGamepads) _gamepads.Add(gamepadPair.Value); } } } /// /// By default, this method just loops through it's children /// and calls on them, passing in /// the delta time it receives. /// /// The amount of time that has /// passed since this update was last called. public override void Update(TimeSpan deltaTime) { // Check for new gamepads. foreach (PlayerIndex playerIndex in Enum.GetValues(typeof(PlayerIndex))) { // Get the state of the gamepad // TODO: use GamePadDeadZone.None instead and calculate our own deadzone. GamePadState gamepadState = GamePad.GetState(playerIndex, GamePadDeadZone.Circular); XnaGamepad xnaGamepad; _xnaGamepads.TryGetValue(playerIndex, out xnaGamepad); if(gamepadState.IsConnected == true) { if(xnaGamepad == null) { // This gamepad has just connected. We need to create a // new gamepad to represent it. xnaGamepad = new XnaGamepad(Services, playerIndex, gamepadState); MakeParentChild(this, xnaGamepad); _xnaGamepads.Add(playerIndex, xnaGamepad); if (Gamepads != null) Gamepads.Add(xnaGamepad); } else { // The gamepad already exists so we'll just update its // state. xnaGamepad.State = gamepadState; } } else { // This gamepad is no longer available. Remove it from our // lists. if (xnaGamepad != null) { xnaGamepad.State = gamepadState; SeparateParentChild(this, xnaGamepad); _xnaGamepads.Remove(playerIndex); if (Gamepads != null) Gamepads.Remove(xnaGamepad); } } } base.Update(deltaTime); } /// /// The instances currently connected to this /// device. /// SortedList _xnaGamepads; /// /// The backing field to . /// IKeyboard _keyboard; /// /// The backing field to . /// IMouse _mouse; /// /// The backing field to . /// IUpdateable _updateable; /// /// The backing field to . /// IEventCollection _gamepads; } }