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;
}
}