diff --git a/OTD.EnhancedOutputMode.Lib/Tools/TouchSettings.cs b/OTD.EnhancedOutputMode.Lib/Tools/TouchSettings.cs index f35d38d..158a015 100644 --- a/OTD.EnhancedOutputMode.Lib/Tools/TouchSettings.cs +++ b/OTD.EnhancedOutputMode.Lib/Tools/TouchSettings.cs @@ -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" + diff --git a/OTD.EnhancedOutputMode/Output/EnhancedRelativeOutputMode.cs b/OTD.EnhancedOutputMode/Output/EnhancedRelativeOutputMode.cs index b6998ed..e1d90b7 100644 --- a/OTD.EnhancedOutputMode/Output/EnhancedRelativeOutputMode.cs +++ b/OTD.EnhancedOutputMode/Output/EnhancedRelativeOutputMode.cs @@ -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 { + private IList _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; @@ -44,22 +50,56 @@ public void Initialize() GateFilters = Filters.OfType().ToList(); AuxFilters = Filters.OfType().ToList(); + FetchFilters(); + // Initialize filters that require initialization foreach (var filter in Filters.OfType()) 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) @@ -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; @@ -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()) + pos = filter.Filter(pos); + + pos = Vector2.Transform(pos, this.TouchTransformationMatrix); + + // Post Filter + foreach (IFilter filter in this.postFilters ??= Array.Empty()) + pos = filter.Filter(pos); + + var delta = pos - this._lastTransformedPos; + this._lastTransformedPos = pos; + + if (_skipReport) + { + _skipReport = false; + return null; + } + return (deltaTime > ResetTime) ? null : delta; + } } } \ No newline at end of file