Add support for large button setting, which extends the size of the ring buttons to fill the rendered area of the touch pannel

Re-write button handling to decrese latency and fix issues where some notes where not picked up during slide actions
master
LeapwardKoex 2025-04-06 10:04:13 +12:00
parent df962b7304
commit 643fb31505
9 changed files with 558 additions and 110 deletions

View File

@ -37,6 +37,9 @@
<setting name="UserSettingsUpgradeRequired" serializeAs="String">
<value>True</value>
</setting>
<setting name="IsLargeButtonsEnabled" serializeAs="String">
<value>False</value>
</setting>
</WpfMaiTouchEmulator.Properties.Settings>
</userSettings>
</configuration>

View File

@ -99,7 +99,7 @@
<Label x:Name="languageLabel" Content="{Binding LbLanguageDropdown}" d:Content="Language"/>
<ComboBox x:Name="languageSelector" ItemsSource="{Binding SupportedLanguages}" DisplayMemberPath="NativeName" SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}"/>
<Separator Margin="0,6"/>
<CheckBox x:Name="largeButtons" Content="{Binding LbLargeButtons}" d:Content="LargeButtons" IsChecked="{Binding Path=IsLargeButtonsEnabled}" Click="largeButtons_Click" Cursor="" Focusable="False" ToolTip="Extend ring button hitboxes" />
<CheckBox x:Name="debugMode" Content="{Binding LbDebugMode}" d:Content="Debug mode" IsChecked="{Binding Path=IsDebugEnabled}" Click="debugMode_Click" Cursor="" Focusable="False" ToolTip="Show the touchpad with translucency and show inputs highlighted" />
<CheckBox x:Name="automaticTouchPanelPositioning" d:Content="Automatic touch panel positioning" Content="{Binding LbAutoSensorPositioning}" IsChecked="{Binding Path=IsAutomaticPositioningEnabled}" Click="automaticTouchPanelPositioning_Click" ToolTip="{Binding LbAutoSensorPositioningTT}"/>
<CheckBox x:Name="automaticPortConnecting" d:Content="Automatic port connecting" Content="{Binding LbAutoPortConnecting}" IsChecked="{Binding Path=IsAutomaticPortConnectingEnabled}" Click="automaticPortConnecting_Click" ToolTip="{Binding LbAutoPortConnectingTT}"/>

View File

