Generalize SharedStore

This commit is contained in:
X9VoiD 2022-01-13 01:58:20 +08:00
parent 8c96ec7537
commit 3dd078ea2d
14 changed files with 101 additions and 72 deletions

View file

@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Platform.Pointer;
using OpenTabletDriver.Plugin.Tablet; using OpenTabletDriver.Plugin.Tablet;
using VoiDPlugins.Library.VMulti; using VoiDPlugins.Library.VMulti;
using VoiDPlugins.Library.VMulti.Device; using VoiDPlugins.Library.VMulti.Device;
using VoiDPlugins.Library.VoiD;
namespace VoiDPlugins.OutputMode namespace VoiDPlugins.OutputMode
{ {
@ -15,7 +16,7 @@ namespace VoiDPlugins.OutputMode
public VMultiAbsolutePointer(TabletReference tabletReference, IVirtualScreen virtualScreen) public VMultiAbsolutePointer(TabletReference tabletReference, IVirtualScreen virtualScreen)
{ {
_instance = VMultiInstanceManager.RetrieveVMultiInstance("VMultiAbs", tabletReference, () => new AbsoluteInputReport()); _instance = GlobalStore<VMultiInstance>.GetOrInitialize(tabletReference, () => new VMultiInstance<AbsoluteInputReport>("VMultiAbs", new AbsoluteInputReport()));
_rawPointer = _instance.Pointer; _rawPointer = _instance.Pointer;
_conversionFactor = new Vector2(32767, 32767) / new Vector2(virtualScreen.Width, virtualScreen.Height); _conversionFactor = new Vector2(32767, 32767) / new Vector2(virtualScreen.Width, virtualScreen.Height);
} }

View file

@ -3,6 +3,7 @@ using OpenTabletDriver.Plugin.Platform.Pointer;
using OpenTabletDriver.Plugin.Tablet; using OpenTabletDriver.Plugin.Tablet;
using VoiDPlugins.Library.VMulti; using VoiDPlugins.Library.VMulti;
using VoiDPlugins.Library.VMulti.Device; using VoiDPlugins.Library.VMulti.Device;
using VoiDPlugins.Library.VoiD;
namespace VoiDPlugins.OutputMode namespace VoiDPlugins.OutputMode
{ {
@ -14,7 +15,7 @@ namespace VoiDPlugins.OutputMode
public VMultiRelativePointer(TabletReference tabletReference) public VMultiRelativePointer(TabletReference tabletReference)
{ {
_instance = VMultiInstanceManager.RetrieveVMultiInstance("VMultiRel", tabletReference, () => new RelativeInputReport()); _instance = GlobalStore<VMultiInstance>.GetOrInitialize(tabletReference, () => new VMultiInstance<RelativeInputReport>("VMultiAbs", new RelativeInputReport()));
_rawPointer = _instance.Pointer; _rawPointer = _instance.Pointer;
} }

View file

@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin;
using OpenTabletDriver.Plugin.Attributes; using OpenTabletDriver.Plugin.Attributes;
using OpenTabletDriver.Plugin.Tablet; using OpenTabletDriver.Plugin.Tablet;
using VoiDPlugins.Library.VMulti; using VoiDPlugins.Library.VMulti;
using VoiDPlugins.Library.VoiD;
namespace VoiDPlugins.OutputMode namespace VoiDPlugins.OutputMode
{ {
@ -29,7 +30,7 @@ namespace VoiDPlugins.OutputMode
private void Initialize(TabletReference tabletReference) private void Initialize(TabletReference tabletReference)
{ {
_instance = VMultiInstanceManager.RetrieveVMultiInstance(tabletReference); _instance = GlobalStore<VMultiInstance>.Get(tabletReference);
} }
public void Press(TabletReference tablet, IDeviceReport report) public void Press(TabletReference tablet, IDeviceReport report)

View file

@ -1,5 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<VMultiLibrary>true</VMultiLibrary> <VMultiLibrary>true</VMultiLibrary>
<VoiDLibrary>true</VoiDLibrary>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -9,7 +9,7 @@ namespace VoiDPlugins.OutputMode
{ {
private readonly Vector2 _conversionFactor; private readonly Vector2 _conversionFactor;
public WinInkAbsolutePointer(TabletReference tabletReference, IVirtualScreen screen) : base(tabletReference) public WinInkAbsolutePointer(TabletReference tabletReference, IVirtualScreen screen) : base("Windows Ink", tabletReference)
{ {
_conversionFactor = new Vector2(32767, 32767) / new Vector2(screen.Width, screen.Height); _conversionFactor = new Vector2(32767, 32767) / new Vector2(screen.Width, screen.Height);
} }

View file

@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Tablet;
using VoiDPlugins.Library; using VoiDPlugins.Library;
using VoiDPlugins.Library.VMulti; using VoiDPlugins.Library.VMulti;
using VoiDPlugins.Library.VMulti.Device; using VoiDPlugins.Library.VMulti.Device;
using VoiDPlugins.Library.VoiD;
using static VoiDPlugins.OutputMode.WindowsInkConstants; using static VoiDPlugins.OutputMode.WindowsInkConstants;
namespace VoiDPlugins.OutputMode namespace VoiDPlugins.OutputMode
@ -12,21 +13,24 @@ namespace VoiDPlugins.OutputMode
{ {
protected DigitizerInputReport* RawPointer { get; } protected DigitizerInputReport* RawPointer { get; }
protected VMultiInstance<DigitizerInputReport>? Instance { get; } protected VMultiInstance<DigitizerInputReport>? Instance { get; }
protected SharedStore? SharedStore { get; }
public WinInkBasePointer(TabletReference tabletReference) public WinInkBasePointer(string name, TabletReference tabletReference)
{ {
Instance = VMultiInstanceManager.RetrieveVMultiInstance("WindowsInk", tabletReference, () => new DigitizerInputReport()); Instance = new VMultiInstance<DigitizerInputReport>(name, new DigitizerInputReport());
Instance.InitializeData(POINTER, this); SharedStore = GlobalStore<SharedStore>.GetOrInitialize(tabletReference, () => new SharedStore());
Instance.InitializeData(ERASER_STATE, new Boxed<bool>(false)); SharedStore.InitializeData(INSTANCE, Instance);
Instance.InitializeData(MANUAL_ERASER, new Boxed<bool>(false)); SharedStore.InitializeData(POINTER, this);
SharedStore.InitializeData(ERASER_STATE, new Boxed<bool>(false));
SharedStore.InitializeData(MANUAL_ERASER, new Boxed<bool>(false));
RawPointer = Instance.Pointer; RawPointer = Instance.Pointer;
} }
public void SetEraser(bool isEraser) public void SetEraser(bool isEraser)
{ {
if (!Instance!.GetData<Boxed<bool>>(MANUAL_ERASER).Value) if (!SharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value)
{ {
WindowsInkButtonHandler.EraserStateTransition(Instance, ref GetEraser(), isEraser); WindowsInkButtonHandler.EraserStateTransition(Instance!, ref GetEraser(), isEraser);
} }
} }
@ -43,7 +47,6 @@ namespace VoiDPlugins.OutputMode
public void Reset() public void Reset()
{ {
Instance!.DisableButtonBit((int)WindowsInkButtonFlags.InRange);
} }
public void Flush() public void Flush()
@ -53,7 +56,7 @@ namespace VoiDPlugins.OutputMode
private ref Boxed<bool> GetEraser() private ref Boxed<bool> GetEraser()
{ {
return ref Instance!.GetData<Boxed<bool>>(ERASER_STATE); return ref SharedStore!.GetData<Boxed<bool>>(ERASER_STATE);
} }
} }
} }

View file

@ -11,7 +11,7 @@ namespace VoiDPlugins.OutputMode
private Vector2 _currentPoint; private Vector2 _currentPoint;
private Vector2 _error; private Vector2 _error;
public WinInkRelativePointer(TabletReference tabletReference, IVirtualScreen screen) : base(tabletReference) public WinInkRelativePointer(TabletReference tabletReference, IVirtualScreen screen) : base("Windows Ink", tabletReference)
{ {
_maxPoint = new Vector2(screen.Width, screen.Height); _maxPoint = new Vector2(screen.Width, screen.Height);
_currentPoint = _maxPoint / 2; _currentPoint = _maxPoint / 2;

View file

@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Tablet;
using VoiDPlugins.Library; using VoiDPlugins.Library;
using VoiDPlugins.Library.VMulti; using VoiDPlugins.Library.VMulti;
using VoiDPlugins.Library.VMulti.Device; using VoiDPlugins.Library.VMulti.Device;
using VoiDPlugins.Library.VoiD;
using static VoiDPlugins.OutputMode.WindowsInkConstants; using static VoiDPlugins.OutputMode.WindowsInkConstants;
namespace VoiDPlugins.OutputMode namespace VoiDPlugins.OutputMode
@ -12,6 +13,7 @@ namespace VoiDPlugins.OutputMode
public unsafe partial class WindowsInkButtonHandler : IStateBinding public unsafe partial class WindowsInkButtonHandler : IStateBinding
{ {
private VMultiInstance? _instance; private VMultiInstance? _instance;
private SharedStore? _sharedStore;
public static string[] ValidButtons { get; } = new string[] public static string[] ValidButtons { get; } = new string[]
{ {
@ -24,14 +26,13 @@ namespace VoiDPlugins.OutputMode
[Property("Button"), PropertyValidated(nameof(ValidButtons))] [Property("Button"), PropertyValidated(nameof(ValidButtons))]
public string? Button { get; set; } public string? Button { get; set; }
public bool IsManuallySet { get; set; }
[TabletReference] [TabletReference]
public TabletReference Reference { set => Initialize(value); } public TabletReference Reference { set => Initialize(value); }
private void Initialize(TabletReference tabletReference) private void Initialize(TabletReference tabletReference)
{ {
_instance = VMultiInstanceManager.RetrieveVMultiInstance(tabletReference); _sharedStore = GlobalStore<SharedStore>.Get(tabletReference);
_instance = _sharedStore.GetData<VMultiInstance>(INSTANCE);
} }
public void Press(TabletReference tablet, IDeviceReport report) public void Press(TabletReference tablet, IDeviceReport report)
@ -48,12 +49,12 @@ namespace VoiDPlugins.OutputMode
break; break;
case "Eraser (Toggle)": case "Eraser (Toggle)":
IsManuallySet = true; _sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = !eraserState.Value;
EraserStateTransition(_instance!, ref eraserState, !eraserState.Value); EraserStateTransition(_instance!, ref eraserState, !eraserState.Value);
break; break;
case "Eraser (Hold)": case "Eraser (Hold)":
IsManuallySet = true; _sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = true;
EraserStateTransition(_instance!, ref eraserState, true); EraserStateTransition(_instance!, ref eraserState, true);
break; break;
} }
@ -72,6 +73,7 @@ namespace VoiDPlugins.OutputMode
break; break;
case "Eraser (Hold)": case "Eraser (Hold)":
_sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = false;
EraserStateTransition(_instance!, ref GetEraser(), false); EraserStateTransition(_instance!, ref GetEraser(), false);
break; break;
} }
@ -111,7 +113,7 @@ namespace VoiDPlugins.OutputMode
private ref Boxed<bool> GetEraser() private ref Boxed<bool> GetEraser()
{ {
return ref _instance!.GetData<Boxed<bool>>(ERASER_STATE); return ref _sharedStore!.GetData<Boxed<bool>>(ERASER_STATE);
} }
} }
} }

View file

@ -2,8 +2,9 @@ namespace VoiDPlugins.OutputMode
{ {
public static class WindowsInkConstants public static class WindowsInkConstants
{ {
public const int POINTER = 0; public const int INSTANCE = 0;
public const int ERASER_STATE = 1; public const int POINTER = 1;
public const int MANUAL_ERASER = 2; public const int ERASER_STATE = 2;
public const int MANUAL_ERASER = 3;
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using HidSharp; using HidSharp;
using OpenTabletDriver.Plugin; using OpenTabletDriver.Plugin;
@ -9,17 +8,15 @@ namespace VoiDPlugins.Library.VMulti
{ {
public class VMultiInstance public class VMultiInstance
{ {
private readonly object[] _data;
private readonly HidStream _device; private readonly HidStream _device;
protected readonly byte[] Buffer; protected readonly byte[] Buffer;
public unsafe VMultiReportHeader* Header { get; } public unsafe VMultiReportHeader* Header { get; }
internal unsafe VMultiInstance(string name, int size) public unsafe VMultiInstance(string name, int size)
{ {
Buffer = GC.AllocateArray<byte>(size, true); Buffer = GC.AllocateArray<byte>(size, true);
Header = (VMultiReportHeader*)Unsafe.AsPointer(ref Buffer[0]); Header = (VMultiReportHeader*)Unsafe.AsPointer(ref Buffer[0]);
_device = Retrieve(name); _device = Retrieve(name);
_data = new object[32];
} }
public void Write() public void Write()
@ -27,16 +24,6 @@ namespace VoiDPlugins.Library.VMulti
_device.Write(Buffer); _device.Write(Buffer);
} }
public void InitializeData<T>(int i, T data)
{
_data[i] = data!;
}
public unsafe ref T GetData<T>(int i) where T : class
{
return ref Unsafe.AsRef<T>(Unsafe.AsPointer(ref _data[i]));
}
public unsafe void EnableButtonBit(int bit) public unsafe void EnableButtonBit(int bit)
{ {
Header->Buttons = (byte)(Header->Buttons | bit); Header->Buttons = (byte)(Header->Buttons | bit);
@ -84,10 +71,10 @@ namespace VoiDPlugins.Library.VMulti
{ {
public unsafe T* Pointer { get; } public unsafe T* Pointer { get; }
internal unsafe VMultiInstance(string name, Func<T> initialValue) : base(name, Unsafe.SizeOf<T>()) public unsafe VMultiInstance(string name, T initialValue) : base(name, Unsafe.SizeOf<T>())
{ {
Pointer = (T*)Unsafe.AsPointer(ref Buffer[0]); Pointer = (T*)Unsafe.AsPointer(ref Buffer[0]);
*Pointer = initialValue(); *Pointer = initialValue;
} }
} }
} }

View file

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenTabletDriver.Plugin.Tablet;
namespace VoiDPlugins.Library.VMulti
{
public static class VMultiInstanceManager
{
private static readonly object _syncLock = new();
private static readonly Dictionary<string, VMultiInstance> _map = new();
public static VMultiInstance<T> RetrieveVMultiInstance<T>(string name, TabletReference tabletReference, Func<T> initialValue)
where T : unmanaged
{
lock (_syncLock)
{
ref var instance = ref CollectionsMarshal.GetValueRefOrAddDefault(_map, tabletReference.Properties.Name, out var exists);
if (!exists)
instance = new VMultiInstance<T>(name, initialValue);
return (VMultiInstance<T>)instance!;
}
}
public static VMultiInstance RetrieveVMultiInstance(TabletReference tabletReference)
{
return _map[tabletReference.Properties.Name];
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using OpenTabletDriver.Plugin.Tablet;
namespace VoiDPlugins.Library.VoiD
{
/// <summary>
/// Stores one instance of <typeparamref name="T"/> per <see cref="TabletReference"/>.
/// </summary>
/// <typeparam name="T">A class.</typeparam>
public static class GlobalStore<T> where T : class
{
private static readonly object _syncLock = new();
private static readonly Dictionary<string, T> _map = new();
public static U GetOrInitialize<U>(TabletReference tabletReference, Func<U> initialValue) where U : T
{
lock (_syncLock)
{
ref var instance = ref CollectionsMarshal.GetValueRefOrAddDefault(_map, tabletReference.Properties.Name, out var exists);
if (!exists)
instance = initialValue();
return (U)instance!;
}
}
public static U Get<U>(TabletReference tabletReference) where U : T
{
return (U)_map[tabletReference.Properties.Name];
}
public static T Get(TabletReference tabletReference)
{
return _map[tabletReference.Properties.Name];
}
}
}

View file

@ -0,0 +1,27 @@
using System.Runtime.CompilerServices;
namespace VoiDPlugins.Library.VoiD
{
/// <summary>
/// Fast shared store with support for generic ref returning <see cref="GetData"/>.
/// </summary>
public class SharedStore
{
private readonly object[] _data;
public SharedStore()
{
_data = new object[32];
}
public void InitializeData<T>(int i, T data)
{
_data[i] = data!;
}
public unsafe ref T GetData<T>(int i)
{
return ref Unsafe.AsRef<T>(Unsafe.AsPointer(ref _data[i]));
}
}
}

View file

@ -1,5 +1,2 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NotPluginProject>true</NotPluginProject>
</PropertyGroup>
</Project> </Project>