More work on the RecordingInputSystem.
This commit is contained in:
parent
a54acf8f6f
commit
027e823254
@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -58,16 +59,44 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Abstract Class. Classes derived from this class allow recording and Playback of Inputs.
|
/// Abstract Class. Classes derived from this class allow recording and Playback of Inputs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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 RecordingState RecordingState { get; protected set; }
|
||||||
|
|
||||||
|
public event EventHandler EndOfPlaybackReached;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How many bytes this Instance requires per Frame. Must never change!
|
||||||
|
/// </summary>
|
||||||
|
public int FramePacketLenght { get; protected set; }
|
||||||
|
|
||||||
public RecordableDevice()
|
public RecordableDevice()
|
||||||
{
|
{
|
||||||
RecordingState = RecordingState.None;
|
RecordingState = RecordingState.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartRecording()
|
/// <summary>
|
||||||
|
/// Initializes the Device using a new
|
||||||
|
/// MemoryStream for input-buffering.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Initialize()
|
||||||
|
{
|
||||||
|
Initialize(new MemoryStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the Device using the specified stream
|
||||||
|
/// for input-buffering.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Initialize(Stream bufferStream)
|
||||||
|
{
|
||||||
|
recordStream = bufferStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void StartRecording()
|
||||||
{
|
{
|
||||||
if (RecordingState == RecordingState.Recording)
|
if (RecordingState == RecordingState.Recording)
|
||||||
return;
|
return;
|
||||||
@ -75,7 +104,7 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
RecordingState = RecordingState.Recording;
|
RecordingState = RecordingState.Recording;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopRecording()
|
public virtual void StopRecording()
|
||||||
{
|
{
|
||||||
if (RecordingState != RecordingState.Recording)
|
if (RecordingState != RecordingState.Recording)
|
||||||
throw new InvalidOperationException("Recording wasn't started for this device!");
|
throw new InvalidOperationException("Recording wasn't started for this device!");
|
||||||
@ -83,7 +112,7 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
RecordingState = RecordingState.None;
|
RecordingState = RecordingState.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartPlayback()
|
public virtual void StartPlayback()
|
||||||
{
|
{
|
||||||
if (RecordingState == RecordingState.Recording)
|
if (RecordingState == RecordingState.Recording)
|
||||||
throw new InvalidOperationException("Recording is currently running for this device.");
|
throw new InvalidOperationException("Recording is currently running for this device.");
|
||||||
@ -91,9 +120,78 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
RecordingState = RecordingState.Playback;
|
RecordingState = RecordingState.Playback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopPlayback()
|
public virtual void StopPlayback()
|
||||||
{
|
{
|
||||||
RecordingState = RecordingState.None;
|
RecordingState = RecordingState.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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!
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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!
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
|
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class RecordingGamePad : RecordableDevice,IGamePad
|
public class RecordingGamePad : RecordableDevice, IGamePad
|
||||||
{
|
{
|
||||||
public GamePadCapabilities GetCapabilities(PlayerIndex playerIndex)
|
public GamePadCapabilities GetCapabilities(PlayerIndex playerIndex)
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace ANX.InputSystem.Windows.Recording
|
namespace ANX.InputSystem.Windows.Recording
|
||||||
{
|
{
|
||||||
enum RecordingState
|
public enum RecordingState
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This device is recording input.
|
/// This device is recording input.
|
||||||
@ -70,11 +70,18 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PacketType : byte
|
||||||
|
{
|
||||||
|
NullFrameCounter = 0,
|
||||||
|
InputData = 1
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Static Helper-class containing some recording related stuff.
|
/// Static Helper-class containing some recording related stuff.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static class RecordingHelper
|
static class RecordingHelper
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper arround another IKeyboard, will record all inputs and allows playback.
|
/// Wrapper arround another IKeyboard, will record all inputs and allows playback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class RecordingKeyboard : RecordableDevice, IKeyboard
|
public class RecordingKeyboard : RecordableDevice, IKeyboard
|
||||||
{
|
{
|
||||||
public IntPtr WindowHandle { get; set; }
|
public IntPtr WindowHandle { get; set; }
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper aroung another IMotionSensingDevice, will record all inputs and allows playback.
|
/// Wrapper aroung another IMotionSensingDevice, will record all inputs and allows playback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class RecordingMotionSensingDevice : RecordableDevice,IMotionSensingDevice
|
public class RecordingMotionSensingDevice : RecordableDevice, IMotionSensingDevice
|
||||||
{
|
{
|
||||||
public GraphicsDevice GraphicsDevice
|
public GraphicsDevice GraphicsDevice
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using ANX.Framework.NonXNA;
|
using ANX.Framework.NonXNA;
|
||||||
using ANX.Framework.Input;
|
using ANX.Framework.Input;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -57,10 +58,28 @@ using ANX.Framework.Input;
|
|||||||
|
|
||||||
namespace ANX.InputSystem.Windows.Recording
|
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
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
|
/// Wrapper arround another IGamePad, will record all inputs and allows playback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class RecordingMouse : RecordableDevice,IMouse
|
public class RecordingMouse : RecordableDevice, IMouse
|
||||||
{
|
{
|
||||||
public IntPtr WindowHandle { get; set; }
|
public IntPtr WindowHandle { get; set; }
|
||||||
|
|
||||||
@ -73,5 +92,39 @@ namespace ANX.InputSystem.Windows.Recording
|
|||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user