Added event-driven mouse encapsulation

This commit is contained in:
William Moorehouse 2015-06-13 19:17:06 -04:00
parent 29c07a1db2
commit 9388ec3a69
8 changed files with 340 additions and 3 deletions

View File

@ -0,0 +1,25 @@
using System;
namespace TrueCraft.Client.Input
{
/// <summary>
///
/// </summary>
public enum MouseButton
{
/// <summary>
///
/// </summary>
Left,
/// <summary>
///
/// </summary>
Right,
/// <summary>
///
/// </summary>
Middle
}
}

View File

@ -0,0 +1,34 @@
using System;
namespace TrueCraft.Client.Input
{
/// <summary>
///
/// </summary>
public class MouseButtonEventArgs : MouseEventArgs
{
/// <summary>
///
/// </summary>
public MouseButton Button { get; private set; }
/// <summary>
///
/// </summary>
public bool IsPressed { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="button"></param>
/// <param name="isPressed"></param>
public MouseButtonEventArgs(int x, int y, MouseButton button, bool isPressed)
: base(x, y)
{
Button = button;
IsPressed = isPressed;
}
}
}

View File

@ -0,0 +1,157 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace TrueCraft.Client.Input
{
/// <summary>
/// Encapsulates mouse input in an event-driven manner.
/// </summary>
public class MouseComponent : GameComponent
{
/// <summary>
///
/// </summary>
public event EventHandler<MouseMoveEventArgs> Move;
/// <summary>
///
/// </summary>
public event EventHandler<MouseButtonEventArgs> ButtonDown;
/// <summary>
///
/// </summary>
public event EventHandler<MouseButtonEventArgs> ButtonUp;
/// <summary>
///
/// </summary>
public event EventHandler<MouseScrollEventArgs> Scroll;
/// <summary>
/// Gets the state for this mouse component.
/// </summary>
public MouseState State { get; private set; }
/// <summary>
/// Creates a new mouse component.
/// </summary>
/// <param name="game"></param>
public MouseComponent(Game game)
: base(game)
{
}
/// <summary>
/// Initializes this mouse component.
/// </summary>
public override void Initialize()
{
State = Mouse.GetState();
base.Initialize();
}
/// <summary>
/// Updates this mouse component.
/// </summary>
/// <param name="gameTime"></param>
public override void Update(GameTime gameTime)
{
var newState = Mouse.GetState();
Process(newState, State);
State = newState;
base.Update(gameTime);
}
/// <summary>
/// Processes a change between two states.
/// </summary>
/// <param name="newState"></param>
/// <param name="last"></param>
private void Process(MouseState current, MouseState last)
{
// Movement.
if ((current.X != last.X) || (current.Y != last.Y))
{
var args = new MouseMoveEventArgs(current.X, current.Y, (current.X - last.X), (current.Y - last.Y));
if (Move != null)
Move(this, args);
}
// Scrolling.
if (current.ScrollWheelValue != last.ScrollWheelValue)
{
var args = new MouseScrollEventArgs(current.X, current.Y, current.ScrollWheelValue, (current.ScrollWheelValue - last.ScrollWheelValue));
if (Scroll != null)
Scroll(this, args);
}
// A bit of code duplication here, shame XNA doesn't expose button state through an enumeration...
// Left button.
if (current.LeftButton != last.LeftButton)
{
var args = new MouseButtonEventArgs(current.X, current.Y, MouseButton.Left, (current.LeftButton == ButtonState.Pressed));
if (args.IsPressed)
{
if (ButtonDown != null)
ButtonDown(this, args);
}
else
{
if (ButtonUp != null)
ButtonUp(this, args);
}
}
// Right button.
if (current.RightButton != last.RightButton)
{
var args = new MouseButtonEventArgs(current.X, current.Y, MouseButton.Right, (current.RightButton == ButtonState.Pressed));
if (args.IsPressed)
{
if (ButtonDown != null)
ButtonDown(this, args);
}
else
{
if (ButtonUp != null)
ButtonUp(this, args);
}
}
// Middle button.
if (current.MiddleButton != last.MiddleButton)
{
var args = new MouseButtonEventArgs(current.X, current.Y, MouseButton.Middle, (current.MiddleButton == ButtonState.Pressed));
if (args.IsPressed)
{
if (ButtonDown != null)
ButtonDown(this, args);
}
else
{
if (ButtonUp != null)
ButtonUp(this, args);
}
}
}
/// <summary>
/// Disposes of this mouse component.
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
Move = null;
ButtonDown = null;
ButtonUp = null;
Scroll = null;
base.Dispose(disposing);
}
}
}

