Fix relative mode issues

This commit is contained in:
X9VoiD 2022-11-30 02:26:47 +08:00
parent aa6c011fd8
commit 59eed1faa5
9 changed files with 84 additions and 90 deletions

View file

@ -20,13 +20,17 @@ namespace VoiDPlugins.OutputMode
public VMultiAbsolutePointer(TabletReference tabletReference, IVirtualScreen virtualScreen) public VMultiAbsolutePointer(TabletReference tabletReference, IVirtualScreen virtualScreen)
{ {
_instance = new VMultiInstance<AbsoluteInputReport>("VMultiAbs", new AbsoluteInputReport());
var sharedStore = SharedStore.GetStore(tabletReference, STORE_KEY); var sharedStore = SharedStore.GetStore(tabletReference, STORE_KEY);
if (!sharedStore.TryAdd(INSTANCE, _instance)) _instance = sharedStore.GetOrUpdate(ABS_INSTANCE, createInstance, out _);
_instance = sharedStore.Get<VMultiInstance<AbsoluteInputReport>>(INSTANCE);
_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);
sharedStore.SetOrAdd(MODE, ABS_INSTANCE);
static VMultiInstance<AbsoluteInputReport> createInstance()
{
return new VMultiInstance<AbsoluteInputReport>("VMultiAbs", new AbsoluteInputReport());
}
} }
public void SetPosition(Vector2 pos) public void SetPosition(Vector2 pos)

View file

