Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.5.x] Add option to match pen speed in Relative Mode #6

Merged
merged 1 commit into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions OTD.EnhancedOutputMode.Lib/Tools/TouchSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ public int PenResetTime

public TimeSpan PenResetTimeSpan => penResetTime;

[BooleanProperty("Match Pen Sensibility in Relative Mode", ""),
DefaultPropertyValue(false),
ToolTip("OTD.EnhancedOutputMode:\n\n" +
"When Enabled, the touch sensitivity will match to the sensitivity of the pen in Relative output mode.")]
public bool MatchPenSensibilityInRelativeMode { get; set; }

[Property("Max X"),
DefaultPropertyValue(4095),
ToolTip("OTD.EnhancedOutputMode:\n\n" +
Expand Down
73 changes: 70 additions & 3 deletions OTD.EnhancedOutputMode/Output/EnhancedRelativeOutputMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@
using OTD.EnhancedOutputMode.Lib.Interface;
using OTD.EnhancedOutputMode.Lib.Tools;
using OTD.EnhancedOutputMode.Lib.Tablet;
using OpenTabletDriver.Plugin;

namespace OTD.EnhancedOutputMode.Output
{
[PluginName("Enhanced Relative Mode")]
public class EnhancedRelativeOutputMode : RelativeOutputMode, IPointerOutputMode<IRelativePointer>
{
private IList<IFilter> _filters, preFilters, postFilters;
private ITabletReport _convertedReport = new TouchConvertedReport();
private HPETDeltaStopwatch _Touchstopwatch = new(true);
private HPETDeltaStopwatch _penStopwatch = new(true);
private bool _firstReport = true;
private int _lastTouchID = -1;
private Vector2 _lastTransformedPos;
private Vector2 _lastPos;
private bool _skipReport = false;

public Matrix3x2 TransformationMatrix { get; private set; }
public Matrix3x2 TouchTransformationMatrix { get; private set; }

public override IRelativePointer Pointer => SystemInterop.RelativePointer;
Expand All @@ -44,22 +50,56 @@ public void Initialize()
GateFilters = Filters.OfType<IGateFilter>().ToList();
AuxFilters = Filters.OfType<IAuxFilter>().ToList();

FetchFilters();

// Initialize filters that require initialization
foreach (var filter in Filters.OfType<IInitialize>())
filter.Initialize();

this._skipReport = true;

UpdateTransformMatrix();

// Someone asked for a feature to match the pen's speed in relative mode
if (TouchSettings.MatchPenSensibilityInRelativeMode)
UpdateTouchTransformMatrix();

// we don't want to initialize again
_firstReport = false;
}

private void FetchFilters()
{
if (Info.Driver.InterpolatorActive)
this.preFilters = Filters.Where(t => t.FilterStage == FilterStage.PreTranspose).ToList();
else
this.preFilters = Filters.Where(t => t.FilterStage == FilterStage.PreTranspose || t.FilterStage == FilterStage.PreInterpolate).ToList();

this.postFilters = Filters.Where(t => t.FilterStage == FilterStage.PostTranspose).ToList();
}

private void UpdateTransformMatrix()
{
this.TouchTransformationMatrix = Matrix3x2.CreateRotation(
TransformationMatrix = Matrix3x2.CreateRotation(
(float)(-Rotation * System.Math.PI / 180));

this.TouchTransformationMatrix *= Matrix3x2.CreateScale(
TransformationMatrix *= Matrix3x2.CreateScale(
Sensitivity.X * ((Tablet?.Digitizer?.Width / Tablet?.Digitizer?.MaxX) ?? 0.01f),
Sensitivity.Y * ((Tablet?.Digitizer?.Height / Tablet?.Digitizer?.MaxY) ?? 0.01f));

TouchTransformationMatrix = TransformationMatrix;
}

// This is only used when
private void UpdateTouchTransformMatrix()
{
// Pen & Touch digitizer suffer from a difference in resolution,
// resulting in different speeds for the same sensitivity.
var XMultiplier = Tablet.Digitizer.MaxX / TouchSettings.MaxX;
var YMultiplier = Tablet.Digitizer.MaxY / TouchSettings.MaxY;

// This should achieve about the same speed as the pen
TouchTransformationMatrix = TransformationMatrix * Matrix3x2.CreateScale(XMultiplier, YMultiplier);
}

public override void Read(IDeviceReport report)
Expand Down Expand Up @@ -111,7 +151,7 @@ protected virtual bool HandleTouch(IDeviceReport report, ITouchReport touchRepor
{
_lastPos = _convertedReport.Position;

if (Transpose(_convertedReport) is Vector2 pos && _lastTouchID == TouchConvertedReport.CurrentFirstTouchID)
if (TransposeTouch(_convertedReport) is Vector2 pos && _lastTouchID == TouchConvertedReport.CurrentFirstTouchID)
Pointer.Translate(pos);

_lastTouchID = TouchConvertedReport.CurrentFirstTouchID;
Expand All @@ -128,5 +168,32 @@ protected bool ShouldReport(IDeviceReport report, ref ITabletReport tabletreport

return true;
}

public Vector2? TransposeTouch(ITabletReport report)
{
var deltaTime = _Touchstopwatch.Restart();

var pos = report.Position;

// Pre Filter
foreach (IFilter filter in this.preFilters ??= Array.Empty<IFilter>())
pos = filter.Filter(pos);

pos = Vector2.Transform(pos, this.TouchTransformationMatrix);

// Post Filter
foreach (IFilter filter in this.postFilters ??= Array.Empty<IFilter>())
pos = filter.Filter(pos);

var delta = pos - this._lastTransformedPos;
this._lastTransformedPos = pos;

if (_skipReport)
{
_skipReport = false;
return null;
}
return (deltaTime > ResetTime) ? null : delta;
}
}
}