diff --git a/src/JuliusSweetland.OptiKey.Core/JuliusSweetland.OptiKey.Core.csproj b/src/JuliusSweetland.OptiKey.Core/JuliusSweetland.OptiKey.Core.csproj index 3ca7637de..2b9e0d29d 100644 --- a/src/JuliusSweetland.OptiKey.Core/JuliusSweetland.OptiKey.Core.csproj +++ b/src/JuliusSweetland.OptiKey.Core/JuliusSweetland.OptiKey.Core.csproj @@ -268,6 +268,8 @@ + + diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/ISensitivityFunction.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/ISensitivityFunction.cs index 2120525ff..657e861e5 100644 --- a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/ISensitivityFunction.cs +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/ISensitivityFunction.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using System.Windows; namespace JuliusSweetland.OptiKey.Models.ScalingModels @@ -10,6 +6,7 @@ namespace JuliusSweetland.OptiKey.Models.ScalingModels interface ISensitivityFunction { Vector CalculateScaling(Point current, Point centre); - List GetContours(); + bool Contains(Point point); + List GetContours(); } } diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/PiecewiseScaling.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/PiecewiseScaling.cs index 3999611ec..27acadf9e 100644 --- a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/PiecewiseScaling.cs +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/PiecewiseScaling.cs @@ -59,9 +59,9 @@ public void SetCoords(float[] list_of_all_coords) } } - public List GetContours() + public List GetContours() { - List ctrs = new List(); + List ctrs = new List(); float lastVal = 0; float lastX = 0; foreach (var coord in individualCoords) @@ -72,12 +72,12 @@ public List GetContours() if (lastVal == 0 && currVal > 0) { // previous contour was zero-crossing - ctrs.Add(new Point(screenScale * lastX, screenScale * lastX)); + ctrs.Add(new Region(.5 - lastX, .5 - lastX * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * lastX, 2 * lastX * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * lastX)); } else if (lastVal > 0 && currVal == 0) { // new contour is zero-crossing - ctrs.Add(new Point(screenScale * currX, screenScale * currX)); + ctrs.Add(new Region(.5 - currX, .5 - currX * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * currX, 2 * currX * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * currX)); } lastVal = currVal; lastX = currX; @@ -86,7 +86,6 @@ public List GetContours() return ctrs; } - private float map_val(float f) { foreach (var pair in pairwiseCoords) @@ -118,11 +117,6 @@ public Vector CalculateScaling(Point current, Point centre) // Map back to x, y return new Vector(amount * Math.Cos((double)theta), amount * Math.Sin((double)theta)); } - - private double signedSqrt(double x) - { - // return sqrt of magnitude but with original sign - return Math.Sign(x) * Math.Sqrt(Math.Abs(x)); - } + public bool Contains(Point point) { return true; } } } diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/Region.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/Region.cs new file mode 100644 index 000000000..4acbb2633 --- /dev/null +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/Region.cs @@ -0,0 +1,39 @@ +using System; +using System.Windows; + +namespace JuliusSweetland.OptiKey.Models.ScalingModels +{ + public struct Region + { + public Region(double left, double top, double width, double height, + double radius = 0, double amount = 0, double gradient = .5, bool visible = false) + { + Left = left; + Top = top; + Width = width; + Height = height; + Radius = radius; + Amount = amount; + Gradient = gradient; + Visible = visible; + } + public double Left; + public double Top; + public double Width; + public double Height; + public double Radius; + public double Amount; + public double Gradient; + public bool Visible; + public Point Center { get { return new Point(Left + Width / 2, Top + Height / 2); } } + public double Right { get { return Left + Width; } } + public double Bottom { get { return Top + Height; } } + public bool Contains(double x, double y) + { + if (Radius > 0) //use ellipse logic + return Math.Pow(x, 2) / Math.Pow(Width / 2, 2) + Math.Pow(y, 2) / Math.Pow(Height / 2, 2) <= 1; + else //use rectangle logic + return x >= Left && x <= Right && y >= Top && y <= Bottom; + } + } +} diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/RegionScaling.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/RegionScaling.cs new file mode 100644 index 000000000..0159d63dd --- /dev/null +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/RegionScaling.cs @@ -0,0 +1,114 @@ +using JuliusSweetland.OptiKey.Static; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; + +namespace JuliusSweetland.OptiKey.Models.ScalingModels +{ + class RegionScaling : ISensitivityFunction + { + private List deadzones; + private List regions; + + public RegionScaling(List deadzones, List regions) + { + this.deadzones = deadzones; + this.regions = regions; + } + + public List GetContours() + { + var regions = this.regions; + if (deadzones!= null && deadzones.Any()) + { + regions.AddRange(deadzones); + } + + var ctrs = new List(); + ctrs.AddRange(regions.Where(r => r.Visible)); + + return ctrs; + } + + public Vector CalculateScaling(Point point, Point centre) + { + point.X /= Graphics.PrimaryScreenWidthInPixels; + point.Y /= Graphics.PrimaryScreenHeightInPixels; + + if (regions.First().Radius > 0) + return RingScaling(point); + else + return RectangleScaling(point); + } + + public Vector RingScaling(Point point) + { + var amount = 0d; + var vector = point - regions[0].Center; + + for (int i = 0; i < regions.Count() - 1; i++) + { + var min = regions[i]; + var max = regions[i + 1]; + + if (!(min.Contains(point.X, point.Y) && max.Contains(point.X, point.Y))) + { + var delta = vector.Length - min.Radius; + var maxDelta = max.Radius - min.Radius; + amount = max.Gradient == 0 ? min.Amount : max.Gradient == 1 ? max.Amount + : max.Gradient == .5 ? min.Amount + (max.Amount - min.Amount) * delta / maxDelta + : min.Amount + (max.Amount - min.Amount) * Math.Pow(delta / maxDelta, 2 * max.Gradient); + } + } + + var theta = Math.Atan2(vector.Y, vector.X); + return new Vector(amount * Math.Cos(theta), amount * Math.Sin(theta)); + } + + public Vector RectangleScaling(Point point) + { + var amountX = 0d; + var amountY = 0d; + + for (int i = 0; i < regions.Count() - 1; i++) + { + var min = regions[i]; + var max = regions[i + 1]; + + if (!(min.Left <= point.X && min.Right >= point.X) && max.Left <= point.X && max.Right >= point.X) + { + var sX = point.X < min.Left ? -1 : 1; + var deltaX = sX < 0 ? min.Left - point.X : point.X - min.Right; + var maxX = sX < 0 ? min.Left - max.Left : max.Right - min.Right; + amountX = max.Gradient == 0 ? min.Amount : max.Gradient == 1 ? max.Amount + : max.Gradient == .5 ? min.Amount + (max.Amount - min.Amount) * deltaX / maxX + : min.Amount + (max.Amount - min.Amount) * Math.Pow(deltaX / maxX, 2 * max.Gradient); + amountX *= sX; + } + + if (!(min.Top <= point.Y && min.Bottom >= point.Y) && max.Top <= point.Y && max.Bottom >= point.Y) + { + var sY = point.Y < min.Top ? -1 : point.Y > min.Bottom ? 1 : 0; + var deltaY = sY < 0 ? min.Top - point.Y : point.Y - min.Bottom; + var maxY = sY < 0 ? min.Top - max.Top : max.Bottom - min.Bottom; + amountY = max.Gradient == 0 ? min.Amount : max.Gradient == 1 ? max.Amount + : max.Gradient == .5 ? min.Amount + (max.Amount - min.Amount) * deltaY / maxY + : min.Amount + (max.Amount - min.Amount) * Math.Pow(deltaY / maxY, 2 * max.Gradient); + amountY *= sY; + } + } + + return new Vector(amountX, amountY); + } + + public bool Contains(Point point) + { + point.X /= Graphics.PrimaryScreenWidthInPixels; + point.Y /= Graphics.PrimaryScreenHeightInPixels; + //point within regions.Last(); and not within a deadzone + return (regions.Last().Contains(point.X, point.Y)) + && !(deadzones != null && deadzones.Any() && deadzones.Exists(x => x.Contains(point.X, point.Y))); + } + } +} diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SegmentScaling.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SegmentScaling.cs index a017a9046..8317be8b7 100644 --- a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SegmentScaling.cs +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SegmentScaling.cs @@ -31,15 +31,15 @@ public SegmentScaling(int n, float innerRadius, float outerRadius, double scale= // To make sure things don't get stretched, we scale to the smaller axis // which makes things spherical in the centre, and extend beyond 1 outside screenScale = Math.Min(Graphics.PrimaryScreenHeightInPixels, Graphics.PrimaryScreenWidthInPixels)/2; - } + } - public List GetContours() + public List GetContours() { - List ctrs = new List(); - ctrs.Add(new Point(screenScale * innerRadius, screenScale * innerRadius)); - ctrs.Add(new Point(screenScale * outerRadius, screenScale * outerRadius)); - - return ctrs; + return new List() + { + new Region(.5 - innerRadius, .5 - innerRadius * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * innerRadius, 2 * innerRadius * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * innerRadius), + new Region(.5 - outerRadius, .5 - outerRadius * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * outerRadius, 2 * outerRadius * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels, 2 * outerRadius) + }; } @@ -69,6 +69,8 @@ public Vector CalculateScaling(Point current, Point centre) // Map back to x, y return new Vector(scale * Math.Cos(theta_snap), scale * Math.Sin(theta_snap)); - } + } + + public bool Contains(Point point) { return true; } } } diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SensitivityFunctionFactory.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SensitivityFunctionFactory.cs index b026e742c..aa40acbb0 100644 --- a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SensitivityFunctionFactory.cs +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SensitivityFunctionFactory.cs @@ -1,9 +1,8 @@ using JuliusSweetland.OptiKey.Extensions; +using JuliusSweetland.OptiKey.Static; using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Text.RegularExpressions; namespace JuliusSweetland.OptiKey.Models.ScalingModels @@ -12,7 +11,8 @@ class SensitivityFunctionFactory { public static ISensitivityFunction Create(string inputString) { - + var deadzones = new List(); + var regions = new List(); // Empty string: classic SqrtScalingFromSettings double baseSpeed = 0; double acceleration = 0.02; @@ -26,8 +26,8 @@ public static ISensitivityFunction Create(string inputString) { inputString = inputString.Trim(); } - - string inputStringWithoutWhitespace = inputString.RemoveWhitespace(); + + string inputStringWithoutWhitespace = inputString.RemoveWhitespace().ToLower(); // String contains numbers, separator, whitespace only: classic SqrtScalingFromSettings if (inputString.All(x => char.IsWhiteSpace(x) || x == ',' || char.IsDigit(x))) @@ -50,10 +50,10 @@ public static ISensitivityFunction Create(string inputString) yScale = parts[1]; } - SqrtScalingFromSettings sqrtScaling = new SqrtScalingFromSettings(baseSpeed, acceleration); + SqrtScalingFromSettings sqrtScaling = new SqrtScalingFromSettings(baseSpeed, acceleration); sqrtScaling.SetScaleFactor(new float[] { xScale, yScale }); - return sqrtScaling; + return sqrtScaling; } catch (Exception e) { @@ -61,13 +61,119 @@ public static ISensitivityFunction Create(string inputString) } } + var regex = new Regex(@"deadzones\(([\d.]*,[\d.]*,[\d.]*,[\d.]*,[\d])\)"); + if (regex.IsMatch(inputStringWithoutWhitespace)) + { + Match m = regex.Match(inputStringWithoutWhitespace); + if (m.Success) + { + var inputData = m.Groups[1].Captures[0].ToString(); + var inputList = Regex.Split(inputData, @"[\s \)\(]").Where(s => s != String.Empty); + if (inputList.Any()) + { + foreach (var input in inputList) + { + var split = input.Split(',').Where(s => s != String.Empty); + var nums = (from number in split select number.ToFloat()).ToArray(); + if (nums.Any() && nums.Count() > 4) + { + var visible = nums.Count() > 4 && nums[4] == 1; + + deadzones.Add(new Region(nums[0], nums[1], nums[2], nums[3], 0, 0, 0, visible)); + } + } + } + } + } + + regex = new Regex(@"rings([\d.,()]*)"); + if (regex.IsMatch(inputStringWithoutWhitespace)) + { + Match m = regex.Match(inputStringWithoutWhitespace); + if (m.Success) + { + var inputData = m.Groups[1].Captures[0].ToString(); + var inputList = Regex.Split(inputData, @"[\s \)\(]").Where(s => s != String.Empty); + if (inputList.Any()) + { + foreach (var input in inputList) + { + var split = input.Split(',').Where(s => s != String.Empty); + var nums = (from number in split select number.ToFloat()).ToArray(); + if (nums.Any() && nums.Count() > 1) + { + var ratio = Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels; + var visible = nums.Count() > 3 ? nums[3] == 1 : input == inputList.First() || input == inputList.Last(); + + if (!regions.Any()) + { + var radius = nums[2]; + var left = nums[0] - radius; + var top = nums[1] - radius; + var width = 2 * radius; + var height = width * ratio; + regions.Add(new Region(left, top, width, height, radius, 0, 0, visible)); + } + else + { + var radius = nums[0]; + var left = regions[0].Center.X - radius; + var top = regions[0].Center.Y - radius; + var width = 2 * radius; + var height = width * ratio; + var amount = nums[1]; + var gradient = nums.Count() > 2 ? nums[2] : .5; + regions.Add(new Region(left, top, width, height, radius, amount, gradient, visible)); + } + } + } + } + if (regions.Count > 1) + { + RegionScaling regionScaling = new RegionScaling(deadzones, regions); + return regionScaling; + } + } + } + + regex = new Regex(@"rectangles([\d.,()]*)"); + if (regex.IsMatch(inputStringWithoutWhitespace)) + { + Match m = regex.Match(inputStringWithoutWhitespace); + if (m.Success) + { + var inputData = m.Groups[1].Captures[0].ToString(); + var inputList = Regex.Split(inputData, @"[\s \)\(]").Where(s => s != String.Empty); + if (inputList.Any()) + { + foreach (var input in inputList) + { + var split = input.Split(',').Where(s => s != String.Empty); + var nums = (from number in split select number.ToFloat()).ToArray(); + if (nums.Any() && nums.Count() > 4) + { + var gradient = nums.Count() > 5 ? nums[5] : .5; + var visible = nums.Count() > 6 ? nums[6] == 1 : input == inputList.First() || input == inputList.Last(); + regions.Add(new Region(nums[0], nums[1], nums[2], nums[3], + 0, nums[4], gradient, visible)); + } + } + } + if (regions.Count > 1) + { + RegionScaling regionScaling = new RegionScaling(deadzones, regions); + return regionScaling; + } + } + } + // special case for "ring": i,e spherical tophat // "ring[inner radius, outer radius, amount]" // e.g ring[0.3, 0.5, 1.0] - Regex rgxMatchRing= new Regex(@"ring\[([\d.]*),([\d.]*),([\d.]*)\]"); - if (rgxMatchRing.IsMatch(inputStringWithoutWhitespace)) + regex = new Regex(@"ring\[([\d.]*),([\d.]*),([\d.]*)\]"); + if (regex.IsMatch(inputStringWithoutWhitespace)) { - Match m = rgxMatchRing.Match(inputStringWithoutWhitespace); + Match m = regex.Match(inputStringWithoutWhitespace); if (m.Success) { if (m.Groups.Count >= 4) @@ -75,7 +181,7 @@ public static ISensitivityFunction Create(string inputString) // TODO: add some exception handling for these conversions? float innerRadius = Convert.ToSingle(m.Groups[1].Captures[0].ToString()); float outerRadius = Convert.ToSingle(m.Groups[2].Captures[0].ToString()); - float scale = 1.0f; + float scale = 1.0f; if (m.Groups.Count >= 4 && m.Groups[3].Length > 0) { scale = Convert.ToSingle(m.Groups[3].Captures[0].ToString()); @@ -97,10 +203,10 @@ public static ISensitivityFunction Create(string inputString) // string "piecewise" and a list of coordinates // e.g. triangle would be "piecewise[(0.25, 0), (0.5, 1), (0.75, 0)]" - Regex rgxMatchPiecewise = new Regex(@"piecewise\[([\d.,()]*)\]"); - if (rgxMatchPiecewise.IsMatch(inputStringWithoutWhitespace)) + regex = new Regex(@"piecewise\[([\d.,()]*)\]"); + if (regex.IsMatch(inputStringWithoutWhitespace)) { - Match m = rgxMatchPiecewise.Match(inputStringWithoutWhitespace); + Match m = regex.Match(inputStringWithoutWhitespace); if (m.Success) { string coords = m.Groups[1].Captures[0].ToString(); @@ -111,16 +217,16 @@ public static ISensitivityFunction Create(string inputString) piecewiseScaling.SetCoords(allCoords.ToArray()); return piecewiseScaling; - } + } } // string "segments" and params // e.g. "segments[4, 0.5, 0.8, 0.5]" where params are // number of segments, inner radius, outer radius, (optional) maximum scaling - Regex rgxMatchSegment= new Regex(@"segments?\[(\d*),([\d.]*),([\d.]*),?([\d.]*)?\]"); - if (rgxMatchSegment.IsMatch(inputStringWithoutWhitespace)) + regex = new Regex(@"segments?\[(\d*),([\d.]*),([\d.]*),?([\d.]*)?\]"); + if (regex.IsMatch(inputStringWithoutWhitespace)) { - Match m = rgxMatchSegment.Match(inputStringWithoutWhitespace); + Match m = regex.Match(inputStringWithoutWhitespace); if (m.Success) { if (m.Groups.Count >= 4) { @@ -144,6 +250,5 @@ public static ISensitivityFunction Create(string inputString) sqrtScalingFallback.SetScaleFactor(new float[] { 1.0f, 1.0f }); return sqrtScalingFallback; } - } } diff --git a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SqrtScalingFromSettings.cs b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SqrtScalingFromSettings.cs index b61a740bc..82a811c0f 100644 --- a/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SqrtScalingFromSettings.cs +++ b/src/JuliusSweetland.OptiKey.Core/Models/ScalingModels/SqrtScalingFromSettings.cs @@ -21,22 +21,20 @@ public SqrtScalingFromSettings(double baseSpeed, double acceleration) { this.acceleration = acceleration; } - public void SetScaleFactor(float[] scaleXY) { scaleX = scaleXY[0]; scaleY = scaleXY[1]; } - public List GetContours() + public List GetContours() { - double deadzoneWidth = (double)Settings.Default.JoystickHorizontalDeadzonePercentScreen * Graphics.PrimaryScreenWidthInPixels / 100.0d; - double deadzoneHeight = deadzoneWidth / Settings.Default.JoystickDeadzoneAspectRatio; + var deadzoneWidth = Settings.Default.JoystickHorizontalDeadzonePercentScreen / 100d; + var deadzoneHeight = deadzoneWidth * Graphics.PrimaryScreenWidthInPixels / Graphics.PrimaryScreenHeightInPixels / Settings.Default.JoystickDeadzoneAspectRatio; - Point deadzone = new Point(deadzoneWidth / 2.0f, deadzoneHeight / 2.0f); - return new List { deadzone }; + return new List() { new Region(.5 - deadzoneWidth / 2, .5 - deadzoneHeight / 2, deadzoneWidth, deadzoneHeight, 1) }; } public Vector CalculateScaling(Point current, Point centre) @@ -94,6 +92,7 @@ private Vector CalculateLookToScrollVelocityVec( } } + public bool Contains(Point point) { return true; } private Vector ellipseIntersection(Vector vector, double rx, double ry) { diff --git a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/ILookToScrollOverlayViewModel.cs b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/ILookToScrollOverlayViewModel.cs index ca37b81f2..1f440acfb 100644 --- a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/ILookToScrollOverlayViewModel.cs +++ b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/ILookToScrollOverlayViewModel.cs @@ -1,13 +1,13 @@ // Copyright (c) 2020 OPTIKEY LTD (UK company number 11854839) - All Rights Reserved +using JuliusSweetland.OptiKey.Models.ScalingModels; using System.Collections.Generic; using System.ComponentModel; -using System.Windows; namespace JuliusSweetland.OptiKey.UI.ViewModels { public interface ILookToScrollOverlayViewModel : INotifyPropertyChanged { bool IsActive { get; } - List ZeroContours { get; } + List ZeroContours { get; } } } diff --git a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/Look2DInteractionHandler.cs b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/Look2DInteractionHandler.cs index 82dd3145c..e135c683e 100644 --- a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/Look2DInteractionHandler.cs +++ b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/Look2DInteractionHandler.cs @@ -87,8 +87,8 @@ public Thickness ActiveMargins private set { SetProperty(ref activeMargins, value); } } - private List zeroContours = new List(); - public List ZeroContours + private List zeroContours = new List(); + public List ZeroContours { get { return zeroContours; } private set { SetProperty(ref zeroContours, value); } @@ -101,14 +101,14 @@ public List ZeroContours public void Enable(KeyValue keyValue) { Log.InfoFormat("Activating 2D control: {0}", this.triggerKey); - + sensitivityFunction = SensitivityFunctionFactory.Create(keyValue.String); zeroContours = sensitivityFunction.GetContours(); RaisePropertyChanged("ZeroContours"); // Choose joystick centre via "Reset" key if (keyStateService.KeyDownStates[KeyValues.ResetJoystickKey].Value == KeyDownStates.LockedDown) - { + { ChooseLookToScrollBoundsTarget(false); } // Default to centre of screen @@ -254,7 +254,7 @@ private bool ShouldUpdateLookToScroll(Point position, out Rect bounds, out Point keyPadding = 25; if (keyStateService.KeyDownStates[KeyValues.SleepKey].Value.IsDownOrLockedDown() || - mainViewModel.IsPointInsideValidKey(position, keyPadding) || + //mainViewModel.IsPointInsideValidKey(position, keyPadding) || choosingBoundsTarget || !lastUpdate.HasValue) { @@ -282,7 +282,7 @@ private bool ShouldUpdateLookToScroll(Point position, out Rect bounds, out Point bounds = boundsContainer.Value; centre = pointBoundsTarget.Value; - return bounds.Contains(position); + return sensitivityFunction.Contains(position); } private Rect? GetCurrentLookToScrollBoundsRect() @@ -294,22 +294,6 @@ private bool ShouldUpdateLookToScroll(Point position, out Rect bounds, out Point return bounds; } - private Vector ellipseIntersection(Vector vector, double rx, double ry) - { - if (vector.LengthSquared == 0) - { - return new Vector(0, 0); - } - else { - // Intersection computed using parametric form for ellipse - // x = rx*cos(t), y = ry*sin(t) for parameter t [0,2π] - var t = Math.Atan2((rx * vector.Y), (ry * vector.X)); - - return new Vector(rx * Math.Cos(t), ry * Math.Sin(t)); - } - } - - private void UpdateLookToScrollOverlayProperties(Rect bounds, Point centre) { double hDeadzone = (double)Settings.Default.JoystickHorizontalDeadzonePercentScreen * Graphics.PrimaryScreenWidthInPixels / 100.0d; @@ -330,38 +314,6 @@ private void UpdateLookToScrollOverlayProperties(Rect bounds, Point centre) ActiveDeadzone = Graphics.PixelsToDips(deadzone); ActiveMargins = Graphics.PixelsToDips(bounds.CalculateMarginsAround(deadzone)); } - - private static float[] ParseScaleFromString(string s) - { - float xScale = 1.0f; - float yScale = 1.0f; - - if (!String.IsNullOrEmpty(s)) - { - try - { - char[] delimChars = { ',' }; - float[] parts = s.ToFloatArray(delimChars); - if (parts.Length == 1) - { - xScale = yScale = parts[0]; - } - else if (parts.Length > 1) - { - xScale = parts[0]; - yScale = parts[1]; - } - } - catch (Exception e) - { - Log.ErrorFormat("Couldn't parse scale {0}", s); - } - } - - float[] scale = { xScale, yScale }; ; - return scale; - } - #endregion } } \ No newline at end of file diff --git a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/MainViewModel.LookToScroll.cs b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/MainViewModel.LookToScroll.cs index 6cc948a26..cf1cd834a 100644 --- a/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/MainViewModel.LookToScroll.cs +++ b/src/JuliusSweetland.OptiKey.Core/UI/ViewModels/MainViewModel.LookToScroll.cs @@ -146,18 +146,18 @@ private void ToggleJoystick(KeyValue requestedKeyValue) else JoystickHandlers[requestedFunctionKey].Enable(requestedKeyValue); } - else if (joystickKeys.Contains(keyVal.FunctionKey.Value)) - { - // Any other key which should be mutually-exclusive. - // Disable button and joystick - if (keyStateService.KeyDownStates[keyVal].Value == KeyDownStates.Down || - keyStateService.KeyDownStates[keyVal].Value == KeyDownStates.LockedDown) - { - keyStateService.KeyDownStates[keyVal].Value = KeyDownStates.Up; - if (keyVal.FunctionKey.Value != requestedFunctionKey) - JoystickHandlers[keyVal.FunctionKey.Value].Disable(); - } - } + //else if (joystickKeys.Contains(keyVal.FunctionKey.Value)) + //{ + // // Any other key which should be mutually-exclusive. + // // Disable button and joystick + // if (keyStateService.KeyDownStates[keyVal].Value == KeyDownStates.Down || + // keyStateService.KeyDownStates[keyVal].Value == KeyDownStates.LockedDown) + // { + // keyStateService.KeyDownStates[keyVal].Value = KeyDownStates.Up; + // if (keyVal.FunctionKey.Value != requestedFunctionKey) + // JoystickHandlers[keyVal.FunctionKey.Value].Disable(); + // } + //} } } } diff --git a/src/JuliusSweetland.OptiKey.Core/UI/Windows/LookToScrollOverlayWindow.xaml.cs b/src/JuliusSweetland.OptiKey.Core/UI/Windows/LookToScrollOverlayWindow.xaml.cs index 94987b56d..4722829c8 100644 --- a/src/JuliusSweetland.OptiKey.Core/UI/Windows/LookToScrollOverlayWindow.xaml.cs +++ b/src/JuliusSweetland.OptiKey.Core/UI/Windows/LookToScrollOverlayWindow.xaml.cs @@ -7,6 +7,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Shapes; +using JuliusSweetland.OptiKey.Models.ScalingModels; using JuliusSweetland.OptiKey.Static; using JuliusSweetland.OptiKey.UI.ViewModels; @@ -30,23 +31,19 @@ public LookToScrollOverlayWindow(ILookToScrollOverlayViewModel viewModel) this.UpdateContours(viewModel.ZeroContours); } - private void AddEllipse(Point centre, Point radii) + private void AddEllipse(Region region) { - double w = Graphics.PrimaryScreenWidthInPixels; - double h = Graphics.PrimaryScreenHeightInPixels; - Rectangle rect = new Rectangle(); - rect.Width = radii.X * 2; - rect.Height = radii.Y * 2; - rect.RadiusX = radii.X; - rect.RadiusY = radii.Y; + rect.Width = region.Width * Graphics.PrimaryScreenWidthInPixels / Graphics.DipScalingFactorX; + rect.Height = region.Height * Graphics.PrimaryScreenHeightInPixels / Graphics.DipScalingFactorY; + rect.RadiusX = region.Radius * Graphics.PrimaryScreenWidthInPixels / Graphics.DipScalingFactorX; ; + rect.RadiusY = rect.RadiusX; rect.Stroke = Brushes.CadetBlue; rect.Opacity = 0.25; rect.StrokeThickness = 4; - var top = centre - radii; - Canvas.SetTop(rect, top.Y); - Canvas.SetLeft(rect, top.X); + Canvas.SetLeft(rect, region.Left * Graphics.PrimaryScreenWidthInPixels / Graphics.DipScalingFactorX); + Canvas.SetTop(rect, region.Top * Graphics.PrimaryScreenHeightInPixels / Graphics.DipScalingFactorY); canvas.Children.Add(rect); } @@ -62,19 +59,13 @@ protected override void OnSourceInitialized(EventArgs e) Static.Windows.SetWindowExTransparent(hWnd); } - private void UpdateContours(List zeroContours) + private void UpdateContours(List zeroContours) { canvas.Children.Clear(); - Point centre = new Point(SystemParameters.PrimaryScreenWidth / 2, SystemParameters.PrimaryScreenHeight / 2); - foreach (Point radii in zeroContours) + foreach (var region in zeroContours) { - // we convert from px to dip for canvas - Point radiiScaled = radii; - radiiScaled.X /= Graphics.DipScalingFactorX; - radiiScaled.Y /= Graphics.DipScalingFactorY; - - this.AddEllipse(centre, radiiScaled); + this.AddEllipse(region); } } diff --git a/src/JuliusSweetland.OptiKey.Core/app.manifest b/src/JuliusSweetland.OptiKey.Core/app.manifest index 4a6015358..7fe241f4d 100644 --- a/src/JuliusSweetland.OptiKey.Core/app.manifest +++ b/src/JuliusSweetland.OptiKey.Core/app.manifest @@ -16,7 +16,7 @@ If you want to utilize File and Registry Virtualization for backward compatibility then delete the requestedExecutionLevel node. --> - + diff --git a/src/JuliusSweetland.OptiKey.Crayta/JuliusSweetland.OptiKey.OptikeyGaming.csproj b/src/JuliusSweetland.OptiKey.Crayta/JuliusSweetland.OptiKey.OptikeyGaming.csproj index d57178a3c..fa2512da5 100644 --- a/src/JuliusSweetland.OptiKey.Crayta/JuliusSweetland.OptiKey.OptikeyGaming.csproj +++ b/src/JuliusSweetland.OptiKey.Crayta/JuliusSweetland.OptiKey.OptikeyGaming.csproj @@ -1046,15 +1046,11 @@ - rd /s /q $(TargetDir)\Resources\Presage\ - -if "$(ConfigurationName)"=="Release" ( - $(ProjectDir)\..\..\installer\tools\signtool.exe sign /a /n "Open Source Developer, Kirsty McNaught" /t http://time.certum.pl /fd sha256 /v $(ProjectDir)\obj\$(ConfigurationName)\$(TargetFileName) -) + + - if "$(ConfigurationName)"=="Release" ( - "C:\Program Files\Git\bin\git.exe" rev-parse --short HEAD > "$(ProjectDir)\version.txt" -) + "C:\Program Files\Git\bin\git.exe" rev-parse --short HEAD > "$(ProjectDir)\version.txt" + \ No newline at end of file