From db958ab3f45e6ab34d13ee82f6dd53589f5c3928 Mon Sep 17 00:00:00 2001 From: Ted Newman Date: Thu, 15 Feb 2024 17:37:19 -0800 Subject: [PATCH] New input viewer (#3890) * Move input viewer into SoH * Remove unnecessary comments * Update button outline mode to match default viewer * Fix ambiguous call * CVar name changes and minor fixes * Two more cvars * Separate C-buttons into individual toggles * Account for text height regardless of scale * A few extra comments * Use new LoadTextureFromRawImage to load layer textures --- soh/assets/custom/textures/buttons/ABtn.png | Bin 10967 -> 1485 bytes .../custom/textures/buttons/ABtnOutline.png | Bin 0 -> 1818 bytes .../custom/textures/buttons/AnalogStick.png | Bin 0 -> 2206 bytes .../textures/buttons/AnalogStickOutline.png | Bin 0 -> 3677 bytes soh/assets/custom/textures/buttons/BBtn.png | Bin 1300 -> 1534 bytes .../custom/textures/buttons/BBtnOutline.png | Bin 0 -> 1878 bytes soh/assets/custom/textures/buttons/CDown.png | Bin 11241 -> 1285 bytes .../custom/textures/buttons/CDownOutline.png | Bin 0 -> 1544 bytes soh/assets/custom/textures/buttons/CLeft.png | Bin 11232 -> 1291 bytes .../custom/textures/buttons/CLeftOutline.png | Bin 0 -> 1544 bytes soh/assets/custom/textures/buttons/CRight.png | Bin 11284 -> 1336 bytes .../custom/textures/buttons/CRightOutline.png | Bin 0 -> 1541 bytes soh/assets/custom/textures/buttons/CUp.png | Bin 11219 -> 1305 bytes .../custom/textures/buttons/CUpOutline.png | Bin 0 -> 1546 bytes .../custom/textures/buttons/DPadDown.png | Bin 0 -> 946 bytes .../textures/buttons/DPadDownOutline.png | Bin 0 -> 984 bytes .../custom/textures/buttons/DPadLeft.png | Bin 0 -> 929 bytes .../textures/buttons/DPadLeftOutline.png | Bin 0 -> 953 bytes .../custom/textures/buttons/DPadRight.png | Bin 0 -> 922 bytes .../textures/buttons/DPadRightOutline.png | Bin 0 -> 954 bytes soh/assets/custom/textures/buttons/DPadUp.png | Bin 0 -> 968 bytes .../custom/textures/buttons/DPadUpOutline.png | Bin 0 -> 993 bytes .../buttons/InputViewerBackground.png | Bin 0 -> 941 bytes soh/assets/custom/textures/buttons/LBtn.png | Bin 355 -> 1031 bytes .../custom/textures/buttons/LBtnOutline.png | Bin 0 -> 1089 bytes soh/assets/custom/textures/buttons/RBtn.png | Bin 379 -> 992 bytes .../custom/textures/buttons/RBtnOutline.png | Bin 0 -> 1074 bytes .../custom/textures/buttons/RightStick.png | Bin 0 -> 2150 bytes .../textures/buttons/RightStickOutline.png | Bin 0 -> 2407 bytes .../custom/textures/buttons/StartBtn.png | Bin 11868 -> 973 bytes .../textures/buttons/StartBtnOutline.png | Bin 0 -> 1031 bytes soh/assets/custom/textures/buttons/ZBtn.png | Bin 1241 -> 1005 bytes .../custom/textures/buttons/ZBtnOutline.png | Bin 0 -> 1069 bytes soh/soh/Enhancements/controls/InputViewer.cpp | 519 ++++++++++++++++++ soh/soh/Enhancements/controls/InputViewer.h | 47 ++ soh/soh/SohGui.cpp | 6 + soh/soh/SohGui.hpp | 1 + soh/soh/SohMenuBar.cpp | 25 +- 38 files changed, 594 insertions(+), 4 deletions(-) create mode 100644 soh/assets/custom/textures/buttons/ABtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/AnalogStick.png create mode 100644 soh/assets/custom/textures/buttons/AnalogStickOutline.png create mode 100644 soh/assets/custom/textures/buttons/BBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/CDownOutline.png create mode 100644 soh/assets/custom/textures/buttons/CLeftOutline.png create mode 100644 soh/assets/custom/textures/buttons/CRightOutline.png create mode 100644 soh/assets/custom/textures/buttons/CUpOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadDown.png create mode 100644 soh/assets/custom/textures/buttons/DPadDownOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadLeft.png create mode 100644 soh/assets/custom/textures/buttons/DPadLeftOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadRight.png create mode 100644 soh/assets/custom/textures/buttons/DPadRightOutline.png create mode 100644 soh/assets/custom/textures/buttons/DPadUp.png create mode 100644 soh/assets/custom/textures/buttons/DPadUpOutline.png create mode 100644 soh/assets/custom/textures/buttons/InputViewerBackground.png create mode 100644 soh/assets/custom/textures/buttons/LBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/RBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/RightStick.png create mode 100644 soh/assets/custom/textures/buttons/RightStickOutline.png create mode 100644 soh/assets/custom/textures/buttons/StartBtnOutline.png create mode 100644 soh/assets/custom/textures/buttons/ZBtnOutline.png create mode 100644 soh/soh/Enhancements/controls/InputViewer.cpp create mode 100644 soh/soh/Enhancements/controls/InputViewer.h diff --git a/soh/assets/custom/textures/buttons/ABtn.png b/soh/assets/custom/textures/buttons/ABtn.png index c1b06571c3a9c4427420bcbccec364f28c7c4778..031924cb963fdd399db122ccc7e584ab77d0b782 100644 GIT binary patch delta 1343 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 Fe*n=C2|@q> literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/AnalogStick.png b/soh/assets/custom/textures/buttons/AnalogStick.png new file mode 100644 index 0000000000000000000000000000000000000000..d3fec7d015eb293346187db09fea10407ad7cf2a GIT binary patch literal 2206 zcmb_ci#rqQAK!?%#3r|4ZFAHwmnE05>bT6TF}b9edu5HEilNOdj!sr9mmwm#)ei?- zE};o2cd?Mel9tO_B4Soav2@n&Z#eJsyzl#cKF{a*yzl4vzMuDor#oInNmmH~0I0Y) zJ9z;BK)kfBSCE&kkw!2xDR4C$i}iHDVv$iXl+f@CWB|Z0CppK~xyMuEs>cajPMY(P z>xO5m-L;(3(FD!()AyP+{b^*8)GP(}b{`JH{VfZUDC+})=aT?%#%=17|9 zj=*^Pa>@{}E8s3=xFld1Rt0vr7Wyzr76y|M;)a4Z;^Qa_Z?;#$hee=vrI_Bw2H6SH zzQ~8T;++7MfLy?B2RY7BDWVwV>~|3WP*(pnfq*;3P$>way13y$i$J)x5qiYAdRz+W zP;tIgEF~g>97zRWW5{Qy`QaO!`Nco#QM;-9M8Qgxb(6Xs<6>y_!Q2>vrTXs)nQ z$r&VwZ3t6z&QqOXBV)n4?gkVW0azgJ-V1X1z|@6gP1H0-DceHSFi~ft7Cy)f$=S5) zbU>=T$c9QjAx5I0GSb8Uh2hX1@4oLy(eS6?P)m2C4i$YmlmvH-mk@ajAAU+z9t$eO z5^DTWS|&mAbP`1-x+6Fx!#sEb_-&UrAza7tk$N5y)(*Q)#7hc|=?z1TA3rDA)l>IE zm<#ZXxTThM_;j9%u5xITeA9ADhRJe z9KrIb=j_UeO;aeaK7Bp0WYTg3`2NpRezuX;dOhbMOb@n6P5QO^f}o_Kir{b46RYC07COsmNLau_Z!f=mT5Lg4 zVthwaVum>jjzQbi)TH^xejjUZTjBn7c|sF|w!Y(DrR|0pn`cF5U3{iei$QY|W(Qc} zqNQlsT&ryNgJ|dJD*Q@hZ1T5WgPWa&4AOXZBCkMsCdTyIOC;iIR+rbS?@*8}=_$5ab1qPMO`G zT>d{>Q7W;(Cfk-r?f3=zLRE@sXzSXrj~@(ZB5O!{9{4T(uT3#_9MX67BvKJKMv zXwsWCL{H|bLU(jkU&z==+xZAl)9Q=t%}t#J)oNG(qd;it@qFTz2-h>|8l*-iu~A&p zBGv$u6viGH4!t-XGg3ywL725mI(%{&YoKk|Z6)|lrPK^%{gtmvAGE$bHivH<>}{Yh zfMpN#3)ZQJJ649|>iBI<=Z+Z#)#zf-aDUr6$Iqr#LQdhVx>EmgzJThB()xADQ5Kxv zEex?JEdIE|?Z=+yxbY36N^l#Zxb9<~9x;C&(IaROD;7dYb}-f1JaU4Uh*Os;Zrcm3 z*Gj*Nn?=G-X=KMqqX5>IaD>Y?=KbO*^veF5e^bEg zPob0ShAyCyu#`|wX3uuh^V&b5j*l*SNSXClVw$EhP7o-hjD#Q2+l!O{pbrhQ9i*mf fE&DJ0>m6TG*pl|y5|BpPFEtmOyHlOx=_~&Lon_D` literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/AnalogStickOutline.png b/soh/assets/custom/textures/buttons/AnalogStickOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d8d71907601d74393ae9514df947db71252e19 GIT binary patch literal 3677 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 W?mz4GDbwrMD=pAAsA>~j!hZk&QN3UQ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/BBtn.png b/soh/assets/custom/textures/buttons/BBtn.png index 99b1197c9982d8d2027987f6ae578a9656db2d26..8e2fbb54b5345f3d11afb2d62e2361d982fdfbab 100644 GIT binary patch literal 1534 zcmb`G`#aMM9LK*S=F-JNZgV--g;jFDm$3ESrp81r!)TF-ZD!@V2$f4@Em3pL4o=9a z(2;tu7ILcy$EA}+E-i`L=-A=tf9U-@@6YpoUO#-E&+~kqccup(+@_?h1OUJ`EC%HX z01$99*DJ_xPO357bQ4^rxVm~^U0n_63|bf^G86!e*ev#8%ySR5%kC%9>@18!hS8a7 z{4P|sElxc`~_v?f(EXA7ym0v&+`_f~&=sjUEa!zBst81h;!Q@`1yMcUCk_h*}h>#@C7 z?r_6h*}4Z}P4{adqi@>QR%?G$_A5~DCl(FiavHz9Bx!b?+fTVasO=1Q!x$*S%p;5{ zWRziJR-VUsbB;4Y{R>ho9dCPap2%5A>Cp|I!xn6P$(A;xyFlWcDrnu1 zc48T=ub3!;SM4}@C9E+?77mx0LU#wP#KqEPC)O7zeT&c*C5GTBA}@aPFY>3|Kosyh zzyS)6$~7I^B#Ly5Ukm^!tNt_uxKpIL3875v2{d#LqNlN6#-5=%wTZNtXkVr)Eh;LM z$^={)p&`uBGX}8~X1D=}J>lVVX}bmh$PQsq&R%h23-1Vc9Z(bcl{QRBN9I`{ZkOyX ztU}Tj6kSXJv0{qqUqYEeqNRHwH`2WgCy~wiP<$jEW1McZC+?YO{i6HR;A0jQPVa3V zE&sgmSF6q1tujU58{hMZj8aE`t_tuXOd}ayFajFIdOY|ke6XrCTapm{wzn6~XV*2X z-FL(q=O8*)6LR}U!bdO4|w3Rpy$}kqC`6;{@lQVIe z*OJ$hV6awkI40js`^ii%JGnVApsFC>pZcwxG0k500zuXp93+#@Lqt7rx>;U%vt!p* zAqLFk?6^9(zT++*ZToP~L2;f}%b=$?gN}0hFTc2jCRE9#Z>Y63Blv9bVrszcEh@Pa zHUj1C1?CE%y+Qa@4_sOK z_tIT)_m*^oNPIe_KqtE*EbOC7ZmqWk@Dc*yPaP?9t9;4@I4XUyqdqIK50YQQ(RK5 z0uoFpzilb5?t?xU?Mys!9paVyy*^dyE8wclH;7IpL^BbZqnaA#NrMY(<1o9(i&8BhS5 z40rofXo5T&Hd!ioXYzWF8jrf~5}f)!;y`<# literal 1300 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 e;TaV literal 11241 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 U5$hkg$@^Cfx?)}Godd7^16AUFtN;K2 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CLeft.png b/soh/assets/custom/textures/buttons/CLeft.png index 5e26a2067e159b8bc2c9116664f9e72b5d7896fa..43b04412fbc0752e6589dd93235700e259ec9f64 100644 GIT binary patch delta 1127 zcmV-t1ep8aSBnZEiBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9Fq3f#6@Ms^ zeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9A2ex5Qd}Gb*MfsTi&X~~ zXI&j!1wrr!#M!|~(M3wUFDbN$@xtSMoOjRRz54*6QDLgtH3_JiWu)RUF`HWzdtTwg zCOGqFI5i)8hqXG*N+BH&4r06{6;U9MVNpi{LDua<@0e@AfkQ_hw zAN-!JS(u)3lL9fI`^C0D#(2000SaNLh0L01FcU01FcV z0GgZ_00007bV*G`2j~GF7b`nucbn?~000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2H zM@dakSAh-}0008wNkl7zN;S;|`K80Ad1Ql9B;HVkm-;36Nj_(n%U7 zK(GMbqqT1zNL8sVPy_@g`96sU#DlG$_~_g?@lBIaA4`+K8xVhZOT`G_d3P5%>XZFZ zGOo!u4?juLmZVLRu4I-UY4=Vaen&XMM!LDoK~poW$-xURszp~a+dIy}6on&fPAHyd z+%&m*X(;|PB)d#BN#O_^(H2KF-`@Blo9vuqZo2DbWCZZw_A=AA4#p&@$<^&;rY5X8 z!deDnYR=yIYCC`1Jo zcF?T;y}*w+CYmD*x;1K#nj>h9PiUH4`44E0pfzfbnj@^m3;$ETeDpaq&Fj8_gK&h6 z)F=CgEp3Wm2VR$e6>qq|d-E>$sd)Q957rD;|-Z9=ias6qIz@J(p5RNcN zeaU1SkBxAIC+!_)QM3A80ZX#5Rf2GYL91P6t6t)Eoz^HEVd(AgG;K=es|v`z*+Jg>Gk2G1hBN+yZR{a@$nveRtra1XLlDls>$>%1JYjAmesKK zc1|+yOC}|+53`!g1*7H&8|UUS2Tjd%`B2*bZjv>b*OIS7Q8>cZ1m!aPeg)+?Nn4V( tPufv(-E~>G8x50DA4`+K8w?j4>?hWcnVy|(M}+_Y002ovPDHLkV1kll_JRNa literal 11232 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 P{-XmPLv+0FK)(1tYki4q literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CRight.png b/soh/assets/custom/textures/buttons/CRight.png index 9e6180639b9b332424a585c3ba7e57d287742779..c2d1afabfa0994a1c73817d8172f7bfba44b0433 100644 GIT binary patch delta 1163 zcmV;61a$k9Shxy*iBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ zsT&@D=m8!VEEaF+QCR>002y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00R$6L_t(|+U?!VO&d`dhS7KING!8R15N`VDgY`86aW$x7*~J<1>jT?Qvreom}NF; zAj$Y<0m&l5{3K@Zc+Qc$KrHSsLXW=dv3wJgaU)ZcKpY5vmZ@?JfWO_GWq+RR43bev zM!9<>NnIs%k~CE&`I&nA`0i(M1lH2kd3J{-;PDhHcKnRfl&4E%dQKV6?^yzDS0Nl7lQ&oeeT0-X$F zN={z6E+<=mhna{Y(A%x_BJ(PHU42j^j?kwto@O){=C;i>=S@C#@ga@(9HB?5Vf*g| zzQvj*M_{F=#x75fCPy$ezPjNs7bZu*)VK!Iqsb9^VDK)VT3YJcBh%xqZ8gwW9~MrI z$&NSzE2S!}PHkmDY)0Y;td!Djn7*&THHahdENzB=X=4ShK^%c+sass@>k3?hI07r@ z{W|;+;s`xZwL7(KtiUyhBk;6&yJ32;E2ZkzxATZ2^uQpwT=1(O?#{w#8|Z`Uv)twl zpBQf)b*ncfN1zRL*DhEbp(o~54*IyZI0BE_KFqA7{Zj#}WY)!_62uXDq%@hdy~S;s z?oEw<;s|}49*?{)F~7;%Ii+B(eSK9EoBhW~p%ebUvF2bXgLfKIwU zyLvyb@$sIHpII%A&~rCu*)Pd>nSt!`S=F}HK$2whDAReBgDU?Yvyx2LC5$FV;E${G z><&xD_g_l;>`AgD(^BR0x}M002ovPDHLkV1joC1z!LF literal 11284 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 a-T&@2YJoFO%U-?#^v9T38ecYa-}N5>&$}J~ diff --git a/soh/assets/custom/textures/buttons/CRightOutline.png b/soh/assets/custom/textures/buttons/CRightOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..d450084ead24fc1b64c507881cb1f094b7b7a572 GIT binary patch literal 1541 zcmcJO`#;kQ7{|YJTW)EIg}I!TyO!LVLsn*OGe&fqxnHJ{+gxU(T+&S@n+|4{UX`4P z&Y4T)62fUYi<09OCUVJP$mL|xS${;&>-9XZ=k@;O^Ln1o^IZ2NVpWy2l>h)x#p7JO z004xQ_BA^cq&3AEXP_dANfV5h-Bfy?Y{b zf;5(P>GTWMVJ(sR^_imRvmH7e)+N8aVcbD>xU!rt5FLYh<*(~MLo{x6J)3>fYK=Z_ zWa|Ojrrq|lJijth z!-6+IDOva&u%cBHj4k<8vm@74{R#TTjw^0#U)JA;x@_hMdy z+Q?-w!cy`)?4jDxE0nqmvM`v;B<8jMMlwBS=EL>^RVW5GD$zQc;I|l3Ulf7~SQp>{ zzy^wr%GV#462({?DINfn)qf-i;Bfa!Avgi=jseet^q>}y<=l=FO0r*hhqT+(WUd7*ZNuws{wC( z8E~rtr~m|efZyf3GsNdac4^!r45aZ5;=jR}_@*&2J30NTA2s{pH*3BFTPpao;t8P> z4qRMy?3w%3UeA!taa;LjjOVay@PC>;6ExWLb&FppV?_oB#8x^3zWt%=UAstCuF>T) zq#amMtn;!Rdl|VAquL2Y({A(8R8~7gVN4Tio9D3eHs1rvn3eFgzHX!kZPE%W{lFot z_fy;5e$_VEvck3^&b%72a6aHoJRFvhrR_Q}b+^Fg!E|1K1b>iLATY5<*z)yH{}E7& zu%DZE&W*kNi~MAi(Y?5qmfcD@9#H$CX`e7|C5xM+FlC0?h|BNd!c}lu^d9+Y0zO0m&{ zZ)>H}X*lrS%730Nz$WdSdg90Jz(Wn|7544GP38)DBsS$tThac++aXbZ)<*{v^0m`JmLWi)$z?tc8ZU{oz0EAZ|fH*SXvHe5kcsqr3-Ed!4XV=H6j z)_Zf>Rv`g33BKM)nbet1yN0IGw7^7P{#>7|I@2-~tKU1#-0a_#4Ocl!O>Hh;bb59C zK;=73yxh9*xnYsh$2HFI?x%IDk#xO@9kRXaDeibmBbV+wMp+p~9FYp@l!PezN93`Y zHQ{4b^E#hfqAr-jf@UMC>2XzUD+oRl{ajlJ86?cJ_|@qbdX`ccCHR5GkEI)$%+~MJ z6duN1QXec`wo}izQ^3=v?y5-oGRtB!`DCWlh}<%VB;i+ogZS?Zo+OGq^~Eu-rWDKf zS*x*)cGlg?5(=^&&TVsRO!3|X&G{+Q@po! zSYAs$EZ{i4XN{{F?#YHPMR-QHi)+fbq5K=oM9ztoTA#4D4PPoiKj&>ke%o@-)8w}5 S)QhkFP{3n|F4fL~ng0X($aydT literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/CUp.png b/soh/assets/custom/textures/buttons/CUp.png index 6c0e29d2de653af5f5518cfd1c6a5d3b956b1e33..aca46472857d3db116e5042f097e2ab27bb7c723 100644 GIT binary patch delta 1138 zcmV-&1daRCSD6ZbiBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ zXd51X=m8!VEDC$*4Hf_Z02y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00QtyL_t(|+U?!VO&dV~1>iR}g)9vaxdNO@0tFa}3V;fb;sS6giBkb04P?8>1@Giw zU&2r10JhigebSyV7|m**-poof2><{90001!#~v?#Pb-E1`swyM&EOzklBCp(Ytm$S zwX27>?UHto{5U$x%!mm`c=w@LhPf!o$$$J>n1dLW^culfU;RZjCqKWwZXHu|1hx~5*J%dB{MzDIw%%lGj?jC(H*xrITHy$PJk*CZKkJUd5&B3l2}eLc3rAo*t^Ywd z0uPiP1XB@?!V!3^6OO_W`esp{-B+=0@uC0WP6$Wnm-}a1+txOLSuAWkAsnG+M(1fu zb{9@HnK^h%IKsY7tv4TzCEwfu;RyX~kCV)I(H?6uvzMcAgnqZjMNYLw;RrlzkIS`x z$JYd8U0wI-e{6}x5!~lW^d4V=G`KPf>CpX_the=(+r2XdBH(kZC7$C6on&vgpeF}$?+g* zRy%k%S#2CqlD3v*5L#CR000000001!xFK{I0DxZm1EaN`Nc^1!IRF3v07*qoM6N<$ Ef(ZEcVgLXD literal 11219 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 bZO&Y|BP(K(_C3BvKV^}Y))p1#T%!L4P5g(G literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadDown.png b/soh/assets/custom/textures/buttons/DPadDown.png new file mode 100644 index 0000000000000000000000000000000000000000..cec0af1e5575f8e0e6eebacd062afc96b8440f5d GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}gPR?K3xGnBC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uUs^mK6yskrs_#zw&=1BteW_OBGqIUd#GJ1DDb zdeial0l_shnq7C?2tKh;wsM};)$%*lih@A1hXg24ILUJSdTH#<;yM}k`>a>3XEHd* zFdh+n5H2o!CH?QR9p8P0?tlas3R!*}nw{Lb$FOO(a)Sj^2QEUPkKs|o)|)H}eSgG{ zx9@b2SsmadSvIFOibv_3n#I1%Sl lT5l@YiW%k=<>Tg(=UKIn$db;|#taD0e0szR&GfMyf literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadDownOutline.png b/soh/assets/custom/textures/buttons/DPadDownOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..e8dca39b69449bf33a532f091d6f9649b21d72fa GIT binary patch literal 984 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}&ApFzCIE#bOI#yLobz*YQ}ap~ zoQqNuOHxx5$}>wc6x=<11Hv2m#DVd>-qXb~q~g}w+Xpib8;GzySiY?}g>Sx**RE#P zea~{$)1;G<5{-`USAU+&Ti^6FoAVg1r6<(-Z$LXOsLi56>KTe%+j p`0Ui)D^cf{PT|*N#0=U4&hyXc8F6TrX&HhfJzf1=);T3K0RXK7P$&QZ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadLeft.png b/soh/assets/custom/textures/buttons/DPadLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..2a4a09b7983c12c9ad6888ecdc215309386175c3 GIT binary patch literal 929 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!iLYuM(m)}}64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSE`c)B=-RNQ)d6OYQU* z2g5Xu`aP1>lRIGeA&&9nnfYhtp9MK!NPq)w X)7&PfTBJQk1f;>!)z4*}Q$iB}bC4wB literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadLeftOutline.png b/soh/assets/custom/textures/buttons/DPadLeftOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..ba3dbf4e8a15d38b6f7407087d2bd118069aa753 GIT binary patch literal 953 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!F1GnUgMmVlC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uTx;OXKRQgQ3;t&O>d4Fp&(BtLPSU}n zGTnC*0v82tI=NHy#j#!nMnXMYuq?W41AH(&pFXa4W{ zuD`_xo>)x!{`cX;&m=m=T#)oydV5>@~Bz};iE)qM#?GHz*cOBqg0 y^vljYeWqK*!LlfR!u8Bqc1lT;K{<>FV6#}ds6*>{pk|&gNVTV{pUXO@geCytfi*V( literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadRight.png b/soh/assets/custom/textures/buttons/DPadRight.png new file mode 100644 index 0000000000000000000000000000000000000000..e7854a2192b6af2b3deae8700e4baa3f0f300fb5 GIT binary patch literal 922 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!CJvXvM4*sliEBiObAE1aYF-J0 zb5UwyNotBhd1gt5g1e`0KzJjcI555oJzX3_DsH{Ky;1OxfdI<^ac4!nqiZiT%P?<@ zWeH(gx?{4s!a+3_^-p<>TzWey|9S`lO&${9!UUzJZ@h;mNXy!~ADJ`rdgiQola{Hn z3w~(UQ~DKjYVoxyG4@k}*TN?R>219hC#2#2L(k)~@>z?ng!*HJF>hx5-!b{klJ1j& zQc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}bN4qb%s?T@64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSE;^mK6yskrs__Qu@91_G=Xk|#LYbcLVf6IpPs zOx;21&`gzkN1|L7aGRS=KG6E0t!n)g2GRXL9t5Va0Bsl&z(l2UL2c~ysphp+eH}Ze z6wO-pQYka)lOj{t4c8-fOTSDmw(DSi%JG$B(j~*^d#1CT608$na#i{450Qi4dLIAS zay{m~=e76$FMt1=7db84G_856@@+Go!!fo&eH!izPdVy8Ft<&+S$t<{9 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadUp.png b/soh/assets/custom/textures/buttons/DPadUp.png new file mode 100644 index 0000000000000000000000000000000000000000..8d70d96dad432d4f23185bb474e9f62bbb4faae9 GIT binary patch literal 968 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!)wO;{KyfTt;u=xnoS&PUnpeW$ zT$GwvlA5AWo>`Ki;O^-g5Z=fq4vg>lo-U3d6}R5r*;shULBQc+tTUsYW2wd@?M9^% zLuZ|@PMi*ltX@3fm?NQNoSbIxJx(Kb%fajCSi6803_j5CU#)k6>|+bQnLE2X9v*+} z?Glr<_IKqx|79%q!`v>k1)VZ8<`=wpcki#B4n5=TwfB#2(n-I}G&|W_`te8e^z60q zW*!|s44T;XHO!pNe(s$Q&ykIyhndr@A2Su^xPD)|u!QI$F6j2m(bnQsWMtcW`7KC;r>mdK II;Vst0Pem!Q2+n{ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/DPadUpOutline.png b/soh/assets/custom/textures/buttons/DPadUpOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..8ad2d7959750842c432eb01ab039b72047d1f8aa GIT binary patch literal 993 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcd!`D`cI9Y7(;64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSG!@N{tuskrs_&PLxO4gwArC4CsDB-|=U(R$dm z;j!?{rKS2)7*y6Bo~y%na<1|Oheuo9w?6Mx`yrQKAPBT#@PUHtOB}ZheJ{_L`Mg6y zzwVxL()z9Y*1Z0e=k;N!ag*7Z&o!scT<>_n-!G@M==_<>20R;cZ?|VQp53^#_v2gZ z^z60%W*!|ojGNf*HOxG3Z&7V#C~!Qi=lI(VQzk8)@@Ch&j|JPz^?*V#tnWWF{**b6Mw<&;$TX{Z1MH literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/InputViewerBackground.png b/soh/assets/custom/textures/buttons/InputViewerBackground.png new file mode 100644 index 0000000000000000000000000000000000000000..091d686c0006e444615a666f5e297103ff343b5e GIT binary patch literal 941 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcc}DJJ6^Wk4ax64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSG6c)B=-RNQ)d#gLIff#-n10X4RYfWyYjKU^62 zwz)X`-vH$=8 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/LBtn.png b/soh/assets/custom/textures/buttons/LBtn.png index 2e0a8f00c3b02c2b5d254311bfda6a703f13efa7..351ea383a7d97df9eb27444e5bf5d6a4dd18b64b 100644 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUHTkS#KzRnq64!_l=ltB<)VvY~ z=c3falGGH1^30M91$R&1fbd2>abSGk^K@|xskrs__C?>r1`@3o@4r(hY3_57SfVtS zrBujAErIzIo2(*F&}?=A{tph)OG3Dw>j=DDU6tzX$pW+k6Z{F>b*=gLzWD1=@1wJ0 zy;gn>u8~w$3i4{7a%tZbBQK`^DKgt{=gtqRn(}|mLY>0~Z#xsG z=e+mQWLHf%_W$l3{xw^z471pdef+)BQ0dyH_?*8t`63=!%=1$}Z1ML?#cC#<5}9Bx z^GW`fqpE`$#jN@)pNF4Z9=SG*T{L0gV+r~7%X&7&-#h!eZ^MH^ouxgN&*#1opTEPj zd1rohvHgb%o4(m+)sz-Z{$IX!>s0h!~u;e$N`HuDdzk8suV6S3j3^P6 literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijK0(?STo12?guU_r!>}+jqU0+|neEIV7^78rf=jZ3=o12?YpFUk*Uq3rL zJ2^QyIyxGt>C%_@*FZ|3B*-uLKPq5&pd2d+l;bS$h%9Dc;5!V$jK}j=qyPmMc)B=- zSom+fd|RklfyXtFOXQ-{&;R>#g`8&j9e(g-Q@qRhOXjiBU#uT2(@kS4**imU#(CKl zH>=Mt7u>fdj^FHoaY~cK`kK%F3Xhlt9!se(G~ZCj6!_(+w4syZAe)lUgwNMl1sHCe z({_0vu5QZ$*1w7wbzHiqGTQH}%=ug0MN4vl2 ezQ4t`d}Ac-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUB?)$>ETE8NiEBiObAE1aYF-J0 zb5UwyNotBhd1gt5g1e`0KzJjcI0FNdgr|#RNX4zUx8HW&F%V%5@C^2t!?mo%qP61D z%9NX4i%#$^Y4)+2AvDKH=k5H|#62y4nb_wPO9{j*JYLJz4zvXekQe!X_26TRvaQ$h z*KV~tc4K#!dNGIM5ea?6W54Ho))D&Q-}cymC%Nb2?jP}{8pWDV<3u)merVB`9H0GH z_1AT8&Dyh;@hXhc`*yG8U$Zr<$B6mt$EDY9L|OY^o)UXB*zN8noxi^}H-F=>&g(n9 zslB^S?J+^%Az-37WioX zjpIF?C((A%^v=4g%P+rNx3z5Y>4yayf(}nh&3oPc|Hs+DL&UjN*C0 zUg;b6?<_pcV^((K*MZkxt>pWU3pl+v`hU~4TR>&OLK_}$t=gNk{o1>%wR7*Y&tHF0 pv1LxsuZQ0qu>{S~5PDE6$FOoz^>L1~oSq;Td%F6$taD0e0svfcg;oFn literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RBtn.png b/soh/assets/custom/textures/buttons/RBtn.png index c255643c35893d1e10a5c7056459a364ff8d9a16..ecb96bd6c10fe4736841b2ced7f1f0f404adc657 100644 GIT binary patch literal 992 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUA-j7<$AChTC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uUc?&;zfQgQ3;?T5b24h*ah?rr1{-q7?`K_Tw} z+cD2BgN_}IiA*vrarLvqfuw7i+N=^5Ecta}*$Y|qnDFagcgI(Tt$kZ4(boKwW2Sc3Bh95IUXT8D sT`X#muCV*Dc+Gr%CQJ_u4Us?f>1VD46sEmde;?#vPgg&ebxsLQ0Izjb6951J literal 379 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijK0(?STo12?guU_r!>}+jqy?pud`ucivbMx}@a(#XM`Sa)J=jTtKK0P}- zJ2^QyIyxGtsej3mM?gxTB*-uLKPq5&pd2d+l;bS$h%9Dc;5!V$jK}j=qyPnXc)B=- zSop7B*A@50-GH zDcompl@4(gy|8%e83*+lrxFaG%}#jA`GU1rP=}*uqU1!qz5^>dH<%ID@VQJw{43z!zQ13&09ha znEf=GaFs_#aPg*lza3l(Ok7<5=~>MCuOr$1M{3Sc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdU-p$wSje$avC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;tUK-oSrU@Ar-gY-ac4(+kuC{p~*{eje~BBUdxxI z%_R#0RnwL@Eh?E1$m*jg^68{=+LIoWx~F@7KmOYw-Nf*GT_(^POz>c?6W4?L#|rPH zrpXKL&Dmp={!B)2`Qe8f!et&dYb-4}y=jj|*LTrV+j8eG%bb6Z|-X>xq4yH%$w_XDYX`+&RS-v^zHS#jkEZd=(g=H2`UJW6LDX$ zr+7~I`SVMs#HGdcUp>9)P1xMWA>K9rEDz=0pSA4e`mW@YXN>w5pZQa`GiFvt#QMK0 zRPCP2JmfuWP*XnT`NF*4B{p*Nd#(oTJe&4e)!5(Y<43N==LFw9`1N4+s(p4Gm|-zA cL_Ylg&8sL=9ea7Qa}mhJp00i_>zopr0ED!F1^@s6 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RightStick.png b/soh/assets/custom/textures/buttons/RightStick.png new file mode 100644 index 0000000000000000000000000000000000000000..6b8490aafd7e750ab8e46ff435a3f2196d94e6a6 GIT binary patch literal 2150 zcmd5+{X5g^A0K6kZ^v21iVyl8=QxBAWkOR7n};0oIP3*Zs^&e5IY)5cun!8ZM18;n1TrJ+?A+0IcE@7LBtk@V7zCo1dnMP#smJ|r z<^@kw?sX?ChTf$rH#K`E0;9?d{_~-#e}W0^jkbA&lScrcF#c->lIf)g565W+D4ct* z*gM&c9!6n0jP)NfK0KMf!lnwOom-GUe+l7Cp4wk^C+z;5scA7*l^!VV(SyS5FNRi@ zIvEpY{em{eTod3@zv(Nf-n>67j?Ny+TDnd2?bYZtD=y^I$`HMnKhCGPS%vfnLLK9()SWOG*rf{r|kGKi=j zRX+zfJ005(I~l2WPhJ@|b;`r#{%h-3QtiZTG&Z{a1KyGSpm)7~+E+yy5 zo8H}e+Jfv$E5+UQYn83yMZ{9bPWUV)YOCfz@Ta`>WUR8b+#XTa(*$hZM%tie@N4v~ ze+}erKfHEcE(v*$^jxkRdzUm+f_)1-P_g}uz)jf$0P^#w=YbnZRML`oM;0-(s@SeX z?(NXYp@F1cgP{`*!6NT&w+Y=Tn;f;mI*7Ov6&vw*oB= zA(T3vKfhB0b#CBSFE6vew*Ply*2{TEq08CQ+WJPm$NhDKWHLWDo;5h=EZw)g0cdKX z__W0+GT&4^`9`AKjlo!*y&pa-MR$? zzUB3DhM)|o>^PgS{4trkCx%M3fM#?*A3p%ic+}Zhr_3FIg1yj=vD&!{vXy$}=l+*>TaAq3pvynU&huuo!Xt&x4oEA7?Rse}NT} zFFf!p(0QK>06?#(l{5~WGZeddVzdb%zWs=$6dU#IvtB7LJ=}LTKj5R7=1*Xk?=N3l zA#aISH>^hAtT!+w=yN9X<$9k40zp4hrEtm86B8E~*Hpl3UaW!M@ogQg5Xn|tAB?UF z_VqCse9D=xQ*S?>txf)=gmyu?FB;b>!W}J?5UIu$>mPGlgO=EemP=oyvA3_6C*6vl zzR9==i^Hkrz~ZK4i5ptVukt+>O(Sa3;apB#33p_s#(#mm*8e$l5Kma$RUcf-<8ddv z9(*4&|4^$y$9-^MV1S&!ZL~dEj5qWt$dJZv5^*LD_Uy8EqM6!AjN+T%1J+o6mjPd>Zr>-7`gIQHLQnor=i-q3DIAy!)1{isSp zOwD4DxwJ3OCa_?X%i)`fB@$e%x>d#O_9puS!6@;w*_pMcMV}{_vaiF#xv_f#y@e+V zGCN0BoiE_Vi}1CFa#V%$TO$)qb>F07psA%*uUt+RBBsYCESHKsoL1|UdN_DhRu}VP zwklS^s$zVXl+lxF(E4&M$l>1bNK?%65A7f;083SF9g9#y#WhzqiDaLWT*LH%^xe|G zrqLUE`UeRoU%XLY?C+uumbY;AAHwk?u|gH0GB zk!Wg-A@XOySX~aspS_{@TfN};OTFsigDiVD1f!&+#2=pe%o2Gm1QQ{n zlljAu-2b{z;5!mXy2GjJy=5K|N{+MIvW0~ob@R~TnHh`7Vx6n9`RTqwThQI+IRp6~ z0RaIWckpVUNc3)JBrA~q$JT>KcT{Hk3r`<=cQW)_5RG!PuRkCB>p%IZ B&b|Nu literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/RightStickOutline.png b/soh/assets/custom/textures/buttons/RightStickOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..8fbd54fcc36d766bfb97b99365685f88426c4dbf GIT binary patch literal 2407 zcmd5-`9IWKAD@w>lDd<%jOC$Qw!%ebA}S{9*vAstmvHZxX6$Pc4MIZ1kbPf5LqZ4@ zGAd1@8M2IK40mR(D?8(Ud!FaF=O1{^>vhiSyxyPJ=X}=l{-oMinTQ-ceG~)&iI|xh z+krq}6X4!*SP(eT%1{jeNDeeIvN1CKv&p^s8LZ)GTrpk8z(LR1$<3J9t-@n5z5Fxp-`T zMuthwyL^jFaO``edumQJm05sx9+Do?Dtb(cdI}pde{?O@O5f{)K&o8Vh3>sKT}#jU zwT!Nx)v<;uNTkcCMQEs=Qn{TAYpgx}UDzdGoa9O%n`aO?BOX%kf>i^XCr@96TA0co zf&3PvRKX_9 zaHL^H$S8QgwKQbB*mVV3bK**hKQZ`;&5!ziFG zg5DM;#-J)t4yfRYK*x0eIf5~D!GS=+qCYnnR7j8lK%r1GBtmEjEGwxh-c|Pa3;>-9 zML35Vh5Ye{A379dg!S_Z_4AdF2n@X?Z(@eDaY{Tc38)#E8DDjXq_SrW@lcA4&|kB( z%f2#%exyb%4&!CxrK`fPLU?l)oQQn%27I5!TUZFMqSrUv`=a(v!zKn*a|8Bu1 z9~pu%c3&tI4{PNxJM&^Zo`8FTyAU$_YM+SVkHQ@Dq22WqCo6_n%?9w# z7j<<#wmIG0OOTId%Dv$axr+q3&KphGz`(kms5OS}Ysl8erSR^Ms$56Kg(St2Wi$#I ze*v0!U=bV~tbSfyy(RN4-O8MW^;xR?A+N9cWZJaM)}S&UDvW6NaDE zBdv?>(L9}T2~`zYR>o3N5QH<^l+x6L@)&tRiT*kYR1s!mAx`!=jg5_o*;SoCOfc(p z=T71yW1jkFVM*UdN6ov4#Pz4uDXy-r>Rb-T%CSwIjr%sSv(M9e4T0gr>5=-pwz82~ zh4Mc)cM}d0nFoHPt{fb1yys$*g9`qTQLwL*DgHR+&`=jr34m@??~ zev5>IGnLX56cjo-I}KCu)-Pu`4X9tgrsC7rHI0YvtC-ALI=i~Yu=cjs4l?V4AHbQj z;)qpBG!5NJlfv&N`?B4*HMzXs!j@R=0Tc1zZt2?R4}#`29_Qz;q^nym54>n?g#ZzK z7?6Tw+oid;NJ>jft3z9MA_0|aI*)z+1x*}u3@@gZwYi_qyk3E@oT;F!AnZNpt1lFx ziS`tB_-q<}jQC9L#H9=p+=K+**^dXZ^$spqIq@V8g<^aUvJ_?(Dq=hVD-)XQix%dr zZzK{afv_M*e}9XzW5&7R9K+c%gwSkcl(^+d^O%U+*)4k<&y<= zDm66&?bljoxm@W75J)F_rqC7ng>>_a0k8CQ5r*ID8wS?sF&pDBgVkE0&L!3lyMSH9 zhTq>I{IH$T+rG8a9+V^ul&@!J!DN5OW5z4#HuaO;+W9H19f{2Tk(KanF1bTSx~Z`- z7m1?VT2@bKy@5a=sM(4-)_yRh#UsH9#&@os>g-J|Wx22_95N=saBK2rsl+?sCfQ`g z54Ymt_Sb9Kb2Hji20`Sh&}J6xp8tdS8#<1FRa3Ha-e~YZ|P^DiTm~KJBl$GMVF7=A531q9Qrs=rq1T$sSR#$>4ljGfjCbsHpRWf}FwCZP_GRLCiOa28>irU3@{^&>rznzKCm(Sj z#De&gmu)YBX2lwzA{Gq-ihWKFp=Q^W*FCfQTwr{=)URK+Va&bAWt*6Yh)z+>7(^6= zOmD6GR+E95~M(hQ8~nZ|hM{lt<&eSY_&zzvY~K@&pceGa8#jO_STBD5V#w{z@U5tIn5sOp_k{oB z>P?cR`p)~vlpVBAM{=7e3{z0gY0CX%7&NfHHqzi+6uwq+{AIaPNndl=$?{!d%T9t$ z)sG1(vrj2)0hgzU2} (r4~HbCfY?S!AFdw%3n*yd|bwbx6pkw`FvYe)u}zqJcIq zVwIlUf64TUta0~D331(JAI|-ID!wK`2O|{|6O)9GycD+N-ARi}um!`TxR!C^JJ^l?is`CT%L{I-Wi2a0uJ6KcnUHh>60=zKdt=3cc98$*^wfphZ>G- z-6%E$eq$LxG!OnwG_qNJ1Zg$p84KmS97&9fV_3S)IrmtB;JD}m#>U2m6F?aD(Y@bl zAgdb&&^1S2@p+Z&bfIT(J4`j@t`Itm7`g*py{AoMm&uHt8xF>h!TD!e zvRQh>2zOmnYL;TTegwxY3Yx_a^kyR}hl?UF65&WrP3~xMadFnfXhE_f#``~W0O?q% n$aG^6#t@u2k^dQ4YSaX9!QkZTc|kSuPoWvY%DDNO=iPq*Z-H#} literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/StartBtn.png b/soh/assets/custom/textures/buttons/StartBtn.png index c3e08dc3600853304c65a79b2ba937d297c03c78..ec85f261957998dde16f4ebda829b14c68527681 100644 GIT binary patch delta 786 zcmV+t1MU3WT+Ii6iBL{Q4GJ0x0000DNk~Le0003;000252nGNE0B$K9FaQ7ng=s@W zP)S2WAaHVTW@&6?001bFeUUv#!%!53Pg6yaiby+%C}gNk7DS6UN)?M>p|llRbufA9 zA2ex5Qd}Gb*MfsTi&X~~XI&j!1wrr!#M!|~(M3wUFDbNti1EVXeVljC;l29+p;2L~ z*)<8Mnq{QoF)^E46?M=HVZ9 z{7G`jl~*K zK!#?ud;=UD0^>!>UiWx+Z|B_p?P<;L2fGS##JnSrc>n+a24YJ`L;$4#lK_}N1-3?$ z@f{w2=m8!VDm3iVw>tm;02y>eSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{ z00E>)L_t(|+U?xIZNe}ZhT)G+;!T=OI!Z=?O#+jIP0S&w6sbss)(0zj9_hdO@E=~; z2uJ_`0000000000000000001h#mNe2ttKUZ$ybtLo%?2Pr{rQwz@eg8ld&fCmlCbP`}dk*9DhcJH6*#-g6>F48lO?N)5fPebz6dP;pT`qvO6upR;&?m1aU+hIe>eEGcMMMII=g_P67+!NLOy1oB`06nw)(J9N=dm z9E+b10<;OFKb`;%70A(38sK>(hxK#FX>&`Q)^HXZ0+T@^WRp-LQ5W9u0E?Lpn2Z4b Q$N&HU07*qoM6N<$f@-Zr?*IS* literal 11868 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 diff --git a/soh/assets/custom/textures/buttons/StartBtnOutline.png b/soh/assets/custom/textures/buttons/StartBtnOutline.png new file mode 100644 index 0000000000000000000000000000000000000000..a7902edbdafeb8bdc1a440f700e08cdc06664c32 GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdU{j_a$*MUNkC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uU6=jq}YQgQ3;orAf}1|n<^+|@s79BBhvF<;eRAVlf z9?G!{4dryYM1N>;I65$bu{77){C=pUQQ l={zhm$FmjHw?l;2AiJ(G!GtHH+Tk3?#h$KyF6*2UngC=DT%rH~ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/buttons/ZBtn.png b/soh/assets/custom/textures/buttons/ZBtn.png index def8d9a6da2fcab6486b6106064d9fcd11dd47ba..4fee52d5762f0763b5fb1a5059937b35c1796370 100644 GIT binary patch literal 1005 zcmeAS@N?(olHy`uVBq!ia0y~yU~~tv*K@D|$vjON1E4@_rn7T^r?ay{K~a8MW=<*t zgT}<#iMAex14LT=gIyc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUnVV_y2Z2J8C9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;=uSm;_2cTQgQ3;?Tfz60TOKw|Fyf$SfG7_kLeLx zUc#Iu9L*8t26GwM8!u;X_3aW@lbip%@AmX(k0(qy3raL3fFGNknm%pG{XM1lp6e06 zUjJotK8pw*Pn4MV^nk@b;n?d}KikOnJj!*R8FcG=t-a?#RnMj(iDRL!D(CSV75J(; zO3qsLQt44(r|5cL!LMbz|60uTd!O~-NyMvOpO=2EvvuOvy;nVGA*S>EP3bT8{XaWa z0C|VXj|o1G_;Io@C~-@5g!SqRH9S`#-I*%9TG}ct^W& za`MAftEx^|%1<@uv9K&^JkP%V(@zBw{5TLw53ILlJ`@#Lc&OqQJIH=dS3j3^P64z!-JE+(X)vKtE{9js;Vf8EX$%O3WC7%d^Ve9S=K|x zSrm&?(;VtXPt{sVp(e={K?-@n<#>zDYBVELR4$!iNs=OZji^&AwW>iQ@@gd~4(y6= zm0csWb>C7wv*74*QIpJqpvyT;;%lK5d0J=}JX0!aIYZ%8k(G0_A6Sm77j4zB6ipWu zH76;YAY~EV`9vRg<-M41`AlqNN;2VcfRhP!yBNpl`)HadNysn=umHFNFa{U^^Z?ob z4S*P+3=jag07U=;U^c^kADc~#B6MBUG!%ryJc&S(i9o_ms0l9wumLojPjKADevEA& z>jp+52K2s5&7JhLm>!$tKqvN8=qS*V0db7jMvM?`Laox7yY_tk=gIf%qo)9#`0M?v`Zx4T z><_y)E_`?O1>!Oi7k7B}p>t2ay!`d*t>=6=f9%hd^)>U;o%pVAmmWTUJM}lvza;hA z(cv38M|?_9rj`P~oKp8a)c Yb??E?_CD!fN=}5$jjjCd`nlKt0Xc-g^`>U~ z?of8|^jO&#R>u$QM{XYUyy)t+M_+SG$HzmDYv+`of4KKI!@|JCRX0sJSIkOX^2pF| zcC=`9+{42fY=SN!Nz3MW=%+o1jQ@Vcw^aOLF(FB_9ZPKA({naYXuv@$6~m zD(71q@tWjR<7bn2fwfb9r{3;A$9BHhaKPBvP0iF_MoFw&R;S!RTT-iVip820Qct-f zr;DD8o^#c!ck8>8@e(JpwKLaUmU5Kw_E6vyG|JLg%)~8t%QVPm$qSoj59Q1Lcov;} zqSZVxnK5+51R47u@_**7jhr#BXfl)Gg5O8C*&l0|7rP*G``h=)xAW#P{7Zk}mHm4) zZ^F09U#gQL70(Y)*K0-AbW|YuPgftMmcdUalb9cJb^-zC9V-A&iT2ysd*&~ z&PAz-C8;S2<(VZJ3hti10pX2&;tUK-ES@foAr-gY-aeRn+d+W!f~;2S3Z|_By96%H z=DXCm!0U`htIJD;09GHx)hAUQQk>Yle|N`m{twA*5!0A}_K*PnYl#1+{tJ+g%{!P*f>fr_&ELa%f*FVY8vQ8)N*Y~GN>Qf${Qa@h# z@lQa5*0#WDT)OQ-x>CX=0Ztx!hw^YO1$x`G>Rek)48D?DH5 z+Lrj^oz{8h%in&MSlN0qWq&=DYc^YdX63Y&q$5vG$kxf%Ouo;~NJ97wgwlUI?=RX~ U9s92IvpL9mPgg&ebxsLQ0BZnzNB{r; literal 0 HcmV?d00001 diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp new file mode 100644 index 000000000..6b25589c6 --- /dev/null +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -0,0 +1,519 @@ +#include "InputViewer.h" + +#include "public/bridge/consolevariablebridge.h" +#include "libultraship/libultra/controller.h" +#include "Context.h" +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include +#include +#include + +#include "../../UIWidgets.hpp" + +// Text colors +static ImVec4 textColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); +static ImVec4 range1Color = ImVec4(1.0f, 0.7f, 0, 1.0f); +static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f); + +static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed", + "Shown Only While Pressed", "Always Hidden" }; + +static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" }; + +static Color_RGBA8 vec2Color(ImVec4 vec) { + Color_RGBA8 color; + color.r = vec.x * 255.0; + color.g = vec.y * 255.0; + color.b = vec.z * 255.0; + color.a = vec.w * 255.0; + return color; +} + +static ImVec4 color2Vec(Color_RGBA8 color) { + return ImVec4(color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0); +} + +InputViewer::~InputViewer() { + SPDLOG_TRACE("destruct input viewer"); +} + +void InputViewer::RenderButton(std::string btnTexture, std::string btnOutlineTexture, int state, ImVec2 size, + int outlineMode) { + const ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SetNextItemAllowOverlap(); + // Render Outline based on settings + if (outlineMode == BUTTON_OUTLINE_ALWAYS_SHOWN || (outlineMode == BUTTON_OUTLINE_NOT_PRESSED && !state) || + (outlineMode == BUTTON_OUTLINE_PRESSED && state)) { + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnOutlineTexture), size, + ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + // Render button if pressed + if (state) { + ImGui::SetCursorPos(pos); + ImGui::SetNextItemAllowOverlap(); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(btnTexture), size, + ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } +} + +void InputViewer::DrawElement() { + if (CVarGetInteger("gOpenWindows.InputViewer", 0)) { + static bool sButtonTexturesLoaded = false; + if (!sButtonTexturesLoaded) { + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage( + "Input-Viewer-Background", "textures/buttons/InputViewerBackground.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn", "textures/buttons/ABtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn", "textures/buttons/BBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn", "textures/buttons/LBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn", "textures/buttons/RBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn", "textures/buttons/ZBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn", + "textures/buttons/StartBtn.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left", "textures/buttons/CLeft.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right", "textures/buttons/CRight.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up", "textures/buttons/CUp.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down", "textures/buttons/CDown.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick", + "textures/buttons/AnalogStick.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left", + "textures/buttons/DPadLeft.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right", + "textures/buttons/DPadRight.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", + "textures/buttons/DPadDown.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", + "textures/buttons/RightStick.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", + "textures/buttons/ABtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("B-Btn Outline", + "textures/buttons/BBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("L-Btn Outline", + "textures/buttons/LBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("R-Btn Outline", + "textures/buttons/RBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Z-Btn Outline", + "textures/buttons/ZBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Start-Btn Outline", + "textures/buttons/StartBtnOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Left Outline", + "textures/buttons/CLeftOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Right Outline", + "textures/buttons/CRightOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Up Outline", + "textures/buttons/CUpOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("C-Down Outline", + "textures/buttons/CDownOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Analog-Stick Outline", + "textures/buttons/AnalogStickOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Left Outline", + "textures/buttons/DPadLeftOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Right Outline", + "textures/buttons/DPadRightOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up Outline", + "textures/buttons/DPadUpOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", + "textures/buttons/DPadDownOutline.png"); + LUS::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", + "textures/buttons/RightStickOutline.png"); + sButtonTexturesLoaded = true; + } + + ImVec2 mainPos = ImGui::GetWindowPos(); + ImVec2 size = ImGui::GetContentRegionAvail(); + +#ifdef __WIIU__ + const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f) * 2.0f; +#else + const float scale = CVarGetFloat("gInputViewer.Scale", 1.0f); +#endif + const int showAnalogAngles = CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0); + const int buttonOutlineMode = CVarGetInteger("gInputViewer.ButtonOutlineMode", BUTTON_OUTLINE_NOT_PRESSED); + + ImVec2 bgSize = LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); + ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); + + ImGui::SetNextWindowSize(ImVec2( + scaledBGSize.x + 20, + scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f) + 20)); + ImGui::SetNextWindowContentSize( + ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * + CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f))); + ImGui::SetNextWindowPos( + ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), + ImGuiCond_FirstUseEver); + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); + + OSContPad* pads = LUS::Context::GetInstance()->GetControlDeck()->GetPads(); + + ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoFocusOnAppearing; + + if (!CVarGetInteger("gInputViewer.EnableDragging", 1)) { + windowFlags |= ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove; + } + + if (pads != nullptr && ImGui::Begin("Input Viewer", nullptr, windowFlags)) { + ImGui::SetCursorPos(ImVec2(10, 10)); + const ImVec2 aPos = ImGui::GetCursorPos(); + + if (CVarGetInteger("gInputViewer.ShowBackground", 1)) { + ImGui::SetNextItemAllowOverlap(); + // Background + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Input-Viewer-Background"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // A/B + if (CVarGetInteger("gInputViewer.BBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.ABtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode); + } + + // C buttons + if (CVarGetInteger("gInputViewer.CUp", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CLeft", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CRight", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, + buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.CDown", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode); + } + + // L/R/Z + if (CVarGetInteger("gInputViewer.LBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.RBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode); + } + if (CVarGetInteger("gInputViewer.ZBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode); + } + + // Start + if (CVarGetInteger("gInputViewer.StartBtn", 1)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, + buttonOutlineMode); + } + + // Dpad + if (CVarGetInteger("gInputViewer.Dpad", 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, + buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, + buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode); + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, + buttonOutlineMode); + } + + const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; + const bool rightStickIsInDeadzone = !pads[0].right_stick_x && !pads[0].right_stick_y; + + // Analog Stick + const int analogOutlineMode = + CVarGetInteger("gInputViewer.AnalogStick.OutlineMode", STICK_MODE_ALWAYS_SHOWN); + const float maxStickDistance = CVarGetInteger("gInputViewer.AnalogStick.Movement", 12); + if (analogOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (analogOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick Outline"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + const int analogStickMode = + CVarGetInteger("gInputViewer.AnalogStick.VisibilityMode", STICK_MODE_ALWAYS_SHOWN); + if (analogStickMode == STICK_MODE_ALWAYS_SHOWN || + (analogStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !analogStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxStickDistance * ((float)(pads[0].stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxStickDistance * ((float)(pads[0].stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Analog-Stick"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // Right Stick + const float maxRightStickDistance = CVarGetInteger("gInputViewer.RightStick.Movement", 7); + const int rightOutlineMode = + CVarGetInteger("gInputViewer.RightStick.OutlineMode", STICK_MODE_ALWAYS_HIDDEN); + if (rightOutlineMode == STICK_MODE_ALWAYS_SHOWN || + (rightOutlineMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + ImGui::Image( + LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick Outline"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + const int rightStickMode = + CVarGetInteger("gInputViewer.RightStick.VisibilityMode", STICK_MODE_ALWAYS_HIDDEN); + if (rightStickMode == STICK_MODE_ALWAYS_SHOWN || + (rightStickMode == STICK_MODE_HIDDEN_IN_DEADZONE && !rightStickIsInDeadzone)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos( + ImVec2(aPos.x + maxRightStickDistance * ((float)(pads[0].right_stick_x) / MAX_AXIS_RANGE) * scale, + aPos.y - maxRightStickDistance * ((float)(pads[0].right_stick_y) / MAX_AXIS_RANGE) * scale)); + ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("Right-Stick"), + scaledBGSize, ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, 255)); + } + + // Analog stick angle text + if (showAnalogAngles) { + ImGui::SetCursorPos(ImVec2(aPos.x + 10 + CVarGetInteger("gInputViewer.AnalogAngles.Offset", 0) * scale, + scaledBGSize.y + aPos.y + 10)); + // Scale font with input viewer scale + float oldFontScale = ImGui::GetFont()->Scale; + ImGui::GetFont()->Scale *= scale * CVarGetFloat("gInputViewer.AnalogAngles.Scale", 1.0f); + ImGui::PushFont(ImGui::GetFont()); + + // Calculate polar R coordinate from X and Y angles, squared to avoid sqrt + const float rSquared = pads[0].stick_x * pads[0].stick_x + pads[0].stick_y * pads[0].stick_y; + + // ESS range + const int range1Min = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Min", 8); + const int range1Max = CVarGetInteger("gInputViewer.AnalogAngles.Range1.Max", 27); + // Walking speed range + const int range2Min = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Min", 27); + const int range2Max = CVarGetInteger("gInputViewer.AnalogAngles.Range2.Max", 62); + + // Push color based on angle ranges + if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0) && + (rSquared >= (range1Min * range1Min)) && (rSquared < (range1Max * range1Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, + color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)))); + } else if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0) && + (rSquared >= (range2Min * range2Min)) && (rSquared < (range2Max * range2Max))) { + ImGui::PushStyleColor( + ImGuiCol_Text, + color2Vec(CVarGetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)))); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, color2Vec(CVarGetColor("gInputViewer.AnalogAngles.TextColor", + vec2Color(textColor)))); + } + + // Render text + ImGui::Text("X: %-3d Y: %-3d", pads[0].stick_x, pads[0].stick_y); + // Restore original color + ImGui::PopStyleColor(); + // Restore original font scale + ImGui::GetFont()->Scale = oldFontScale; + ImGui::PopFont(); + } + + ImGui::End(); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + } +} + +InputViewerSettingsWindow::~InputViewerSettingsWindow() { + SPDLOG_TRACE("destruct input viewer settings window"); +} + +void InputViewerSettingsWindow::DrawElement() { + ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver); + + if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) { + + // gInputViewer.Scale + UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", "gInputViewer.Scale", 0.1f, 5.0f, "", + 1.0f, false, true); + UIWidgets::Tooltip("Sets the on screen size of the input viewer"); + + // gInputViewer.EnableDragging + UIWidgets::EnhancementCheckbox("Enable Dragging", "gInputViewer.EnableDragging", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(true, true); + + // gInputViewer.ShowBackground + UIWidgets::EnhancementCheckbox("Show Background Layer", "gInputViewer.ShowBackground", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(true, true); + + if (ImGui::CollapsingHeader("Buttons")) { + // gInputViewer.ABtn + UIWidgets::EnhancementCheckbox("Show A-Button Layers", "gInputViewer.ABtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.BBtn + UIWidgets::EnhancementCheckbox("Show B-Button Layers", "gInputViewer.BBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CUp + UIWidgets::EnhancementCheckbox("Show C-Up Layers", "gInputViewer.CUp", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CRight + UIWidgets::EnhancementCheckbox("Show C-Right Layers", "gInputViewer.CRight", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CDown + UIWidgets::EnhancementCheckbox("Show C-Down Layers", "gInputViewer.CDown", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.CLeft + UIWidgets::EnhancementCheckbox("Show C-Left Layers", "gInputViewer.CLeft", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.LBtn + UIWidgets::EnhancementCheckbox("Show L-Button Layers", "gInputViewer.LBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.RBtn + UIWidgets::EnhancementCheckbox("Show R-Button Layers", "gInputViewer.RBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.ZBtn + UIWidgets::EnhancementCheckbox("Show Z-Button Layers", "gInputViewer.ZBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.StartBtn + UIWidgets::EnhancementCheckbox("Show Start Button Layers", "gInputViewer.StartBtn", false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + // gInputViewer.Dpad + UIWidgets::EnhancementCheckbox("Show D-Pad Layers", "gInputViewer.Dpad", false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + + // gInputViewer.ButtonOutlineMode + UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.ButtonOutlineMode", buttonOutlineOptions, + BUTTON_OUTLINE_NOT_PRESSED); + UIWidgets::Tooltip( + "Sets the desired visibility behavior for the button outline/background layers. Useful for " + "custom input viewers."); + + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Analog Stick")) { + // gInputViewer.AnalogStick.VisibilityMode + UIWidgets::PaddedText("Analog Stick Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.VisibilityMode", stickModeOptions, + STICK_MODE_ALWAYS_SHOWN); + UIWidgets::Tooltip( + "Determines the conditions under which the moving layer of the analog stick texture is visible."); + + // gInputViewer.AnalogStick.OutlineMode + UIWidgets::PaddedText("Analog Stick Outline/Background Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.AnalogStick.OutlineMode", stickModeOptions, + STICK_MODE_ALWAYS_SHOWN); + UIWidgets::Tooltip( + "Determines the conditions under which the analog stick outline/background texture is visible."); + + // gInputViewer.AnalogStick.Movement + UIWidgets::EnhancementSliderInt("Analog Stick Movement: %dpx", "##AnalogMovement", + "gInputViewer.AnalogStick.Movement", 0, 200, "", 12, true); + UIWidgets::Tooltip( + "Sets the distance to move the analog stick in the input viewer. Useful for custom input viewers."); + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Additional (\"Right\") Stick")) { + // gInputViewer.RightStick.VisibilityMode + UIWidgets::PaddedText("Right Stick Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.RightStick.VisibilityMode", stickModeOptions, + STICK_MODE_HIDDEN_IN_DEADZONE); + UIWidgets::Tooltip( + "Determines the conditions under which the moving layer of the right stick texture is visible."); + + // gInputViewer.RightStick.OutlineMode + UIWidgets::PaddedText("Right Stick Outline/Background Visibility", true, false); + UIWidgets::EnhancementCombobox("gInputViewer.RightStick.OutlineMode", stickModeOptions, + STICK_MODE_HIDDEN_IN_DEADZONE); + UIWidgets::Tooltip( + "Determines the conditions under which the right stick outline/background texture is visible."); + + // gInputViewer.RightStick.Movement + UIWidgets::EnhancementSliderInt("Right Stick Movement: %dpx", "##RightMovement", + "gInputViewer.RightStick.Movement", 0, 200, "", 7, true); + UIWidgets::Tooltip( + "Sets the distance to move the right stick in the input viewer. Useful for custom input viewers."); + UIWidgets::PaddedSeparator(true, true); + } + + if (ImGui::CollapsingHeader("Analog Angle Values")) { + // gAnalogAngles + UIWidgets::EnhancementCheckbox("Show Analog Stick Angle Values", "gInputViewer.AnalogAngles.Enabled"); + UIWidgets::Tooltip("Displays analog stick angle values in the input viewer"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Enabled", 0)) { + // gInputViewer.AnalogAngles.TextColor + if (ImGui::ColorEdit4("Text Color", (float*)&textColor)) { + CVarSetColor("gInputViewer.AnalogAngles.TextColor", vec2Color(textColor)); + } + // gAnalogAngleScale + UIWidgets::EnhancementSliderFloat("Angle Text Scale: %.2f%%", "##AnalogAngleScale", + "gInputViewer.AnalogAngles.Scale", 0.1f, 5.0f, "", 1.0f, true, true); + // gInputViewer.AnalogAngles.Offset + UIWidgets::EnhancementSliderInt("Angle Text Offset: %dpx", "##AnalogAngleOffset", + "gInputViewer.AnalogAngles.Offset", 0, 400, "", 0, true); + UIWidgets::PaddedSeparator(true, true); + // gInputViewer.AnalogAngles.Range1.Enabled + UIWidgets::EnhancementCheckbox("Highlight ESS Position", "gInputViewer.AnalogAngles.Range1.Enabled"); + UIWidgets::Tooltip( + "Highlights the angle value text when the analog stick is in ESS position (on flat ground)"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Range1.Enabled", 0)) { + // gInputViewer.AnalogAngles.Range1.Color + if (ImGui::ColorEdit4("ESS Color", (float*)&range1Color)) { + CVarSetColor("gInputViewer.AnalogAngles.Range1.Color", vec2Color(range1Color)); + } + } + + UIWidgets::PaddedSeparator(true, true); + // gInputViewer.AnalogAngles.Range2.Enabled + UIWidgets::EnhancementCheckbox("Highlight Walking Speed Angles", + "gInputViewer.AnalogAngles.Range2.Enabled"); + UIWidgets::Tooltip("Highlights the angle value text when the analog stick is at an angle that would " + "produce a walking speed (on flat ground)\n\n" + "Useful for 1.0 Empty Jumpslash Quick Put Away"); + if (CVarGetInteger("gInputViewer.AnalogAngles.Range2.Enabled", 0)) { + // gInputViewer.AnalogAngles.Range2.Color + if (ImGui::ColorEdit4("Walking Speed Color", (float*)&range2Color)) { + CVarSetColor("gInputViewer.AnalogAngles.Range2.Color", vec2Color(range2Color)); + } + } + } + } + + ImGui::End(); + } +} \ No newline at end of file diff --git a/soh/soh/Enhancements/controls/InputViewer.h b/soh/soh/Enhancements/controls/InputViewer.h new file mode 100644 index 000000000..646c15d9d --- /dev/null +++ b/soh/soh/Enhancements/controls/InputViewer.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +typedef enum { + BUTTON_OUTLINE_ALWAYS_SHOWN, + BUTTON_OUTLINE_NOT_PRESSED, + BUTTON_OUTLINE_PRESSED, + BUTTON_OUTLINE_ALWAYS_HIDDEN +} ButtonOutlineMode; + +typedef enum { + STICK_MODE_ALWAYS_SHOWN, + STICK_MODE_HIDDEN_IN_DEADZONE, + STICK_MODE_ALWAYS_HIDDEN, +} StickMode; + +class InputViewer : public LUS::GuiWindow { +public: + using LUS::GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; + + InputViewer(); + ~InputViewer(); + + void Draw(); + + private: + void RenderButton(std::string btn, std::string btnOutline, int state, ImVec2 size, int outlineMode); +}; + +class InputViewerSettingsWindow : public LUS::GuiWindow { +public: + using LUS::GuiWindow::GuiWindow; + + void InitElement() override {}; + void DrawElement() override; + void UpdateElement() override {}; + + InputViewerSettingsWindow(); + ~InputViewerSettingsWindow(); + + void Draw(); +}; \ No newline at end of file diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index a295fed66..4cb43d3a8 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -117,6 +117,8 @@ namespace SohGui { std::shared_ptr mInputEditorWindow; std::shared_ptr mAudioEditorWindow; + std::shared_ptr mInputViewer; + std::shared_ptr mInputViewerSettings; std::shared_ptr mCosmeticsEditorWindow; std::shared_ptr mActorViewerWindow; std::shared_ptr mColViewerWindow; @@ -165,6 +167,10 @@ namespace SohGui { mAudioEditorWindow = std::make_shared("gAudioEditor.WindowOpen", "Audio Editor"); gui->AddGuiWindow(mAudioEditorWindow); + mInputViewer = std::make_shared("gOpenWindows.InputViewer", "Input Viewer"); + gui->AddGuiWindow(mInputViewer); + mInputViewerSettings = std::make_shared("gOpenWindows.InputViewerSettings", "Input Viewer Settings"); + gui->AddGuiWindow(mInputViewerSettings); mCosmeticsEditorWindow = std::make_shared("gCosmeticsEditorEnabled", "Cosmetics Editor"); gui->AddGuiWindow(mCosmeticsEditorWindow); mActorViewerWindow = std::make_shared("gActorViewerEnabled", "Actor Viewer"); diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp index 73a3addd4..0e1d970a8 100644 --- a/soh/soh/SohGui.hpp +++ b/soh/soh/SohGui.hpp @@ -11,6 +11,7 @@ #include #include "SohMenuBar.h" #include "Enhancements/audio/AudioEditor.h" +#include "Enhancements/controls/InputViewer.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 8b33a72ef..d74649290 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -21,6 +21,7 @@ #include "Enhancements/audio/AudioEditor.h" +#include "Enhancements/controls/InputViewer.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugger/actorViewer.h" #include "Enhancements/debugger/colViewer.h" @@ -180,6 +181,8 @@ void DrawShipMenu() { } extern std::shared_ptr mInputEditorWindow; +extern std::shared_ptr mInputViewer; +extern std::shared_ptr mInputViewerSettings; extern std::shared_ptr mAdvancedResolutionSettingsWindow; void DrawSettingsMenu() { @@ -245,11 +248,25 @@ void DrawSettingsMenu() { #ifndef __SWITCH__ UIWidgets::EnhancementCheckbox("Menubar Controller Navigation", "gControlNav"); UIWidgets::Tooltip("Allows controller navigation of the SOH menu bar (Settings, Enhancements,...)\nCAUTION: This will disable game inputs while the menubar is visible.\n\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); + UIWidgets::PaddedSeparator(); #endif - UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); - UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - UIWidgets::PaddedEnhancementSliderFloat("Input Scale: %.2f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false, true, true, false); - UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + if (mInputViewer) { + if (ImGui::Button(GetWindowButtonText("Input Viewer", CVarGetInteger("gOpenWindows.InputViewer", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + mInputViewer->ToggleVisibility(); + } + } + if (mInputViewerSettings) { + if (ImGui::Button(GetWindowButtonText("Input Viewer Settings", CVarGetInteger("gOpenWindows.InputViewerSettings", 0)).c_str(), ImVec2 (-1.0f, 0.0f))) { + mInputViewerSettings->ToggleVisibility(); + } + } + ImGui::PopStyleColor(1); + ImGui::PopStyleVar(3); + UIWidgets::PaddedEnhancementSliderInt("Simulated Input Lag: %d frames", "##SimulatedInputLag", "gSimulatedInputLag", 0, 6, "", 0, true, true, false); UIWidgets::Tooltip("Buffers your inputs to be executed a specified amount of frames later");