mirror of
https://github.com/vale981/VoiDPlugins
synced 2025-03-04 16:51:38 -05:00
Generalize SharedStore
This commit is contained in:
parent
8c96ec7537
commit
3dd078ea2d
14 changed files with 101 additions and 72 deletions
|
@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Platform.Pointer;
|
|||
using OpenTabletDriver.Plugin.Tablet;
|
||||
using VoiDPlugins.Library.VMulti;
|
||||
using VoiDPlugins.Library.VMulti.Device;
|
||||
using VoiDPlugins.Library.VoiD;
|
||||
|
||||
namespace VoiDPlugins.OutputMode
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace VoiDPlugins.OutputMode
|
|||
|
||||
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;
|
||||
_conversionFactor = new Vector2(32767, 32767) / new Vector2(virtualScreen.Width, virtualScreen.Height);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using OpenTabletDriver.Plugin.Platform.Pointer;
|
|||
using OpenTabletDriver.Plugin.Tablet;
|
||||
using VoiDPlugins.Library.VMulti;
|
||||
using VoiDPlugins.Library.VMulti.Device;
|
||||
using VoiDPlugins.Library.VoiD;
|
||||
|
||||
namespace VoiDPlugins.OutputMode
|
||||
{
|
||||
|
@ -14,7 +15,7 @@ namespace VoiDPlugins.OutputMode
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin;
|
|||
using OpenTabletDriver.Plugin.Attributes;
|
||||
using OpenTabletDriver.Plugin.Tablet;
|
||||
using VoiDPlugins.Library.VMulti;
|
||||
using VoiDPlugins.Library.VoiD;
|
||||
|
||||
namespace VoiDPlugins.OutputMode
|
||||
{
|
||||
|
@ -29,7 +30,7 @@ namespace VoiDPlugins.OutputMode
|
|||
|
||||
private void Initialize(TabletReference tabletReference)
|
||||
{
|
||||
_instance = VMultiInstanceManager.RetrieveVMultiInstance(tabletReference);
|
||||
_instance = GlobalStore<VMultiInstance>.Get(tabletReference);
|
||||
}
|
||||
|
||||
public void Press(TabletReference tablet, IDeviceReport report)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<VMultiLibrary>true</VMultiLibrary>
|
||||
<VoiDLibrary>true</VoiDLibrary>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace VoiDPlugins.OutputMode
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Tablet;
|
|||
using VoiDPlugins.Library;
|
||||
using VoiDPlugins.Library.VMulti;
|
||||
using VoiDPlugins.Library.VMulti.Device;
|
||||
using VoiDPlugins.Library.VoiD;
|
||||
using static VoiDPlugins.OutputMode.WindowsInkConstants;
|
||||
|
||||
namespace VoiDPlugins.OutputMode
|
||||
|
@ -12,21 +13,24 @@ namespace VoiDPlugins.OutputMode
|
|||
{
|
||||
protected DigitizerInputReport* RawPointer { 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.InitializeData(POINTER, this);
|
||||
Instance.InitializeData(ERASER_STATE, new Boxed<bool>(false));
|
||||
Instance.InitializeData(MANUAL_ERASER, new Boxed<bool>(false));
|
||||
Instance = new VMultiInstance<DigitizerInputReport>(name, new DigitizerInputReport());
|
||||
SharedStore = GlobalStore<SharedStore>.GetOrInitialize(tabletReference, () => new SharedStore());
|
||||
SharedStore.InitializeData(INSTANCE, Instance);
|
||||
SharedStore.InitializeData(POINTER, this);
|
||||
SharedStore.InitializeData(ERASER_STATE, new Boxed<bool>(false));
|
||||
SharedStore.InitializeData(MANUAL_ERASER, new Boxed<bool>(false));
|
||||
RawPointer = Instance.Pointer;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
Instance!.DisableButtonBit((int)WindowsInkButtonFlags.InRange);
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
|
@ -53,7 +56,7 @@ namespace VoiDPlugins.OutputMode
|
|||
|
||||
private ref Boxed<bool> GetEraser()
|
||||
{
|
||||
return ref Instance!.GetData<Boxed<bool>>(ERASER_STATE);
|
||||
return ref SharedStore!.GetData<Boxed<bool>>(ERASER_STATE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace VoiDPlugins.OutputMode
|
|||
private Vector2 _currentPoint;
|
||||
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);
|
||||
_currentPoint = _maxPoint / 2;
|
||||
|
|
|
@ -4,6 +4,7 @@ using OpenTabletDriver.Plugin.Tablet;
|
|||
using VoiDPlugins.Library;
|
||||
using VoiDPlugins.Library.VMulti;
|
||||
using VoiDPlugins.Library.VMulti.Device;
|
||||
using VoiDPlugins.Library.VoiD;
|
||||
using static VoiDPlugins.OutputMode.WindowsInkConstants;
|
||||
|
||||
namespace VoiDPlugins.OutputMode
|
||||
|
@ -12,6 +13,7 @@ namespace VoiDPlugins.OutputMode
|
|||
public unsafe partial class WindowsInkButtonHandler : IStateBinding
|
||||
{
|
||||
private VMultiInstance? _instance;
|
||||
private SharedStore? _sharedStore;
|
||||
|
||||
public static string[] ValidButtons { get; } = new string[]
|
||||
{
|
||||
|
@ -24,14 +26,13 @@ namespace VoiDPlugins.OutputMode
|
|||
[Property("Button"), PropertyValidated(nameof(ValidButtons))]
|
||||
public string? Button { get; set; }
|
||||
|
||||
public bool IsManuallySet { get; set; }
|
||||
|
||||
[TabletReference]
|
||||
public TabletReference Reference { set => Initialize(value); }
|
||||
|
||||
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)
|
||||
|
@ -48,12 +49,12 @@ namespace VoiDPlugins.OutputMode
|
|||
break;
|
||||
|
||||
case "Eraser (Toggle)":
|
||||
IsManuallySet = true;
|
||||
_sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = !eraserState.Value;
|
||||
EraserStateTransition(_instance!, ref eraserState, !eraserState.Value);
|
||||
break;
|
||||
|
||||
case "Eraser (Hold)":
|
||||
IsManuallySet = true;
|
||||
_sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = true;
|
||||
EraserStateTransition(_instance!, ref eraserState, true);
|
||||
break;
|
||||
}
|
||||
|
@ -72,6 +73,7 @@ namespace VoiDPlugins.OutputMode
|
|||
break;
|
||||
|
||||
case "Eraser (Hold)":
|
||||
_sharedStore!.GetData<Boxed<bool>>(MANUAL_ERASER).Value = false;
|
||||
EraserStateTransition(_instance!, ref GetEraser(), false);
|
||||
break;
|
||||
}
|
||||
|
@ -111,7 +113,7 @@ namespace VoiDPlugins.OutputMode
|
|||
|
||||
private ref Boxed<bool> GetEraser()
|
||||
{
|
||||
return ref _instance!.GetData<Boxed<bool>>(ERASER_STATE);
|
||||
return ref _sharedStore!.GetData<Boxed<bool>>(ERASER_STATE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,9 @@ namespace VoiDPlugins.OutputMode
|
|||
{
|
||||
public static class WindowsInkConstants
|
||||
{
|
||||
public const int POINTER = 0;
|
||||
public const int ERASER_STATE = 1;
|
||||
public const int MANUAL_ERASER = 2;
|
||||
public const int INSTANCE = 0;
|
||||
public const int POINTER = 1;
|
||||
public const int ERASER_STATE = 2;
|
||||
public const int MANUAL_ERASER = 3;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using HidSharp;
|
||||
using OpenTabletDriver.Plugin;
|
||||
|
@ -9,17 +8,15 @@ namespace VoiDPlugins.Library.VMulti
|
|||
{
|
||||
public class VMultiInstance
|
||||
{
|
||||
private readonly object[] _data;
|
||||
private readonly HidStream _device;
|
||||
protected readonly byte[] Buffer;
|
||||
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);
|
||||
Header = (VMultiReportHeader*)Unsafe.AsPointer(ref Buffer[0]);
|
||||
_device = Retrieve(name);
|
||||
_data = new object[32];
|
||||
}
|
||||
|
||||
public void Write()
|
||||
|
@ -27,16 +24,6 @@ namespace VoiDPlugins.Library.VMulti
|
|||
_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)
|
||||
{
|
||||
Header->Buttons = (byte)(Header->Buttons | bit);
|
||||
|
@ -84,10 +71,10 @@ namespace VoiDPlugins.Library.VMulti
|
|||
{
|
||||
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 = initialValue();
|
||||
*Pointer = initialValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
38
VoiDPlugins.Library/VoiD/GlobalStore.cs
Normal file
38
VoiDPlugins.Library/VoiD/GlobalStore.cs
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
27
VoiDPlugins.Library/VoiD/SharedStore.cs
Normal file
27
VoiDPlugins.Library/VoiD/SharedStore.cs
Normal 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]));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,2 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<NotPluginProject>true</NotPluginProject>
|
||||
</PropertyGroup>
|
||||
</Project>
|
Loading…
Add table
Reference in a new issue