From b7068808f648e3a6306eb8bd1026062dedf05f34 Mon Sep 17 00:00:00 2001 From: David Gilbert <gilbert@vr.rwth-aachen.de> Date: Fri, 10 Nov 2023 12:29:27 +0100 Subject: [PATCH] refactor(interaction): Restructures the widget interaction to work with the current system --- Content/BP_VirtualRealityPawn.uasset | Bin 48636 -> 46093 bytes .../BP_VRWidgetInteractionComponent.uasset | Bin 0 -> 15903 bytes .../WidgetInteraction/IA_WidgetClick.uasset | Bin 0 -> 1377 bytes .../IMCWidgetInteraction.uasset | Bin 0 -> 2811 bytes .../VRWidgetInteractionComponent.cpp | 154 +++++++++++++++ .../Pawn/BasicVRInteractionComponent.cpp | 175 ------------------ .../Private/Pawn/VirtualRealityPawn.cpp | 5 +- .../VRWidgetInteractionComponent.h | 65 +++++++ .../Public/Pawn/BasicVRInteractionComponent.h | 90 --------- .../Public/Pawn/VirtualRealityPawn.h | 5 - 10 files changed, 220 insertions(+), 274 deletions(-) create mode 100644 Content/Components/WidgetInteraction/BP_VRWidgetInteractionComponent.uasset create mode 100644 Content/Components/WidgetInteraction/IA_WidgetClick.uasset create mode 100644 Content/Components/WidgetInteraction/IMCWidgetInteraction.uasset create mode 100644 Source/RWTHVRToolkit/Private/Interaction/Interactors/VRWidgetInteractionComponent.cpp delete mode 100644 Source/RWTHVRToolkit/Private/Pawn/BasicVRInteractionComponent.cpp create mode 100644 Source/RWTHVRToolkit/Public/Interaction/Interactors/VRWidgetInteractionComponent.h delete mode 100644 Source/RWTHVRToolkit/Public/Pawn/BasicVRInteractionComponent.h diff --git a/Content/BP_VirtualRealityPawn.uasset b/Content/BP_VirtualRealityPawn.uasset index 4c150048c03e3d2bd214195ab0b680a67ecba972..47c76b941807f2128d88b3f0fa1d5c399257aaea 100644 GIT binary patch delta 13300 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 delta 15813 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 F003l~Z5;pr diff --git a/Content/Components/WidgetInteraction/BP_VRWidgetInteractionComponent.uasset b/Content/Components/WidgetInteraction/BP_VRWidgetInteractionComponent.uasset new file mode 100644 index 0000000000000000000000000000000000000000..5ce64da195cb87fc1e8952fc0c106da63a2e1432 GIT binary patch literal 15903 zcmX@utTpe)|Ns9Jm>C$jm>3v7GBbbyHv<F1{O%t@f4oXNcy87#)7)!iq0hj;U~@3e z{I|ywwht`~Tk8t7)L0l87=mJNMS6G|2~|W^?C5^Eqkw~ffuT)8Hlf8oWzD_IVymtl zf5n^6z`)RWwKj9LqyMuvfnKXLwr$^6#=yX!bTwqoK7X|pZtRLvE;MaP)L~#?cw%&8 z1FwIl{Pw!@YZiI^HREDnV6ZRwbH2f4gY$iniIa;JWW`k(7#N)5X5Vo0-K(-<jZjOa zc*=c{``%`3c=FO|$`|fihKn3`yXk2#Ffe2!b3BjmQO+)qwrrUgrzQsS+jKn!1|J3n z2K}J$5Rb5+ko^3d?938<=ltA){Jhk>l4AYv%#`%h63@Jn)S|@XlFa-(eW!r<upkU! zxE64@WiT)>m@+XiFoOKc!@!`(z`)?*YGml_<Yek(Zf@dgXl!m`Zf<Pm=3-{#>}urb zY+?r1xPXU&0Tgfo0t^gd3=9k)zJM^qAP->%h5%s(h8$rAhCiZy@}bW<96Jk2LNjK2 zSWo2q8L)i)X1^&{mwAV$GwuRe3^E7g5U{}nh}r#1IzdX_2s1Fewgs^e`2YX^|3Lxe z#lXPu9!ZYc0e4>G+crK11_sBXqQuI8qWpr?qLNAm&kc_=`5~hD<%m!Y4N0>D2`4$` z<m8vTq~@f8B8TDsN50pfa7%Jd%nM4aEGbG%PIWCyEvgL3OwMLl`~7K&C<6mSl5>7; zZfahMQ)yCCPHI4AUS4VnL!q9k4@4`nWLRc#W>QWnL!gR{jWkHBPilH%a;0BtYD!3c zKxt8WYH)UHPEcxEF+=~_7;BLGopMT33yL!HO595`Qy9*(ONGjSk||6yxFE4SFEJ@6 z72%ohE8eaXM^RH*T#}j_mReMtnV-kdSi-4|VsJ=hK`H}};H3M!AWixCIq=XDVA;?m z1ahW-S!z*HW=g7CX&yM)G6;N|5Ul`GP9XV8ai2&48(UeD3ODwdpY8zx1_lP_#FEtX z{G!U>{GyV~ymST;LAi5a@tnlsV)vr_(gMH4+|*)*xqZxkLCFsq&J3p{_skar<$=_+ z#L}D+_oBpt48Q!8RE8~&o|SPjFfgQ~=A@=4mZUO#|2?Z8WW7sjPDx^LYI1&FN-@Ks zkZNWgkoL^tf}F%kkR1$FQ=d5rGcYi?rev0+rnuxMmx5x{GcPTlVRyX1Z;)*eDgUIb z)Z~(Y#F7k#bB^;Hq(FL*@^esPB{+^Vb234x&8lz%$a+_B45b8@fZTLY)$cAlNLyZd zW?m}8c1D+HpfGj?`2a;>o5StTpt#16v9fZ>EC$7S3d6?L|E@r6D9we3Z{YR04j>P@ zmZj#ED1d{9;n`35^`I0E77I#EOD#&xOHO52zUbj<Rt5%!)QZ$(hMHG@q}Ui37}9d` z6H6FGD(9X7r4u(04{rAF<@f%A%yCc6OD#$)NlkGEMHWLFM??syNCjI4PN|EUPM3j9 z26LPPer14kd1R)fLSsEMwU|N7`^5oJ4)XMM#wY?AW}Kd{42lxe(Dh9%&R~#a`&c5$ zz`%eig%t38zu$6!LclYx1n%;sm(9FH7#J9Q5{pY9aS4m&Vg?>LrVF4F+&48hDYXck zB6{REZv%xaL?|G!C^fHyq3&g^4Jd^|1QEelw{53A$gRHlDWy57L8&>3C7ETZ;8aqe z)SU=22V^MRElr;|yg=>)#W^fhC#b}K1|?pQ7&y=_u3=dX69~vJj$|ludz%W1ACQV- zhMoUr=YRs(FF!Ap;S2LoUQhr-lP9dWbG*Iz6<D~mq@c6}RIY)u1yAlIUs(nQhJeK6 z?8Nj`pZw&+oXo03P?-mEW^qAcaw>yRNo5DfjS#OxqFLhZ(rA#KMX8B73}Gi%>VYyw zP-=2&W?8CJYI<f~Ku%&MLt|~yDUeR61h}yD4*Ubo+rf!tsVQNZspbA@X~n4}3^ga- zxPU?wEFP7gpX->LUz%6K5HHqy5|m4VlQU9t6B+*R?k)#;Bsf2<1nNgn7OY=*dm+fC z;F2PE*jgVfQUNP1DJo4yM85&UoIfC^mt>^oF*I(x)Bq|`Kvi@|W&y+2SM2*hdP0*@ zi_$^GNkC$HYB7V9@*-nU41}d7m*f{2xiEwp<Zy!G8JyH|QvLHh^2<_-{PS`u8D?)` zEdrIgkc8}<lbM|DnO9I+;s_})zxV%pYE5F>z|%1v$ux#j9VwNLq#A)OXL)jl@u^@M z6p){p2P%hy5-atC5-a1uSuOQ_CJ)G4`oYOXnFS^Ki0TLwObjn?*SLT(6-?SWzbG{n z5<v_<Jaxg9DooB5QsA{Yw0eSSMuc!iVqS7;3OKYFuC6=%23Z!RDaF8j_UmL&JUN2m z15x8`6kfLsl!zRQijZn`1BMkG&FP?03GQeH5ldrU2~fQSt3T1oG0oWpx=J8<{PkMA zGsBKay0<`?5t1=V$}1*ngX$DWl@uROpj{X5%;0FR`brI13*L5M&IUy_P>OX;0T;0h zEcshvL75NAhh&p@ZzF~s2WRktiZXCP4^bPtlra_*YG~;xt80@5DD!{=9-2&rBocT) z@d+05O)MzL%u9F9&nro-C}H?!VgDFZl6f0}3ZQtf1q{WlQPQ9+;+tBM=#p5H$nd0L z%Vbc-g(iYj@3)K~cSDOBhGO>)QBYJt`EYG>b(W-p%z-Dow>F{LAb)@=&CFzQS`><O z2muvacmt}&=F3-DYZFv`f!H8(z|Mt)hd)S+fq{VuO27L5|9>!)4QV(-IDQa{AskA- z|NsAgG?Yz9T>=s6-u?goKaogvNkpi7`~Uy{AR^Vl{Ep8bAoD_qG%u7$bx}m9d-MPQ z|8y+s0-$1XQ2NvV|Nmp5Y-E4H)Wt*PKK}pzAJk_9ago)*;x`#20mYzh35ZEZoi|7k z0|Nsgb)aqyNGTz8z92<Jm<Mw+A@g8qoRGReEcU|mra|RC{Qv(y70O0752hCuSD<){ z#G>x!|NsA?!VD}73=FWmrpds<04fVWa-c3Dhz4O$cN2zTd=L%7pzb4xM#iAA24p^R zwr7PV^yPX870718L_uO8Ha7FW|NsC0E0Q0=KnfWc7(nF}EUm3EfC}QE@R<)C9)atO zfU*o37#I#i*?$O_4^_s1&Hdky+ztwk7^q@Uxx5j|-Vd@2%Em`wGygA=`Jg5isO$sz z7i7K-)N=(!_)JB}5o<okA0YF6KnaS0fnkj)!VG*YZ07$#az99K3W$K#51*m#|6vIg zWPl8xfc%FLL9noy4{|H0jzO0LiG!LDpz0E29*7O1L41UX_*oz`P@6c!bjw4885r<2 zgNSPaB?vPxv_tb1$Q{Jk4C=NaT7IA&upXjy25QiNGA~>NJTw6o2?&V{aE<rNFUn2K zVE{G3;c5^)7Enlmq&#yA@{3ARQ{Xbi44_!l&;$>HdFB@6q=I_)peAQYYEfEZa%wS1 zD+AafSi=z9c_YS0pq3R{D{>mBaSd%SLt4EEPogSSr{Y+l9>F%JIs>S^huon9RVT3M zKx(_|fm^leFd39axE{XdmpTJzEW;1l{RQ=z!6q?K-yTr%^()N{N-fCAOa=`^Ks$h- zaRpFfG++RYEWlHVOKLH=0|OcX14TB-nQ%$ykVGX&0!<sz7!gPo)RF}I$So%^y%<~r z7@Am`m>8KEFo5Jdi$RTGaEB075{49&rh-Rc-7=j(5)1)f|Nm!ZU<AX944hzE9ZW*R zKqN#I#FBu@xHDui<TIo)croNNI5Xrjlrf|+6fzWpMN1j{7?K$B8Il+>7}6Mu85kLO zpt=GXiWv$R3c;eK3|S0m3?&3*nV@<pbpspJoG^xDu>Fh-m?E%npq5?!3`q=m3~3Aq zyAUEQQ1>A0;)9C#Fk~^5fc2F!gfOHqWHO{N<S`^MFfzzORd_HIGbAw-GGsEig4Gr> z<T4~NR58FzPhfCkC}&7x$Y&^JK&VB;19n+fsObn7kr&&%P;*?t@tXop6@?6-_%2|` zXJBL?BoB)hggdyQCSs;EMg{?>oIgVWl3zm^3K$9)a>2G1GB7f5KviinfYjwPq%mkQ zFfy=1MG-cU=VO>TAhT1!zDAghECzE0C?|n16Ewep*f2RC24k=rLFQnKu>^Q5Gct%l z-H(V*MTQy%cZM>Ce1;UT-$5Y`OBHntj0~{c1WRkU)G{)_QUl0sqELIn7y=lQ8L}DD zz@}qQd!QVx2vzR{R#(7K%;3UMz>vpK$N+K=BwboF1cS{<W5@!hRcD4Yh754|5eQAq z2;U>*6d4e*uvml9j11((9xQdafbA_|C_xHgd~#e+UkXBLMCc;3U?GhhugLk6kpX50 zrT&1q2bSVI7|Iy37*ZJ+8F0(MN@o0iP=fl<mBEa`lEIR}mBEC;gu$G_l);U`oWYR6 ziNS)wgu#@-oWYF2jKLVJ#*)F1!HU5Us@jdgjlmr$?^Ehmn7fh7M_4*Xq#NwAuo%Jb zXCbJc-564l$`xc26Bs~o%E-VERY|FzV5Nu$LoP!VxO7L9BFJK}5)Z%o#i6c3l>Z=~ zWHFR7fbye0QVo&7V8md~P|3i^05g$NpTI%{;pz~EQidvqT!u7;5Qa2{QU*k*;Zp;P z1DLyz^A)TlL)0h8{zKTu$RG?22}*qhOLGVpgG#kraCjop9Cld|s2lM6L?5b3lOdSF zj=_jQpTQ6b>N0p>6?Mic>V!oUROi9Ua!Nx3rXLgrdEnLxsI|ceuhG!OVRaS$5D0~a zKqx~dxMicrkk3%S0ICZWq5M=Zoy3p~PEDx{ir}^;h^}DBV#sC4Wq{}@Wl#jS^b{FV z7?Qx^X$+|h`V8C*uHe>F27@9)0Yf@NI)frZA-LWtVNe9;4v;=j$(hRlGBq8oHU*gl z%0*QSpxA=tGFWJkTL;0~Jb_S`AX<zF5m@bpKLla20Ssjfr3{5&Qjx)xAq^Z}84O7b zrQjB+Bs8Qcbvdjw1=*0!ki<|1Zgqu&!yMErU}PYyLJH~@P+J3p85lt%2unj{D0L;Q z%?Sxj7icJCfb(t@QoV#rUIyw8Sm<IeiD30CD7}KpIz(v0TJDtk1E$}Lp@hMSp%|Q! zLGH&TE(ditOrG5I2@5}vy`XkmI=Bx7YRRR5QxhS1d8j+^haW5#q%l;2+lGt`3Q&EZ zv;e}xwZ#leU!=5{Lm9FdQW$cOdY1?hSPL9~c*ELt?hHl@&J4y3<_wk$&J3;$rVP#u z77R`d&J30e77UgQCJYt~M&LG{5rY+j6@x2-6N5X0IfDzB?aIK&05b`{eXw=`sH_0> z&5{@t!R>(*aK9iGJQ|=3jd56CoPiNm)5CfshTwXUkwFEj62G0WG*!%y1}>8r8C0SA zsFf!|7|Ixu8E}^=xa8HK?!fPUSgSCd0o2j}mEMdD)eK4u1`J9JRt(V$u?#v4N(_cj z9!SOr%vNGBW>5mlnLzobP`(+M9}PAIrq&!PX91Q|Vz7kr4WagcYyjB-u?wcl5N?Md z1I!jf2ADmD3=o?@dST`pGQeyA^$Z~HGlJV;1oj8W4kHGL9jLA}g4<^Vx6cS}pAp<X zP<s|;HpIR(hD3%OhGK?PaEKUz{b$8sz);JegAxwNronuKEC%zDG1$!zmlCoe7Q+@} zxIZC!v4yuWI0Qg87=l?=;8=#m>1cQp8>7Zp(u^@U^?<?_k!FnH>BtzKjzA?MvFQjD z%aFW?$eFbaAW;Se&@2LE1RB0Vq!>KcZ^!^z+JG4Kg|Ev6%YqDIU?4b#&Y({8;64Lr zB8TueHSNdbK_k<UrD>ok5e8yrH9+$y5G^RH*+669prLa}_|kSJ0px02W9=wYH8^I8 zK+A|G{Ivrwn+CZXdFmR(w*nCi3=HN_8ak86zyO--1<k2}#6gRCKr~zuG`HXe5`j(x zf|#I*NDvJ(32Y^3{2w;E4Vu*hDF8(^h=xzLf+XZYA`A=+pk?YHCP)lKUjPxHWwKBj zY${BVGgNRklm@NQf-+GlQ2GOjz%;--0$NE1632?|prSBMFn_p1#j#Nj&Rl6c0G7B_ za=;$UU|>*&(lA>Y7#JGtVG#jZg9eg^1shxuXtoZNcR-S`AOo=>7#7;-jsq>Gf~Y_v z&s<pdRwq@?Z{xeVd-Jrp55VjPDMMz1;vFQ0j#)UCF#P`i|37HOHb@SX1VA(hBkKpb zUlSyVEm6Jx|NlQo0Z1O*PmBy&AYldu2GC?8hzau}Xu1@{XYc@%3=FV!EEr+-`Tzg_ zo=`;?l3)J+{||FDh9oGxA$!9Cmnr}L|Njr0W(R2kse^e1W-7QS1x;jw;tv#$$cjL0 z2nKDn0I`UU!(YxR-`xCnxpe$$s+cKs^cAv$LFE~;VX*88+PeV~$H34zYs{Sg>;M1% zx=`h?JPL~n1{<gZ%xchDIFJx52taHQW@G@Z3J0;|Km-G14+e+{TFnij89=MpKnzeB z0irRD00kj-8Q4M!Cy+D)0|RWe2m@%TR!Bx>u|i&cN~%I;u|f)TmAFD;UW!6_W=@Vm zUVe!}QmR67VopwKiXN9sQDVA6ep;GBL1tdDLP@?tQfX#Rib5K6m46~=5xX9PG1MZW z<I3!E$5oT%34RS7L8<TUdMCgF3}g;06@vUH&;H?WocAHGMT<Y0ZxVm1k4?-1qzQ__ zi-=&0C>TL?IY<K8bPykmK@kayFR%cS1lS6gT2LAXVHh8s2Dx`-X!$oIwz&@dAz3~9 zY#g$&iMb$Y1X}?21864?ND`|b@JfIrabU0&FgcL>K^VqIr|Fb;U>kj49>tw^OrS2r zsCYru;Rw%IdownDtk_ZIJ=0L!{O-wbw_u?O3Nlz(3o3WD&gA}8OqO@qwWIdZgGqa5 zViThvW5FU5WG%6nq(ljFZ{X(x=2rR64wHRtR-IgM$O@a-V9r<|_fFa!8}j%-ruVGl z`~j=i6gFcM1Fcel1tK_*K!pRSj{)AZqyXKt#0B1kqo7fonU|iEs#{Q$nw$yR&85k} z2-;NuG61w@3q)gJ<Wzzo2^9dfObql4z{@j1G*p-Y>>?NkRE~f!jE_zuTLdZxK}iy1 zFle15NG+(gD*>&D0rk*80-*44E-fy}&jl}@0SUp?fPw%d0BXgD6lJETrxqy$WK<Ss zCKre0=alBAGJvcAIS15L0jY#*1sRJ~0;CG$AW#nm#0J%D`dV5F;I-k<T2UdjEVZao zA+0DeH&r1sO`#++IU7`&rb6~`DQM|~SCN6VgDeDZZZQDy7#J8p4O(!ICAAoN*C*<3 z1-%RgSEzbWW1a-N!Mc#$e;w2n)zVVn;#AO5fcI+^GGQy+KzqbM{>dv*NXsu$D9=dE zQz*$uRY->Qd_f*d0`1$$%gjqxD9A~y)PV&<QfgX$QK~{_NwGqHIaoRowCO^<SOLD# z2W%})b5knw5_2;_O^r&0<f2s25-o6eW~3^B14JPsu~;E7rzkZsr4nRjDR}dc9@sO8 zFa~u3!4@ijw-%8b(nmmhI$%rt=odiL4jgz2pi!0r<r>&RS5Vu8;4Wj(R`2QGmNw{F dAGru>+QD16V3#s5l-;ukWI4586BchE^#INJ5hDNq literal 0 HcmV?d00001 diff --git a/Content/Components/WidgetInteraction/IA_WidgetClick.uasset b/Content/Components/WidgetInteraction/IA_WidgetClick.uasset new file mode 100644 index 0000000000000000000000000000000000000000..1e8b6c8dbba9ffe7beac263c84b4c800c521e468 GIT binary patch literal 1377 zcmX@utTpe)|Ns9Jm>C$jm>3v7GBbbyBLf4&+l&oQUOG+r!hOqdk>hSRJq-p1h6gMR z4Au+`4EjOgAs%5tA^G_^*_kE!&iT0o`FW{%CB^#TnJMY1C7yXDsYQv&C7Jno`ks#Q z5JBgh%;apa@!Sjy3^5=(7#J98nHU%p85kIhU5(8xoJ<`}%`Kb_4Gk<!EM3eDjVzp; zT+B^eT}>Rp8bOMg7#J92nHd;ZpqlSO-Tai9fdPcSGBYq--E!pdwN*ELm$~q+&y*80 zkG5LzljFcwx5<$+=1eWr{|d4jWDdw73`78{*yqbY$`n`_7<5@dECl}l|NnnbxPZ(v zM3MtB{qplt8NM(d<&|Y%U<gP|&Q45E^~q08%*m`u1O<*?Vs2`2L1J<$gHTCj2ZbSf zsw1UR1Qa>J$wiq3pjatN4fRjTN=+_d_~EH*Cx#^FnwOE7mz<j7nO9I+!f<un={IZ) z3=GaWiN(bXCFK<p`571(&>}9YYm)^JNEoEW5gfM+LJ|o)oD2*MzNsaNE{P?H3{M)i zOy)rNm7&<ZLsS64hpU^bvm_N7Zw#P-0tM&a|NsAk^n%#P7+u|;|NsB9BP)QiVd_8* zf(kLf#9(|74HH9F2TDvJIb{6r|NsBUd{791_@G1s3J4Gz6!9P$8wMpZ5C+MC5($V# z#^_>PP)Sfif+TkahBrtK1DOTFP-Q3-x>+caXdI9kAoqjg9vYEY;`=2t1H%=l^&l-+ zlqlg!QF_Q`gZu;XTUcUFX=+GiK`H|%mYwqRb5axY7(g!ZODxGOONFF9TO>1`^WiC2 z4=k&$4^7)B=@;2Hb#S==vJTDH7+jE_Ko}%JQ~?AkET?~4+Ms8B<RZvVG9aBuxa^)q OAj_%!ng&oYka_@7EEl{0 literal 0 HcmV?d00001 diff --git a/Content/Components/WidgetInteraction/IMCWidgetInteraction.uasset b/Content/Components/WidgetInteraction/IMCWidgetInteraction.uasset new file mode 100644 index 0000000000000000000000000000000000000000..6135a5b20e421c7fd3784230af445a929ac91e35 GIT binary patch literal 2811 zcmX@utTpe)|Ns9Jm>C$jm>3v7GBbbyBLf4&+l&oQUOG+r!hOqdk>hSRJq-p11_urX z21f=42K}J$5Rb5+ko^3d?938<=ltA){Jhk>l4AYv%#`%h63@Jn)S|@XlFa-(eNSI! z3_-9ZAOn*?HZd?TG_x`=C^9fGI6E5|o0*sxxH($7SQt7xIhr_`xw;vfTNpW-yBb)S zfHi^?GchnQ6tgifut7B&vxB7=tl1gB*qfb!A>^3c=Y}QwJogq@OuMx0%Ay~p=hX^U zhPkYpW6NkC$QS~$8)Od1ArRg8$<IfVZ-Z2{urn|m=K`@1`2YX^|3RT6!@$6B8c7c1 zEJtuaFudn>E#_ljU~nudN~{bh$}dPQDyd}f-0(P4h=GA2$+I{hC$TcM$TzW|ATcQ? zl|i?{bPX>91A|k3ehyr@0Lz9h0R{#Jm(1dVoWx4!#FEtX{Gv*RStp-<<3Wh~CFZ6w zR84*6B+0<Q;F_0_n3tTI0&$0TY9+{u%)E4lY4fa2KsLDMmFB{22)sVmK^deA)j8g& zmBFbcC7F5YPN^A*WtsU!#SH1Cs&nm#Qfg)8nU|4Tlvx5bqu8w|KNsR2hNA8M(ku)N z4Bn}g3|nj?rf@*mU@z1K7qEc5>yw&R;+tPuoa$6sQj(v?Aox{xGbaNB1JozQ40jKf zrhx@gOA=EOOA;BLG@N_^iU;5Pl+3iu)S_Yr#XA|<tPBhcV1q4XEpCFm4&uPQ-t>vX z3#=kPFO}g7^HE-Y1_lQIq^#8B61W=2+nZm>GB7X%BqnDkrl<PkCnx4)RwaUxI>@Zz zg2d!h2BDJ54p7Kr1fhQcNMSL<#>TacQXo@Mq8t&%#SFV@KOYvuPyy3_uJ~aPC|sby z35ya2yG2L8fE*oMQdElMXaj~he?YzsNv%Nm<cL+tc2JOo6lJETg97N0L+(mzQggRs zJS2BJ=VT^lGo0#3siaB);mH}sCjxRyaB@**0jP*6N)3fX1;Y<dT{}?F=tJdT>Dx1} zptOYH>blc!K&66nPGWH}LrHnXL{NZuqPjDyYm<d20|Nur!fD3o`O2WY1U3(vNQER4 zctGv}i$PPJbADb)YDEddHw*j6pn&vEElG5Nq`fVZL8%y;Mi`3SJ48XT1?9ul&DB|w zDhDk?6rl9)|NsB1LfN2l0m@`RSNH4x|NkmbNn~~MP%%&z1~LEq|NkFUvVz#i>R{%n zfh3?9RCs}ygw(<G5>f|q3$nU@|Ns97*#W~!PzE;x1A`l=G=^3)P+<%TRA_@RNCH&o zf@oxnE~XBZ1Q`uVnILW(s9*pw7#J8pW`Qu2i$bBBg(8W@0hxg-f#6JO_UsG{CZLo8 zbqG#{T1Z&|CAsTiOOPP9fD*7@Vo7FMDkLMgBAMWv56?_`U|DsnSqYoj>fjnz59)bP znF3;hECkV#pipLDU;veUAU-&BVTxdaPoSznnG~!Doe+l#z%+D0`Jm8&GEpf|tqKwm z1`!Ml44~Qs%4A>wWjqi^5JWIAFhGNwfdQ5(K_xy&4pbh4Xi!!L(O?Wtt1$C$tALp$ z4b}unRUjrzC(LCaF$Pe11Y$tL0q$HBMIZ$r3=@Qz#PIk3|NpS`3kxAlkV*yy2ADXM zi=aTc3&g_+1W+;oNx(b+jX(xyLl7hd#S%~&)S>|~Vc`g)8DQZCDw;tGFkB82gxLe5 zk;Oo45C(+{C@X>3prVUlqY%`Lo&IfUgP!$~iy#lc$}x}uAY69OB9P_OeoX@qhk=0s Gq#gj0r#KJ* literal 0 HcmV?d00001 diff --git a/Source/RWTHVRToolkit/Private/Interaction/Interactors/VRWidgetInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Interaction/Interactors/VRWidgetInteractionComponent.cpp new file mode 100644 index 00000000..5e41c026 --- /dev/null +++ b/Source/RWTHVRToolkit/Private/Interaction/Interactors/VRWidgetInteractionComponent.cpp @@ -0,0 +1,154 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Interaction/Interactors/VRWidgetInteractionComponent.h" + +#include "EnhancedInputComponent.h" +#include "EnhancedInputSubsystems.h" +#include "Interaction/Interactors/GrabComponent.h" +#include "Misc/Optional.h" +#include "Utility/VirtualRealityUtilities.h" + +UVRWidgetInteractionComponent::UVRWidgetInteractionComponent() +{ + PrimaryComponentTick.bCanEverTick = true; +} + +void UVRWidgetInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent) +{ + IInputExtensionInterface::SetupPlayerInput(PlayerInputComponent); + + const APawn* Pawn = Cast<APawn>(GetOwner()); + if (!Pawn) + return; + + auto* InputSubsystem = GetEnhancedInputLocalPlayerSubsystem(Pawn); + if (!InputSubsystem) + return; + + // Because we cannot use the regular debug ray (only works in editor), we set up our own (mesh) ray. + SetupInteractionRay(); + + // add Input Mapping context + InputSubsystem->AddMappingContext(IMCWidgetInteraction, 0); + + UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(Pawn->InputComponent); + if (EI == nullptr) + return; + + EI->BindAction(WidgetClickInputAction, ETriggerEvent::Started, this, &UVRWidgetInteractionComponent::OnBeginClick); + EI->BindAction(WidgetClickInputAction, ETriggerEvent::Completed, this, &UVRWidgetInteractionComponent::OnEndClick); +} + +// Called every frame +void UVRWidgetInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // only raytrace for targetable objects if user wants to enable this feature + if (!bCanRaytraceEveryTick) + return; + + // Disable/enable ray on hover + if (InteractionRayVisibility == EInteractionRayVisibility::VisibleOnHoverOnly) + { + if (IsOverInteractableWidget()) + { + InteractionRay->SetVisibility(true); + } + else + { + InteractionRay->SetVisibility(false); + } + } +} + +void UVRWidgetInteractionComponent::SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility) +{ + InteractionRayVisibility = NewVisibility; + InteractionRay->SetVisibility(NewVisibility == Visible); + + if (InteractionRayVisibility == EInteractionRayVisibility::VisibleOnHoverOnly && !bCanRaytraceEveryTick) + { + UE_LOG(Toolkit, Warning, + TEXT("VisibleOnHoverOnly needs bCanRaytraceEveryTick=true, so this is forcibly set!")); + bCanRaytraceEveryTick = true; + } + if (InteractionRayVisibility == EInteractionRayVisibility::Visible && !bCanRaytraceEveryTick) + { + UE_LOG(Toolkit, Warning, + TEXT( + "VisibleOnHoverOnly will need two clicks to interact with widgets if bCanRaytraceEveryTick is not set!" + )); + } +} + +// Forward the click to the WidgetInteraction +void UVRWidgetInteractionComponent::OnBeginClick(const FInputActionValue& Value) +{ + PressPointerKey(EKeys::LeftMouseButton); +} + +// Forward the end click to the WidgetInteraction +void UVRWidgetInteractionComponent::OnEndClick(const FInputActionValue& Value) +{ + ReleasePointerKey(EKeys::LeftMouseButton); +} + +void UVRWidgetInteractionComponent::SetupInteractionRay() +{ + // Only create a new static mesh component if we haven't gotten one already + if (!InteractionRay) + { + // Create the new component + InteractionRay = NewObject<UStaticMeshComponent>(this); + + // If we're not already attached, attach. Not sure why this is needed, taken from engine code. + if (!InteractionRay->GetAttachParent() && !InteractionRay->IsAttachedTo(this)) + { + const AActor* Owner = GetOwner(); + + // Copied from engine code - I don't think this case will ever happen + if (!Owner || !Owner->GetWorld()) + { + if (UWorld* World = GetWorld()) + { + InteractionRay->RegisterComponentWithWorld(World); + InteractionRay->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + } + else + { + InteractionRay->SetupAttachment(this); + } + } + else + { + // Usual case, just attach it to ourselves. + InteractionRay->AttachToComponent(this, FAttachmentTransformRules::SnapToTargetNotIncludingScale); + InteractionRay->RegisterComponent(); + } + } + } + + if (InteractionRay) + { + // Setup the interaction ray. + // The static mesh reference is set in the blueprint, avoid ConstructorHelpers and hardcoded paths! + // this ray model has an inlayed cross with flipped normals so it can be seen as a cross in desktop mode + // where the right hand is attached to the head + + if (InteractionRayMesh) + { + InteractionRay->SetStaticMesh(InteractionRayMesh); + } + + InteractionRay->SetCastShadow(false); + // turns off collisions as the InteractionRay is only meant to visualize the ray + InteractionRay->SetCollisionProfileName(TEXT("NoCollision")); + + //the ray model has a length of 100cm (and is a bit too big in Y/Z dir) + InteractionRay->SetRelativeScale3D(FVector(InteractionDistance / 100.0f, 0.5f, 0.5f)); + SetInteractionRayVisibility(InteractionRayVisibility); + } +} diff --git a/Source/RWTHVRToolkit/Private/Pawn/BasicVRInteractionComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/BasicVRInteractionComponent.cpp deleted file mode 100644 index 257313fc..00000000 --- a/Source/RWTHVRToolkit/Private/Pawn/BasicVRInteractionComponent.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - - -#include "Pawn/BasicVRInteractionComponent.h" - -#include "Misc/Optional.h" - -DEFINE_LOG_CATEGORY(LogVRInteractionComponent); - -// Sets default values for this component's properties -UBasicVRInteractionComponent::UBasicVRInteractionComponent() -{ - // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features - // off to improve performance if you don't need them. - PrimaryComponentTick.bCanEverTick = true; - - // Setup the interaction ray. - InteractionRay = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Interaction Ray")); - InteractionRay->SetCastShadow(false); - // turns off collisions as the InteractionRay is only meant to visualize the ray - InteractionRay->SetCollisionProfileName(TEXT("NoCollision")); - // The static mesh reference is set in the blueprint, avoid ConstructorHelpers and hardcoded paths! - // this ray model has an inlayed cross with flipped normals so it can be seen as a cross in desktop mode where the right hand is attached to the head - - bShowDebug = false; //otherwise the WidgetInteractionComponent debug vis is shown - InteractionSource = EWidgetInteractionSource::Custom; - //can also be kept at default (World), this way, however, we efficiently reuse the line traces -} - -void UBasicVRInteractionComponent::BeginPlay() -{ - Super::BeginPlay(); - - //WidgetInteractionComponent - InteractionDistance = MaxClickDistance; - InteractionRay->SetRelativeScale3D(FVector(MaxClickDistance / 100.0f, 0.5f, 0.5f)); - //the ray model has a length of 100cm (and is a bit too big in Y/Z dir) - SetInteractionRayVisibility(InteractionRayVisibility); -} - -void UBasicVRInteractionComponent::BeginInteraction() -{ - if (!InteractionRayEmitter) return; - - // start and end point for raytracing - const FTwoVectors StartEnd = GetHandRay(MaxClickDistance); - TOptional<FHitResult> Hit = RaytraceForFirstHit(StartEnd); - if (!Hit.IsSet()) - return; - - AActor* HitActor = Hit->GetActor(); - - //trigger interaction of WidgetInteractionComponent - SetCustomHitResult(Hit.GetValue()); - //if !bCanRaytraceEveryTick, you have to click twice, since the first tick it only highlights and can't directly click - PressPointerKey(EKeys::LeftMouseButton); -} - -void UBasicVRInteractionComponent::EndInteraction() -{ - if (!InteractionRayEmitter) return; - - //end interaction of WidgetInteractionComponent - ReleasePointerKey(EKeys::LeftMouseButton); -} - -// Called every frame -void UBasicVRInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType, - FActorComponentTickFunction* ThisTickFunction) -{ - Super::TickComponent(DeltaTime, TickType, ThisTickFunction); - - if (!InteractionRayEmitter) return; - - // only raytrace for targetable objects if bool user wants to enable this feature - if (!bCanRaytraceEveryTick) - return; - - const FTwoVectors StartEnd = GetHandRay(MaxClickDistance); - TOptional<FHitResult> Hit = RaytraceForFirstHit(StartEnd); - - if (!Hit.IsSet() || !Hit->GetActor()) - { - if (InteractionRayVisibility == EInteractionRayVisibility::VisibleOnHoverOnly) - { - InteractionRay->SetVisibility(false); - } - return; - } - - AActor* HitActor = Hit->GetActor(); - - // widget interaction - SetCustomHitResult(Hit.GetValue()); - if (InteractionRayVisibility == EInteractionRayVisibility::VisibleOnHoverOnly) - { - if (IsOverInteractableWidget()) - { - InteractionRay->SetVisibility(true); - } - else - { - InteractionRay->SetVisibility(false); - } - } - LastActorHit = HitActor; // Store the actor that was hit to have access to it in the next frame as well -} - -void UBasicVRInteractionComponent::Initialize(USceneComponent* RayEmitter) -{ - if (InteractionRayEmitter) return; /* Return if already initialized */ - - InteractionRayEmitter = RayEmitter; - - InteractionRay->AttachToComponent(RayEmitter, FAttachmentTransformRules::KeepRelativeTransform); - this->AttachToComponent(RayEmitter, FAttachmentTransformRules::KeepRelativeTransform); -} - -void UBasicVRInteractionComponent::SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility) -{ - InteractionRayVisibility = NewVisibility; - if (InteractionRay) - { - switch (InteractionRayVisibility) - { - case Visible: - InteractionRay->SetVisibility(true); - break; - case VisibleOnHoverOnly: - case Invisible: - InteractionRay->SetVisibility(false); - break; - default: ; - } - } - - if (InteractionRayVisibility == EInteractionRayVisibility::VisibleOnHoverOnly && !bCanRaytraceEveryTick) - { - UE_LOG(LogVRInteractionComponent, Warning, - TEXT("VisibleOnHoverOnly needs bCanRaytraceEveryTick=true, so this is set!")); - bCanRaytraceEveryTick = true; - } - if (InteractionRayVisibility == EInteractionRayVisibility::Visible && !bCanRaytraceEveryTick) - { - UE_LOG(LogVRInteractionComponent, Warning, - TEXT( - "VisibleOnHoverOnly will need two clicks to interact with widgets if bCanRaytraceEveryTick is not set!" - )); - } -} - -FTwoVectors UBasicVRInteractionComponent::GetHandRay(const float Length) const -{ - const FVector Start = InteractionRayEmitter->GetComponentLocation(); - const FVector Direction = InteractionRayEmitter->GetForwardVector(); - const FVector End = Start + Length * Direction; - - return FTwoVectors(Start, End); -} - -TOptional<FHitResult> UBasicVRInteractionComponent::RaytraceForFirstHit(const FTwoVectors& Ray) const -{ - const FVector Start = Ray.v1; - const FVector End = Ray.v2; - - // will be filled by the Line Trace Function - FHitResult Hit; - - FCollisionQueryParams Params; - Params.AddIgnoredActor(GetOwner()->GetUniqueID()); // prevents actor hitting itself - if (GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECollisionChannel::ECC_Visibility, Params)) - return {Hit}; - else - return {}; -} diff --git a/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp index 5d52b65f..28309ec3 100644 --- a/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp +++ b/Source/RWTHVRToolkit/Private/Pawn/VirtualRealityPawn.cpp @@ -36,9 +36,6 @@ AVirtualRealityPawn::AVirtualRealityPawn(const FObjectInitializer& ObjectInitial LeftHand = CreateDefaultSubobject<UReplicatedMotionControllerComponent>(TEXT("Left Hand MCC")); LeftHand->SetupAttachment(RootComponent); - - BasicVRInteraction = CreateDefaultSubobject<UBasicVRInteractionComponent>(TEXT("Basic VR Interaction")); - BasicVRInteraction->Initialize(RightHand); } void AVirtualRealityPawn::Tick(float DeltaSeconds) @@ -121,7 +118,7 @@ void AVirtualRealityPawn::SetupPlayerInputComponent(UInputComponent* PlayerInput PlayerController->bEnableClickEvents = true; PlayerController->bEnableMouseOverEvents = true; } - + // Set up mappings on input extension components, need to do this nicely for (UActorComponent* Comp : GetComponentsByInterface(UInputExtensionInterface::StaticClass())) diff --git a/Source/RWTHVRToolkit/Public/Interaction/Interactors/VRWidgetInteractionComponent.h b/Source/RWTHVRToolkit/Public/Interaction/Interactors/VRWidgetInteractionComponent.h new file mode 100644 index 00000000..4228f9cd --- /dev/null +++ b/Source/RWTHVRToolkit/Public/Interaction/Interactors/VRWidgetInteractionComponent.h @@ -0,0 +1,65 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/WidgetInteractionComponent.h" +#include "Pawn/InputExtensionInterface.h" +#include "VRWidgetInteractionComponent.generated.h" + +UENUM() +enum EInteractionRayVisibility +{ + Visible UMETA(DisplayName = "Interaction ray visible"), + VisibleOnHoverOnly UMETA( + DisplayName = + "Interaction ray only visible when hovering over Clickable or Targetable objects, or interactable widgets"), + Invisible UMETA(DisplayName = "Interaction ray invisible") +}; + + +UCLASS(Blueprintable, Abstract, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class RWTHVRTOOLKIT_API UVRWidgetInteractionComponent : public UWidgetInteractionComponent, + public IInputExtensionInterface +{ + GENERATED_BODY() + +public: + UVRWidgetInteractionComponent(); + + virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override; + + virtual void TickComponent(float DeltaTime, ELevelTick TickType, + FActorComponentTickFunction* ThisTickFunction) override; + + UFUNCTION(BlueprintCallable) + void SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility); + + UPROPERTY(EditAnywhere) + UStaticMesh* InteractionRayMesh; + + UPROPERTY(BlueprintReadOnly) + UStaticMeshComponent* InteractionRay; + + // Enable this if you want to interact with Targetable classes or use EInteractionRayVisibility::VisibleOnHoverOnly + UPROPERTY(EditAnywhere) + bool bCanRaytraceEveryTick = false; + + UPROPERTY(EditAnywhere) + TEnumAsByte<EInteractionRayVisibility> InteractionRayVisibility = EInteractionRayVisibility::Invisible; + + UPROPERTY(EditDefaultsOnly, Category = "Input") + class UInputMappingContext* IMCWidgetInteraction; + + UPROPERTY(EditAnywhere, Category = "Input") + class UInputAction* WidgetClickInputAction; + +private: + UFUNCTION() + void OnBeginClick(const FInputActionValue& Value); + + UFUNCTION() + void OnEndClick(const FInputActionValue& Value); + + void SetupInteractionRay(); +}; diff --git a/Source/RWTHVRToolkit/Public/Pawn/BasicVRInteractionComponent.h b/Source/RWTHVRToolkit/Public/Pawn/BasicVRInteractionComponent.h deleted file mode 100644 index aa3ed916..00000000 --- a/Source/RWTHVRToolkit/Public/Pawn/BasicVRInteractionComponent.h +++ /dev/null @@ -1,90 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#pragma once - -#include "CoreMinimal.h" -#include "Components/WidgetInteractionComponent.h" -#include "BasicVRInteractionComponent.generated.h" - -DECLARE_LOG_CATEGORY_EXTERN(LogVRInteractionComponent, Log, All); - -class UGrabbingBehaviorComponent; - -UENUM() -enum EInteractionRayVisibility -{ - Visible UMETA(DisplayName = "Interaction ray visible"), - VisibleOnHoverOnly UMETA( - DisplayName = - "Interaction ray only visible when hovering over Clickable or Targetable objects, or interactable widgets"), - Invisible UMETA(DisplayName = "Interaction ray invisible") -}; - - -UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) -class RWTHVRTOOLKIT_API UBasicVRInteractionComponent : public UWidgetInteractionComponent -{ - GENERATED_BODY() - -public: - // Sets default values for this component's properties - UBasicVRInteractionComponent(); - - virtual void BeginPlay() override; - - virtual void TickComponent(float DeltaTime, ELevelTick TickType, - FActorComponentTickFunction* ThisTickFunction) override; - - UFUNCTION(BlueprintCallable) - void BeginInteraction(); - - UFUNCTION(BlueprintCallable) - void EndInteraction(); - - UFUNCTION(BlueprintCallable) - void Initialize(USceneComponent* RayEmitter); - - UFUNCTION(BlueprintCallable, BlueprintPure) - AActor* GetGrabbedActor() const { return GrabbedActor; } - - UFUNCTION(BlueprintCallable, BlueprintPure) - USceneComponent* GetInteractionRayEmitter() const { return InteractionRayEmitter; } - - UFUNCTION(BlueprintCallable) - void SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility); - - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Interaction") - UStaticMeshComponent* InteractionRay; - - UPROPERTY(EditAnywhere, BlueprintReadWrite) - float MaxGrabDistance = 50; - - UPROPERTY(EditAnywhere, BlueprintReadWrite) - float MaxClickDistance = 500; - - // Enable this if you want to interact with Targetable classes or use EInteractionRayVisibility::VisibleOnHoverOnly - UPROPERTY(EditAnywhere) - bool bCanRaytraceEveryTick = false; - - UPROPERTY(EditAnywhere) - TEnumAsByte<EInteractionRayVisibility> InteractionRayVisibility = EInteractionRayVisibility::Invisible; - -private: - /* Holding a reference to the actor that is currently being grabbed */ - UPROPERTY() - AActor* GrabbedActor; - - /* Holds a reference to the grabbed actors physics simulating component if there was one*/ - UPROPERTY() - UPrimitiveComponent* ComponentSimulatingPhysics = nullptr; - - UPROPERTY() - USceneComponent* InteractionRayEmitter = nullptr; - - /* Stores the reference of the Actor that was hit in the last frame*/ - UPROPERTY() - AActor* LastActorHit = nullptr; - - FTwoVectors GetHandRay(float Length) const; - TOptional<FHitResult> RaytraceForFirstHit(const FTwoVectors& Ray) const; -}; diff --git a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h index 5bc5dbc2..53e7bda6 100644 --- a/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h +++ b/Source/RWTHVRToolkit/Public/Pawn/VirtualRealityPawn.h @@ -2,7 +2,6 @@ #pragma once -#include "BasicVRInteractionComponent.h" #include "CoreMinimal.h" #include "LiveLinkRole.h" #include "Pawn/Navigation/VRPawnMovement.h" @@ -35,10 +34,6 @@ public: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|MotionControllers") UMotionControllerComponent* LeftHand; - /* Interaction */ - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Interaction") - UBasicVRInteractionComponent* BasicVRInteraction; - /* Movement */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pawn|Movement") UVRPawnMovement* PawnMovement; -- GitLab