@ -30,6 +30,7 @@ public partial class MainWindow : Window
IsAutomaticPositioningEnabled = Properties.Settings.Default.IsAutomaticPositioningEnabled,
IsExitWithSinmaiEnabled = Properties.Settings.Default.IsExitWithSinmaiEnabled,
IsRingButtonEmulationEnabled = Properties.Settings.Default.IsRingButtonEmulationEnabled,
IsLargeButtonsEnabled = Properties.Settings.Default.IsLargeButtonsEnabled,
BorderColour = Properties.Settings.Default.BorderColour,
LbAppVersion = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "1.0.0.0",
};
@ -82,8 +83,14 @@ public partial class MainWindow : Window
Logger.Info("Main window loaded, creating touch panel");
_touchPanel = new TouchPanel();
_touchPanel.onTouch = (value) => { buttonState.PressButton(value); };
_touchPanel.onRelease = (value) => { buttonState.ReleaseButton(value); };
_touchPanel.onTouch = (value) => {
buttonState.PressButton(value);
connector.SendTouchscreenState();
};
_touchPanel.onRelease = (value) => {
buttonState.ReleaseButton(value);
connector.SendTouchscreenState();
};
_touchPanel.onInitialReposition = () => { WindowState = WindowState.Minimized; };
_touchPanel.SetBorderMode((BorderSetting)Properties.Settings.Default.BorderSetting, dataContext.BorderColour);
_touchPanel.Show();
@ -91,6 +98,7 @@ public partial class MainWindow : Window
_touchPanel.DataContext = dataContext;
_touchPanel.SetDebugMode(dataContext.IsDebugEnabled);
_touchPanel.SetLargeButtonMode(dataContext.IsLargeButtonsEnabled);
if (Properties.Settings.Default.IsAutomaticPositioningEnabled)
{
_touchPanel.DragWindowHandle.Visibility = Visibility.Hidden;
@ -216,6 +224,16 @@ public partial class MainWindow : Window
_touchPanel?.SetDebugMode(dataContext.IsDebugEnabled);
}
private void largeButtons_Click(object sender, RoutedEventArgs e)
{
var dataContext = (MainWindowViewModel)DataContext;
var enabled = !dataContext.IsLargeButtonsEnabled;
dataContext.IsLargeButtonsEnabled = !enabled;
Properties.Settings.Default.IsLargeButtonsEnabled = dataContext.IsLargeButtonsEnabled;
Properties.Settings.Default.Save();
_touchPanel?.SetLargeButtonMode(dataContext.IsLargeButtonsEnabled);
}
private void automaticTouchPanelPositioning_Click(object sender, RoutedEventArgs e)
{
var dataContext = (MainWindowViewModel)DataContext;

View File

@ -36,6 +36,10 @@ public class MainWindowViewModel : INotifyPropertyChanged
{
get; set;
}
public string? LbLargeButtons
{
get; set;
}
public string? LbExitWithSinmai
{
get; set;
@ -222,6 +226,7 @@ public class MainWindowViewModel : INotifyPropertyChanged
private bool _isAutomaticPortConnectingEnabled;
private bool _isDebugEnabled;
private bool _isLargeButtonsEnabled;
private bool _isAutomaticPositioningEnabled;
private bool _isExitWithSinmaiEnabled;
private CultureInfo _selectedLanguage;
@ -265,6 +270,16 @@ public class MainWindowViewModel : INotifyPropertyChanged
}
}
public bool IsLargeButtonsEnabled
{
get => _isLargeButtonsEnabled;
set
{
_isLargeButtonsEnabled = value;
OnPropertyChanged();
}
}
public bool IsAutomaticPositioningEnabled
{
get => _isAutomaticPositioningEnabled;
@ -349,6 +364,7 @@ public class MainWindowViewModel : INotifyPropertyChanged
LbConnectionStateNotConnected = resourceManager.GetString("lbConnectionStateNotConnected");
LbConnectToPort = resourceManager.GetString("lbConnectToPort");
LbDebugMode = resourceManager.GetString("lbDebugMode");
LbLargeButtons = resourceManager.GetString("lbLargeButtons");
LbExitWithSinmai = resourceManager.GetString("lbExitWithSinmai");
LbEmulateRingButtons = resourceManager.GetString("lbEmulateRingButtons");
LbOpenLogFolder = resourceManager.GetString("LbOpenLogFolder");

View File

@ -182,7 +182,7 @@ internal class MaiTouchComConnector(MaiTouchSensorButtonStateManager buttonState
}
}
void SendTouchscreenState()
public void SendTouchscreenState()
{
if (_connected && _isActiveMode)
{

View File

@ -12,7 +12,7 @@ namespace WpfMaiTouchEmulator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.12.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -142,5 +142,17 @@ namespace WpfMaiTouchEmulator.Properties {
this["UserSettingsUpgradeRequired"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool IsLargeButtonsEnabled {
get {
return ((bool)(this["IsLargeButtonsEnabled"]));
}
set {
this["IsLargeButtonsEnabled"] = value;
}
}
}
}

View File

@ -32,5 +32,8 @@
<Setting Name="UserSettingsUpgradeRequired" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="IsLargeButtonsEnabled" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -27,42 +27,42 @@
Width="1440" VerticalAlignment="Bottom">
<Canvas x:Name="TouchCanvas" Width="1440" Height="1440" Margin="-10,-10,-10,-10">
<Polygon Canvas.Left="620" Canvas.Top="6" Points="0,5 50,2 100,0 150,2 200,5 165,253 100,188 35,253" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D1}" Fill="White" />
<Polygon Canvas.Left="786" Canvas.Top="11" Points="150,28 245,65 360,133 208,338 145,338 49,297 0,249 35,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A1}" Fill="White" />
<Polygon Canvas.Left="995" Canvas.Top="144" Points="153,0 187,32 225,67 259,104 295,147 96,297 96,205 0,205" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D2}" Fill="White" />
<Polygon Canvas.Left="1091" Canvas.Top="292" Points="261,101 303,195 339,327 91,362 42,314 0,219 0,150 202,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A2}" Fill="White" />
<Polygon Canvas.Left="1182" Canvas.Top="620" Points="248,0 251,48 253,100 251,150 247,199 0,165 65,100 0,35" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D3}" Fill="White" />
<Polygon Canvas.Left="1092" Canvas.Top="786" Points="305,150 269,246 201,364 0,213 0,144 41,48 89,0 337,34" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A3}" Fill="White" />
<Polygon Canvas.Left="1000" Canvas.Top="1000" Points="292,151 260,187 225,225 188,259 151,291 0,92 92,92 92,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D4}" Fill="White" />
<Polygon Canvas.Left="786" Canvas.Top="1092" Points="260,259 167,301 37,335 0,83 48,35 144,0 212,0 364,200" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A4}" Fill="White" />
<Polygon Canvas.Left="621" Canvas.Top="1175" Points="199,252 151,255 99,257 49,255 0,252 34,0 99,65 164,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D5}" Fill="White" />
<Polygon Canvas.Left="291" Canvas.Top="1092" Points="104,259 197,301 327,335 363,83 316,35 220,0 152,0 0,201" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A5}" Fill="White" />
<Polygon Canvas.Left="150" Canvas.Top="1000" Points="140,292 104,260 66,225 32,188 0,151 199,0 199,92 291,92" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D6}" Fill="White" />
<Polygon Canvas.Left="16" Canvas.Top="785" Points="32,150 68,246 133,365 333,214 333,144 296,48 248,0 0,35" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A6}" Fill="White" />
<Polygon Canvas.Left="10" Canvas.Top="620" Points="5,199 2,151 0,99 2,49 6,0 253,34 188,99 253,164" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D7}" Fill="White" />
<Polygon Canvas.Left="16" Canvas.Top="291" Points="78,101 36,195 0,327 248,362 297,314 333,219 333,151 132,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A7}" Fill="White" />
<Polygon Canvas.Left="149" Canvas.Top="150" Points="0,140 32,104 67,66 104,32 145,0 298,199 200,199 200,291" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.D8}" Fill="White" />
<Polygon Canvas.Left="295" Canvas.Top="11" Points="210,28 115,65 0,138 153,338 215,338 311,297 359,249 324,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.A8}" Fill="White" />
<Polygon Canvas.Left="620" Canvas.Top="6" Points="0,5 50,2 100,0 150,2 200,5 165,253 100,188 35,253" Tag="{x:Static local:TouchValue.D1}" Fill="White" />
<Polygon Canvas.Left="786" Canvas.Top="11" Points="150,28 245,65 360,133 208,338 145,338 49,297 0,249 35,0" Tag="{x:Static local:TouchValue.A1}" Fill="White" />
<Polygon Canvas.Left="995" Canvas.Top="144" Points="153,0 187,32 225,67 259,104 295,147 96,297 96,205 0,205" Tag="{x:Static local:TouchValue.D2}" Fill="White" />
<Polygon Canvas.Left="1091" Canvas.Top="292" Points="261,101 303,195 339,327 91,362 42,314 0,219 0,150 202,0" Tag="{x:Static local:TouchValue.A2}" Fill="White" />
<Polygon Canvas.Left="1182" Canvas.Top="620" Points="248,0 251,48 253,100 251,150 247,199 0,165 65,100 0,35" Tag="{x:Static local:TouchValue.D3}" Fill="White" />
<Polygon Canvas.Left="1092" Canvas.Top="786" Points="305,150 269,246 201,364 0,213 0,144 41,48 89,0 337,34" Tag="{x:Static local:TouchValue.A3}" Fill="White" />
<Polygon Canvas.Left="1000" Canvas.Top="1000" Points="292,151 260,187 225,225 188,259 151,291 0,92 92,92 92,0" Tag="{x:Static local:TouchValue.D4}" Fill="White" />
<Polygon Canvas.Left="786" Canvas.Top="1092" Points="260,259 167,301 37,335 0,83 48,35 144,0 212,0 364,200" Tag="{x:Static local:TouchValue.A4}" Fill="White" />
<Polygon Canvas.Left="621" Canvas.Top="1175" Points="199,252 151,255 99,257 49,255 0,252 34,0 99,65 164,0" Tag="{x:Static local:TouchValue.D5}" Fill="White" />
<Polygon Canvas.Left="291" Canvas.Top="1092" Points="104,259 197,301 327,335 363,83 316,35 220,0 152,0 0,201" Tag="{x:Static local:TouchValue.A5}" Fill="White" />
<Polygon Canvas.Left="150" Canvas.Top="1000" Points="140,292 104,260 66,225 32,188 0,151 199,0 199,92 291,92" Tag="{x:Static local:TouchValue.D6}" Fill="White" />
<Polygon Canvas.Left="16" Canvas.Top="785" Points="32,150 68,246 133,365 333,214 333,144 296,48 248,0 0,35" Tag="{x:Static local:TouchValue.A6}" Fill="White" />
<Polygon Canvas.Left="10" Canvas.Top="620" Points="5,199 2,151 0,99 2,49 6,0 253,34 188,99 253,164" Tag="{x:Static local:TouchValue.D7}" Fill="White" />
<Polygon Canvas.Left="16" Canvas.Top="291" Points="78,101 36,195 0,327 248,362 297,314 333,219 333,151 132,0" Tag="{x:Static local:TouchValue.A7}" Fill="White" />
<Polygon Canvas.Left="149" Canvas.Top="150" Points="0,140 32,104 67,66 104,32 145,0 298,199 200,199 200,291" Tag="{x:Static local:TouchValue.D8}" Fill="White" />
<Polygon Canvas.Left="295" Canvas.Top="11" Points="210,28 115,65 0,138 153,338 215,338 311,297 359,249 324,0" Tag="{x:Static local:TouchValue.A8}" Fill="White" />
<Polygon Canvas.Left="607" Canvas.Top="195" Points="0,113 113,0 226,113 113,226" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E1}" Fill="White" />
<Polygon Canvas.Left="720" Canvas.Top="346" Points="0,78 78,0 209,55 209,165 180,195 70,195 0,130" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B1}" Fill="White" />
<Polygon Canvas.Left="930" Canvas.Top="350" Points="0,0 0,160 160,160, 160,0 0,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E2}" Fill="White" />
<Polygon Canvas.Left="900" Canvas.Top="511" Points="117,209 195,132 140,0 30,0 0,30 0,139 65,209" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B2}" Fill="White" />
<Polygon Canvas.Left="1020" Canvas.Top="607" Points="0,113 113,0 226,113 113,226" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E3}" Fill="White" />
<Polygon Canvas.Left="900" Canvas.Top="721" Points="120,0 198,78 140,208 30,208 0,180 0,71 65,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B3}" Fill="White" />
<Polygon Canvas.Left="930" Canvas.Top="930" Points="0,0 0,160 160,160, 160,0 0,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E4}" Fill="White" />
<Polygon Canvas.Left="721" Canvas.Top="901" Points="0,112 87,198 208,140 208,29 177,0 71,0 0,65" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B4}" Fill="White" />
<Polygon Canvas.Left="607" Canvas.Top="1013" Points="0,113 113,0 226,113 113,226" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E5}" Fill="White" />
<Polygon Canvas.Left="512" Canvas.Top="901" Points="208,112 121,198 0,140 0,29 31,0 137,0 208,65" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B5}" Fill="White" />
<Polygon Canvas.Left="350" Canvas.Top="930" Points="0,0 0,160 160,160, 160,0 0,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E6}" Fill="White" />
<Polygon Canvas.Left="349" Canvas.Top="721" Points="78,0 0,78 58,208 163,208 193,180 193,71 133,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B6}" Fill="White" />
<Polygon Canvas.Left="200" Canvas.Top="607" Points="0,113 113,0 226,113 113,226" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E7}" Fill="White" />
<Polygon Canvas.Left="345" Canvas.Top="511" Points="82,209 0,127 55,0 165,0 195,30 195,139 137,209" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B7}" Fill="White" />
<Polygon Canvas.Left="350" Canvas.Top="350" Points="0,0 0,160 160,160, 160,0 0,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.E8}" Fill="White" />
<Polygon Canvas.Left="511" Canvas.Top="346" Points="209,78 131,0 0,55 0,165 29,195 139,195 209,130" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.B8}" Fill="White" />
<Polygon Canvas.Left="607" Canvas.Top="195" Points="0,113 113,0 226,113 113,226" Tag="{x:Static local:TouchValue.E1}" Fill="White" />
<Polygon Canvas.Left="720" Canvas.Top="346" Points="0,78 78,0 209,55 209,165 180,195 70,195 0,130" Tag="{x:Static local:TouchValue.B1}" Fill="White" />
<Polygon Canvas.Left="930" Canvas.Top="350" Points="0,0 0,160 160,160, 160,0 0,0" Tag="{x:Static local:TouchValue.E2}" Fill="White" />
<Polygon Canvas.Left="900" Canvas.Top="511" Points="117,209 195,132 140,0 30,0 0,30 0,139 65,209" Tag="{x:Static local:TouchValue.B2}" Fill="White" />
<Polygon Canvas.Left="1020" Canvas.Top="607" Points="0,113 113,0 226,113 113,226" Tag="{x:Static local:TouchValue.E3}" Fill="White" />
<Polygon Canvas.Left="900" Canvas.Top="721" Points="120,0 198,78 140,208 30,208 0,180 0,71 65,0" Tag="{x:Static local:TouchValue.B3}" Fill="White" />
<Polygon Canvas.Left="930" Canvas.Top="930" Points="0,0 0,160 160,160, 160,0 0,0" Tag="{x:Static local:TouchValue.E4}" Fill="White" />
<Polygon Canvas.Left="721" Canvas.Top="901" Points="0,112 87,198 208,140 208,29 177,0 71,0 0,65" Tag="{x:Static local:TouchValue.B4}" Fill="White" />
<Polygon Canvas.Left="607" Canvas.Top="1013" Points="0,113 113,0 226,113 113,226" Tag="{x:Static local:TouchValue.E5}" Fill="White" />
<Polygon Canvas.Left="512" Canvas.Top="901" Points="208,112 121,198 0,140 0,29 31,0 137,0 208,65" Tag="{x:Static local:TouchValue.B5}" Fill="White" />
<Polygon Canvas.Left="350" Canvas.Top="930" Points="0,0 0,160 160,160, 160,0 0,0" Tag="{x:Static local:TouchValue.E6}" Fill="White" />
<Polygon Canvas.Left="349" Canvas.Top="721" Points="78,0 0,78 58,208 163,208 193,180 193,71 133,0" Tag="{x:Static local:TouchValue.B6}" Fill="White" />
<Polygon Canvas.Left="200" Canvas.Top="607" Points="0,113 113,0 226,113 113,226" Tag="{x:Static local:TouchValue.E7}" Fill="White" />
<Polygon Canvas.Left="345" Canvas.Top="511" Points="82,209 0,127 55,0 165,0 195,30 195,139 137,209" Tag="{x:Static local:TouchValue.B7}" Fill="White" />
<Polygon Canvas.Left="350" Canvas.Top="350" Points="0,0 0,160 160,160, 160,0 0,0" Tag="{x:Static local:TouchValue.E8}" Fill="White" />
<Polygon Canvas.Left="511" Canvas.Top="346" Points="209,78 131,0 0,55 0,165 29,195 139,195 209,130" Tag="{x:Static local:TouchValue.B8}" Fill="White" />
<Polygon Canvas.Left="720" Canvas.Top="583" Points="0,0 60,0 140,80 140,200 60,280 0,280 0,0" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.C1}" Fill="White" />
<Polygon Canvas.Left="579" Canvas.Top="583" Points="141,280 81,280 0,199 1,81 81,0 141,0 141,280" PreviewTouchDown="Element_TouchDown" PreviewTouchMove="Element_TouchMove" PreviewTouchUp="Element_TouchUp" Tag="{x:Static local:TouchValue.C2}" Fill="White" />
<Polygon Canvas.Left="720" Canvas.Top="583" Points="0,0 60,0 140,80 140,200 60,280 0,280 0,0" Tag="{x:Static local:TouchValue.C1}" Fill="White" />
<Polygon Canvas.Left="579" Canvas.Top="583" Points="141,280 81,280 0,199 1,81 81,0 141,0 141,280" Tag="{x:Static local:TouchValue.C2}" Fill="White" />
<Border x:Name="ResizeGrip" Width="150" Height="90" Background="White" MouseDown="ResizeGrip_MouseDown" Canvas.Left="1290" Canvas.Top="1350" HorizontalAlignment="Center" VerticalAlignment="Top">