View File

@ -0,0 +1,31 @@
using System;
namespace TrueCraft.Client.Input
{
/// <summary>
///
/// </summary>
public class MouseEventArgs : EventArgs
{
/// <summary>
///
/// </summary>
public int X { get; private set; }
/// <summary>
///
/// </summary>
public int Y { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public MouseEventArgs(int x, int y)
{
X = x;
Y = y;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
namespace TrueCraft.Client.Input
{
/// <summary>
///
/// </summary>
public class MouseMoveEventArgs : MouseEventArgs
{
/// <summary>
///
/// </summary>
public int DeltaX { get; private set; }
/// <summary>
///
/// </summary>
public int DeltaY { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="deltaX"></param>
/// <param name="deltaY"></param>
public MouseMoveEventArgs(int x, int y, int deltaX, int deltaY)
: base(x, y)
{
DeltaX = deltaX;
DeltaY = DeltaY;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
namespace TrueCraft.Client.Input
{
/// <summary>
///
/// </summary>
public class MouseScrollEventArgs : MouseEventArgs
{
/// <summary>
///
/// </summary>
public int Value { get; private set; }
/// <summary>
///
/// </summary>
public int DeltaValue { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="value"></param>
/// <param name="deltaValue"></param>
public MouseScrollEventArgs(int x, int y, int value, int deltaValue)
: base(x, y)
{
Value = value;
DeltaValue = deltaValue;
}
}
}

View File

@ -94,6 +94,12 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Input\MouseButton.cs" />
<Compile Include="Input\MouseButtonEventArgs.cs" />
<Compile Include="Input\MouseComponent.cs" />
<Compile Include="Input\MouseEventArgs.cs" />
<Compile Include="Input\MouseMoveEventArgs.cs" />
<Compile Include="Input\MouseScrollEventArgs.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Rendering\Camera.cs" />

View File

@ -13,6 +13,7 @@ using System.ComponentModel;
using TrueCraft.Core.Networking.Packets;
using TrueCraft.API.World;
using System.Collections.Concurrent;
using TrueCraft.Client.Input;
namespace TrueCraft.Client
{
@ -37,6 +38,8 @@ namespace TrueCraft.Client
private Camera Camera;
private bool MouseCaptured;
private KeyboardState PreviousKeyboardState;
private MouseComponent MouseComponent { get; set; }
private GameTime GameTime { get; set; }
private BasicEffect OpaqueEffect, TransparentEffect;
@ -57,6 +60,10 @@ namespace TrueCraft.Client
IncomingTransparentChunks = new ConcurrentBag<ChunkMesh>();
PendingMainThreadActions = new ConcurrentBag<Action>();
MouseCaptured = true;
var mouseComponent = new MouseComponent(this);
MouseComponent = mouseComponent;
Components.Add(mouseComponent);
}
protected override void Initialize()
@ -78,6 +85,7 @@ namespace TrueCraft.Client
UpdateCamera();
PreviousKeyboardState = Keyboard.GetState();
Window.ClientSizeChanged += (sender, e) => CreateRenderTarget();
MouseComponent.Move += OnMouseComponentMove;
CreateRenderTarget();
}
@ -183,14 +191,20 @@ namespace TrueCraft.Client
if (state.IsKeyUp(Keys.Tab) && oldState.IsKeyDown(Keys.Tab))
MouseCaptured = !MouseCaptured;
}
private void OnMouseComponentMove(object sender, MouseMoveEventArgs e)
{
if (MouseCaptured)
{
var centerX = GraphicsDevice.Viewport.Width / 2;
var centerY = GraphicsDevice.Viewport.Height / 2;
var mouse = Mouse.GetState();
var look = new Vector2(centerX - mouse.Position.X, centerY - mouse.Position.Y)
* (float)(gameTime.ElapsedGameTime.TotalSeconds * 70);
Mouse.SetPosition(centerX, centerY);
var look = new Vector2(
(centerX - e.X),
(centerY - e.Y) * (float)(GameTime.ElapsedGameTime.TotalSeconds * 70));
Client.Yaw += look.X;
Client.Pitch += look.Y;
Client.Yaw %= 360;
@ -203,6 +217,8 @@ namespace TrueCraft.Client
protected override void Update(GameTime gameTime)
{
GameTime = gameTime;
foreach (var i in Interfaces)
{
i.Update(gameTime);