@ -18,20 +18,22 @@ namespace VoiDPlugins.OutputMode
public VMultiRelativePointer(TabletReference tabletReference) public VMultiRelativePointer(TabletReference tabletReference)
{ {
_instance = new VMultiInstance<RelativeInputReport>("VMultiRel", new RelativeInputReport());
var sharedStore = SharedStore.GetStore(tabletReference, STORE_KEY); var sharedStore = SharedStore.GetStore(tabletReference, STORE_KEY);
if (!sharedStore.TryAdd(INSTANCE, _instance)) _instance = sharedStore.GetOrUpdate(REL_INSTANCE, createInstance, out var updated);
_instance = sharedStore.Get<VMultiInstance<RelativeInputReport>>(INSTANCE);
_rawPointer = _instance.Pointer; _rawPointer = _instance.Pointer;
sharedStore.SetOrAdd(MODE, REL_INSTANCE);
static VMultiInstance<RelativeInputReport> createInstance()
{
return new VMultiInstance<RelativeInputReport>("VMultiRel", new RelativeInputReport());
}
} }
public void SetPosition(Vector2 delta) public void SetPosition(Vector2 delta)
{ {
if (delta == Vector2.Zero && _prev == Vector2.Zero) if (delta == Vector2.Zero && _prev == Vector2.Zero)
return; return;
if (_rawPointer is null)
return;
delta += _error; delta += _error;
_error = new Vector2(delta.X % 1, delta.Y % 1); _error = new Vector2(delta.X % 1, delta.Y % 1);

View file

@ -33,7 +33,9 @@ namespace VoiDPlugins.OutputMode
{ {
try try
{ {
_instance = SharedStore.GetStore(tabletReference, STORE_KEY).Get<VMultiInstance>(INSTANCE); var sharedStore = SharedStore.GetStore(tabletReference, STORE_KEY);
var mode = sharedStore.Get<int>(MODE);
_instance = sharedStore.Get<VMultiInstance>(mode);
} }
catch catch
{ {

View file

@ -3,6 +3,8 @@ namespace VoiDPlugins.OutputMode
public static class VMultiModeConstants public static class VMultiModeConstants
{ {
public const string STORE_KEY = "VMultiMode"; public const string STORE_KEY = "VMultiMode";
public const int INSTANCE = 0; public const int MODE = 0;
public const int ABS_INSTANCE = 1;
public const int REL_INSTANCE = 2;
} }
} }

View file

@ -7,13 +7,11 @@ namespace VoiDPlugins.OutputMode
{ {
public unsafe class WinInkAbsolutePointer : WinInkBasePointer, IAbsolutePointer public unsafe class WinInkAbsolutePointer : WinInkBasePointer, IAbsolutePointer
{ {
private readonly Vector2 _conversionFactor;
private Vector2 _prev; private Vector2 _prev;
public WinInkAbsolutePointer(TabletReference tabletReference, IVirtualScreen screen) public WinInkAbsolutePointer(TabletReference tabletReference, IVirtualScreen screen)
: base("Windows Ink", tabletReference, screen) : base("Windows Ink", tabletReference, screen)
{ {
_conversionFactor = new Vector2(32767, 32767) / new Vector2(screen.Width, screen.Height);
} }
public void SetPosition(Vector2 pos) public void SetPosition(Vector2 pos)
@ -23,7 +21,7 @@ namespace VoiDPlugins.OutputMode
SetInternalPosition(pos); SetInternalPosition(pos);
Instance.EnableButtonBit((int)WindowsInkButtonFlags.InRange); Instance.EnableButtonBit((int)WindowsInkButtonFlags.InRange);
pos *= _conversionFactor; pos = Convert(pos);
RawPointer->X = (ushort)pos.X; RawPointer->X = (ushort)pos.X;
RawPointer->Y = (ushort)pos.Y; RawPointer->Y = (ushort)pos.Y;
Dirty = true; Dirty = true;

View file

@ -12,6 +12,7 @@ namespace VoiDPlugins.OutputMode
{ {
public unsafe abstract class WinInkBasePointer : IPressureHandler, ITiltHandler, IEraserHandler, ISynchronousPointer public unsafe abstract class WinInkBasePointer : IPressureHandler, ITiltHandler, IEraserHandler, ISynchronousPointer
{ {
private readonly Vector2 _conversionFactor;
private readonly IVirtualScreen _screen; private readonly IVirtualScreen _screen;
private ThinOSPointer? _osPointer; private ThinOSPointer? _osPointer;
private Vector2 _internalPos; private Vector2 _internalPos;
@ -30,20 +31,22 @@ namespace VoiDPlugins.OutputMode
public WinInkBasePointer(string name, TabletReference tabletReference, IVirtualScreen screen) public WinInkBasePointer(string name, TabletReference tabletReference, IVirtualScreen screen)
{ {
_screen = screen; _screen = screen;
Instance = new VMultiInstance<DigitizerInputReport>(name, new DigitizerInputReport()); _conversionFactor = new Vector2(32767, 32767) / new Vector2(screen.Width, screen.Height);
SharedStore = SharedStore.GetStore(tabletReference, STORE_KEY); SharedStore = SharedStore.GetStore(tabletReference, STORE_KEY);
if (SharedStore.TryAdd(INSTANCE, Instance)) Instance = SharedStore.GetOrUpdate(INSTANCE, createInstance, out var updated);
{
SharedStore.TryAdd(POINTER, this);
SharedStore.TryAdd(ERASER_STATE, false);
SharedStore.TryAdd(MANUAL_ERASER, false);
SharedStore.TryAdd(TIP_PRESSED, false);
RawPointer = Instance.Pointer; RawPointer = Instance.Pointer;
if (updated)
{
SharedStore.SetOrAdd(POINTER, this);
SharedStore.SetOrAdd(ERASER_STATE, false);
SharedStore.SetOrAdd(MANUAL_ERASER, false);
SharedStore.SetOrAdd(TIP_PRESSED, false);
} }
else
VMultiInstance<DigitizerInputReport> createInstance()
{ {
Instance = SharedStore.Get<VMultiInstance<DigitizerInputReport>>(INSTANCE); return new VMultiInstance<DigitizerInputReport>(name, new DigitizerInputReport());
RawPointer = Instance.Pointer;
} }
} }
@ -87,6 +90,11 @@ namespace VoiDPlugins.OutputMode
} }
} }
protected Vector2 Convert(Vector2 pos)
{
return pos * _conversionFactor;
}
protected void SetInternalPosition(Vector2 pos) protected void SetInternalPosition(Vector2 pos)
{ {
_internalPos = pos; _internalPos = pos;

View file

@ -21,16 +21,18 @@ namespace VoiDPlugins.OutputMode
public void SetPosition(Vector2 delta) public void SetPosition(Vector2 delta)
{ {
if (_prev == Vector2.Zero && delta == Vector2.Zero) if (delta == Vector2.Zero)
return; return;
Instance.EnableButtonBit((int)WindowsInkButtonFlags.InRange);
delta += _error; delta += _error;
_error = new Vector2(delta.X % 1, delta.Y % 1); _error = new Vector2(delta.X % 1, delta.Y % 1);
_currentPoint = Vector2.Clamp(_currentPoint + delta, Vector2.Zero, _maxPoint); _currentPoint = Vector2.Clamp(_currentPoint + delta, Vector2.Zero, _maxPoint);
SetInternalPosition(_currentPoint); SetInternalPosition(_currentPoint);
RawPointer->X = (ushort)_currentPoint.X; Instance.EnableButtonBit((int)WindowsInkButtonFlags.InRange);
RawPointer->Y = (ushort)_currentPoint.Y; var pos = Convert(_currentPoint);
RawPointer->X = (ushort)pos.X;
RawPointer->Y = (ushort)pos.Y;
Dirty = true; Dirty = true;
_prev = delta; _prev = delta;
} }

View file

@ -97,7 +97,7 @@ namespace VoiDPlugins.OutputMode
_instance.Write(); _instance.Write();
} }
public static void EraserStateTransition(SharedStore store, VMultiInstance instance, bool isEraser) internal static void EraserStateTransition(SharedStore store, VMultiInstance instance, bool isEraser)
{ {
var eraserState = store.Get<bool>(ERASER_STATE); var eraserState = store.Get<bool>(ERASER_STATE);
if (eraserState != isEraser) if (eraserState != isEraser)

View file

@ -1,23 +1,16 @@
using System.Collections; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenTabletDriver.Plugin.Tablet; using OpenTabletDriver.Plugin.Tablet;
namespace VoiDPlugins.Library.VoiD namespace VoiDPlugins.Library.VoiD
{ {
public class SharedStore : IDictionary<int, object> public class SharedStore
{ {
private static readonly Dictionary<TabletReference, Dictionary<string, SharedStore>> _storeMap = new(new Comparer()); private static readonly Dictionary<TabletReference, Dictionary<string, SharedStore>> _storeMap = new(new Comparer());
private readonly Dictionary<int, object> _sharedStore = new(); private readonly Dictionary<int, object> _sharedStore = new();
public object this[int key] { get => ((IDictionary<int, object>)_sharedStore)[key]; set => ((IDictionary<int, object>)_sharedStore)[key] = value; }
public ICollection<int> Keys => ((IDictionary<int, object>)_sharedStore).Keys;
public ICollection<object> Values => ((IDictionary<int, object>)_sharedStore).Values;
public int Count => ((ICollection<KeyValuePair<int, object>>)_sharedStore).Count;
public bool IsReadOnly => ((ICollection<KeyValuePair<int, object>>)_sharedStore).IsReadOnly;
public static SharedStore GetStore(TabletReference reference, string storeKey) public static SharedStore GetStore(TabletReference reference, string storeKey)
{ {
lock (_storeMap) lock (_storeMap)
@ -39,69 +32,52 @@ namespace VoiDPlugins.Library.VoiD
return (T)_sharedStore[key]; return (T)_sharedStore[key];
} }
public T GetOrUpdate<T>(int key, Func<T> valueFactory, out bool updated)
{
if (_sharedStore.TryGetValue(key, out object? value) && SafeCast<T>(value) is T casted)
{
updated = false;
return casted;
}
var newValue = valueFactory();
_sharedStore[key] = newValue!;
updated = true;
return newValue;
}
public void Set<T>(int key, T value) public void Set<T>(int key, T value)
{ {
_sharedStore[key] = value!; _sharedStore[key] = value!;
} }
public void Add(int key, object value) public void Add<T>(int key, T value)
{ {
((IDictionary<int, object>)_sharedStore).Add(key, value); _sharedStore.Add(key, value!);
} }
public bool TryAdd(int key, object value) public void SetOrAdd<T>(int key, T value)
{ {
return _sharedStore.TryAdd(key, value); if (_sharedStore.ContainsKey(key))
{
_sharedStore[key] = value!;
}
else
{
_sharedStore.Add(key, value!);
}
} }
public void Add(KeyValuePair<int, object> item) private static T? SafeCast<T>(object value)
{ {
((ICollection<KeyValuePair<int, object>>)_sharedStore).Add(item); try
{
return (T)value;
} }
catch
public void Clear()
{ {
((ICollection<KeyValuePair<int, object>>)_sharedStore).Clear(); return default;
} }
public bool Contains(KeyValuePair<int, object> item)
{
return ((ICollection<KeyValuePair<int, object>>)_sharedStore).Contains(item);
}
public bool ContainsKey(int key)
{
return ((IDictionary<int, object>)_sharedStore).ContainsKey(key);
}
public void CopyTo(KeyValuePair<int, object>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<int, object>>)_sharedStore).CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<int, object>> GetEnumerator()
{
return ((IEnumerable<KeyValuePair<int, object>>)_sharedStore).GetEnumerator();
}
public bool Remove(int key)
{
return ((IDictionary<int, object>)_sharedStore).Remove(key);
}
public bool Remove(KeyValuePair<int, object> item)
{
return ((ICollection<KeyValuePair<int, object>>)_sharedStore).Remove(item);
}
public bool TryGetValue(int key, [MaybeNullWhen(false)] out object value)
{
return ((IDictionary<int, object>)_sharedStore).TryGetValue(key, out value);
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_sharedStore).GetEnumerator();
} }
private class Comparer : IEqualityComparer<TabletReference> private class Comparer : IEqualityComparer<TabletReference>