View File

@ -17,7 +17,7 @@ public partial class TouchPanel : Window
internal Action<TouchValue>? onRelease;
internal Action? onInitialReposition;
private readonly Dictionary<int, Polygon> activeTouches = [];
private readonly Dictionary<int, (Polygon polygon, Point lastPoint)> activeTouches = new Dictionary<int, (Polygon, Point)>();
private readonly TouchPanelPositionManager _positionManager;
private List<Polygon> buttons = [];
private bool isDebugEnabled = Properties.Settings.Default.IsDebugEnabled;
@ -42,24 +42,7 @@ public partial class TouchPanel : Window
Topmost = true;
_positionManager = new TouchPanelPositionManager();
Loaded += Window_Loaded;
StateCheckLoop();
}
private async void StateCheckLoop()
{
while (true)
{
if (activeTouches.Count != 0 && !TouchesOver.Any())
{
await Task.Delay(100);
if (activeTouches.Count != 0 && !TouchesOver.Any())
{
DeselectAllItems();
}
}
await Task.Delay(100);
}
Touch.FrameReported += OnTouchFrameReported;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
@ -112,70 +95,101 @@ public partial class TouchPanel : Window
IntPtr.Zero);
}
private void Element_TouchDown(object sender, TouchEventArgs e)
private void OnTouchFrameReported(object sender, TouchFrameEventArgs e)
{
// Cast the sender to a Border to ensure it's the correct element type.
if (sender is Polygon element)
var currentTouchPoints = e.GetTouchPoints(this);
var currentIds = new HashSet<int>();
foreach (var touch in currentTouchPoints)
{
// Highlight the element and add it to the active touches tracking.
HighlightElement(element, true);
var touchValue = (TouchValue)element.Tag;
if (isRingButtonEmulationEnabled && RingButtonEmulator.HasRingButtonMapping((TouchValue)element.Tag))
var id = touch.TouchDevice.Id;
// If the touch is released, process it as a TouchUp.
if (touch.Action == TouchAction.Up)
{
RingButtonEmulator.PressButton((TouchValue)element.Tag);
if (activeTouches.TryGetValue(id, out var touchInfo2))
{
if (activeTouches.Values.Count(v => v.polygon == touchInfo2.polygon) == 1)
{
HighlightElement(touchInfo2.polygon, false);
onRelease?.Invoke((TouchValue)touchInfo2.polygon.Tag);
if (isRingButtonEmulationEnabled)
{
RingButtonEmulator.ReleaseButton((TouchValue)touchInfo2.polygon.Tag);
}
}
activeTouches.Remove(id);
}
continue;
}
currentIds.Add(id);
// New touch (TouchDown)
if (!activeTouches.TryGetValue(id, out var touchInfo))
{
if (VisualTreeHelper.HitTest(this, touch.Position)?.VisualHit is Polygon polygon)
{
HighlightElement(polygon, true);
activeTouches[id] = (polygon, touch.Position);
onTouch?.Invoke((TouchValue)polygon.Tag);
if (isRingButtonEmulationEnabled && RingButtonEmulator.HasRingButtonMapping((TouchValue)polygon.Tag))
{
RingButtonEmulator.PressButton((TouchValue)polygon.Tag);
}
}
}
// Existing touch (TouchMove)
else
{
onTouch?.Invoke((TouchValue)element.Tag);
}
activeTouches[e.TouchDevice.Id] = element;
}
e.Handled = true;
}
var previousPosition = touchInfo.lastPoint;
var currentPosition = touch.Position;
var sampleCount = 10;
var changed = false;
private void Element_TouchMove(object sender, TouchEventArgs e)
{
// Attempt to find the element under the current touch point.
var touchPoint = e.GetTouchPoint(this).Position;
var hitTestResult = VisualTreeHelper.HitTest(this, touchPoint);
if (hitTestResult != null && hitTestResult.VisualHit is Polygon newElement)
{
// If this touch point is already tracking another element, unhighlight the previous one.
if (activeTouches.TryGetValue(e.TouchDevice.Id, out var previousElement) && previousElement != newElement)
{
Task.Delay(50)
.ContinueWith(t =>
for (var i = 1; i <= sampleCount; i++)
{
var t = (double)i / sampleCount;
var samplePoint = new Point(
previousPosition.X + (currentPosition.X - previousPosition.X) * t,
previousPosition.Y + (currentPosition.Y - previousPosition.Y) * t);
if (VisualTreeHelper.HitTest(this, samplePoint)?.VisualHit is Polygon polygon && polygon != touchInfo.polygon)
{
HighlightElement(previousElement, false);
Application.Current.Dispatcher.Invoke(() =>
if (activeTouches.Values.Count(v => v.polygon == touchInfo.polygon) == 1)
{
onRelease?.Invoke((TouchValue)previousElement.Tag);
});
});
HighlightElement(touchInfo.polygon, false);
onRelease?.Invoke((TouchValue)touchInfo.polygon.Tag);
}
HighlightElement(polygon, true);
onTouch?.Invoke((TouchValue)polygon.Tag);
activeTouches[id] = (polygon, samplePoint);
changed = true;
break;
}
}
if (!changed)
{
activeTouches[id] = (touchInfo.polygon, currentPosition);
}
}
// Highlight the new element and update the tracking.
HighlightElement(newElement, true);
onTouch?.Invoke((TouchValue)newElement.Tag);
activeTouches[e.TouchDevice.Id] = newElement;
}
e.Handled = true;
}
private void Element_TouchUp(object sender, TouchEventArgs e)
{
// When touch is lifted, unhighlight the associated element and remove it from tracking.
if (activeTouches.TryGetValue(e.TouchDevice.Id, out var element))
// Process any touches that might not be reported this frame.
var endedTouches = activeTouches.Keys.Except(currentIds).ToList();
foreach (var id in endedTouches)
{
HighlightElement(element, false);
RingButtonEmulator.ReleaseButton((TouchValue)element.Tag);
onRelease?.Invoke((TouchValue)element.Tag);
activeTouches.Remove(e.TouchDevice.Id);
var touchInfo = activeTouches[id];
if (activeTouches.Values.Count(v => v.polygon == touchInfo.polygon) == 1)
{
HighlightElement(touchInfo.polygon, false);
onRelease?.Invoke((TouchValue)touchInfo.polygon.Tag);
if (isRingButtonEmulationEnabled)
{
RingButtonEmulator.ReleaseButton((TouchValue)touchInfo.polygon.Tag);
}
}
activeTouches.Remove(id);
}
e.Handled = true;
}
private void DeselectAllItems()
@ -183,8 +197,8 @@ public partial class TouchPanel : Window
// Logic to deselect all items or the last touched item
foreach (var element in activeTouches.Values)
{
HighlightElement(element, false);
onRelease?.Invoke((TouchValue)element.Tag);
HighlightElement(element.polygon, false);
onRelease?.Invoke((TouchValue)element.polygon.Tag);
}
activeTouches.Clear();
RingButtonEmulator.ReleaseAllButtons();
@ -199,6 +213,388 @@ public partial class TouchPanel : Window
});
}
public void SetLargeButtonMode(bool enabled)
{
TouchValue[] ringButtonsValues = {
TouchValue.A1,
TouchValue.A2,
TouchValue.A3,
TouchValue.A4,
TouchValue.A5,
TouchValue.A6,
TouchValue.A7,
TouchValue.A8,
TouchValue.D1,
TouchValue.D2,
TouchValue.D3,
TouchValue.D4,
TouchValue.D5,
TouchValue.D6,
TouchValue.D7,
TouchValue.D8,
};
var a1 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A1);
var a2 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A2);
var a3 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A3);
var a4 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A4);
var a5 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A5);
var a6 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A6);
var a7 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A7);
var a8 = buttons.First(button => (TouchValue)button.Tag == TouchValue.A8);
var d1 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D1);
var d2 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D2);
var d3 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D3);
var d4 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D4);
var d5 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D5);
var d6 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D6);
var d7 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D7);
var d8 = buttons.First(button => (TouchValue)button.Tag == TouchValue.D8);
if (enabled)
{
d1.Points = new PointCollection
{
new Point(-5, -50),
new Point(205, -50),
new Point(165, 253),
new Point(100, 188),
new Point(35, 253),
};
a1.Points = new PointCollection
{
new Point(495, -50),
new Point(208, 338),
new Point(145, 338),
new Point(49, 297),
new Point(0, 249),
new Point(42, -55),
};
d2.Points = new PointCollection
{
new Point(290, -182),
new Point(500, -180),
new Point(500, -5),
new Point(96, 297),
new Point(96, 205),
new Point(0, 205),
};
a2.Points = new PointCollection
{
new Point(405, 317),
new Point(91, 362),
new Point(42, 314),
new Point(0, 219),
new Point(0, 150),
new Point(405, -150),
};
d3.Points = new PointCollection
{
new Point(315, -10),
new Point(315, 208),
new Point(0, 165),
new Point(65, 100),
new Point(0, 35),
};
a3.Points = new PointCollection
{
new Point(406, 520),
new Point(0, 213),
new Point(0, 144),
new Point(41, 48),
new Point(89, 0),
new Point(406, 43),
};
d4.Points = new PointCollection
{
new Point(500, 309),
new Point(500, 491),
new Point(305, 491),
new Point(0, 92),
new Point(92, 92),
new Point(92, 0),
};
a4.Points = new PointCollection
{
new Point(45, 400),
new Point(0, 83),
new Point(48, 35),
new Point(144, 0),
new Point(212, 0),
new Point(515, 400),
};
d5.Points = new PointCollection
{
new Point(208, 317),
new Point(-10, 317),
new Point(34, 0),
new Point(99, 65),
new Point(164, 0),
};
a5.Points = new PointCollection
{
new Point(317, 400),
new Point(363, 83),
new Point(316, 35),
new Point(220, 0),
new Point(152, 0),
new Point(-150, 400),
};
d6.Points = new PointCollection
{
new Point(-10, 492),
new Point(-200, 492),
new Point(-200, 295),
new Point(199, 0),
new Point(199, 92),
new Point(291, 92),
};
a6.Points = new PointCollection
{
new Point(-67, 505),
new Point(333, 214),
new Point(333, 144),
new Point(296, 48),
new Point(248, 0),
new Point(-67, 45),
};
d7.Points = new PointCollection
{
new Point(-60, 207),
new Point(-60, -7),
new Point(253, 34),
new Point(188, 99),
new Point(253, 164),
};
a7.Points = new PointCollection
{
new Point(-65, 320),
new Point(248, 362),
new Point(297, 314),
new Point(333, 219),
new Point(333, 151),
new Point(-65, -150),
};
d8.Points = new PointCollection
{
new Point(-195, -10),
new Point(-195, -195),
new Point(-5, -195),
new Point(298, 199),
new Point(200, 199),
new Point(200, 291),
};
a8.Points = new PointCollection
{
new Point(-148, -55),
new Point(153, 338),
new Point(215, 338),
new Point(311, 297),
new Point(359, 249),
new Point(318, -55),
};
}
else
{
d1.Points = new PointCollection
{
new Point(0, 5),
new Point(50, 2),
new Point(100, 0),
new Point(150, 2),
new Point(200, 5),
new Point(165, 253),
new Point(100, 188),
new Point(35, 253),
};
a1.Points = new PointCollection
{
new Point(150, 28),
new Point(245, 65),
new Point(360, 133),
new Point(208, 338),
new Point(145, 338),
new Point(49, 297),
new Point(0, 249),
new Point(35, 0),
};
d2.Points = new PointCollection
{
new Point(153, 0),
new Point(187, 32),
new Point(225, 67),
new Point(259, 104),
new Point(295, 147),
new Point(96, 297),
new Point(96, 205),
new Point(0, 205),
};
a2.Points = new PointCollection
{
new Point(261, 101),
new Point(303, 195),
new Point(339, 327),
new Point(91, 362),
new Point(42, 314),
new Point(0, 219),
new Point(0, 150),
new Point(202, 0),
};
d3.Points = new PointCollection
{
new Point(248, 0),
new Point(251, 48),
new Point(253, 100),
new Point(251, 150),
new Point(247, 199),
new Point(0, 165),
new Point(65, 100),
new Point(0, 35),
};
a3.Points = new PointCollection
{
new Point(305, 150),
new Point(269, 246),
new Point(201, 364),
new Point(0, 213),
new Point(0, 144),
new Point(41, 48),
new Point(89, 0),
new Point(337, 34),
};
d4.Points = new PointCollection
{
new Point(292, 151),
new Point(260, 187),
new Point(225, 225),
new Point(188, 259),
new Point(151, 291),
new Point(0, 92),
new Point(92, 92),
new Point(92, 0),
};
a4.Points = new PointCollection
{
new Point(260, 259),
new Point(167, 301),
new Point(37, 335),
new Point(0, 83),
new Point(48, 35),
new Point(144, 0),
new Point(212, 0),
new Point(364, 200),
};
d5.Points = new PointCollection
{
new Point(199, 252),
new Point(151, 255),
new Point(99, 257),
new Point(49, 255),
new Point(0, 252),
new Point(34, 0),
new Point(99, 65),
new Point(164, 0),
};
a5.Points = new PointCollection
{
new Point(104, 259),
new Point(197, 301),
new Point(327, 335),
new Point(363, 83),
new Point(316, 35),
new Point(220, 0),
new Point(152, 0),
new Point(0, 201),
};
d6.Points = new PointCollection
{
new Point(140, 292),
new Point(104, 260),
new Point(66, 225),
new Point(32, 188),
new Point(0, 151),
new Point(199, 0),
new Point(199, 92),
new Point(291, 92),
};
a6.Points = new PointCollection
{
new Point(32, 150),
new Point(68, 246),
new Point(133, 365),
new Point(333, 214),
new Point(333, 144),
new Point(296, 48),
new Point(248, 0),
new Point(0, 35),
};
d7.Points = new PointCollection
{
new Point(5, 199),
new Point(2, 151),
new Point(0, 99),
new Point(2, 49),
new Point(6, 0),
new Point(253, 34),
new Point(188, 99),
new Point(253, 164),
};
a7.Points = new PointCollection
{
new Point(78, 101),
new Point(36, 195),
new Point(0, 327),
new Point(248, 362),
new Point(297, 314),
new Point(333, 219),
new Point(333, 151),
new Point(132, 0),
};
d8.Points = new PointCollection
{
new Point(0, 140),
new Point(32, 104),
new Point(67, 66),
new Point(104, 32),
new Point(145, 0),
new Point(298, 199),
new Point(200, 199),
new Point(200, 291),
};
a8.Points = new PointCollection
{
new Point(210, 28),
new Point(115, 65),
new Point(0, 138),
new Point(153, 338),
new Point(215, 338),
new Point(311, 297),
new Point(359, 249),
new Point(324, 0),
};
}
}
public void SetBorderMode(BorderSetting borderSetting, string borderColour)
{
if (borderSetting == BorderSetting.Rainbow)