diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordableDevice.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordableDevice.cs
index eff1a9fc..34f16fae 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordableDevice.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordableDevice.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.IO;
#endregion
@@ -58,16 +59,44 @@ namespace ANX.InputSystem.Windows.Recording
///
/// Abstract Class. Classes derived from this class allow recording and Playback of Inputs.
///
- abstract class RecordableDevice
+ public abstract class RecordableDevice
{
+ protected Stream recordStream; //The stream where the input is written to
+ protected int nullStateCounter; //Used to sum up frames with no input.
+
public RecordingState RecordingState { get; protected set; }
+ public event EventHandler EndOfPlaybackReached;
+
+ ///
+ /// How many bytes this Instance requires per Frame. Must never change!
+ ///
+ public int FramePacketLenght { get; protected set; }
+
public RecordableDevice()
{
RecordingState = RecordingState.None;
}
-
- public void StartRecording()
+
+ ///
+ /// Initializes the Device using a new
+ /// MemoryStream for input-buffering.
+ ///
+ public virtual void Initialize()
+ {
+ Initialize(new MemoryStream());
+ }
+
+ ///
+ /// Initializes the Device using the specified stream
+ /// for input-buffering.
+ ///
+ public virtual void Initialize(Stream bufferStream)
+ {
+ recordStream = bufferStream;
+ }
+
+ public virtual void StartRecording()
{
if (RecordingState == RecordingState.Recording)
return;
@@ -75,7 +104,7 @@ namespace ANX.InputSystem.Windows.Recording
RecordingState = RecordingState.Recording;
}
- public void StopRecording()
+ public virtual void StopRecording()
{
if (RecordingState != RecordingState.Recording)
throw new InvalidOperationException("Recording wasn't started for this device!");
@@ -83,7 +112,7 @@ namespace ANX.InputSystem.Windows.Recording
RecordingState = RecordingState.None;
}
- public void StartPlayback()
+ public virtual void StartPlayback()
{
if (RecordingState == RecordingState.Recording)
throw new InvalidOperationException("Recording is currently running for this device.");
@@ -91,9 +120,78 @@ namespace ANX.InputSystem.Windows.Recording
RecordingState = RecordingState.Playback;
}
- public void StopPlayback()
+ public virtual void StopPlayback()
{
RecordingState = RecordingState.None;
}
+
+ ///
+ /// Writes the current input state to the buffering stream. Pass null
+ /// for state, if no input is done (no keys down etc.).
+ /// Must be called once per Frame!
+ ///
+ protected virtual void WriteState(byte[] state)
+ {
+ if (state == null)
+ {
+ nullStateCounter++;
+ return;
+ }
+
+ if (state.Length != FramePacketLenght)
+ throw new InvalidOperationException("The passed state's lenght does not match the speficed FramePaketLenght.");
+
+ if (nullStateCounter > 0) //Note how many packets we had nothing
+ {
+ recordStream.WriteByte((byte)PacketType.NullFrameCounter);
+ recordStream.Write(BitConverter.GetBytes(nullStateCounter), 0, 4);
+ }
+
+ recordStream.WriteByte((byte)PacketType.InputData);
+ recordStream.Write(state, 0, state.Length);
+ }
+
+ ///
+ /// Reads the next input-state from the buffering stream. Might
+ /// return null, if no input was made in this frame.
+ /// Must be called once per Frame!
+ ///
+ protected virtual byte[] ReadState()
+ {
+ if (nullStateCounter > 0) //we have null-states pending
+ {
+ nullStateCounter--;
+ return null;
+ }
+
+ if (recordStream.Position == recordStream.Length)
+ {
+ OnEndOfPlaybackReached();
+ return null; //TODO: Better switch to RecordingState.None here?
+ }
+
+ PacketType type = (PacketType)recordStream.ReadByte();
+ switch (type)
+ {
+ case PacketType.NullFrameCounter:
+ byte[] buffer = new byte[4];
+ recordStream.Read(buffer, 0, 4);
+ nullStateCounter = BitConverter.ToInt32(buffer, 0) - 1;
+ return null;
+ case PacketType.InputData:
+ byte[] buffer2 = new byte[FramePacketLenght];
+ recordStream.Read(buffer2, 0, FramePacketLenght);
+ return buffer2;
+ default:
+ throw new NotImplementedException("The PaketType " + Enum.GetName(typeof(PacketType), type) + "is not supported.");
+ }
+
+ }
+
+ protected virtual void OnEndOfPlaybackReached()
+ {
+ if (EndOfPlaybackReached != null)
+ EndOfPlaybackReached(this, EventArgs.Empty);
+ }
}
}
diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingGamePad.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingGamePad.cs
index 77b651bc..3e7ee303 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingGamePad.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingGamePad.cs
@@ -61,7 +61,7 @@ namespace ANX.InputSystem.Windows.Recording
///
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
///
- class RecordingGamePad : RecordableDevice,IGamePad
+ public class RecordingGamePad : RecordableDevice, IGamePad
{
public GamePadCapabilities GetCapabilities(PlayerIndex playerIndex)
{
diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingHelper.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingHelper.cs
index 68f5c07b..130202f6 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingHelper.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingHelper.cs
@@ -55,7 +55,7 @@ using System.Text;
namespace ANX.InputSystem.Windows.Recording
{
- enum RecordingState
+ public enum RecordingState
{
///
/// This device is recording input.
@@ -70,11 +70,18 @@ namespace ANX.InputSystem.Windows.Recording
///
None
}
+
+ enum PacketType : byte
+ {
+ NullFrameCounter = 0,
+ InputData = 1
+ }
///
/// Static Helper-class containing some recording related stuff.
///
static class RecordingHelper
{
+
}
}
diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingKeyboard.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingKeyboard.cs
index 282d117c..a52a2e8f 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingKeyboard.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingKeyboard.cs
@@ -60,7 +60,7 @@ namespace ANX.InputSystem.Windows.Recording
///
/// Wrapper arround another IKeyboard, will record all inputs and allows playback.
///
- class RecordingKeyboard : RecordableDevice, IKeyboard
+ public class RecordingKeyboard : RecordableDevice, IKeyboard
{
public IntPtr WindowHandle { get; set; }
diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMotionSensingDevice.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMotionSensingDevice.cs
index 42510a66..8982f7e2 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMotionSensingDevice.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMotionSensingDevice.cs
@@ -61,7 +61,7 @@ namespace ANX.InputSystem.Windows.Recording
///
/// Wrapper aroung another IMotionSensingDevice, will record all inputs and allows playback.
///
- class RecordingMotionSensingDevice : RecordableDevice,IMotionSensingDevice
+ public class RecordingMotionSensingDevice : RecordableDevice, IMotionSensingDevice
{
public GraphicsDevice GraphicsDevice
{
diff --git a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMouse.cs b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMouse.cs
index a1c8aec9..070d2784 100644
--- a/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMouse.cs
+++ b/InputSystems/ANX.InputSystems.Windows.Recording/RecordingMouse.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using ANX.Framework.NonXNA;
using ANX.Framework.Input;
+using System.IO;
#endregion
@@ -57,10 +58,28 @@ using ANX.Framework.Input;
namespace ANX.InputSystem.Windows.Recording
{
+ [Flags]
+ public enum MouseRecordInfo : byte
+ {
+ LeftButton = 1,
+ RightButton = 2,
+ MiddleButton = 4,
+ X1Button = 8,
+ X2Button = 16,
+ ScrollWheel = 32,
+ XPosition = 64,
+ YPosition = 128,
+ LRMButtons = LeftButton | RightButton | MiddleButton,
+ XButtons = X1Button | X2Button,
+ AllButtons = LRMButtons | XButtons,
+ Position = XPosition | YPosition,
+ All = AllButtons | Position | ScrollWheel
+ }
+
///
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
///
- class RecordingMouse : RecordableDevice,IMouse
+ public class RecordingMouse : RecordableDevice, IMouse
{
public IntPtr WindowHandle { get; set; }
@@ -73,5 +92,39 @@ namespace ANX.InputSystem.Windows.Recording
{
throw new NotImplementedException();
}
+
+ public void Initialize(MouseRecordInfo info)
+ {
+ base.Initialize();
+ }
+
+ public void Initialize(MouseRecordInfo info, Stream bufferStream)
+ {
+ base.Initialize(bufferStream);
+ }
+
+ private int GetPaketSize(MouseRecordInfo info)
+ {
+ int ret = 0; //TODO: Pack the bools in one byte to save space sizeof(bool) == sizeof(byte)!
+ if (info.HasFlag(MouseRecordInfo.LeftButton))
+ ret += sizeof(bool);
+ if (info.HasFlag(MouseRecordInfo.RightButton))
+ ret += sizeof(bool);
+ if (info.HasFlag(MouseRecordInfo.MiddleButton))
+ ret += sizeof(bool);
+ if (info.HasFlag(MouseRecordInfo.X1Button))
+ ret += sizeof(bool);
+ if (info.HasFlag(MouseRecordInfo.X2Button))
+ ret += sizeof(bool);
+
+ if (info.HasFlag(MouseRecordInfo.XPosition))
+ ret += sizeof(int);
+ if (info.HasFlag(MouseRecordInfo.YPosition))
+ ret += sizeof(int);
+ if (info.HasFlag(MouseRecordInfo.ScrollWheel))
+ ret += sizeof(int);
+
+ return ret;
+ }
}
}