From 6b309f11b06f7704f4be4f1cab8b4039819b4218 Mon Sep 17 00:00:00 2001 From: QI Mingxuan Date: Thu, 7 May 2026 10:01:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BB=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=8F=B3=E4=BE=A7=E7=A1=AC=E4=BB=B6=E6=A0=8F=E7=9B=AE=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6=EF=BC=8C=E8=BF=90=E5=8A=A8=E6=8E=A7=E5=88=B6=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=A2=9E=E5=8A=A0=E5=9B=BE=E6=A0=87=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XP.Common/Controls/VirtualJoystick.cs | 48 +++++- .../Resources/BackPointDisable.png | Bin 0 -> 6017 bytes .../Resources/BackPointEnable.png | Bin 0 -> 6439 bytes .../Resources/SavePoint.png | Bin 0 -> 4258 bytes .../Resources/SwingDisable.png | Bin 0 -> 8195 bytes .../Resources/SwingEnable.png | Bin 0 -> 8977 bytes .../Resources/ToggleDisable.png | Bin 0 -> 5930 bytes .../Resources/ToggleEnable.png | Bin 0 -> 6333 bytes .../ViewModels/AxisControlViewModel.cs | 26 ++++ .../Views/AxisControlView.xaml | 146 ++++++++++++------ .../XP.Hardware.MotionControl.csproj | 31 ++-- XplorePlane/App.config | 2 +- XplorePlane/Views/Main/MainWindow.xaml | 10 +- XplorePlane/XplorePlane.csproj | 1 + 14 files changed, 194 insertions(+), 70 deletions(-) create mode 100644 XP.Hardware.MotionControl/Resources/BackPointDisable.png create mode 100644 XP.Hardware.MotionControl/Resources/BackPointEnable.png create mode 100644 XP.Hardware.MotionControl/Resources/SavePoint.png create mode 100644 XP.Hardware.MotionControl/Resources/SwingDisable.png create mode 100644 XP.Hardware.MotionControl/Resources/SwingEnable.png create mode 100644 XP.Hardware.MotionControl/Resources/ToggleDisable.png create mode 100644 XP.Hardware.MotionControl/Resources/ToggleEnable.png diff --git a/XP.Common/Controls/VirtualJoystick.cs b/XP.Common/Controls/VirtualJoystick.cs index 14fc43b..3066547 100644 --- a/XP.Common/Controls/VirtualJoystick.cs +++ b/XP.Common/Controls/VirtualJoystick.cs @@ -136,6 +136,27 @@ namespace XP.Common.Controls #endregion + #region SwapMouseButtons 依赖属性 | SwapMouseButtons Dependency Property + + public static readonly DependencyProperty SwapMouseButtonsProperty = + DependencyProperty.Register(nameof(SwapMouseButtons), typeof(bool), typeof(VirtualJoystick), + new PropertyMetadata(false, OnSwapMouseButtonsChanged)); + + /// 是否交换左右键功能 | Whether to swap left and right button functions + public bool SwapMouseButtons + { + get => (bool)GetValue(SwapMouseButtonsProperty); + set => SetValue(SwapMouseButtonsProperty, value); + } + + private static void OnSwapMouseButtonsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is VirtualJoystick joystick) + joystick.UpdateIconVisibility(); + } + + #endregion + #region 四向图标依赖属性 | Directional Icon Dependency Properties // 左键图标 | Left button icons @@ -185,7 +206,9 @@ namespace XP.Common.Controls { base.OnMouseLeftButtonDown(e); if (_isDragging || !IsEnabled) return; - StartDrag(MouseButtonType.Left); + // 如果启用了左右键交换,则左键触发右键逻辑,反之亦然 + var buttonType = SwapMouseButtons ? MouseButtonType.Right : MouseButtonType.Left; + StartDrag(buttonType); e.Handled = true; } @@ -193,7 +216,9 @@ namespace XP.Common.Controls { base.OnMouseRightButtonDown(e); if (_isDragging || !IsEnabled) return; - StartDrag(MouseButtonType.Right); + // 如果启用了左右键交换,则右键触发左键逻辑,反之亦然 + var buttonType = SwapMouseButtons ? MouseButtonType.Left : MouseButtonType.Right; + StartDrag(buttonType); e.Handled = true; } @@ -233,7 +258,10 @@ namespace XP.Common.Controls protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); - if (!_isDragging || ActiveMouseButton != MouseButtonType.Left) return; + if (!_isDragging) return; + // 结束拖拽时,根据当前实际按下的按钮类型判断 + var expectedType = SwapMouseButtons ? MouseButtonType.Right : MouseButtonType.Left; + if (ActiveMouseButton != expectedType) return; EndDrag(); e.Handled = true; } @@ -241,7 +269,10 @@ namespace XP.Common.Controls protected override void OnMouseRightButtonUp(MouseButtonEventArgs e) { base.OnMouseRightButtonUp(e); - if (!_isDragging || ActiveMouseButton != MouseButtonType.Right) return; + if (!_isDragging) return; + // 结束拖拽时,根据当前实际按下的按钮类型判断 + var expectedType = SwapMouseButtons ? MouseButtonType.Left : MouseButtonType.Right; + if (ActiveMouseButton != expectedType) return; EndDrag(); e.Handled = true; } @@ -326,16 +357,21 @@ namespace XP.Common.Controls SetVisibility(Visibility.Visible, defaultTop, defaultBottom, defaultLeft, defaultRight); // 根据 ActiveMouseButton 切换 | Switch based on ActiveMouseButton + // 如果启用了左右键交换,则显示相反的图标组 switch (ActiveMouseButton) { case MouseButtonType.Left: SetVisibility(Visibility.Collapsed, defaultTop, defaultBottom, defaultLeft, defaultRight); - SetVisibility(Visibility.Visible, leftTop, leftBottom, leftLeft, leftRight); + // 如果交换了左右键,这里显示的是右键图标组 + var leftIcons = SwapMouseButtons ? new[] { rightTop, rightBottom, rightLeft, rightRight } : new[] { leftTop, leftBottom, leftLeft, leftRight }; + SetVisibility(Visibility.Visible, leftIcons); if (_thumbElement != null) _thumbElement.Fill = new SolidColorBrush(Color.FromRgb(0x3A, 0x7B, 0xC8)); break; case MouseButtonType.Right: SetVisibility(Visibility.Collapsed, defaultTop, defaultBottom, defaultLeft, defaultRight); - SetVisibility(Visibility.Visible, rightTop, rightBottom, rightLeft, rightRight); + // 如果交换了左右键,这里显示的是左键图标组 + var rightIcons = SwapMouseButtons ? new[] { leftTop, leftBottom, leftLeft, leftRight } : new[] { rightTop, rightBottom, rightLeft, rightRight }; + SetVisibility(Visibility.Visible, rightIcons); if (_thumbElement != null) _thumbElement.Fill = new SolidColorBrush(Color.FromRgb(0x5B, 0xA8, 0x5B)); break; default: diff --git a/XP.Hardware.MotionControl/Resources/BackPointDisable.png b/XP.Hardware.MotionControl/Resources/BackPointDisable.png new file mode 100644 index 0000000000000000000000000000000000000000..88b197fd7e44288e47ae534daf52d41494ebae1a GIT binary patch literal 6017 zcmV-{7k=o8P)=5KaL_s10gE6;Nu5CkQc#WV6}KCczBGY<4%B z2OE+I}2?wz^!&V79M z{C|62|NDP@{`Y%-|NnpP+)1_Q&ocr&Jw3-`>#>)5dwYkm?btP*WuSy2ML^>6sJT|I zT=|JflO{ca&BES1n(UvjybZBsSt=xqfW+lNgX5j993CFNi=>XkCIrN`6oFkf;ed9; znt;UBVDloHt4ZQctZG1D9aSUfVC)D;Tn#iS9%}}o+3YZha~;M@YP8tZTjHv-Nf~2( zmQy!j3L;RJfW%c6OZA<2tZNx#-C8}?grkEK_Gm|}2}oQnn-^hS&nX)*w_(8T35p+W z0uq;t_M zMUdz6f?|Zykhm%|79MK}-lnUG^9C5j5C&pOzpzSgjr__u}*HWIV zCZ%{qkhn_P6OXkFAuKJ~?Zu|VOjJTK;v=_u>Tt$3_0c#Ka3%(QHFlq0BaVcGn(Gk5~A6jy(L{~=SR zOxXg?=~!5TJXcs+BA{}_PFx!|Zk%%9zyTB1#{y#LC>wb$N0?$2DOTcQeD%iNyLX$g zriHDQH0BChi}+uj*obSziWNuT9kzn(PqEO2R4S!0SLj;B-vY%#Tz!3gN2b$h^H>+V z#}&*O@?61i4pT0X7uWLT%a6|I^Cql|!UVRoEb?5XMB=|4X>l>edh6uLlTBFm3yz^~ zEqSg`H;*rci>$a-ty*===osrfU&wfz=)k~$##|mV4SRBt6xW(HYmUw3ayEJK{;&fs zl#el?#8rTikfnQZH5m-Eg6}$b@Sq9ntR@%5RrY-LrVo)_5sQB0NQsLv*70}%8)Kaj zHT2nRR-P+rjn-g!BO@-R+fQPQWx_hG!8$kN^x2~W1p3+=g zb>}XxRX4imo)~&@_4f9jhQ~5tofuurEgEn6(Rd+GGt}auD`;b@t%&PAA?H}Dc=BAe z2*vPtXvMX1<;wSsb_L%V1MU)63>wjG6+$U4##rZ25u3a?mSr4*x`lCQMVEC5owyid zokurt>+taKF)r&8+UV3ro-4Gi<6pr-B`&&x_Kcv7vEJfem4i>28$~EQSMW7Yc8;MD z7atH`#6@Vcf=9)zNz8L`|5AF*uP;oRcD zI3Kg${`vxGU(33^=FQ&kVPEXLfPH6Ur(*BM-i8^6-(gu#Xyv3MF-z-AmLJ0Y0<*Ua zcfh%eiK4%z41dSIe`fjQlqpkQLv=qxXgjgZ*iyEywz2QpwQG+iooO>!NEZj-D|XydDc5v&cpM40B?7wM_I=#^@6xEwdk$FW}8_aemh2975-G(}w8?WWThCagrm zkKQ{dv_u4Zq*HDRSImP!ZWLck_hY)oxk zNt?OcMf=~5&0M{D^}FIy$x8JIR9wtHUBz9^-rZiQJlY>`0>{$+pTTY!8X9^Yk!{1X z&55hf0uvW~@T-}9x+C7#j%w$I03y4T`2BGenup>7Q-#3Y$p*dl`&boXXm`>HlnM>6 z_Bng!f0ViSE-oP1FF9_CG9;BfSOO+A?5hV39C(5r&w{S5t~Uo;0&jBjRa|&1dm79z)HzTx2 zyhp_saZ&j>+;P@7N>t~IKrsQjioeTsHJ5!)Fx=?HDm>&(j1UCR#YKg0pkDo$f(ZCV z0HH0&=kq(ck=p~wzU9+M!k&tYuHbwsy{3@@>0A+TN&qirA4J<%c($!rvEo9f=LHqd zGjVYTv9B}q1yyk6BLW2i+|Vygr_~#qz6+Ffo2kz!=%S| z=|S1|<(gTJk-Qrg7h|j&NohHz5LE&(DmPulW3kN$?3U%rmpAow5eo;>-X?(S}TP`oL%s#{!i1(#8QrA;ZdG8F-51Wrh$Qg`75)-mC6gtJq; zi&dAn=n8gGge91Q2!x&hPGB|@9uINd2Ksw$uEoV&pqH+oy=*1)P*p$?C?aqg*X_OZ zxa`G1MZ5i5btNu@wTipI0{@B=jg(c&$P%!(YS}C8W&}|K$KpcqYY|pk5QS16BH%ND zOuR1#xI8_M|C?ddh-G#t> z>y1?v7h|kjD9iPjf(XQt00LWu1No#Mm8&Q&GQ5p3)=UpFRT3f)b^_nvdbd}8ds@!2 z;=)zlPA=DA3L=mc0`_ASo(gP&xKQxdah0D*3Q^Tl1d0fFDzI_lVvJ?KeDUd`%(N;3 zNh4s>^yhj}=`nHPvF>J!b%hs+Dh&|`DFG+NI*drGy1TpI#Im6da85i9nJFOlM}@ z)t4;Ib3L3SLaM6>G(ccsS67#Po7qtksg8~g`%${DI*P4G)d}cm+zFhJPNyAzY1lkh z%h1r!61s;^#+{7nCjyNUU~=PnKKpuylXOPJwP?|zUl9391okvb1rZQ|$^>k7-O(3_ zN5p06EL^zoSyVY4d&0J5A|L|g3E+fgF*RTF^WiaZSu%{jo^Ne!y`1&OF$ED2f${_n zLtr(%*En%mI`ihu`%x;DGJ$>Hw*54vEdo&`fVgI@Sh3=aYUQ6GE{ojW-u?n7UrrbC zQQMY@fCx+=fDcMtHDPbjjfbBbJ+@g< zToz;T;>9nLfC+57ZOcSJ1jZ3~>%oHuD}H;ws<l2hc(4znPxJX-OM6hh8Mfvwq+t90>2@^+{F34y}cLzW^4R^N8++m+S=OoKla#T zA7OnPrXT_$FiHTYQ?_g9SX`FQmMvRyd=_Q`yVtg5A|L`SEqJeK<=z(MN?Zky2<$Qv z{AOWWOA$yo0ed9s!=()B5|<^yRQ<N;la3h}7#Qch8WxwqL|~u7Eq>kB zWg?JZ0^WX+woxeJ^c=S;^wPdfJcb8F}OShuey{Xfebmh^CPPfySB1qhys%MwLk zGg)rL6oMu2Di{7EWNGh1nQej@8X7ttF&$2uOvO&ZK4?7*W_mMNKihxb+1a_nsd3Id z*aptK5u1rk!_LIshP9I4QRMf>lwlfnBkT9D+=V43Q0K9qAM#vWMiJ20k;w*Imw8VB zwohQ25L0_TpTDHFwbd@}Be?L-gZ=f`dK1i|MT?$8OnbdALHQKP?`86Piu~`xzRdb` zmd8=XsU~*L>cY&^v504&P0lIQ%olN4;()d8!#Z1+HAG;Lvmc_-ma+UWqBO%XBR5to470kK+ff& zSZnJt#{~Ak>|4Zc7f_F_%SH(Nl>avV_y`U0cJAbt zaDip5>%{)V2CkExSUcCs=~#vv&T|okF*0Kqh`0<87f^MmnXGQdE?6Whcr!^k0 zjua?kbHrt3;W3E6W7We{k(gC)v+oFJPezc-XhtmnQ=obCpuy zPGpbJbe8Uq^EP9M;W*bXsJe0O+``Q2g?Na&gUZuwK9ueFrisf63#4vT-eK!95pY9* znbjZR#Xf1*4;OOio@=CB$2L`529q(^O5n`5b(sjbC1BSN-R%!?UZ`Hb&NY2Z)5Qgp z7Vbc+S>AvtM4Uh~ijTmy<0(vF|Im#5E9Ck1P>9P4M;GyC0L`)WxEgm@O=$SkxCrbu zuAx6C`3JD3htPPg0to^*VldJXfJ+nM}sM3ua%s zEbNNSQnQ7@G$q4~^T?^$&t-;V%ms*XfxFM`xYbXM+o=r^b+XMK000LnNklGci(2C1S%@}Mea4xg; zI2hweO=tw%kX%3S4>-%Q>_ROrD_J90j4FB$vny=hxMTcY+EJ*ZV2GLRuKPHERYZ>aTyUj*yBJt3z0?Ti*r`&5o7GA z35^jF&H0D-`Y&=efwAyEL{40W1V~S@wD&CRVHugA3617A72~g7O7X9l?;(=nGAekm z|6zF=_A5+51l$nlb`!bYxRDi?RTvMpYjAMz6xLtC6hy!g0le3@8CHDFQRIq|Y9ENS zxU72i!WX(*Cj#r|wk;C@hXnq{VZ6GdMP6K1b3Q11W&i&D?_u5E2gpJ}1gaBYSn)k3 z#(e!vxmbwHFlMvaJ^S|UdnfBZ#zGl1TNtip85$b$)qBN8T-Iy|>;U7iKV&_WKU+ih zRZp1EIAIB$ot--vPHgq7Jh2j&LBiD!GhjWA&EC2!wAzmUI6BrB6Li{~f z0Tlr4mog&rd%T5mYZ(jydN*Eo4U^%y3e7_o@l4i3^=4MeqYwfD^ltu%Vt6?|PmbpT z+(r#i-tpNJXc*L5ZHyBXdfc7P!NF;0-g*Rm>@~ExC|u%yOgC3 zW?3kRK+8@q7^G6EpC{sTu3E4V*hjh3`1Sy2t^9R7R0KTvm6U@A5B^Z%8f{mmV(r!0 zcZ_aokx&BMXrJds`&@(7|J9;Ji;_E`Q4StpKMmMT<&J4zatQEIO(PRs2I_z9pFEdQ zC^9_QHEi0?7_m@DA_2s8eJMLgJb0PZhyNV^h1fXRr49+TtRk+`Z| zCw$QS1&;S&3JD{?=Uw)yh(=!7r*2`bYX%RtfH+;4Lh=YaS#Oo|`Mf-r6L<)0G4YmS z3ce5sXQGUo?5)mq6^?GD#O0J60{aqiJ28di5U5vNd%0eIW|%agVH6w~z`Akw^BqK0 zlz0%Rt6PZ28}V9(K;kkA4lR?(tS0JgOd;k3_V3?cm**eXq;-irz#5wC~GqvrnhfV=qFIxZKh!ijN2T1|DpB(XOhiG}eDtji7^} zB0$@^{b{O!_V)I%_i#vD4K^np>>iSshSdstTU%QjeIT?}9y;zJ0mS9jbB%c|D~7~n z6dE)pIqst&F0Pgg$NSpa+V)qAqhsMBKu^P!xM<@a6xSg3;wrAJpX+$Aebcy`=QZG@fx?dGamh#2L${AyJ^*bh>v)VVau=dqhc?V}QwU&Q@Qm$r1}xri@u z`Pn2kphZj@uUOfGz$`Cz%iN?hfrXrBnUARuwM zfTgG+;DW%eOeRzIl>qWwE+{Ih2$T|-G-=XzOZOGFC9VPqEk&RX0(1!_t~$6y>=YHZ z83gkAeA&qiD~mjrQILs183NgC_V6;hi+Am0y!C&@JBrsOu3{Qm7l9%IQ>RWntY~w> zYPIo}MV7dXf=mR;5EvXBtm?U{jkhd0iOVR+M4$`-JX1x_#jzI;J@nABPi7R7O0KvH z1hf=^3IuYwTt&}?*V-|6?%aV2r;hBFxJEGOp9oAOkV>U0iVM$G)oWR55|>esi9i_w z2&iJW&^%X}Q^xI*xW?hoh6wzY0H0x%^;`(+k&cdz=YJcs{F=m7o{RR1fDtI`x#%v| z>=N3^j>Tn>Wg?Iy0(1+@dM+63z-k7Gt0p2vNGbukf91sWLVJ6=JXcaL3f0>`0tjvg z9&Ol34)R=1C@D@N38d5MyGtw1zTVP(m9{0WN@TP@v;=}G7~Q{T_#pWmYWzZ}jqqtF! zhbDA&24TbECkkX;cTrYY1y&xbF1rXUk92hsS&>(!s{>gcNv7*~?j$qJqkFolySlm_ zr@woqZdKjq@AiN0tGikQd3i>l$JjVOnK$!nFX@I!NyEHXFPLX~mVqP`Dgq)dkD7}` zbg~WA2M{64wwFp40X_r-H|qKI10b*15fE{C(B#QA8%|{r-O5SzuuXNSUDjimpO|_> zu0)xDh^xic?Jk(7qix^PC>a~zqDEolezXXPxLRn>?tJkKBDmRM5=S}=7uR5stG9@& z$tKnF=2?Wew#n!cEd~TcTun4`(kLwkgd1E%McD2tyaWzC0TGwWCQKI03<3?hj0U{m zvCVZHi4bZ6A}$xr*Ig(rK?1`?l(C?^EdR#XiFjf`K*Z&+nRUZFkBC+~3_c|oFMN31 zb4|%YE(DB#h|58P=!MdS9PC=QrX3+j&($=&a7GkyHE6eFzIYK3UDY61!`nQZl%A_0 zrDz2ZaZS^n-G;dW5wDmgh~rz*b2&y8nSdg$I!)PalrABFm33~rzRU|6(sQ|{7VZe~ z5toa0((~&F2byKK_s)=v>dT&+_KRSF`mam|%9 zOdbZ}CF3r6=e2Da7J5fB6e)?gb~O`k5MRObq7}PNy+3H0^jzLk4RnekE^Zz@Z(c=2 z?fpuK^ju6jUaqdV;(|dp%xeKbZ4$S&%81f)wH0sx6OXmHl6g~ooasD2+J#W&Tz+s4 zQXa7t7jF<7h_J-3#z2zQLcdrCC7)P|OE-#xyg{7tvk?fS=kk+x5b}zhxOBt30RR_+ z&o2a-b3v1@uttlOxb#9veJ%g2PBa$xl(Ns&3Gf}vGdAMl4dR=D=!{OWCX%n5bc%ha z@{NVK^nCFa-XK1`Q;=1@D4WO%L#!;~;v&@Z=B$Cb2|fF#1;rgP?ZIZK(vH^g@~NE-Z}W( z+bUgfJI}E`!Vd?AYK?*<>>1K?)!-84OQ9B5&+4b&IlRMGix(dXdLs?P zHtD&7-bfyoFSO#)^QC=lEwK)Oj`EmETaueO>n+lAwS{bO6Ah)f_AG3g3uv$74dM?3 z7wyE7?XXG2H4#bV&)kcv!$|hZmr_W>>j3a@2+?cyOihM`A!;u#iW(|$^%zgjuOg{A z)}dZh-p@4t@TL8v=kgPH0P+frxb!vV0XBB2<@SREz|CzDcwgIX6bT=80-+FBa&W`D z!6vmq{O*tfmtHHR4cAJs123*U^TmU)%8M6(`?pfjj>aXB`Bpm`AmC{RT3kIw>Cgls zFJ3@jz&TD|Jo(|f>G?$TZeYdLeO>W=Ho!Wbtn`MTy*ySe{B7vI27we8ZxA0r8uH== z&2?X;AjXi#ss*uC+Fho=i7RQWKWb!y7+~LaSKhbu<>!NZLmi}y0wu1Vg83l?jptbS z4v5l=C=d%8Q9>Gqx&%gC-D@^{*d}0M!JIIFb5%y}xsrytQZE$0s~g2Z_TS9Mb$Y(| zbN1h(8|HuNM)6VIFpGM@{39QS*j{5J_g37&aW?BlsmS&_J#XI4=eMzcQ2k6&w_&bG z8XNkPh0-ZJ{5~#eY&>YM{1dyos*ePAL?962((@aSC0i}GL${++hb<7n(Fm{t2+sw; z#q2+wkBb2D1okfkfcFF7K>&~jf_?a?IJ}jQO*ri0NId|QW;+ZJKFa5xVgF+FGf4!n z62UGY(T@P>-w>*gR&nN5J#W6C8|H&a!@OB9n3r`I%+pzXN2ss#aC~u15a_tLlGm+2 z0ko>>vG#1D{1U}00tkC^Qb(}ZPiKJ-5W&qXz6XbQRF&wq>fEz-8|DvLgy-|7{s-r- z-Sid?FK!wF9TitHZ=Q(Ab1Z^ArYWP`>O27+HsV3t>zxJ&*YKwP{ja<}{JL(KkL&s3 zT5iW|cVYeEFfh>3_fzLFO)NpjV00U$Pa(oOZmcGUKNBm`hBHaBF@e7Z#51@Z^F-Qj z^*Nub^04w@-6&nD=Fl+k#LUJ?L^ni7#HAOCiwI~PV~sU@u7Bhl0vrlJ%Xtp{OMTAF zSGi~Vxt=%A@6K;HEOM1?P$A#Nr5DVTfkr;klxR>kxgCB2UEH&s06df=w13Av+9tM} z^nB@T^}W3CS8w_n_$scXQ9KO@Zk@hJayPmJXfF3^U*v_7>#Im6&)M$e>A}*d3e7ih zsij>6{9$z8I8w7F2prGTgH=%#nup@5kG4BsJY!^Ow|)@0BLpT0EmGTROC`lSZpjiS4xD?R- zwfew9vuSu4uVr!Z>dmDD+TVLwC`rp_0+GrN=c*4Z=mqoop1~*I(aEZ{BrZK~4)E&D zH#%7X$y*52BtUSsJv`$c{W|mHn)iLU*tEEGqjWhST;@X=B?}?Y907y{puw%lyt#U| z@l3M0M4FG)l(>?Hxe|abX+B$tDFpl@z5WQPx3w=Kc-S+AuvW@ZL&~0a_p=H&zQJ$!@LauPXT!ef#?!&QnTHV z=<4L)hS^R6PZwrHT*-X#A`ax~c$3o;Cj`Pu;C)!NuWq&QTGH5f6e51J)r2Iz5QrFo zvv@RjUMqFd5N-8A#u=?7B5{R4Lm`P~6?!A<_o@_2Zi6sPLMPQNoDJ(ZN)=eX3J+6DI+iCr^ za)0V(1YF}Zf`prffZU2U0mKC}FyZ)1!)jOv+wC2f@WRHU(Iz9c69OI(K+Mcu{q%lL zQW_E0)+PIwk>FGyc-%=O2_pnzOrR%`=yLQ0;t_EvP~}|TQ;CGO2mu~Z=VC%Y2-G7$ zS$&P!aDRAATq>E({k`Te&`E&!usRnL0z#lBf!&-u{$hf-R5CAT`!?ED?Iia9maVN$ z5*GqtCBW0DY>)BOq0^OrinvtZElcJ-1H+&M_K-Rk69PhD3IWZAuG6Mm9e1IoxYT`X zS^8Nmv4aIhvJa+!hzWto1c**~`!!GKlP`~+*A06ztJ2>~IX2=w3%`(w&8 z-kK7ZN}!TWe;N?hDZg0k2uOt|6VPDFysK$(skE(3T0QIVR^=BH0x>6WEUYqTjc3r3 zxKu(`Hhl`u!ERB0F(D9R0{bQt6ML_g#id~K9PD#E2m68YiwS|)5|}hJ^h8_=CeOjX zz{~VEDZiKyh$8_cSUA4ko{38(%FFa$;^Pf$;wBL2_{qy$f~NrKS89a8!}u%ErgH(c zlk6%ibZSVnhzN23q#l2M1E=#d*!lIOKXLk1wz#_kdyI|qMncjcevNV04 zQ!D5Cep1P$4J+GsDW`Wfr*oo}Ngc-ieb~CT55pXS>U#+3L|+WT0!bdulnN0qawOgWp*E5Qsc*}wSW z7yjZ^?@LfS#s6QH-dxEpc&w7?`&l`g`lgjlEwXZb^C+S1sl?8`=1L%l_7`ypju@rW z7ICS>%b9eJfL1HNSW5)9bL@M#2e_Qym>-+*>TA1~v*|;uZ2C+qm%7@@r0*(c=Br^D z2MeaFoYVWV5_=_^zSzp853A0YF^@~CMmRs><5spPx%ZD&rfuR<8C0@;%lPQ!AeeO~TZ0G~`7+gQ{i1@aOOI4pCo)3Umfty#n!m^m)E+G5sYUsqgW?R|5zhNO= zTh8_VSJY9cFXgKFUnQGfNY&~Gfk6G}T%dd6Ms3oy0}fYV+Ac1YiIq()=Xt^v$}cuT z;5hDS8#2&;sG*${$w?`r<>7+C|MT%h|rw{EwMM1{ZVLUSkWqBP9RDrKniB z)YpLjgDbz75O7L>1-4QHJQ~#A8Tj~WA}hoW^jxFmv@+?h7m4pa000QkNkluW3{U{**b0_kznWt^PD-hyRg|l*f-$SyODt}~67Bt${v_oet*lJ}`f6E!% z%@zQs1*7L0B~i}JzmACdN6+Ob1l$tfQP9T#@B!%Xi}$*M({qiosO0(v5m9~Va`aMk zj%~@D2-XPGII-li^je zeYfyFhI(|{&tPmtIE%>IWdyY4}YRG<_-?w=}Aua`SD7WBVuUxbU9btU`fm0Qv56A`jtE$})Gv7D`TLFn*A3M8 zMySQ5s;3_KvLj*d&lA-b)w!4ua72LM9~^~iAyDYWrRu)*ocTjgg+2g!PMwPhfkp(Z zZ2C8Z_=85_TDczyaVY@Svh*u&f9X%X?EfQMFrBOx2C7|XnA+NVMMhkz)&4NB@C_@I z`YZMa^Ji;hwUC=8IBw(##{}!zRia3VYXlM^ahE@jH=0W$=Rx`t=bkG_?J%J%c;kdq z4^N^eu3c~{*>sxcVC#3C%0UR!B(QVk5bvycv&D;%6_?^-W&0NJ@kusuLZB`IqUyiY zz1jSYp-78Map582fxJxrxblk$fm#G+V&bQK-D305Q91JBQnajG`XB@d*)L_Nl8gC4 zK>ex;Zz?N+d6*qWzvmjIRnDdlft|lRKYA(9M=6}Y1Z)CNhlaeM7LT55w3&FB{xJ3j z>&dKKAaR{1uqB)RS1yHT^K&GKPtV2RMjX$<-p`(g*u)8e2?Pkyv!NksF&Y+*r^o_3 zl9%c4AAe2!LI8>G@QQ+M+wmF}jt9rf^hfi!_}=l?#2;@0{7?5cOu&=h{fbi0#Z270 zN;Z8A$NB}EI3ci;0FftC1}%aGKiqXHhnN!B+}~?*)r)K` zIIL`4vVVLRG-{D6XVRbN>ucG>#hCz6D+^t`5KS8tKIyp>g>lAnurq;ZaNH&F#*6@J z+FdPG8ENF}P9m-v6s=reKM<~}aZ4`6fB@O>aBJ1nL|oGWv~sC)xqrWEx-fDtngqD* z)uSSseqlFQ+T|{@eM*);WWI2ivj^`PFzH~cE5-%hK1`gcLC4Gv`mE(WDA}&|NCI#lD+V3OSXH2^6&#C0%9|0oQ50|wG#vX9_jl{ku){Ue03++eAn9*R9vV8UOeCqzJ2B#M_&$W`nC?p+;{mW~h>J+pB|^R|M3AwvtO57WY)jhIT$|(yQbp z9UloK5M7C@y!kolxqNIN$tuJIc5L73d{~J1I1DTt9$#JQxyI8FzYrKlV9WXMojQLW zcYnN>rvejtEp>0QxYRWfh#&$nuR@EDvR`7ih`IBs6k+_{1dy^xcufN#0M+q_5RACQEy_%@` z$&AsY;w!FE0&)}rbqFBY^?NR|?<*}!Z>tk^0o1VWurQI>KIK#Jlaml}O(r7eLST$Qy`GC6*xY}BIToyrN5oYJj9eB1Hfgnc zE^Is`RP-E+O9d7a0&yaMRJ-RwfQCat;FpMtA&3(KwF%VP=fY>o{k;trGgNvaE=561 z2skES-v@}~B)Evn2_*>=PXY<;wkZ|Y@X9II>Rb?U)d3@ygG<1#l3D%fCv63002ovPDHLkV1m33 BDF^@n literal 0 HcmV?d00001 diff --git a/XP.Hardware.MotionControl/Resources/SavePoint.png b/XP.Hardware.MotionControl/Resources/SavePoint.png new file mode 100644 index 0000000000000000000000000000000000000000..a8a97986b7966d32bacf76eb8eac899bdb15feb4 GIT binary patch literal 4258 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 Hyfx~7V+{$% literal 0 HcmV?d00001 diff --git a/XP.Hardware.MotionControl/Resources/ToggleEnable.png b/XP.Hardware.MotionControl/Resources/ToggleEnable.png new file mode 100644 index 0000000000000000000000000000000000000000..bd97663584f219684a96af9846cc469de92dea46 GIT binary patch literal 6333 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 literal 0 HcmV?d00001 diff --git a/XP.Hardware.MotionControl/ViewModels/AxisControlViewModel.cs b/XP.Hardware.MotionControl/ViewModels/AxisControlViewModel.cs index 94ebafd..4c7ce5e 100644 --- a/XP.Hardware.MotionControl/ViewModels/AxisControlViewModel.cs +++ b/XP.Hardware.MotionControl/ViewModels/AxisControlViewModel.cs @@ -82,6 +82,7 @@ namespace XP.Hardware.MotionControl.ViewModels // 初始化命令 | Initialize commands ToggleEnableCommand = new DelegateCommand(ExecuteToggleEnable, () => IsPlcConnected); + ToggleSwapMouseButtonsCommand = new DelegateCommand(ExecuteToggleSwapMouseButtons); SavePositionsCommand = new DelegateCommand(ExecuteSavePositions); RestorePositionsCommand = new DelegateCommand(ExecuteRestorePositions, () => _savedPositions != null && IsPlcConnected); @@ -254,6 +255,10 @@ namespace XP.Hardware.MotionControl.ViewModels /// 摇杆使能状态 | Joystick enable state public bool IsJoystickEnabled { get => _isJoystickEnabled; set => SetProperty(ref _isJoystickEnabled, value); } + private bool _swapMouseButtons; + /// 是否交换摇杆左右键功能 | Whether to swap left and right joystick button functions + public bool SwapMouseButtons { get => _swapMouseButtons; set => SetProperty(ref _swapMouseButtons, value); } + private bool _isPlcConnected; /// PLC 连接状态 | PLC connection status public bool IsPlcConnected { get => _isPlcConnected; set => SetProperty(ref _isPlcConnected, value); } @@ -264,11 +269,21 @@ namespace XP.Hardware.MotionControl.ViewModels #endregion + #region 保存位置状态 | Saved Positions State + + /// 是否有保存的位置数据 | Whether saved position data exists + public bool HasSavedPositions => _savedPositions != null; + + #endregion + #region 命令 | Commands /// 切换使能开关命令 | Toggle enable switch command public DelegateCommand ToggleEnableCommand { get; } + /// 切换摇杆左右键功能命令 | Toggle joystick button swap command + public DelegateCommand ToggleSwapMouseButtonsCommand { get; } + /// 保存当前轴位置命令 | Save current axis positions command public DelegateCommand SavePositionsCommand { get; } @@ -375,6 +390,7 @@ namespace XP.Hardware.MotionControl.ViewModels private void RaiseCommandCanExecuteChanged() { ToggleEnableCommand.RaiseCanExecuteChanged(); + ToggleSwapMouseButtonsCommand.RaiseCanExecuteChanged(); SavePositionsCommand.RaiseCanExecuteChanged(); RestorePositionsCommand.RaiseCanExecuteChanged(); } @@ -440,6 +456,15 @@ namespace XP.Hardware.MotionControl.ViewModels // TODO: 发送使能状态到 PLC(根据实际 PLC 信号定义)| Send enable state to PLC (based on actual PLC signal definition) } + /// + /// 切换左右键交换状态 | Toggle swap mouse buttons state + /// + private void ExecuteToggleSwapMouseButtons() + { + SwapMouseButtons = !SwapMouseButtons; + _logger.Info("摇杆左右键功能交换:{Enabled} | Joystick button swap toggled: {Enabled}", SwapMouseButtons); + } + /// /// 保存当前 6 个轴位置到内部变量 | Save current 6 axis positions to internal variable /// @@ -456,6 +481,7 @@ namespace XP.Hardware.MotionControl.ViewModels FixtureRotation = FixtureRotationAngle }; RestorePositionsCommand.RaiseCanExecuteChanged(); + RaisePropertyChanged(nameof(HasSavedPositions)); _logger.Info("轴位置已保存 | Axis positions saved"); } diff --git a/XP.Hardware.MotionControl/Views/AxisControlView.xaml b/XP.Hardware.MotionControl/Views/AxisControlView.xaml index 4b9acd2..325e094 100644 --- a/XP.Hardware.MotionControl/Views/AxisControlView.xaml +++ b/XP.Hardware.MotionControl/Views/AxisControlView.xaml @@ -61,25 +61,25 @@ - + - + - + - + - + - + - + @@ -90,6 +90,7 @@ JoystickMode="SingleAxisY" Width="41" Height="150" IsEnabled="{Binding IsJoystickEnabled}" + SwapMouseButtons="{Binding SwapMouseButtons}" DefaultTopIcon="↑" DefaultBottomIcon="↓" LeftButtonTopIcon="SZ↑" LeftButtonBottomIcon="SZ↓" RightButtonTopIcon="DZ↑" RightButtonBottomIcon="DZ↓" @@ -100,6 +101,7 @@ JoystickMode="DualAxis" Width="150" Height="150" IsEnabled="{Binding IsJoystickEnabled}" + SwapMouseButtons="{Binding SwapMouseButtons}" DefaultTopIcon="↑" DefaultBottomIcon="↓" DefaultLeftIcon="←" DefaultRightIcon="→" LeftButtonTopIcon="Y+" LeftButtonBottomIcon="Y-" LeftButtonLeftIcon="X-" LeftButtonRightIcon="X+" RightButtonTopIcon="R+" RightButtonBottomIcon="R-" RightButtonLeftIcon="DT-" RightButtonRightIcon="DT+" @@ -107,64 +109,110 @@ - - - - - - - - - - - - - - - - - - - + + - - - + + - - - + + ToolTip="{loc:Localization AC_Enable}" + telerik:StyleManager.Theme="Crystal"> + + + + + + + + + + + - + ToolTip="{loc:Localization AC_Save}" + telerik:StyleManager.Theme="Crystal"> + + + + - + ToolTip="{loc:Localization AC_Restore}" + IsEnabled="{Binding HasSavedPositions}" + telerik:StyleManager.Theme="Crystal"> + + + + diff --git a/XP.Hardware.MotionControl/XP.Hardware.MotionControl.csproj b/XP.Hardware.MotionControl/XP.Hardware.MotionControl.csproj index 1519476..740fc18 100644 --- a/XP.Hardware.MotionControl/XP.Hardware.MotionControl.csproj +++ b/XP.Hardware.MotionControl/XP.Hardware.MotionControl.csproj @@ -13,16 +13,29 @@ - - ResXFileCodeGenerator - Resources.Designer.cs - + - - True - True - Resources.resx - + + Never + + + Never + + + Never + + + Never + + + Never + + + Never + + + Never + diff --git a/XplorePlane/App.config b/XplorePlane/App.config index 7465d52..fcf4686 100644 --- a/XplorePlane/App.config +++ b/XplorePlane/App.config @@ -148,7 +148,7 @@ - + diff --git a/XplorePlane/Views/Main/MainWindow.xaml b/XplorePlane/Views/Main/MainWindow.xaml index a1995f5..3bec450 100644 --- a/XplorePlane/Views/Main/MainWindow.xaml +++ b/XplorePlane/Views/Main/MainWindow.xaml @@ -514,7 +514,7 @@ - + - + - - - + + + diff --git a/XplorePlane/XplorePlane.csproj b/XplorePlane/XplorePlane.csproj index df3b7ca..77b0a66 100644 --- a/XplorePlane/XplorePlane.csproj +++ b/XplorePlane/XplorePlane.csproj @@ -52,6 +52,7 @@ ..\ExternalLibraries\Telerik ..\bin\ + x64