From a2fb558eb8ec052714c26cc329c8b5f89906639b Mon Sep 17 00:00:00 2001 From: "guilhem.duche" Date: Sun, 1 Jun 2008 16:35:39 +0000 Subject: [PATCH] git-svn-id: http://wiiusej.googlecode.com/svn/trunk@172 ae48ae66-6a45-0410-b38e-211266189506 --- WiiUseJ_0.12/.classpath | 6 + WiiUseJ_0.12/.project | 17 + .../.settings/org.eclipse.jdt.ui.prefs | 3 + WiiUseJ_0.12/README.TXT | 56 + WiiUseJ_0.12/WiiUseJ.dll | Bin 0 -> 30473 bytes WiiUseJ_0.12/img/wiimote.png | Bin 0 -> 44340 bytes WiiUseJ_0.12/libWiiuseJ.so | Bin 0 -> 19652 bytes WiiUseJ_0.12/libwiiuse.so | Bin 0 -> 40551 bytes WiiUseJ_0.12/src/img/wiimote.png | Bin 0 -> 44340 bytes WiiUseJ_0.12/src/wiiusej/WiiUseApi.java | 351 +++++ .../src/wiiusej/WiiUseApiManager.java | 662 ++++++++ WiiUseJ_0.12/src/wiiusej/Wiimote.java | 435 ++++++ .../src/wiiusej/test/CloseGuiTestCleanly.java | 58 + WiiUseJ_0.12/src/wiiusej/test/Main.java | 45 + .../src/wiiusej/test/NunchukGuiTest.java | 377 +++++ WiiUseJ_0.12/src/wiiusej/test/Tests.java | 367 +++++ .../src/wiiusej/test/WiiuseJGuiTest.java | 1329 +++++++++++++++++ .../AccelerationExpansionEventPanel.java | 39 + .../src/wiiusej/utils/AccelerationPanel.java | 281 ++++ .../utils/AccelerationWiimoteEventPanel.java | 37 + .../src/wiiusej/utils/ButtonsEventPanel.java | 363 +++++ .../utils/GForceExpansionEventPanel.java | 38 + .../src/wiiusej/utils/GForcePanel.java | 282 ++++ .../utils/GForceWiimoteEventPanel.java | 37 + WiiUseJ_0.12/src/wiiusej/utils/IRPanel.java | 253 ++++ .../src/wiiusej/utils/JoystickEventPanel.java | 231 +++ .../utils/NunchukJoystickEventPanel.java | 37 + .../utils/OrientationExpansionEventPanel.java | 38 + .../src/wiiusej/utils/OrientationPanel.java | 283 ++++ .../utils/OrientationWiimoteEventPanel.java | 38 + WiiUseJ_0.12/src/wiiusej/values/GForce.java | 80 + WiiUseJ_0.12/src/wiiusej/values/IRSource.java | 106 ++ .../src/wiiusej/values/Orientation.java | 117 ++ .../src/wiiusej/values/RawAcceleration.java | 81 + .../wiiusej/wiiusejevents/GenericEvent.java | 59 + .../physicalevents/ButtonsEvent.java | 128 ++ .../physicalevents/ExpansionEvent.java | 40 + .../wiiusejevents/physicalevents/IREvent.java | 317 ++++ .../physicalevents/JoystickEvent.java | 135 ++ .../physicalevents/MotionSensingEvent.java | 203 +++ .../physicalevents/NunchukButtonsEvent.java | 90 ++ .../physicalevents/NunchukEvent.java | 169 +++ .../physicalevents/WiimoteButtonsEvent.java | 267 ++++ .../wiiusejevents/utils/EventsGatherer.java | 355 +++++ .../utils/WiiUseApiListener.java | 37 + .../wiiusejevents/utils/WiimoteListener.java | 107 ++ .../wiiuseapievents/DisconnectionEvent.java | 45 + .../wiiuseapievents/NunchukInsertedEvent.java | 51 + .../wiiuseapievents/NunchukRemovedEvent.java | 50 + .../wiiuseapievents/StatusEvent.java | 293 ++++ .../wiiuseapievents/WiiUseApiEvent.java | 66 + .../wiiuseapievents/WiimoteEvent.java | 345 +++++ WiiUseJ_0.12/wiiuse.dll | Bin 0 -> 114688 bytes 53 files changed, 8804 insertions(+) create mode 100644 WiiUseJ_0.12/.classpath create mode 100644 WiiUseJ_0.12/.project create mode 100644 WiiUseJ_0.12/.settings/org.eclipse.jdt.ui.prefs create mode 100644 WiiUseJ_0.12/README.TXT create mode 100644 WiiUseJ_0.12/WiiUseJ.dll create mode 100644 WiiUseJ_0.12/img/wiimote.png create mode 100644 WiiUseJ_0.12/libWiiuseJ.so create mode 100644 WiiUseJ_0.12/libwiiuse.so create mode 100644 WiiUseJ_0.12/src/img/wiimote.png create mode 100644 WiiUseJ_0.12/src/wiiusej/WiiUseApi.java create mode 100644 WiiUseJ_0.12/src/wiiusej/WiiUseApiManager.java create mode 100644 WiiUseJ_0.12/src/wiiusej/Wiimote.java create mode 100644 WiiUseJ_0.12/src/wiiusej/test/CloseGuiTestCleanly.java create mode 100644 WiiUseJ_0.12/src/wiiusej/test/Main.java create mode 100644 WiiUseJ_0.12/src/wiiusej/test/NunchukGuiTest.java create mode 100644 WiiUseJ_0.12/src/wiiusej/test/Tests.java create mode 100644 WiiUseJ_0.12/src/wiiusej/test/WiiuseJGuiTest.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/AccelerationExpansionEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/AccelerationPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/AccelerationWiimoteEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/ButtonsEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/GForceExpansionEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/GForcePanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/GForceWiimoteEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/IRPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/JoystickEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/NunchukJoystickEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/OrientationExpansionEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/OrientationPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/utils/OrientationWiimoteEventPanel.java create mode 100644 WiiUseJ_0.12/src/wiiusej/values/GForce.java create mode 100644 WiiUseJ_0.12/src/wiiusej/values/IRSource.java create mode 100644 WiiUseJ_0.12/src/wiiusej/values/Orientation.java create mode 100644 WiiUseJ_0.12/src/wiiusej/values/RawAcceleration.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/GenericEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ButtonsEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ExpansionEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/IREvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/JoystickEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/MotionSensingEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukButtonsEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/WiimoteButtonsEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/EventsGatherer.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiiUseApiListener.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiimoteListener.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/DisconnectionEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukInsertedEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukRemovedEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/StatusEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiiUseApiEvent.java create mode 100644 WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiimoteEvent.java create mode 100644 WiiUseJ_0.12/wiiuse.dll diff --git a/WiiUseJ_0.12/.classpath b/WiiUseJ_0.12/.classpath new file mode 100644 index 0000000..d171cd4 --- /dev/null +++ b/WiiUseJ_0.12/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/WiiUseJ_0.12/.project b/WiiUseJ_0.12/.project new file mode 100644 index 0000000..9485f4a --- /dev/null +++ b/WiiUseJ_0.12/.project @@ -0,0 +1,17 @@ + + + WiiUseJava + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/WiiUseJ_0.12/.settings/org.eclipse.jdt.ui.prefs b/WiiUseJ_0.12/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..81f7b8f --- /dev/null +++ b/WiiUseJ_0.12/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +#Thu May 08 01:25:43 CEST 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/WiiUseJ_0.12/README.TXT b/WiiUseJ_0.12/README.TXT new file mode 100644 index 0000000..ba8e176 --- /dev/null +++ b/WiiUseJ_0.12/README.TXT @@ -0,0 +1,56 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ + + +WiiuseJ is a java API to use wiimotes on your computer. This API is built on top of an excellent API call Wiiuse using JNI. + +WiiuseJ intent to be a very simple, easy to use and lightweight java API for wiimotes. + +Some of the great aspects of this API are : + + * The compatibility which is as large as Wiiuse's API compatibility + + * Cross-platform : Windows and linux (like Wiiuse) + + * Easy to use + + +WiiuseJ is made by Guilhem Duché : guiguito1@hotmail.com. +You can contact me if you need more information. + +Go to : http://wiiusej.googlecode.com/ for further documentations. + + + +CHANGELOG : + +wiiusej 0.12 : +- added nunchuk support. +- all new stuffs from wiiuse 0.12. +- added timeout method. +- added IR sensitivity. +- updated to be able to reconnect wiimotes. +- new architecture behind the scene. +- cleaning of the project. + +wiiusej 0.11 : +- updated with new stuffs from wiiuse 0.11. +- Linux version. +- selectionnable rumble on wiimotes connection. + +wiiusej 0.1 : +- first version on wiiuse 0.1. \ No newline at end of file diff --git a/WiiUseJ_0.12/WiiUseJ.dll b/WiiUseJ_0.12/WiiUseJ.dll new file mode 100644 index 0000000000000000000000000000000000000000..aeebf074fd0f7c8a792644a62f9f2f42686bf09a GIT binary patch literal 30473 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%0DhO3{%PeE6n}D<^ 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 W8wDsT*@Df(ctTw;crkI^@P7e1{>1+P literal 0 HcmV?d00001 diff --git a/WiiUseJ_0.12/img/wiimote.png b/WiiUseJ_0.12/img/wiimote.png new file mode 100644 index 0000000000000000000000000000000000000000..3f26f5202b22a89c5fa3e1c1eb524f78e4e76e81 GIT binary patch literal 44340 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 z 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 Ef|!^34gdfE literal 0 HcmV?d00001 diff --git a/WiiUseJ_0.12/libWiiuseJ.so b/WiiUseJ_0.12/libWiiuseJ.so new file mode 100644 index 0000000000000000000000000000000000000000..0caea089a41f707ad3162de0ab895835a0dad99b GIT binary patch literal 19652 zcmeHPdvsLQxj&OcjFOUo(Ne)W*jR%?5+J-P*5NTgTmg|JND&<-$-oRwX3}{ew4o*r zsYy>msYvVcY8S12*e-3U@@h-lNNB;Ut%|KBUecRVY==S>yU>d*HTU=1XYZLak29gJ z{&Uy5JL@}p|MvIoZ-4uF_BnID-0!SiXtUWg74o%wO`t0@ts0q&XBeDn&8`(_<+xsB z@KpiCXDbZ4gn1>J!LLGEQY#d;fksGv9^z8)6uk^gBEJB1#~YDmL>WQxuLoy7=)<5} zr4-9u4I)p4OOcoaDh5piIY10If~J9{fIbGg88i>XFd9?|DgxaA8U>mKngC+B2{azW zZn*|@If%_EMj|c&jgeT48`5PGo1;%i@FB#7GF>X;u`*^f88j305dwrO zK^zPA5zCPrnpW?y6}CP3u}SmnQ%;mb3JSHwQ@;6p-q*)`q@&=;xs+v4eP&0R{i5tr zW6O54&&+{i%CX^io5z7;$?@S>bBx#@w3C5-$iOzTkJ!%+5Q7?vJ-`3n)35*am8mVG ze=%du*G4~A_p4i<`^&3uje75$=`q*Dy;t7w`pec?!C-;U#Nyua^5zk7P6_g&9d zPj}Vz|Hm`mjvu}J&#&%Sdh@u|m7Sme-c;X`HNQSyJ?+6c)9#qPJ@393`aivL{FWP| zum0qZ54E+uRy6A8V;-%Y818+q{zpH1Z@%-lXP)nP@BR^AJN(i2cW Mo+a3RGvS$ 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 B4XOYD literal 0 HcmV?d00001 diff --git a/WiiUseJ_0.12/libwiiuse.so b/WiiUseJ_0.12/libwiiuse.so new file mode 100644 index 0000000000000000000000000000000000000000..481e0e20e582d736d0abaeef24676b37ffcfea74 GIT binary patch literal 40551 zcmeIbeS8!})-T?ZOkjXWM~s3l>L_71D29ND0a;BVlORhlAR(>_Lr7*wG-N{3BQFYO z=mgTXBk=`sy}Q2Q^DM5q;)(%$BOz=8=dRtVAe%m?VvdUsY|SjF+5}T}sCP zg(BU;r$6j&!^IIukVLwOyASbnF_Pqj>u07TD2+y*(MY3f15C$sJKW4ql_GejTvqz^ zNSOzh1jjNjg1Z(DEK8Yix4}(^<24B`4^D;yYvLM$|EX|e;Ksr^;AX>-?yYb)!|}Qr zZYbPbxI{S0V>q03xe&M%?m{^7eKFh=xLI(#Mj4)z0pAJ7dgsGk3CHUOxL?4HAb@L- z;YruQp8$70+-SI);0C~51$PbH1#q{(&4J@}mf`(d|H&q{XpB1! z4#i53L953}u~kfIob<#LR3P16Wt-+6l5Xo~lk9dV&a}S|+IDV2?!^DTbC`p)s1MX_ z)`>h@ZN>WYqE4`Wlshl#CG~~+O1>yR>WL*E_6_Pb+mLNZnOki_-JV_vLEzWu2hW$5Oe|6~>?|e1*qh|+xnKZEF^0~j0 zUr)LEPZ?i-*%kWo^N%jP)G_F)>6_vox%&BGuk0*292)V_xDl`4H2?Cy{;_NF#WOcu zl~a*+&DY`2KI&ZZZsLpQ{3A4SN^#kHzdRHQTv}N%ZNeKJ4Od+4e6#wYUoH6Oo8IjC zF@v7I?*406J~HaNjF-l(JluZYtW|lwhd;P$@kTwXZBCdeqs z2}eD#E++y*%=~vU47b39A3#RJx0*29gm7#h{IgAd-Z9g=%yhOj@gFuB_`3Z%=D2Mp>ndPxx5PkuUSHMg!i!)%W{O=7=^daKsn(6B-e6zfJkjC`$ zO#Dvxm%`03(;q{a=?lQmrbUwE7w{m_UlPto9})BhNr%WUgvWj~1eTm*UY$>perv+D zfafFqgb9ZrxUOPj{38CFfLj66E)k|ZNnCx_reBHrrj|+41~dIz#5>U#zeYug---NEiD4%QUj+QRQp1K2z8lHq7-%@|5q<;t zB@bkSatMC{`J^NN>t=cf(i7%O66MbHZ;{^W?x{~L;PM18wj3Gg=`%9?4WKLLCi zR2=HLi|0Vo{0%I<~@}360O~`DuzXS9VP@nN8z2|_R3;cjd z?|t~2P`*{(YVemz;owS;zV6Nez1)S8bO#fK`#}P zpO?(^2a%o@MQ_?=3Ez%o`jPZ!@J$?8i-<&Y* zFw6T1@^?k)%NEqX4ik=Clin`)?PZemtO@6W-(1KCRS@O<3UpclSp0l|_*B%l)=Zy< z^5dz@0*2LdyB99=?xu%uG)R9s(L zP+94zluAn$EJ~^LrA%OGL8;%P_bGDRvZC@pl~?ps!= zloZ~<(iBf`w4##ALSI>#r%>?}^-d`+C@ZQgF1W)ZEh;E2^%Y8y2)Acxc|loaiLXpr zQc~it^tdZL1x45QSChDXO#(sC)hhRN@nSScw1)F%*{iDkF_xDyCHFE4;%K;T7GZNGdKY zaW4cP6+S;Snvf6ma~FB;BwyfA#FdmS_Lo#FlNJ<=t5o{%@4ge-V3luF$zATNED@R) zRfmGgax{~>f^s&x)3SmkQlYQX(A_>1Aa0VlvqXtVhAklZD@#3|@@QmBF${%wE5%@^ z*jHL~I-G*SLQm4#W618WqhQnJW{=CLTDe#^=VEohOCf_4je!6cXhukbHIPq!e&w{Ri)eecMKsj;wN zI2EbfuS9BDSn4S#^Ow^=78<6~ZPdwKSbT@uTToIexjmw5yWI;aD-9crC^S>{^cym- zcaKX+jfBRgTp0;-FqC*lg~36D42Urp4iFnF(hLkE*7&!J6l1n!lm1`+cyGqJos)h^ z$ywxjJ;o+pHiU~1W;(CRi%T$2#Ys<@aft%oF1=vFM*f&c{$z~T4&)nc`t~5!R4}eO z=p#=&eN1K(=#RqOj=l@)CiF2DC&TZLadb3&%q3IlL$KrNL*!}nXW+h)KIo>?zZ`2G z^!s71MIRHm>GZ)!F8yh^zod_v+)RHU=FIeyBxyeVL6THN|L2&?(2vKMPX8>-59tra zw2S`rlC+e*EJ=6M$3(x1K7>_GA2%Vj^he@efj(~P>*!<5f0+IhNqUt2b(jOw$3*K% z`j}%pLw}YeZKOXzlAfmz`D~&;RgyN-$HZnU{h^ri(!T}s8~Rvu+DZQsN!mpp_XKa# z$K0}&KIWYJ>0=?Gjs8`V^a1@G%xCCBAwHp>iu-K(<0Pq*{s_#6=nt2qBlIzsIYxhu zB%P!`8x4(i?tc;1p6FkScBX$N+L=DuHG%#OXlMGE+YO_Sb{bd+87xjFTqocp!jOp6Q6*p|6{is{7w~Ap>4fJCn5e~5 z3Fiu!hN3u^aJqn*wfJVjsREu%cs^mLfYS*V6HXBD6vE|%B>|Ik@lwKF-y>qfbi!4H z+Xc*`ifakC3Yd*kTt~P;z%07>QNo)94CRoDpCtUGfaeq5NVrbGMT9pIt`aa=E8a@D zT)?G-8wk%AFj+0$ML1W$3gK45=>jI}#chOB1$;N*cEU~pR}l^qP7rW4;V#0GfNKdK zBi!{J>wh0%*elduz;%Qjgj)stFyREk4FZ0Y@G!!g1pI5lPQp(L_({UagzE(S4B=G5 zRRZ2fIE`?*fS)IvPI$h6HxZsnI9I@%3Fi_{7w}fXHxo`3@au%<6Lt!?fp9V51Oe|P zTuxXLFhyIulyKKc*8gq7RfO9GOi>rt5^fdne!_Kx8w58<} zBjGv$e?oW@;VJ>MX^OWJE*Eeo;ReF<16K|o36NxaH@b$5^g8# z6tIL~ahPy|fbE342ulKX5I#n@>tEg7$Q-#~Gj38l?PO58HPFn?DKattITOrciL~A+Z5c4)eT|8ZVIOe`qvxu^@rjOcFxrw>NG-wf-2)s zK=(c)w>~_{U=sZ0&q0lb>pAh^&wvzY`d1~k59-gB>oaWX;h}2RP<6*pwP9#2VrItF zX4sGr+bdya3{vd18L>!->z#twI6coHZ^^KG8+SRrZPjxeRiAvXwP?-W5tF|Cn^#*N z;~g}~tJ!o{{3YLdwPkj>J{N?R#%O<2KfZVtGOM4@|InTk_^chZ45^7GJXml*A9^`q;w_#|zw=IYXpy>Cxa+pmKF zLboM3)W(EdMhM6bq;MWoU(f5(T@Ds(qy;{2plmqJ~4;$lS{JCa?*orAbI5qB=)`Za`OYqOn*>)-H2Y;FFfh;xXzB*YC6ahD)&poklR zxIwgtl1LZ{WopUhqL5^1Th+3J?qEiO(qC)rSO7*_>`CoN4j()YwSM^+V$ke_jMy#)U?0#0=b($}{sgaFpJ~tKe;j%n%n5?F zNGK)}%8X@a>;MA&6OV4x6o7+^^ zWAD_?sk$pcn|mZY0meDd^a~&Qg#VcCcc{l~+KQ9tL&`AqSd4O$KKF=@gcT>XPOI02 zvK*m?1K|(bA74J?Kw?s8Zd>>tsCP|6$knDSIM6nBpEk##&4}=blG%@ZR z8|rUh+;Sj<_$N^EZf!=qmSdEhV3nM256z43xDu^rksK82Z&4h2Ak;C3N!fOT7$QLI zPY2pMeu3x%ZK2(V_8e$C^g2Tww0hs0loLMk&T9cOQ5U^xr=42|!up!u5d<(5!nxZ^`vp zvALsmz(PV95|a!|dGL7KhG8(`p@z2I;BPtzu`pTP3%xw>UT8OR#r$xtFG;@R4%P?! z9WV+Dy&c-!b~rQ~Z5l?iB69Ao(A=%zdH+ON>Ts0!0m^H8*@;lwh9q*}3ZvCSu3aJ5 zR`PJ*y~pJ>?AQkX6zPG`r5 zY4w8T`oRZ39<_I-S@#p6#rw~uav#|7X{S4c|PkJy;hML+?6N)eNcE{yx-M0>Y zVrD1-Xm*6)>pughyoV9v_hd9Eh6|1#PW1Ia(^aMD0Pb+8-e~2d4^F%bQE2C#4dKaSAos-45j$U^+bx+uX+mh_mgsI;k+lquX zor-2CSqOdCop9*k5b~orp_ov~HfUw|Cq#DjMotLbjP3|kY!mlztOFEo5Blvx48+nVwDWG@c6Blbcv_|iUM{Wk) zZ})n&M{YsDJ4nD@Z8f7W*@I~AHL_b7)1`>MtDR|vmB$buZ-E6HgB~7eno?p712x@> zTVKz64tY=D#CP9a^q5?|8BpNF_un%d65)S|_(3Q`*SpxS)X``N$H2~r+&#>b_LNE)05)0yTKV$iBxX^KQ#?=}q9>Qi&WHw$8mKukRzqnxK6k5zuEcG#53>dr*o0135F8_2Dl%J)Z9 z!bpmWOogP*fd5|+doMwQu}9OB9CFP?NF2K_ zIL$UOC%&bMy^NP!{bz(~j>^?7fYk48%H8VsG0G$wc>Dd#sa&F`JGC8Z`^Al4#L3T9 z3x<%U=Q=08E8q7p$o7y^8*NcJlbExaIlpAiS6CJBrQ7c{GkZ?SEK)_WB6Htj1y^R~ zOOP4m^{Ec;pZ^^exHTSJY~yS-A{5>JQV$D_rJx#wc>1d-vc}LHtR(y7GV>nLUu(^g(l^@(uy-(Q? zT)zwWV;fFt?`|W9(CjxzOYa}Hp%h*4pr1$nok$MeOLUkkyT05>%UOO1r5{7>FU5j7 zyU@Em#XGdW1X}hGKbXrB>$Tkk-k3uAZ-}TZ>z@ZzdCL|K3Ud9L-vjb$>)#}i{3Nfo z<#mK=*Kld5df&1neM>r1)=a^_w&m9hZ^>nN&66VL8OFRq%EmY-S5Jn-Fc!+yJaB~Z zP_Fg?Cz#Pbd8oYRw=BE9LEo$vb#`~#4t9U0KLmS%q2e|S6~WhLB32*Bx=#isd^_@T z9f$ThJQArC!3yBEL|RQ3p}v4g zTv*hCQxV5niQ0e)NBkDjSZAd`YLd8jOiT*DfRv8aQqfiy0~b@%th=>0%Mp~fyjhFPm=Y`{RKNOO0lirVsCM;(`0uz0 zLy&GL%sMtJ#yq?BJw_b0IVL;>g4b(A^a*uGeE3P;2@6#-Z+pWr#1NVWZK~cUYdn5s zMy#d!T(g!6C0C!vc%eAP_yO z$eORc`7i?VmX))$)sG_N)!tXlF+U9{NI%v8Hv{Wfs5cjfvA*|X8l+3VAG$g6hrC%6xtP}@7I zQLa6LiHCVFWpMib>LO9h0a1+lR6pXc-Y%#-@&c)}%B$93_6iapq&1G(E7#70%{8f* z`AU$_;76`sMQZ|9Xlt1JCX^YSdwfrBqjKsM%q;{LTD_6%tY$wlZ&&11b3g!hyC3tu z&$y)#QMhe>&nPprYJPMj`VoKC^Nd=>d21xspG`u>t@bK{y!STi@E6q5Q14J+6Eg?6 z4G_uvY*gk0A3QFvVg&DntTtNJ0d!OO*Rulp8kVlFB^iCo>-g8!vwHga28P#=Lv1aK z(za~o|N5=?@7PbRFfDq3?KvqRjCjp!NRaCvVB<`BfNdk!Y!p!eN_~jQ5%~H^Y-_j-Z=#yl?^}49oEf$18M9_SJCfr>tXEOs!C1ap%2W zRJDEv3{#+)lBiwFni>qKEtB=kRBdmdQJCK8hS^rzZDIzG-aZBdO(RB2JUJ0BVz9QB{m zQ37G;cP7>x#rm*ZeJh}rI&~Gs(nA~5kUI)LrL9Wg~f7M?z zhN9M>-j1O`3`Lv}2&0oqZn6>$7PRa%jupTDJK~n4amqUfCYm%(9FYxEdUz%Il9BHoMlupa6^)WX0mu)5;w;*6kK8HQ z^R`&7o<+Wmp#o%eFx2rD?#NEp!e1g0?HW^SOik)%#MZ7gS~#nxg~de0V2CX|GgaFa zCmI;-Mm?-64nH!ySn(bk3yT z949hjEVz=S41wh)b&M9`6PZPWLuaTz;VXz`5HR%n43(*ks)VU#hT=qOW2iGKNOiQT zWN2x4$;V_}48BH8RJE=VRgSJ!TsW51il}M%8HB$WRJFs}F?B~wcrWhXFl={BIRmZ> zxc||v_{>Kr&`^@TU9m*eR@6w;LERB&P313YN3KXOU5~|LEI%3MamzMg80#M}rnTE> zENdU2G3;0iJR?^~Op8KUrIwwpsYIH5?;`w%#K0WNDvzY)i?o>{trUbpS$9X$t`TWh zi8RhdLSljvNgghe&lAa?HRR0uFZluF_)1$CbH$k#5MS`lk-cl?1mE}J#%TX{1zV$ zL5Lj_vCd=k$fMcpw7-BEr$SF=yBHGAN`e*AdhC1BJz8c`WMYo#PuGVa)WtPEp_`#q zoU(;7izBr;Pt+y>|DjdoBCSX8C%}Mw?-4F2uM!f=}{sar|2)DiLmKMcOL-V_v-cZtuib1<{&v#Bkt{d&&(IrsVv(xT^H%K-P8|5ZoVVV1yO z&8JG_`bRXA3LmzJrg8*hNbmXI1;8*g0`ouKSz!LhyAAU2G_a#{bM9*9Hf9y8_M>-L zt-g({W0qswt88O^Y9A2yDz9Tbt1fCXt1Uw#vMXRD!@r94^2Ux*#OXCOB$yL?)CF3N z$L+yoHhIg`SnY(oC2KGgVV}2gw!C+!b zqjuaF2V=9a5xV#CEG{5A)Rs7Ln}mVx4<8_lx^ggPH6PHLp2w}?pRxK|R*LmQa{$EL z1@jvW;y93ym1qvzpT3VAq8I5EV(|VINbnY8@&V}jeE@h5i5iIBOrL}ObqA3+gVV5{ zX}$IWI%Ho-Jc&5!Nk_?P#MBL0&OG!5c2hp;nN_R56InvL5AMJk`BMO}{%G8=zxF82 zi?~&HnGB(pl2NPp@N&qZ!^2iItdV|O#2TeVqhqHOqjvZgM4v!(QT>)xyrsr`QEJXg zuyurSlf$D05JjX}*MZ-@aoZ8c3YZ&b;{@|ifh!QO;@M-=e5QyE0Ho#u=u63uJI82o z&I8<6oHG&EH(z(3W(WiBo9}(Zp%E@TP4?w|vKO8v`y7$o8u9c8Xrc4~&5QmL?S#JV zQT%HU(0=I;{F>naO_25yZHcz6mj4gjhyRYdF|F(+mwL=)BXW5WfRzfF-O98!$ZL)n zAEhQIFeLG|N2tlyoX87{9SR5|8ZeBgdBe~jh06EZShV0PBzTY5=P(wv<$FKIe<&b~ zU%)VaX71f0xrr;^#-LCiph1`v5JsZrcTBE-fYxf#12k50&3X|Ppuw0Fpbe30su9(( zn8w4{k5@aB#r_BOcaDUw{DAAzQ*$9D|1oTQERgH7$5%J_7pgZV#c<#Q395Pc-FML+ z?V>-1-wKJonSe6ycMui^b0)-IxU9?bJQJVP3_ z-?l+y--_%tN0olKxo{})J=ah{@Ic>9K3e7WI2T=cHP)` zJ-N9}VeR*h*7M@S6GUOZKw&MecH+W(-(QU3N%zMGbH3mi5hGs9`9S^BrhbOQLT&oh zdREd#EEZ>D%p2PfTxt``!ef~&r>$nUT%EummbS;gYG79LVY-dju=onTx5f3v#gdK@ zA?HgBN8I#^*m%q?Bleax%C-Nu8S=+=xK?lOi+K%TrK+=v3gddJx!T+ zaCy(H*c`i-hl;%}dD)tqn z-&;_qm=Khcs&l_dZyWLY1s@uYtpZ~QQ`~W|5A&!^xEVZRAF)?Gz^WL8Cy{>)#!sVM z)zxl8YpX3btHG6l8y(6RbAPRc>Y<#6y)b?JR-q5d-i;3bpE};gFsHlP)t#foGWNft z7lTA~DL&+7X zw-7!>*YO_Yz|Qd!MmkdnSO{=IhvxK>eXq`ucR1WnFmC9OA9+u&Lo0{V?mf2G5Co@Y zXA(p`DrX5IOr87z9hzp+`+|6<*P)5R-m;Qs5X4cI2SLn(4>JSKq>dLb*!Fa`YLsI3 z?&Cx<3|z;vm`d~@xqFcIMpfL1uLpLPE@(Ou)W zvHtqi80B#cvpH)3rh*Q*{&4-^;^6F(x*{GMOn7ET9LYQjS;Udd1IVhLh!OiCa`j6B z!crthe;&?U$itaaa5$6pA165S?JvbNXQG5ml#q!MGEqV%O31WJ`uMfjfIUZ#yG>5B=jx&*ERcp@WC~r?fg{AOIe`d$ln&nzPcto@9gI*)1W+HPQK@itxqEF5LAeXtFCInAe4f=0hBqzO_X&ziINgQcz_7&Sc=+w85!LXYhjWZ`M#Uc`uZDeT^iVr z*nC2Ift@rl#<}r_zM%~`y#r+t*T2bTE@-;MyuW8_`6767!;{^;NhB!8GIEfa=f*)J#FMn*Yd_Ko0 zmN)4}v9tRYdx+G2Ol?1Y>kPG(qiTBtYWp=N7)G%_i4=Qw-(r;?TkIWYDz>kXe;+Bf zMTDqxZ*Z;?E#&V=?Z?#i$R4A%qFYk)VxW1tfaEQ+W1xRC9eQ6DxYT6S+!JBp*1jw( z|FJAAwpd`d?_q(^nOW$>+{2nwU_Nn^o}LuG3$hM0)um$tYG;gceo(DLkJDm;>Id{~ zTVeGi9CE8Wy3?)<3#yM9sSkY!e=E!s(zLUij_!0QLxbuwX5z<8g#D4UvkxIHfoZ=t z(>`SyhYY0s_UKM0)3%yvVWx3hNF zbMP=zr$aq%Q`|TxNV?lNMSu18_-k<;5#(JC+b&(6xa*!Vv97L(jrSyjD_g66-o(~> zE{t^@nYiPg^DfVEXfmQl^;35`<_R6a<3tFLZLppwVr5?O}(G zgo_0~EAU{no>_hcXUSZz1g+4jYLWRQGPmtMxCh6|hbM(s{}E8sacdSjw+Z@b)Gs~c za#(AA2SVXNg18gJANNmRJ`E?xw`UE;Mpe9) zgl0@eH1=|UF>|oC*bYmh?o4MT+jQwmtp4SFLY@vcBj{p~$GnTcVb!(RI>EVaxw;a1 zfkNYrn#tSe3`Xq&Ux>v{u~Hm*8&$wF5i5?$TXK$ucC`KJ6-YbhNN`5t!4Am!!xdr3 zR(FMg^OlxnZ`*SaPhs>V&w$F?Ye8Kct^7afC zeuXI8+I+xs2YW=>c}E$nN7;Etq6!Y}X3=PN7~QtF@Hj+-BNUur6g<-r$S?~|mVz^q zl|?8jQsbF@Ys|K_N_B}+4gKm}YMxQ*%s!>MBBf^ZlsXxuPWE5IeFL+7c#xiAfE4AL zW1ML4Kx8jrEEaryDWoypT(kdCd>!1Q&9p-wqh#TaaJAUt%47sv5}%>?)7)ReKA;bj z1~;`r&E@(kC)z7~3sfo4v|1`Wsp2}U-KHKOHeGOzY(^fZdy(&YpL|F z63I5`ujblcwK6#>3QC;wcGb$sJyF$THYC#YalUGchIUONH|kKNtFZp}=nowrUsjx@e> z0{0{xV-RJ?!-Xk=x}CDO$@ectv8aw*(~1F`t?C~R#x&Ff&FN2I3(D0GL6^XqmWM}b z@fgg^gepGWxd=JNHdLL!k)|gQL=tXZX4y0#kI?%i$Rzn^9a9k4m3u`imz)IuppW) zEvFNOve^@`W1&xT*j!zW&N0~*#lhbiGsw8Dvt zzg@9Qhj<%ViV17tkf~;zT6T4YZ)@ynh%PN})2R)yDY_wk^{vqm0nTdIh$dJsn!{*0 zdy?+jB$kE`hrb7^p3|k{@cCNyVzVK#IWwlhsnk3};d1s1lhUJbe6~HJaQYTe0yJwq z>F62aRFl#4`WEt_t*4p=*R!QHVJM6W1`Q3sE$m`2)A2SGA1%plr048Jr@&(#T26z! zmID=fS}^_*(W+EcJ#VL&-d^r%2*y9Cw)YRtz8_ZZdAa%z$ga8?Y}#JAK1SV7V<*f;n7(@<lkSOLIlA$bV_o(jpOD>L04-Y*ZWjLzJMobg2}qjaM`xPb9&)uC9Shs;yT!X4 z&<)1!o|*gMXk>J>8E1Z19K=-dpcu+O2rc^HeLVEG=%9`V+ZLg*HGgZzH28Q<_4hDO zWA}l=EGz$S*;x<0Nu2c%hq|Hx3r1t8csUI;rSYpfu7S<$J%7xf!wIAxcO!Ucdrl0_ zM+^>bc^>#AKM4)eYG1(<{gCx%kuG#0D(8d7WlXUh>ah|48U_}Hx6dJ z`myW{9Pf^m*Hw{7Z9X30o)Z_``UxrGY0U^hJgoJpF zKa0WM^c~26j+1m>=@NZ4^3D&pX1s4@kQ`wXxkkpv61t zd#_f3az*+w>@dOn9~s$zY>n+P16l$*ggmvCg9UMnLKbQ)mT$0f*x2qkg$i03N%4*C z{RXsb70rqKe1IM-EQ^CxGpqh?pjk+F)G?fg0S^X3zn;3k>lGO@m=S9RD>}^rcLZ8k zfA6TgFVGra7^-4m4KNGdp}USCey}&NbZ~d9a-*Kp*_?j1)EuBhP|YrHU^x?h;SH>W z-yCCW&OBRErg;PR5bTG=d4N-!``enc&&D{`iO1k5>~H=Fy}pwX%|h>B?MzbsS47aD zCi&|vN|OIoZ(Vc$C>k$<#;Nm5PA;8zhA7-0ojA}mJQbD{H@rucMe4CQ+Wg9F!~ z<2fiZ`2sVU=U8t?vbxjB`=y$OmFF9Upmdb5t%-#mz^L$0GI!lTrn+J2+ahDo{|%o1w6n5E;d3zD=(FPu zT;im~pSEI1>yw7JVu`eukcPa(@0B-|!oqrR#x}7xklTa_mZzRF?Idb1k>ey5WqKY^ zaYx4FULr^G6eNF(l8j@LJ5e^uwDm3XO0!JCuRTeW`SmNX(BMNu*&Xk5W@kPd>wsAF zvq8c!8sy;HMb&Z2i3g%4Z2|i8M5mZ!?I{Gsc??5T#P3yIOH@xIU*9xKRI8CjR=x*I z;x$jGLu{RRO4V9SgCALs8UUTvR#kyHVg}2G^&Nzy_uY(eq=+xj1Pak8CE5Gx*01J<4wrZ zdS{4uKKrKdmk@QJDHfIHqqi=xZGE%Z%<#m%)S8!>t>?kp9{HN`!?T53T#0xGLHG$l zZu8|(yX<7RQE->Ro;hHI)E!)A%TLnhOxN-g%$L}d^CdReI>p;W{;ikT@clJqc#lob zOKj?tWNeiF&r59ZdYu2`OKg<8@B*9K{ulvmwfWHN3@DfJCZ~MyCa2nLsPfEywfT5u zPKKj4o3FGPP@50M&lp&nJq*yG+I+srCcZX%D4?@y^UvpVzN_ccUOrNUe=U2oSf$kR zQ}K!cS`16`qTg0S>y8c4b|i;Wp=P>%j4^$ml*f@8Dlqhu`=m=Yo#t&d!X5~H#OrEA ze?AA=j`tso67wT=Ues`K^gF81g=_h8p*eQ;WF}|D)nZbCd0y1ZuLPEX5rCK1@bbN(s@wjl?%W1qLb+dQRv8gTb=+==w z&d7eI1%T0m5wM5<_y_j5c;g|_sPk&^CnK!lp|Kfa39$pajDP)c}nk3*2GUs6V z?(ny*-|idXiXSmEb-)g7X6ihxwO4;be+_+!69;(H-(W0DFU_@u(x+>=)0J4DX}Lvx z=PP~T==lpx>kp;V==M$T3yb|PyxQUzGz0rzN$9Z+%JAm&@tmd^rUcVFG>;hfWvGQQ z?i=;zeEViLc%FC#*UN&)t`R`?AJZCjf1;Mx;L*>e^?{WbyKnNj#$n}VSL>`=*WM+A zg(kn#{w%+5<9G4K-nEZYXc%>#nham`Jf>tx>@{W0K zf`YrGhG33CD&BZ$&pX)rtIFADJM?0BCyXQQ59W)ge-dOGKK6T2f3S|d$$`zTe@RC( zlN|oD)SXE^?^g`E{uP;^LOKZB`N;xK$vy>3CN2o~^oL&eBM*r}HeM>^gQxDRHy}6o z#j}$%JbHdArnM3tON6yNzk%~a9F9KB3i*pL$`McGRzEc|~)aHB>^dBbAyeqKoO@=Ux$@Ez8j5{#AP0sbr zp$pNCt8xz84n0!cpuAACPuS;i;OFW?ua9l$C1D`MBVqiZ4fwz6&~K`agIl#>ERJ{| zszcP3hwe4@YYq8gKQBJ~C^RR~^ui^mrHebpi8v1;PCSqP9RSF;K6b&U{ucRSTbwyWQyeMbB?#!IM*B5!dpKlcu>kCb2MV$Y{Td0LF6Y2<6iupBlu0W_#Fm*iv+*(V8Fp| zKKY#mwT2XbVX^%jh||6|@}7F8-Q=2_@;$AIVuvn2ja-9gyy@vjbA4$P*PDL|3DF*l z=O_63Mn2C{h*k(RExi!(U2zhuEyMBT*KWg{!#v`S2fu@Fa+^lXT+U{XKJec-w!m=< zZ>j115JhuVvec55Bq6aSD~-i9XN||Quz1B7miby%^UY%-aGMBx^PKTI432)ilrmZ$ zF@Fxfj)o01?H!Ie3|^i4+A!p%alb1T`S7+LV>JyA(RhvT-YyCu_jz$DX}z=`DyoLI(@18~q{6N_KzM%B`ds-+uMOE;=k zwbS4aH%dm;>^)VRiPEfk>iH+xE`LUC^(CxYOpCac6;%_j84*>>GOKnes^+b;8f}R^ z>_^7aH`gzo2Fa|GVyW0TdySizQ;uKHIjK4RuiK~=MMNqxL$pyGE0T5c2inJKk=Gyv zGzWxzx)upOWeCL88H44><};jar(&Gfl3}z%hS3fgMmuB}?GT8xLx#}~;yAO=s_<@< z5n(_3By~KCija@@7 zM==w{`{H14%=IeFfR92#fu=#{qw_Y%)%QV@jCWTA^$c2^t0@gGN0Kwrf#zeJ!}FhP zPnvuA{^`twXJc>}E)6|b{j5KxS$xBZ6h2pAndhjtK8evq9RI%nIoKu61`^)xCReuu z8E<%#tG9{(PX5=4fL+YTiq-FV`v3cWiW4@%yFCV*t>WDm^=uZbsa1%R-8X|i(slbb zR{t?GZTzcvtcS;iC-zFdt8elJy^?S1oBXdQqKW^!Z}JDdk}v9;{6??jZWaZ$Bdk4+ zWbp)=4FaJkhu{*vIyjtfmGTmyUzy4ANRB0b zTCd#8qjC#jp5H6?tx>t-nES-z(PdAL%H5Bpz0YI{UzB}eRBoJxc96ifUIc_Z1@p}P z8>CSHHQnEfQW&Qp&KfuLc=KKDyff$gI(#iOE6{Wk=2qbZ6c&BQj&ux97Yc-NKnSW* zH*~-Jq@I2f?_pEo)i3Sct$II%{YSVTW73Rzr~OIH-NIAQioe90?C}+j44etTA<6OA zzc1gAj<17c0^WXWe#WdBH_XVM>&z>=qs+IY%o+Jcmy=&~N^xHAEAmWorY;@1l+XL! z>Y6p{##zMXr?s4l&uM&)DtVMsDfT$=IUanV$K%9zvGAcOf4Sl`zQL4SIVy$OBl%}} z3O)GRQQ5*s7JgXAnOsuj99hx_H`DrBnG+ub^AuE6ve*S4XU|8gJVhx^XTDjszf2GT z;nLDm&_o>~bvC&06gfrV<@kJ&M{zDG_LMoxd`|OISI#8`mCi*4MIKRsXn9!@;FpCA z3RgG_ii-HLFlUj^Qwbsp#EH+anRSnp+atZx4uPx5^*I zgWqaNei_VJi1u@iT#B60yqj&!Z@rCn78bC=ij&{sLZg-_&Rf~)qS5Cfqe~E);!*Gk zq)N8p)axIH$qmCecSFHn|INSeb|7ym9P_@0S<+g#cQB#Y0(wK>o1gH4TH#Aj_(+q` zBdI60w}So9XTA81FY9|=(7zjIWZgIyN^O3+j;drS?X5y@Sm6j>md{^CjdVu7a^=LQ z!b%D~mO`8K3_Oca^2o|j&K_zQD6r^Sgl|k5p+}_6X6Sc_HR5*ROSt_7UWMdD`SbW> z8{9*1kHb9+cNW}taT302Qy42<6)RngSt`DyIR&SXugBMO;O~Q9HR-Ao_fM7@?wMls z)fqnL4YSZs%d9VqA*?9udq&?y?-6|yC#5q|Q^t<7goNtg8+}gkSuCf&JSBxXWXR9z zYtdaWs>YIJ=Dm~joTWZ=9~9zrW-goL%qb}>F7T8(rx!rW@hv&$WLS>!f{KD$3zWGF z7eUAFD)K2S3Vn;NMUG-cDW5cEj6pA@4E?iDRHc`(lmstmWOuaBFvcTkqUl3G0xrTF zkn8OHw&Gdv`OQ*JVK&44^ZRaJI%Laf;xR~ux0u5KP)J+g4}zZn2NY>|(D*(!o00c~ zT%q7?XgpSG7=9anT(n7t;|c=rZ!kRgN)ZoMeaI$t!QTXecxq9=i2DC@@!RCqH3>{j zgS!RpcDUtm_rg5}_dB>(;r7722loZs3Alk6I4*#@3~mzKG`L&fZiibAcQ4#yaKD3l z6>bmQdvIUCoq!vN@#+G&%it!#O@q4y?smB4aQDJJ2KPI-SK;=+y$AON+zGgW5a0!H zm%&Yfn+A6a-0g77;qHZd4DNSuufpwtdk^jlxD#*#anF7M++}e5wpbG7k$wI3lbp%f zGxA0`$ES=<8RtySTi`EK{04MIs$W3kvBC5|nExZCAJ!14(`Y#MUBhaie?!-}5JG!G z`#^ib{%&1K2*il50Mp9g#pu9e{?WiQVnnobFFcbj&6c>vEby0<78(CVV;1uBgjbA9 zxyp#RLc!NZ$CO-|HsJ~;j47=2k14EBN>Xl;enh?=V#p_<-JKaXIme}py*lNpRLNFl za6|iLxAC1W$#6e{>M7im{YSX5oh>Ew%j*~G_=#hr;~ZM&Q)3=QYz#kWEZJ=T8hjT1 zc{@UrZ~J!{mn2h;q9Nj9*u=4eY?q9=bEc2%n7gQEYDMic5fM)pkergI+tdEXH18$^M zcuI+H1jz$anN zl+uzi6lr8K^H}owKlxbX7V`-9>CL9&0tM#|yx8~Y@R>#Fs5$;~?m^dv#_fwY5_q&P zq{lf4T{|3UP#5TPZgK@2^AeA97&^{ftV`$(fUDrFc?jnqbgv`MDwp}`GT}IHVVH9l zy7>sRJjT)IH4_f&{vwWZAG&nF7Cqu|4s;8gg~z!P9WxORtO|O>D}*DjoP$wkh2A1; zT~@jC5MkjZ0go=hN<<}Jg3M>$xRl?T(B2%Zyo&NJYxi^59=Uh)~r zeGGV%G0WxraWwGS5Vp#rPd+xlS^U{C_qC&95MksZ9^FPb3y*W;;lL9|2Te>1@1-a_ z&ef7vp1!_YfXDL5AHNr$dIr4LO?vReMLe$USr>WY^+z}>Ot`8F-+5)gyeygT2ON#p zR)xAmMOeZ1K6pn0&_TpmmxcEwBCIgehONT4=c6L5;E6tXsVeTenZdj){?NUIOsx2& zz;jqc5NQSJM~OkI((qU&3<>QM>&^C{?z2x)#@5yPuq3T#qKH*g&L>F<@$@VM`1ccgnbg&43?k_7K_zUa_JUh7B-a zqagNm1EvKv`m_PZ3)mXxV#OVy(MOH+!6Kdg(SUK51{eDsuUH{D=xziy7`N`jV#OUG zWQ=}b;2SeT_6q|x7^nUlFm9r7QO|kBO1LSCx?;s0W=}+HuO3Kztb|8hu@V=*d#+e9 z+C;;{BYMJEyYzLpArS+I@Dv0s`Nd!anr$SBf2O+;vgBivWN8s#OFlNp=PtmOd~CQg zt_95cQJ-w6-+K7`{xdI|bguL`{BpCsSRQq&H45%qego2noAPJ*e*!G-`{1+u_u$j! z^0G;Tr7-+xevSZc=L8KG%Zt`?)^A``1mVm+Fb~XG7t{0m!1Dp;jx@$m(&yvcPXgxn zL0AR6X{<$IkW>rU9t8&h|73Je`h$SmF6)8U13sAA1OFQE^eFf#!0%q!lm6d;pNoQ@ z1N_yvp7c$C-?_X8eg$w!RQjuct&8;)TP0=$;az>w{{*;dx-kc0eM5lDXGjvqJHmV= zopd91R7^MqCZiqjQ}CI79{jpln6IGg6HW%ae6Cp_;1s~Wje^GmelZH31o+h`I34gG zqu?ySqoUyGF@yD)gLLa6?Ck?{Vl*E5OFK$^UJBUi-?o^qyYB~V^>16uxzhgv{IaEQ zF@vN(0B!)Bi2N~tcLU}(xp@(82W;6B((3@s>q0nAo#J3p+sh>BSpg4{&Nppug_%AY zaC$L#Fw=hyxC<~X?GVV1Cl8;Dg6{xa4j3vb(pA8`yl^b0Ku5GU4w{m_se;%WN3* z4~yTQ0q%m4wd6aE>9`E}V?GTyp+J(@rCFZOO#iunar6^#>O#yl%=9`l{V6m3X~6SA zjPnlW-)5$hEskbynQ)egf53!)YQp~j>;&*@6u|t)nO=equZZ+PQvZHvU#BDuHsx_4 zVf43un(ci#U|v_ivHp_*r`{?_FPZ5#0^Ss*Uv~gb&oSm$EN>;?_CnY=k$;f%AmH*5 zl61WZKMS~FGWw`V?^VDFXsq#O`X0b_(C4d7_(Q;wf<9{U`z2vq=;DGup|}V`r38F7 z6ge04Ktj}i1YllnQJ!J9Hepbty(ho7n(0Xb#+yFomC8l^9tfO8k($d*a(JHX|TpG7~>0eUF!I#WJ8Ksq0l%QW#P z0dBw4s{bHqI^c5XH|-V6_X18wd%teN6@aOnc_v&1IE})?#roAS9oJ9c*xvl`M0z=F zbgV(|DKmYYS>KlkW3sx#g`i3VJ>1}AfSXtq?xK72UExy-AbV!U78uaDjb2`1kTVvtrjNUt9F3bmM#fDbC*vlN zm2nfu?zjmPr80k6VX^-XGU6|RCb)||6+ZWsfX!VrB)At8Uhue!yJ9nuM z3V2%V1;C#2%NZFtH(ZZ&91JM)32ddrSC*chJ^hBv>)qp0QcduOA8iOTKO2Elq~XK$2dAFvUO`P9Gz6T$mdgv-36uP#RXF3;tIuknsO@qi*VE- zI$J?up{Ep*K(iJ5N{djZo?b`wpLVBvmbqhpJ+%_8Ye?P=J)!oos}}l8(bmvE#Z!je zQM9?_7OS0N-~TjxuzIFel_)qnp)3>I-qzmsBF`dVoFQMS2TEu1fI^C_FqsjemKci8 zT#jb)RYb>_*`v37C4Xh9$5S4SWp+b%p;A#QG^nz;;0_OLg~t<(#$9=8R0SH#BcZL! zPA7U+xuCL~ou{Gz+G4TIcvH*WeH(+#7+sQu*NboCR7y0OSvzZ$njDQg6H67Iavysx z&c{fVN)aR#O$iNASiUSerqEY;I#T7n(o(BNP^D#MFjEn|@Kuz+bg|N97LK6+Qb{FN zs(X=-WLi)F3rI~eYr`A{p(t&QN`pEH+tbTVxP{TQNWl6)fs5P={EFg(Ju`FDHW)2y zMnJQL;#vrbZ{fmHkGps05l0F9<&tskpjRDAeU-fw#3b9(YLfTN9iyzsU51Y2E=O0w zxdy|6nCEvSZ+QjmXfKJm-PjMXM#+fu7Q#RmdZa}dMtz0R%$dBHr%z6?d_Ab+t=dN` z=$RUT>c3!_yCl*XjrMhy`*=|AER0B+B@m$(h81(W3zrtqj24uZERWKsu_;#? b94{+aBCMtls^Z2`o<2PH(8ie|)cSt|kSxZ* literal 0 HcmV?d00001 diff --git a/WiiUseJ_0.12/src/img/wiimote.png b/WiiUseJ_0.12/src/img/wiimote.png new file mode 100644 index 0000000000000000000000000000000000000000..3f26f5202b22a89c5fa3e1c1eb524f78e4e76e81 GIT binary patch literal 44340 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 z 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 Ef|!^34gdfE literal 0 HcmV?d00001 diff --git a/WiiUseJ_0.12/src/wiiusej/WiiUseApi.java b/WiiUseJ_0.12/src/wiiusej/WiiUseApi.java new file mode 100644 index 0000000..428f522 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/WiiUseApi.java @@ -0,0 +1,351 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej; + +import wiiusej.wiiusejevents.utils.EventsGatherer; + +/** + * Singleton used to manipulate WiiUse Api. + * + * @author guiguito + */ +public class WiiUseApi { + + static { + System.loadLibrary("WiiuseJ"); + } + + private static WiiUseApi instance = new WiiUseApi(); + + /** + * Get the only instance of WiiUseApi. + * + * @return the only instace of WiiUseApi. + */ + protected static WiiUseApi getInstance() { + return instance; + } + + /** + * Connect to a wiimote or wiimotes once an address is known. + * + * @param nbWiimotes + * The number of wiimotes. + * @return The number of wiimotes that successfully connected. + */ + synchronized native int connect(int nbWiimotes); + + /** + * Find a wiimote or wiimotes. + * + * @param nbMaxWiimotes + * The number of wiimotes. + * @param timeout + * The number of seconds before the search times out. + * @return The number of wiimotes found. + */ + synchronized native int find(int nbMaxWiimotes, int timeout); + + /** + * Initialize an array of wiimote structures (for the C side of the + * library). + * + * @param nbPossibleWiimotes + * size of the array. + */ + synchronized native void init(int nbPossibleWiimotes); + + /** + * Close connection to the wiimote with the given id. + * + */ + synchronized native void closeConnection(int id); + + /** + * Get unique id of a wiimote in the wiimotes array. Please make sure you + * call an existing index with a wiimote initialized at this index, other + * wise you'll get a wrong value. + * + * @param index + * index of the wiimote in the wiimotes array. + * @return the unid of the wiimote, or a wrong value if the index was false. + * + */ + synchronized native int getUnId(int index); + + /** + * CleanUp Wiiuse API. + */ + synchronized native void cleanUp(); + + /** + * Activate rumble on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void activateRumble(int id); + + /** + * Deactivate rumble on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void deactivateRumble(int id); + + /** + * Activate IR Tracking on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void activateIRTracking(int id); + + /** + * Deactivate IR Tracking on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void deactivateIRTracking(int id); + + /** + * Activate motion sensing on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void activateMotionSensing(int id); + + /** + * Deactivate motion sensing on the wiimote with the given id. + * + * @param id + * the id of the wiimote. + */ + synchronized native void deactivateMotionSensing(int id); + + /** + * Set wiimote leds status. + * + * @param id + * the id of the wiimote concerned. + * @param led1 + * status of led1: True=ON, False=OFF. + * @param led2 + * status of led2: True=ON, False=OFF. + * @param led3 + * status of led3: True=ON, False=OFF. + * @param led4 + * status of led4: True=ON, False=OFF. + */ + synchronized native void setLeds(int id, boolean led1, boolean led2, + boolean led3, boolean led4); + + /** + * Set how many degrees an angle must change to generate an event. + * + * @param id + * id of the wiimote concerned. + * @param angle + * minimum angle detected by an event. + */ + synchronized native void setOrientThreshold(int id, float angle); + + /** + * Set how much acceleration must change to generate an event. + * + * @param id + * id of the wiimote concerned. + * @param value + * minimum value detected by an event. + */ + synchronized native void setAccelThreshold(int id, int value); + + /** + * Set alpha smoothing parameter for the given id. + * + * @param id + * id of the wiimote concerned. + * @param value + * alpha smoothing value. + */ + synchronized native void setAlphaSmoothing(int id, float value); + + /** + * Try to resync with the wiimote by starting a new handshake. + * + * @param id + * id of the wiimote concerned. + */ + synchronized native void reSync(int id); + + /** + * Make the the accelerometers give smoother results. This is set by + * default. + * + * @param id + * the id of the wiimote concerned. + */ + synchronized native void activateSmoothing(int id); + + /** + * Make the the accelerometers give raw results. + * + * @param id + * the id of the wiimote concerned. + */ + synchronized native void deactivateSmoothing(int id); + + /** + * Make the wiimote generate an event each time we poll. Not set by default. + * + * @param id + * the id of the wiimote concerned. + */ + synchronized native void activateContinuous(int id); + + /** + * Make the wiimote generate an event only when there is one. + * + * @param id + * the id of the wiimote concerned. + */ + synchronized native void deactivateContinuous(int id); + + /** + * Notify wiiuse that your screen has an aspect ratio of 4/3. + * + * @param id + * the id of the wiimote of which we want the status. + */ + synchronized native void setScreenRatio43(int id); + + /** + * Notify wiiuse that your screen has an aspect ratio of 16/9. + * + * @param id + * the id of the wiimote of which we want the status. + */ + synchronized native void setScreenRatio169(int id); + + /** + * Notify wiiuse that the sensor bar is above your screen. + * + * @param id + * the id of the wiimote of which we want the status. + */ + synchronized native void setSensorBarAboveScreen(int id); + + /** + * Notify wiiuse that the sensor bar is below your screen. + * + * @param id + * the id of the wiimote of which we want the status. + */ + synchronized native void setSensorBarBelowScreen(int id); + + /** + * Set virtual screen resolution. It is used to automatically compute the + * position of a cursor on this virtual screen using the sensor bar. These + * results come in the IREvent. + * + * @param id + * the id of the wiimote of which we want the status. + * @param x + * x resolution. + * @param y + * y resolution. + */ + synchronized native void setVirtualScreenResolution(int id, int x, int y); + + /** + * Get status and values from the wiimotes and send it through callbacks. + * + * @param id + * the id of the wiimote of which we want the status. + */ + synchronized native void getStatus(int id); + + /** + * Set the normal and expansion handshake timeouts. + * + * @param id + * the id of the wiimote concerned. + * @param normalTimeout + * The timeout in milliseconds for a normal read. + * @param expansionTimeout + * The timeout in millisecondsd to wait for an expansion + * handshake. + */ + synchronized native void setTimeout(int id, short normalTimeout, + short expansionTimeout); + + /** + * Set the IR sensitivity. + * + * @param id + * the id of the wiimote concerned. + * @param level + * 1-5, same as Wii system sensitivity setting. If the level is < + * 1, then level will be set to 1. If the level is > 5, then + * level will be set to 5. + */ + synchronized native void setIrSensitivity(int id, int level); + + /** + * Set how many degrees an angle must change to generate an event for the + * nunchuk. + * + * @param id + * id of the wiimote concerned. + * @param angle + * minimum angle detected by an event. + */ + synchronized native void setNunchukOrientationThreshold(int id, float angle); + + /** + * Set how much acceleration must change to generate an event for the + * nunchuk. + * + * @param id + * id of the wiimote concerned. + * @param value + * minimum value detected by an event. + */ + synchronized native void setNunchukAccelerationThreshold(int id, int value); + + /** + * Force the bluetooth stack type.(useful only for windows) + * + * @param bluetoothStackType + * must be WiiUseApi.WIIUSE_STACK_UNKNOWN or + * WiiUseApi.WIIUSE_STACK_MS or + * WiiUseApi.WIIUSE_STACK_BLUESOLEIL. + */ + native void windowsSetBluetoothStack(int bluetoothStackType); + + /** + * Check for new Events and Get it. + * + * @param gath + * the object where we store all the new events. + */ + native void specialPoll(EventsGatherer gath); + +} diff --git a/WiiUseJ_0.12/src/wiiusej/WiiUseApiManager.java b/WiiUseJ_0.12/src/wiiusej/WiiUseApiManager.java new file mode 100644 index 0000000..9378660 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/WiiUseApiManager.java @@ -0,0 +1,662 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.swing.event.EventListenerList; + +import wiiusej.wiiusejevents.utils.EventsGatherer; +import wiiusej.wiiusejevents.utils.WiiUseApiListener; +import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent; + +/** + * Class that manages the use of Wiiuse API. + * + * @author guiguito + */ +public class WiiUseApiManager extends Thread { + + private static WiiUseApiManager instance = new WiiUseApiManager(); + + private final EventListenerList listeners = new EventListenerList(); + + private Semaphore semaphore = new Semaphore(0); + + private Wiimote[] wiimotes; + + private WiiUseApi wiiuse = WiiUseApi.getInstance(); + + private int connected = -1; + + private AtomicBoolean running = new AtomicBoolean(false); + + private boolean leave = false; + + public static int WIIUSE_STACK_UNKNOWN = 0; + public static int WIIUSE_STACK_MS = 1; + public static int WIIUSE_STACK_BLUESOLEIL = 2; + + private static WiiUseApiManager getInstance() { + return instance; + } + + /** + * Get wiimotes. Load library if necessary. Connect to wiimotes if + * necessary. Start polling if necessary. Return an array with the connected + * wiimotes. + * + * @param nb + * try to connect nb wiimotes. + * @param rumble + * make the connected wiimotes rumble. + * + * @return an array with connected wiimotes or NULL. + */ + public static Wiimote[] getWiimotes(int nb, boolean rumble) { + return getWiimotesPrivate(nb, rumble, false, WIIUSE_STACK_UNKNOWN); + } + + /** + * Get wiimotes. Load library if necessary. Connect to wiimotes if + * necessary. Start polling if necessary. Return an array with the connected + * wiimotes. + * + * @param nb + * try to connect nb wiimotes. + * @param rumble + * make the connected wiimotes rumble.* + * @param stackType + * the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or + * WiiUseApiManager.WIIUSE_STACK_MS or + * WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL + * + * @return an array with connected wiimotes or NULL. + */ + public static Wiimote[] getWiimotes(int nb, boolean rumble, int stackType) { + return getWiimotesPrivate(nb, rumble, true, stackType); + } + + /** + * Get wiimotes. Load library if necessary. Connect to wiimotes if + * necessary. Start polling if necessary. Return an array with the connected + * wiimotes. + * + * @param nb + * try to connect nb wiimotes. + * @param rumble + * make the connected wiimotes rumble.* + * @param forceStackType + * true if we want to force the stack type. + * @param stackType + * the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or + * WiiUseApiManager.WIIUSE_STACK_MS or + * WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL + * + * @return an array with connected wiimotes or NULL. + */ + private synchronized static Wiimote[] getWiimotesPrivate(int nb, + boolean rumble, boolean forceStackType, int stackType) { + WiiUseApiManager manager = getInstance(); + + if (manager.leave) + return null;// wiiusej definitively stopped + + if (manager.connected <= 0 && !manager.running.get()) { + // connect wiimotes. + int nbWiimotes = manager.connectWiimotes(nb, rumble, + forceStackType, stackType); + manager.wiimotes = new Wiimote[nbWiimotes]; + for (int i = 0; i < nbWiimotes; i++) { + Wiimote wim = new Wiimote(WiiUseApi.getInstance().getUnId(i), + manager); + manager.wiimotes[i] = wim; + manager.addWiiUseApiListener(wim); + } + // Set leds on wiimote + for (Wiimote wiimote : manager.wiimotes) { + int id = wiimote.getId(); + if (id % 4 == 0) { + wiimote.setLeds(true, true, true, true); + } else if (id % 4 == 1) { + wiimote.setLeds(true, false, false, false); + } else if (id % 4 == 2) { + wiimote.setLeds(true, true, false, false); + } else if (id % 4 == 3) { + wiimote.setLeds(true, true, true, false); + } + } + // make the connected wiimotes rumble + if (rumble) { + for (Wiimote wiimote : manager.wiimotes) { + wiimote.activateRumble(); + } + try { + sleep(500); + } catch (InterruptedException e) { + } + for (Wiimote wiimote : manager.wiimotes) { + wiimote.deactivateRumble(); + } + } + } + + if (manager.connected == 0) {// no wiimote connected + // return empty array + return new Wiimote[0]; + } + + if (!manager.isAlive())// start wiiuseJ polling + manager.start(); + + manager.semaphore.release(1); + + return manager.wiimotes; + } + + /** + * Connect wiimote and get the number of wiimotes connected. Supposed to be + * used once. + * + * @param nb + * try to connect nb wiimotes + * @param rumble + * make the connected wiimotes rumble + * @param forceStackType + * true if we want to force the stack type. + * @param stackType + * the stack type : WiiUseApiManager.WIIUSE_STACK_UNKNOWN or + * WiiUseApiManager.WIIUSE_STACK_MS or + * WiiUseApiManager.WIIUSE_STACK_BLUESOLEIL + * @return 0 if nothing connected or the number of wiimotes connected. + */ + private int connectWiimotes(int nb, boolean rumble, boolean forceStackType, + int stackType) { + if (connected <= 0) { + int nbWiimotesFound; + wiiuse.init(nb); + // force bluetooth stack type ? + if (forceStackType) + setBlueToothstackType(stackType); + nbWiimotesFound = wiiuse.find(nb, 3); + connected = wiiuse.connect(nbWiimotesFound); + return connected; + } else {// library not loaded, no wiimotes connected + return 0; + } + } + + /** + * Ask the thread to close a connection. + * + * @param id + * id of the wiimote to disconnect. + */ + protected void closeConnection(int id) { + int index = 0; + boolean found = false; + while (index < wiimotes.length && !found) { + if (wiimotes[index].getId() == id) {// we have a wiimote with this + // id + // remove the wiimote + removeWiiUseApiListener(wiimotes[index]); + wiimotes[index] = null; + connected--; + if (connected == 0) {// stop this thread if there is + // no more wiimotes connected. + // stop thread + running.set(false); + } + /* Close connection in wiiuse */ + wiiuse.closeConnection(index); + } + index++; + } + + } + + /** + * Get the number of wiimotes connected. + * + * @return the number of wiimotes connected. + */ + public static int getNbConnectedWiimotes() { + return getInstance().connected; + } + + /** + * Stop thread and shutdown wiiuse Api. + */ + public static void shutdown() { + WiiUseApiManager manager = getInstance(); + if (manager.connected > 0) { + for (Wiimote wim : manager.wiimotes) { + if (wim != null) + wim.disconnect(); + } + } + manager.running.set(false); + manager.wiiuse.cleanUp(); + } + + /** + * Stop wiiuseJ definitively for this program. It finishes Wiiusej thread + * and shutdown wiiuse API. + */ + public static void definitiveShutdown() { + getInstance().leave = true; + shutdown(); + } + + /** + * Activate the rumble for the wiimote with the given id. + * + * @param id + * id of the wiimote. + */ + protected void activateRumble(int id) { + wiiuse.activateRumble(id); + } + + /** + * Deactivate the rumble for the wiimote with the given id. + * + * @param id + * id of the wiimote. + */ + protected void deactivateRumble(int id) { + wiiuse.deactivateRumble(id); + } + + /** + * Activate IR Tracking for the wiimote with the given id. + * + * @param id + * id of the wiimote. + */ + protected void activateIRTRacking(int id) { + wiiuse.activateIRTracking(id); + } + + /** + * Deactivate IR Tracking for the wiimote with the given id. + * + * @param id + * id of the wiimote. + */ + protected void deactivateIRTRacking(int id) { + wiiuse.deactivateIRTracking(id); + } + + /** + * Activate motion sensing for the wiimote with the given id. + * + * @param id + * id of the wiimote. + */ + protected void activateMotionSensing(int id) { + wiiuse.activateMotionSensing(id); + } + + /** + * Deactivate motion sensing for the wiimoter with the given id. + * + * @param id + * id of the wiimote. + */ + protected void deactivateMotionSensing(int id) { + wiiuse.deactivateMotionSensing(id); + } + + /** + * Activate smoothing the wiimotes with the given id. + * + * @param id + * id of the wiimote. + */ + protected void activateSmoothing(int id) { + wiiuse.activateSmoothing(id); + } + + /** + * Deactivate smoothing the wiimotes with the given id. + * + * @param id + * id of the wiimote. + */ + protected void deactivateSmoothing(int id) { + wiiuse.deactivateSmoothing(id); + } + + /** + * Activate continuous for the wiimotes with the given id. + * + * @param id + * id of the wiimote. + */ + protected void activateContinuous(int id) { + wiiuse.activateContinuous(id); + } + + /** + * Deactivate continuous for the wiimotes with the given id. + * + * @param id + * id of the wiimote. + */ + protected void deactivateContinuous(int id) { + wiiuse.deactivateContinuous(id); + } + + /** + * Set leds for the wiimotes with the given id. + * + * @param id + * id of the wiimote + * @param l1 + * status of led1. True : ON, False : OFF. + * @param l2 + * status of led2. True : ON, False : OFF. + * @param l3 + * status of led3. True : ON, False : OFF. + * @param l4 + * status of led4. True : ON, False : OFF. + */ + protected void setLeds(int id, boolean l1, boolean l2, boolean l3, + boolean l4) { + wiiuse.setLeds(id, l1, l2, l3, l4); + } + + /** + * Set the orientation threshold for the given id. (minimum angle between + * two events) + * + * @param id + * id of the wiimote. + * @param th + * threshold in degrees. + */ + protected void setOrientationThreshold(int id, float th) { + wiiuse.setOrientThreshold(id, th); + } + + /** + * Set the acceleration threshold for the given id. (minimum angle between + * two events) + * + * @param id + * id of the wiimote. + * @param th + * threshold. + */ + protected void setAccelerationThreshold(int id, int th) { + wiiuse.setAccelThreshold(id, th); + } + + /** + * Set alpha smoothing for the given id. + * + * @param id + * id of the wiimote. + * @param th + * threshold. + */ + protected void setAlphaSmoothing(int id, float th) { + wiiuse.setAlphaSmoothing(id, th); + } + + /** + * Try to resync with the wiimote by starting a new handshake. + * + * @param id + * id of the wiimote. + */ + protected void reSync(int id) { + wiiuse.reSync(id); + } + + /** + * Set screen aspect ratio to 4/3 for the given id. + * + * @param id + * id of the wiimote. + */ + protected void setScreenAspectRatio43(int id) { + wiiuse.setScreenRatio43(id); + } + + /** + * Set screen aspect ratio to 16/9 for the given id. + * + * @param id + * id of the wiimote. + */ + protected void setScreenAspectRatio169(int id) { + wiiuse.setScreenRatio169(id); + } + + /** + * Set the sensor bar to be above the screen. + * + * @param id + * id of the wiimote. + */ + protected void setSensorBarAboveScreen(int id) { + wiiuse.setSensorBarAboveScreen(id); + } + + /** + * Set the sensor bar to be below the screen. + * + * @param id + * id of the wiimote. + */ + protected void setSensorBarBelowScreen(int id) { + wiiuse.setSensorBarBelowScreen(id); + } + + /** + * Set virtual resolution. It is used to automatically compute the position + * of a cursor on this virtual screen using the sensor bar. These results + * come in the IREvent. + * + * @param id + * id of the wiimote. + * @param x + * x resolution. + * @param y + * y resolution. + */ + protected void setVirtualResolution(int id, int x, int y) { + wiiuse.setVirtualScreenResolution(id, x, y); + } + + /** + * Get Status for the wiimote for the given id. + * + * @param id + * id of the wiimote. + */ + protected void getStatus(int id) { + wiiuse.getStatus(id); + } + + /** + * Set the normal and expansion handshake timeouts. + * + * @param id + * the id of the wiimote concerned. + * @param normalTimeout + * The timeout in milliseconds for a normal read. + * @param expansionTimeout + * The timeout in millisecondsd to wait for an expansion + * handshake. + */ + protected void setTimeout(int id, short normalTimeout, + short expansionTimeout) { + wiiuse.setTimeout(id, normalTimeout, expansionTimeout); + } + + /** + * Set the IR sensitivity. + * + * @param id + * the id of the wiimote concerned. + * @param level + * 1-5, same as Wii system sensitivity setting. If the level is < + * 1, then level will be set to 1. If the level is > 5, then + * level will be set to 5. + */ + protected void setIrSensitivity(int id, int level) { + wiiuse.setIrSensitivity(id, level); + } + + /** + * Set the nunchuk orientation threshold for the given id. (minimum angle + * between two events) + * + * @param id + * id of the wiimote. + * @param th + * threshold in degrees. + */ + protected void setNunchukOrientationThreshold(int id, float th) { + wiiuse.setNunchukOrientationThreshold(id, th); + } + + /** + * Set the nunchuk acceleration threshold for the given id. (minimum angle + * between two events) + * + * @param id + * id of the wiimote. + * @param th + * threshold. + */ + protected void setNunchukAccelerationThreshold(int id, int th) { + wiiuse.setNunchukAccelerationThreshold(id, th); + } + + /** + * Force the bluetooth stack type.(useful only for windows) + * + * @param type + * must be WIIUSE_STACK_UNKNOWN or WIIUSE_STACK_MS or + * WIIUSE_STACK_BLUESOLEIL. + */ + private void setBlueToothstackType(int type) { + wiiuse.windowsSetBluetoothStack(type); + } + + @Override + public void run() { + + while (!leave) { + try { + semaphore.acquire(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if (connected > 0) { + running.set(true); + + EventsGatherer gather = new EventsGatherer(connected); + + // Start polling and tell the observers when there are Wiimote + // events + while (running.get() && connected > 0) { + + /* Polling */ + wiiuse.specialPoll(gather); + + /* deal with events gathered in Wiiuse API */ + for (WiiUseApiEvent evt : gather.getEvents()) { + if (evt.getWiimoteId() != -1) {// event filled + // there is an event notify observers + notifyWiiUseApiListener(evt); + if (evt.getEventType() == WiiUseApiEvent.DISCONNECTION_EVENT) { + // check if it was a disconnection + // in this case disconnect the wiimote + closeConnection(evt.getWiimoteId()); + } + } else { + System.out + .println("There is an event with id == -1 ??? there is a problem !!! : " + + evt); + } + } + gather.clearEvents(); + } + }/* else { + if (connected <= 0) { + System.out.println("No wiimotes connected !"); + } + }*/ + }// end while true + } + + /** + * Add WiiUseApiListener to the listeners list. + * + * @param listener + * a WiiUseApiListener + */ + protected void addWiiUseApiListener(WiiUseApiListener listener) { + listeners.add(WiiUseApiListener.class, listener); + } + + /** + * Remove WiiUseApiListener from the listeners list. + * + * @param listener + * a WiiUseApiListener + */ + protected void removeWiiUseApiListener(WiiUseApiListener listener) { + listeners.remove(WiiUseApiListener.class, listener); + } + + /** + * Get the list of WiiUseApiListeners. + * + * @return the list of WiiUseApiListeners. + */ + protected WiiUseApiListener[] getWiiUseApiListeners() { + return listeners.getListeners(WiiUseApiListener.class); + } + + /** + * Notify WiiUseApiListeners that an event occured. + * + * @param evt + * GenericEvent occured + */ + private void notifyWiiUseApiListener(WiiUseApiEvent evt) { + for (WiiUseApiListener listener : getWiiUseApiListeners()) { + listener.onWiiUseApiEvent(evt); + } + } + + /** + * Called by the garbage collector at the end. + */ + protected void finalize() throws Throwable { + shutdown(); + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/Wiimote.java b/WiiUseJ_0.12/src/wiiusej/Wiimote.java new file mode 100644 index 0000000..98a5233 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/Wiimote.java @@ -0,0 +1,435 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej; + +import javax.swing.event.EventListenerList; + +import wiiusej.wiiusejevents.utils.WiiUseApiListener; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; +import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent; +import wiiusej.wiiusejevents.wiiuseapievents.WiimoteEvent; + +/** + * Class that represents a wiimote. You can register as an observer of this + * wiimote to listen events from it. You manage it. + * + * @author guiguito + */ +public class Wiimote implements WiiUseApiListener { + + private int id = -1;// wiimote id + + private EventListenerList listeners = new EventListenerList(); + + private WiiUseApiManager manager; + + /** + * Constructor. + * + * @param idd + * id of the wiimote + * @param manager + * manager wo built it. + */ + public Wiimote(int idd, WiiUseApiManager manager) { + id = idd; + this.manager = manager; + } + + /** + * Get the unique id of the wiimote. + * + * @return the id + */ + public int getId() { + return id; + } + + /** + * Disconnect this wiimote. + */ + public void disconnect() { + deactivateIRTRacking(); + deactivateMotionSensing(); + deactivateRumble(); + manager.closeConnection(id); + } + + /** + * Activate the rumble. + */ + public void activateRumble() { + manager.activateRumble(id); + } + + /** + * Deactivate the rumble. + */ + public void deactivateRumble() { + manager.deactivateRumble(id); + } + + /** + * Activate IR Tracking. + */ + public void activateIRTRacking() { + manager.activateIRTRacking(id); + } + + /** + * Deactivate IR Tracking. + */ + public void deactivateIRTRacking() { + manager.deactivateIRTRacking(id); + } + + /** + * Activate motion sensing. + */ + public void activateMotionSensing() { + manager.activateMotionSensing(id); + } + + /** + * Deactivate motion sensing. + */ + public void deactivateMotionSensing() { + manager.deactivateMotionSensing(id); + } + + /** + * Activate smoothing. + */ + public void activateSmoothing() { + manager.activateSmoothing(id); + } + + /** + * Deactivate smoothing. + */ + public void deactivateSmoothing() { + manager.deactivateSmoothing(id); + } + + /** + * Activate continuous. + */ + public void activateContinuous() { + manager.activateContinuous(id); + } + + /** + * Deactivate continuous. + */ + public void deactivateContinuous() { + manager.deactivateContinuous(id); + + } + + /** + * Set leds status. + * + * @param l1 + * status of led1. True : ON, False : OFF + * @param l2 + * status of led2. True : ON, False : OFF + * @param l3 + * status of led3. True : ON, False : OFF + * @param l4 + * status of led4. True : ON, False : OFF + */ + public void setLeds(boolean l1, boolean l2, boolean l3, boolean l4) { + manager.setLeds(id, l1, l2, l3, l4); + } + + /** + * Set the orientation threshold (minimum angle between two degrees with + * accelerometer). + * + * @param th + * threshold in degrees + */ + public void setOrientationThreshold(float th) { + manager.setOrientationThreshold(id, th); + } + + /** + * Set the acceleration threshold(minimum angle between two degrees with + * accelerometer). + * + * @param th + * threshold + */ + public void setAccelerationThreshold(int th) { + manager.setAccelerationThreshold(id, th); + } + + /** + * Set the alpha smoothing value. + * + * @param th + * threshold + */ + public void setAlphaSmoothingValue(float th) { + manager.setAlphaSmoothing(id, th); + } + + /** + * Set the screen aspect ratio to be considered as 4/3. + */ + public void setScreenAspectRatio43() { + manager.setScreenAspectRatio43(id); + } + + /** + * Set the screen aspect ratio to be considered as 16/9. + */ + public void setScreenAspectRatio169() { + manager.setScreenAspectRatio169(id); + } + + /** + * Set the sensor bar to be considered above the screen. + */ + public void setSensorBarAboveScreen() { + manager.setSensorBarAboveScreen(id); + } + + /** + * Set the sensor bar to be considered below the screen. + */ + public void setSensorBarBelowScreen() { + manager.setSensorBarBelowScreen(id); + } + + /** + * Set the screen resolution of the you are pointing at with your wiimote. + * + * @param x + * x resolution. + * @param y + * y resolution. + */ + public void setVirtualResolution(int x, int y) { + manager.setVirtualResolution(id, x, y); + } + + /** + * Set the nunchuk orientation threshold for the given id. (minimum angle + * between two events) + * + * @param th + * threshold in degrees. + */ + public void setNunchukOrientationThreshold(float th) { + manager.setNunchukOrientationThreshold(id, th); + } + + /** + * Set the nunchuk acceleration threshold for the given id. (minimum angle + * between two events) + * + * @param th + * threshold. + */ + public void setNunchukAccelerationThreshold(int th) { + manager.setNunchukAccelerationThreshold(id, th); + } + + /** + * Try to resync the wiimote by starting a new handshake. + */ + public void reSync() { + manager.reSync(id); + } + + /** + * Ask for the status of the wiimote. The result will be received in a + * status event object. Implements onStatusEvent on wiimote listener to get + * it. + */ + public void getStatus() { + manager.getStatus(id); + } + + /** + * Set the normal and expansion handshake timeouts for this wiimote. Normal + * time out is for classic polling. The expansion timeout is used when an + * expansion is detected until the expansion successfully handshakes. + * + * @param normalTimeout + * The timeout in milliseconds for a normal read. + * @param expansionTimeout + * The timeout in millisecondsd to wait for an expansion + * handshake. + */ + public void setTimeout(short normalTimeout, short expansionTimeout) { + manager.setTimeout(id, normalTimeout, expansionTimeout); + } + + /** + * Set the IR sensitivity. + * + * @param level + * 1-5, same as Wii system sensitivity setting. If the level is < + * 1, then level will be set to 1. If the level is > 5, then + * level will be set to 5. + */ + public void setIrSensitivity(int level) { + manager.setIrSensitivity(id, level); + } + + /** + * Method called when a WiiUseApiEvent occurs. + * + * @param e + * the WiiUseApiEvent. + */ + public void onWiiUseApiEvent(WiiUseApiEvent e) { + if (e.getWiimoteId() == id) { + if (e.getEventType() == WiiUseApiEvent.GENERIC_EVENT) { + notifyWiiMoteEventListeners((WiimoteEvent) e); + } else if (e.getEventType() == WiiUseApiEvent.STATUS_EVENT) { + notifyStatusEventListeners((StatusEvent) e); + } else if (e.getEventType() == WiiUseApiEvent.DISCONNECTION_EVENT) { + notifyDisconnectionEventListeners((DisconnectionEvent) e); + } else if (e.getEventType() == WiiUseApiEvent.WIIUSE_NUNCHUK_INSERTED) { + notifyNunchukInsertedEventListeners((NunchukInsertedEvent) e); + } else if (e.getEventType() == WiiUseApiEvent.WIIUSE_NUNCHUK_REMOVED) { + notifyNunchukRemovedEventListeners((NunchukRemovedEvent) e); + } + /* + * events not managed yet || e.getEventType() == WIIUSE_READ_DATA + * WiiUseApiEvent.WIIUSE_CLASSIC_CTRL_INSERTED || e.getEventType() == + * WiiUseApiEvent.WIIUSE_CLASSIC_CTRL_REMOVED || e.getEventType() == + * WiiUseApiEvent.WIIUSE_GUITAR_HERO_3_CTRL_INSERTED || + * e.getEventType() == + * WiiUseApiEvent.WIIUSE_GUITAR_HERO_3_CTRL_REMOVED + */ + } + } + + /** + * Add a WiimoteListener to the listeners list. + * + * @param listener + * a WiimoteListener + */ + public void addWiiMoteEventListeners(WiimoteListener listener) { + listeners.add(WiimoteListener.class, listener); + } + + /** + * Remove a WiimoteListener from the listeners list. + * + * @param listener + * a WiimoteListener + */ + public void removeWiiMoteEventListeners(WiimoteListener listener) { + listeners.remove(WiimoteListener.class, listener); + } + + /** + * Get the list of WiimoteListener. + * + * @return the list of WiimoteListener. + */ + public WiimoteListener[] getWiiMoteEventListeners() { + return listeners.getListeners(WiimoteListener.class); + } + + /** + * Notify WiimoteListeners that an event occured. Notify in first the + * listeners for Buttons Events. In second the listeners for IR Events. In + * third the listeners for Motion sensing events. + * + * @param evt + * GenericEvent occured + */ + private void notifyWiiMoteEventListeners(WiimoteEvent evt) { + for (WiimoteListener listener : getWiiMoteEventListeners()) { + listener.onButtonsEvent(evt.getButtonsEvent()); + if (evt.isThereIrEvent()) { + listener.onIrEvent(evt.getIREvent()); + } + if (evt.isThereMotionSensingEvent()) { + listener.onMotionSensingEvent(evt.getMotionSensingEvent()); + } + if (evt.isThereExpansionEvent()) { + listener.onExpansionEvent(evt.getExpansionEvent()); + } + } + } + + /** + * Notify WiimoteListener that a status event occured. + * + * @param evt + * status event occured + */ + private void notifyStatusEventListeners(StatusEvent evt) { + for (WiimoteListener listener : getWiiMoteEventListeners()) { + listener.onStatusEvent(evt); + } + } + + /** + * Notify WiimoteListener that a disconnection event occured. + * + * @param evt + * disconnection event occured + */ + private void notifyDisconnectionEventListeners(DisconnectionEvent evt) { + for (WiimoteListener listener : getWiiMoteEventListeners()) { + listener.onDisconnectionEvent(evt); + } + } + + /** + * Notify WiimoteListener that a NunchukInserted Event occured. + * + * @param evt + * NunchukInserted Event occured + */ + private void notifyNunchukInsertedEventListeners(NunchukInsertedEvent evt) { + for (WiimoteListener listener : getWiiMoteEventListeners()) { + listener.onNunchukInsertedEvent(evt); + } + } + + /** + * Notify WiimoteListener that a NunchukRemoved Event occured. + * + * @param evt + * NunchukRemoved Event occured + */ + private void notifyNunchukRemovedEventListeners(NunchukRemovedEvent evt) { + for (WiimoteListener listener : getWiiMoteEventListeners()) { + listener.onNunchukRemovedEvent(evt); + } + } + + @Override + public String toString() { + return "Wiimote with ID : " + id; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/test/CloseGuiTestCleanly.java b/WiiUseJ_0.12/src/wiiusej/test/CloseGuiTestCleanly.java new file mode 100644 index 0000000..584f2d9 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/test/CloseGuiTestCleanly.java @@ -0,0 +1,58 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.test; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import wiiusej.WiiUseApiManager; + +/** + * This class is used to close wiiusej cleanly. + * + * @author guiguito + */ +public class CloseGuiTestCleanly implements WindowListener { + + public void windowOpened(WindowEvent e) { + // nothing + } + + public void windowClosing(WindowEvent e) { + WiiUseApiManager.definitiveShutdown(); + } + + public void windowClosed(WindowEvent e) { + // nothing + } + + public void windowIconified(WindowEvent e) { + // nothing + } + + public void windowDeiconified(WindowEvent e) { + // nothing + } + + public void windowActivated(WindowEvent e) { + // nothing + } + + public void windowDeactivated(WindowEvent e) { + // nothing + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/test/Main.java b/WiiUseJ_0.12/src/wiiusej/test/Main.java new file mode 100644 index 0000000..67ef279 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/test/Main.java @@ -0,0 +1,45 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.test; + +import wiiusej.WiiUseApiManager; +import wiiusej.Wiimote; + +/** + * Main Class to launch WiiuseJ GUI Test. + * + * @author guiguito + */ +public class Main { + + /** + * @param args + * the command line arguments + */ + public static void main(String[] args) { + Wiimote[] wiimotes = WiiUseApiManager.getWiimotes(1, true); + WiiuseJGuiTest gui = null; + if (wiimotes.length > 0) { + gui = new WiiuseJGuiTest(wiimotes[0]); + } else { + gui = new WiiuseJGuiTest(); + } + gui.setDefaultCloseOperation(WiiuseJGuiTest.EXIT_ON_CLOSE); + gui.setVisible(true); + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/test/NunchukGuiTest.java b/WiiUseJ_0.12/src/wiiusej/test/NunchukGuiTest.java new file mode 100644 index 0000000..7054de8 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/test/NunchukGuiTest.java @@ -0,0 +1,377 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.test; + +import wiiusej.Wiimote; +import wiiusej.utils.AccelerationExpansionEventPanel; +import wiiusej.utils.AccelerationPanel; +import wiiusej.utils.GForceExpansionEventPanel; +import wiiusej.utils.GForcePanel; +import wiiusej.utils.NunchukJoystickEventPanel; +import wiiusej.utils.OrientationExpansionEventPanel; +import wiiusej.utils.OrientationPanel; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukButtonsEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This frame is used to display events from a nunchuk. + * + * @author guiguito + */ +public class NunchukGuiTest extends javax.swing.JFrame implements + WiimoteListener { + + private Wiimote wiimote; + private boolean isThresholdsRequested = true; + + /** Creates new form NunchukGuiTest */ + public NunchukGuiTest(Wiimote wiimote) { + initComponents(); + this.wiimote = wiimote; + registerListeners(); + } + + private void registerListeners() { + wiimote.addWiiMoteEventListeners(this); + wiimote.addWiiMoteEventListeners((OrientationPanel) orientationPanel); + wiimote.addWiiMoteEventListeners((GForcePanel) gForcePanel); + wiimote + .addWiiMoteEventListeners((AccelerationPanel) rawAccelerationPanel); + wiimote + .addWiiMoteEventListeners((NunchukJoystickEventPanel) joystickEventsPanel); + } + + public void unRegisterListeners() { + wiimote + .removeWiiMoteEventListeners((OrientationPanel) orientationPanel); + wiimote.removeWiiMoteEventListeners((GForcePanel) gForcePanel); + wiimote + .removeWiiMoteEventListeners((AccelerationPanel) rawAccelerationPanel); + wiimote + .removeWiiMoteEventListeners((NunchukJoystickEventPanel) joystickEventsPanel); + wiimote.removeWiiMoteEventListeners(this); + } + + public void requestThresholdsUpdate() { + isThresholdsRequested = true; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + topPanels = new javax.swing.JPanel(); + joystickEventsPanel = joystickEventsPanel = new NunchukJoystickEventPanel(); + motionSensingEventsPanel = new javax.swing.JPanel(); + motionSensingEventsTabbedPanels = new javax.swing.JTabbedPane(); + rawAccelerationPanel = new AccelerationExpansionEventPanel(); + orientationPanel = new OrientationExpansionEventPanel(); + gForcePanel = new GForceExpansionEventPanel(); + setNunchukValuesPanel = new javax.swing.JPanel(); + nunchukButtonsEventPanel = new javax.swing.JPanel(); + cButton = new javax.swing.JButton(); + zButton = new javax.swing.JButton(); + nunchukOrientationPanel = new javax.swing.JPanel(); + nunchukOrientationTextField = new javax.swing.JTextField(); + nunchukOrientationButton = new javax.swing.JButton(); + nunchukAccelerationPanel = new javax.swing.JPanel(); + nunchukAccelerationTextField = new javax.swing.JTextField(); + nunchukAccelerationButton = new javax.swing.JButton(); + messagePanel = new javax.swing.JPanel(); + messageText = new javax.swing.JLabel(); + + setTitle("WiiuseJ Nunchuk Test GUI"); + setMinimumSize(new java.awt.Dimension(400, 400)); + getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.Y_AXIS)); + + topPanels.setMinimumSize(new java.awt.Dimension(400, 200)); + topPanels.setPreferredSize(new java.awt.Dimension(400, 200)); + topPanels.setLayout(new javax.swing.BoxLayout(topPanels, javax.swing.BoxLayout.LINE_AXIS)); + + joystickEventsPanel.setBackground(new java.awt.Color(0, 0, 0)); + joystickEventsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(new javax.swing.border.LineBorder(new java.awt.Color(51, 153, 0), 2, true), "Joystick View", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 11), new java.awt.Color(204, 102, 0))); + joystickEventsPanel.setToolTipText("JoystickEvent"); + joystickEventsPanel.setMinimumSize(new java.awt.Dimension(200, 200)); + + javax.swing.GroupLayout joystickEventsPanelLayout = new javax.swing.GroupLayout(joystickEventsPanel); + joystickEventsPanel.setLayout(joystickEventsPanelLayout); + joystickEventsPanelLayout.setHorizontalGroup( + joystickEventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 601, Short.MAX_VALUE) + ); + joystickEventsPanelLayout.setVerticalGroup( + joystickEventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 174, Short.MAX_VALUE) + ); + + topPanels.add(joystickEventsPanel); + joystickEventsPanel.getAccessibleContext().setAccessibleName("Joystick"); + + motionSensingEventsPanel.setMinimumSize(new java.awt.Dimension(200, 200)); + + rawAccelerationPanel.setToolTipText("Nunchuk MotionSensingEvent"); + + javax.swing.GroupLayout rawAccelerationPanelLayout = new javax.swing.GroupLayout(rawAccelerationPanel); + rawAccelerationPanel.setLayout(rawAccelerationPanelLayout); + rawAccelerationPanelLayout.setHorizontalGroup( + rawAccelerationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 597, Short.MAX_VALUE) + ); + rawAccelerationPanelLayout.setVerticalGroup( + rawAccelerationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 175, Short.MAX_VALUE) + ); + + motionSensingEventsTabbedPanels.addTab("RawAcceleration", rawAccelerationPanel); + + javax.swing.GroupLayout orientationPanelLayout = new javax.swing.GroupLayout(orientationPanel); + orientationPanel.setLayout(orientationPanelLayout); + orientationPanelLayout.setHorizontalGroup( + orientationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 597, Short.MAX_VALUE) + ); + orientationPanelLayout.setVerticalGroup( + orientationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 175, Short.MAX_VALUE) + ); + + motionSensingEventsTabbedPanels.addTab("Orientation", orientationPanel); + + javax.swing.GroupLayout gForcePanelLayout = new javax.swing.GroupLayout(gForcePanel); + gForcePanel.setLayout(gForcePanelLayout); + gForcePanelLayout.setHorizontalGroup( + gForcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 597, Short.MAX_VALUE) + ); + gForcePanelLayout.setVerticalGroup( + gForcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 175, Short.MAX_VALUE) + ); + + motionSensingEventsTabbedPanels.addTab("GForce", gForcePanel); + + javax.swing.GroupLayout motionSensingEventsPanelLayout = new javax.swing.GroupLayout(motionSensingEventsPanel); + motionSensingEventsPanel.setLayout(motionSensingEventsPanelLayout); + motionSensingEventsPanelLayout.setHorizontalGroup( + motionSensingEventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(motionSensingEventsTabbedPanels, javax.swing.GroupLayout.DEFAULT_SIZE, 602, Short.MAX_VALUE) + ); + motionSensingEventsPanelLayout.setVerticalGroup( + motionSensingEventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(motionSensingEventsTabbedPanels, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + ); + + topPanels.add(motionSensingEventsPanel); + + getContentPane().add(topPanels); + + setNunchukValuesPanel.setMinimumSize(new java.awt.Dimension(400, 200)); + setNunchukValuesPanel.setPreferredSize(new java.awt.Dimension(400, 200)); + setNunchukValuesPanel.setLayout(new javax.swing.BoxLayout(setNunchukValuesPanel, javax.swing.BoxLayout.Y_AXIS)); + + nunchukButtonsEventPanel.setToolTipText("Nunchuk ButtonsEvent"); + nunchukButtonsEventPanel.setMinimumSize(new java.awt.Dimension(100, 100)); + nunchukButtonsEventPanel.setPreferredSize(new java.awt.Dimension(100, 100)); + nunchukButtonsEventPanel.setLayout(new javax.swing.BoxLayout(nunchukButtonsEventPanel, javax.swing.BoxLayout.LINE_AXIS)); + + cButton.setText("C"); + cButton.setMaximumSize(new java.awt.Dimension(50, 50)); + cButton.setMinimumSize(new java.awt.Dimension(50, 50)); + cButton.setPreferredSize(new java.awt.Dimension(50, 50)); + nunchukButtonsEventPanel.add(cButton); + + zButton.setText("Z"); + zButton.setMaximumSize(new java.awt.Dimension(50, 50)); + zButton.setMinimumSize(new java.awt.Dimension(50, 50)); + zButton.setPreferredSize(new java.awt.Dimension(50, 50)); + nunchukButtonsEventPanel.add(zButton); + + setNunchukValuesPanel.add(nunchukButtonsEventPanel); + + nunchukOrientationTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + nunchukOrientationPanel.add(nunchukOrientationTextField); + + nunchukOrientationButton.setText("Set Orientation Threshold"); + nunchukOrientationButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + nunchukOrientationButtonMousePressed(evt); + } + }); + nunchukOrientationPanel.add(nunchukOrientationButton); + + setNunchukValuesPanel.add(nunchukOrientationPanel); + + nunchukAccelerationTextField.setPreferredSize(new java.awt.Dimension(60, 20)); + nunchukAccelerationPanel.add(nunchukAccelerationTextField); + + nunchukAccelerationButton.setText("Set Acceleration Threshold"); + nunchukAccelerationButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + nunchukAccelerationButtonMousePressed(evt); + } + }); + nunchukAccelerationPanel.add(nunchukAccelerationButton); + + setNunchukValuesPanel.add(nunchukAccelerationPanel); + + messageText.setText("Message:"); + + javax.swing.GroupLayout messagePanelLayout = new javax.swing.GroupLayout(messagePanel); + messagePanel.setLayout(messagePanelLayout); + messagePanelLayout.setHorizontalGroup( + messagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 1216, Short.MAX_VALUE) + .addGroup(messagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(messagePanelLayout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(messageText) + .addGap(0, 0, Short.MAX_VALUE))) + ); + messagePanelLayout.setVerticalGroup( + messagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 34, Short.MAX_VALUE) + .addGroup(messagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(messagePanelLayout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(messageText) + .addGap(0, 0, Short.MAX_VALUE))) + ); + + setNunchukValuesPanel.add(messagePanel); + + getContentPane().add(setNunchukValuesPanel); + + pack(); + }// //GEN-END:initComponents + + private void nunchukOrientationButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_nunchukOrientationButtonMousePressed + try { + float nb = Float.parseFloat(nunchukOrientationTextField.getText()); + wiimote.setNunchukOrientationThreshold(nb); + messageText.setText("Nunchuk orientation threshold set to " + nb); + } catch (NumberFormatException e) { + messageText + .setText("Number is not an integer, nunchuk orientation threshold not set !"); + } + }// GEN-LAST:event_nunchukOrientationButtonMousePressed + + private void nunchukAccelerationButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_nunchukAccelerationButtonMousePressed + try { + int nb = Integer.parseInt(nunchukAccelerationTextField.getText()); + wiimote.setNunchukAccelerationThreshold(nb); + messageText.setText("Nunchuk acceleration threshold set to " + nb); + } catch (NumberFormatException e) { + messageText + .setText("Number is not an integer, nunchuk acceleration threshold not set !"); + } + }// GEN-LAST:event_nunchukAccelerationButtonMousePressed + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing to do + } + + public void onIrEvent(IREvent arg0) { + // nothing to do + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + // nothing to do + } + + public void onExpansionEvent(ExpansionEvent arg0) { + if (arg0 instanceof NunchukEvent) { + NunchukEvent nunchuk = (NunchukEvent) arg0; + NunchukButtonsEvent buttons = nunchuk.getButtonsEvent(); + if (buttons.isButtonCJustPressed()) { + cButton.setEnabled(false); + } + if (buttons.isButtonCJustReleased()) { + cButton.setEnabled(true); + } + if (buttons.isButtonZJustPressed()) { + zButton.setEnabled(false); + } + if (buttons.isButtonZJustReleased()) { + zButton.setEnabled(true); + } + if (isThresholdsRequested) { + MotionSensingEvent evt = nunchuk.getNunchukMotionSensingEvent(); + nunchukAccelerationTextField.setText(evt + .getAccelerationThreshold() + + ""); + nunchukOrientationTextField.setText(evt + .getOrientationThreshold() + + ""); + isThresholdsRequested = false; + } + } + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing to do + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // nothing + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) { + // nothing + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton cButton; + private javax.swing.JPanel gForcePanel; + private javax.swing.JPanel joystickEventsPanel; + private javax.swing.JPanel messagePanel; + private javax.swing.JLabel messageText; + private javax.swing.JPanel motionSensingEventsPanel; + private javax.swing.JTabbedPane motionSensingEventsTabbedPanels; + private javax.swing.JButton nunchukAccelerationButton; + private javax.swing.JPanel nunchukAccelerationPanel; + private javax.swing.JTextField nunchukAccelerationTextField; + private javax.swing.JPanel nunchukButtonsEventPanel; + private javax.swing.JButton nunchukOrientationButton; + private javax.swing.JPanel nunchukOrientationPanel; + private javax.swing.JTextField nunchukOrientationTextField; + private javax.swing.JPanel orientationPanel; + private javax.swing.JPanel rawAccelerationPanel; + private javax.swing.JPanel setNunchukValuesPanel; + private javax.swing.JPanel topPanels; + private javax.swing.JButton zButton; + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/test/Tests.java b/WiiUseJ_0.12/src/wiiusej/test/Tests.java new file mode 100644 index 0000000..6a3cdb7 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/test/Tests.java @@ -0,0 +1,367 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.test; + +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import wiiusej.WiiUseApiManager; +import wiiusej.Wiimote; +import wiiusej.values.IRSource; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This class used to test WiiuseJ in text mode. + * + * @author guiguito + */ +public class Tests implements WiimoteListener { + + Robot robot; + + private static int DISPLAY_EACH_VALUE = 1; + private static int DUMP = 2; + private static int MOVE_MOUSE = 3; + private static int TEST_LEDS = 5; + + private Wiimote wiimote; + + int dump = DISPLAY_EACH_VALUE; + + public Tests(Wiimote wim) { + wiimote = wim; + wiimote.addWiiMoteEventListeners(this); + try { + robot = new Robot(); + } catch (AWTException e) { + e.printStackTrace(); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent e) { + if (dump == DISPLAY_EACH_VALUE) { + // System.out.println("*********** WIIMOTE ID : "+ + // e.getWiimoteId() + " **************"); + /* button ONE */ + if (e.isButtonOneJustPressed()) { + System.out.println("button one pressed"); + } + if (e.isButtonOneHeld()) { + System.out.println("button one held"); + } + if (e.isButtonOneJustReleased()) { + System.out.println("button one released"); + } + + /* button TWO */ + if (e.isButtonTwoJustPressed()) { + System.out.println("button two pressed"); + } + if (e.isButtonTwoHeld()) { + System.out.println("button two held"); + } + if (e.isButtonTwoJustReleased()) { + System.out.println("button two released"); + } + + /* button A */ + if (e.isButtonAJustPressed()) { + System.out.println("button A pressed"); + } + if (e.isButtonAHeld()) { + System.out.println("button A held"); + } + if (e.isButtonAJustReleased()) { + System.out.println("button A released"); + } + + /* button B */ + if (e.isButtonBJustPressed()) { + System.out.println("button B pressed"); + } + if (e.isButtonBHeld()) { + System.out.println("button B held"); + } + if (e.isButtonBJustReleased()) { + System.out.println("button B released"); + } + + /* button LEFT */ + if (e.isButtonLeftJustPressed()) { + System.out.println("button Left pressed"); + } + if (e.isButtonLeftHeld()) { + System.out.println("button Left held"); + } + if (e.isButtonLeftJustReleased()) { + System.out.println("button Left released"); + } + + /* button RIGHT */ + if (e.isButtonRightJustPressed()) { + System.out.println("button Right pressed"); + } + if (e.isButtonRightHeld()) { + System.out.println("button Right held"); + } + if (e.isButtonRightJustReleased()) { + System.out.println("button Right released"); + } + + /* button UP */ + if (e.isButtonUpJustPressed()) { + System.out.println("button UP pressed"); + } + if (e.isButtonUpHeld()) { + System.out.println("button UP held"); + } + if (e.isButtonUpJustReleased()) { + System.out.println("button UP released"); + } + + /* button DOWN */ + if (e.isButtonDownJustPressed()) { + System.out.println("button DOWN pressed"); + } + if (e.isButtonDownHeld()) { + System.out.println("button DOWN held"); + } + if (e.isButtonDownJustReleased()) { + System.out.println("button DOWN released"); + } + + /* button MINUS */ + if (e.isButtonMinusJustPressed()) { + System.out.println("button MINUS pressed"); + } + if (e.isButtonMinusHeld()) { + System.out.println("button MINUS held"); + } + if (e.isButtonMinusJustReleased()) { + System.out.println("button MINUS released"); + } + + /* button PLUS */ + if (e.isButtonPlusJustPressed()) { + System.out.println("button PLUS pressed"); + } + if (e.isButtonPlusHeld()) { + System.out.println("button PLUS held"); + } + if (e.isButtonPlusJustReleased()) { + System.out.println("button PLUS released"); + } + + /* button HOME */ + if (e.isButtonHomeJustPressed()) { + System.out.println("button HOME pressed"); + } + if (e.isButtonHomeHeld()) { + System.out.println("button HOME held"); + } + if (e.isButtonHomeJustReleased()) { + System.out.println("button HOME released"); + } + + /* get status */ + if (e.isButtonUpJustPressed()) { + wiimote.getStatus(); + } + + /* Activate rumble */ + if (e.isButtonOneJustPressed()) { + System.out.println("Rumble Activated"); + wiimote.activateRumble(); + } + if (e.isButtonTwoJustPressed()) { + System.out.println("Rumble Deactivated"); + wiimote.deactivateRumble(); + } + + /* Activate IR Tracking */ + if (e.isButtonAJustPressed()) { + System.out.println("IR Activated"); + wiimote.activateIRTRacking(); + } + if (e.isButtonBJustPressed()) { + System.out.println("IR Deactivated"); + wiimote.deactivateIRTRacking(); + } + + /* Activate Motion sensing */ + if (e.isButtonPlusJustPressed()) { + System.out.println("Motion sensing Activated"); + wiimote.activateMotionSensing(); + } + if (e.isButtonMinusJustPressed()) { + System.out.println("Motion sensing Deactivated"); + wiimote.deactivateMotionSensing(); + } + + /* leave test */ + if (e.isButtonHomeJustPressed()) { + System.out.println("LEAVING TEST"); + wiimote.disconnect(); + } + + } else if (dump == DUMP) { + System.out.println(e); + /* Activate all */ + if (e.isButtonAJustPressed()) { + System.out.println("IR, rumble and motion sensing Activated"); + wiimote.activateIRTRacking(); + wiimote.activateMotionSensing(); + wiimote.activateRumble(); + } + if (e.isButtonBJustPressed()) { + System.out.println("IR, rumble and motion sensing Deactivated"); + wiimote.deactivateIRTRacking(); + wiimote.deactivateMotionSensing(); + wiimote.deactivateRumble(); + } + + /* leave test */ + if (e.isButtonHomeJustPressed()) { + System.out.println("LEAVING TEST"); + wiimote.disconnect(); + } + } else if (dump == MOVE_MOUSE) { + /* Activate IR Tracking */ + if (e.isButtonOneJustPressed()) { + System.out.println("IR Activated"); + wiimote.activateIRTRacking(); + } + if (e.isButtonTwoJustPressed()) { + System.out.println("IR Deactivated"); + wiimote.deactivateIRTRacking(); + } + + /* button A */ + if (e.isButtonAJustPressed()) { + robot.mousePress(InputEvent.BUTTON1_MASK); + } + if (e.isButtonAJustReleased()) { + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + + /* button B */ + if (e.isButtonBJustPressed()) { + robot.mousePress(InputEvent.BUTTON2_MASK); + } + if (e.isButtonBJustReleased()) { + robot.mouseRelease(InputEvent.BUTTON2_MASK); + } + + /* leave test */ + if (e.isButtonHomeJustPressed()) { + System.out.println("LEAVING TEST"); + wiimote.disconnect(); + } + } else if (dump == TEST_LEDS) { + wiimote.activateMotionSensing(); + if (e.isButtonUpJustPressed()) { + wiimote.setLeds(true, false, false, false); + } + if (e.isButtonDownJustPressed()) { + wiimote.setLeds(false, true, false, false); + } + if (e.isButtonLeftJustPressed()) { + wiimote.setLeds(false, false, true, false); + } + if (e.isButtonRightJustPressed()) { + wiimote.setLeds(false, false, false, true); + } + + /* leave test */ + if (e.isButtonHomeJustPressed()) { + System.out.println("LEAVING TEST"); + wiimote.disconnect(); + } + } + + } + + public void onIrEvent(IREvent e) { + if (dump == MOVE_MOUSE) { + IRSource[] list = e.getIRPoints(); + if (list.length > 0) { + int x1 = (int) list[0].getX(); + int y1 = (int) list[0].getY(); + + int mousex = (int) Math.round(((double) x1 / 1024.0) * 1280.0); + int mousey = (int) Math.round(((double) y1 / 768.0) * 1024.0); + robot.mouseMove(mousex, mousey); + } + } else { + System.out.println(e); + } + } + + public void onMotionSensingEvent(MotionSensingEvent e) { + /* display motion sensing */ + System.out.println(e); + } + + public void onExpansionEvent(ExpansionEvent e) { + System.out.println(e); + } + + public void onStatusEvent(StatusEvent e) { + // Display status variables + System.out.println(e); + } + + public void onDisconnectionEvent(DisconnectionEvent e) { + System.out.println(" wiimote " + e.getWiimoteId() + + "has been disconnected !!"); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent e) { + System.out.println(e); + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent e) { + System.out.println(e); + } + + /** + * @param args + */ + public static void main(String[] args) { + Wiimote[] wiimotes = WiiUseApiManager.getWiimotes(1, true); + if (wiimotes.length > 0) { + System.out.println(wiimotes[0]); + new Tests(wiimotes[0]); + } else { + System.out.println("No wiimotes found !!!"); + } + + // java.util.Timer timer = new java.util.Timer(); + // timer.scheduleAtFixedRate(new LedsTask(), 0, 100); + + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/test/WiiuseJGuiTest.java b/WiiUseJ_0.12/src/wiiusej/test/WiiuseJGuiTest.java new file mode 100644 index 0000000..2a8f229 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/test/WiiuseJGuiTest.java @@ -0,0 +1,1329 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.test; + +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.JFrame; +import wiiusej.WiiUseApiManager; +import wiiusej.Wiimote; +import wiiusej.utils.AccelerationPanel; +import wiiusej.utils.AccelerationWiimoteEventPanel; +import wiiusej.utils.ButtonsEventPanel; +import wiiusej.utils.GForcePanel; +import wiiusej.utils.IRPanel; +import wiiusej.utils.OrientationPanel; +import wiiusej.utils.OrientationWiimoteEventPanel; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * Gui class to test WiiuseJ. + * + * @author guiguito + */ +public class WiiuseJGuiTest extends javax.swing.JFrame implements + WiimoteListener { + + private Wiimote wiimote; + private Robot robot = null; + private boolean statusMotionRequested = false; + private boolean statusIRRequested = false; + private JFrame expansionFrame = null; + private boolean isFirstStatusGot = false; + private WindowListener buttonSetter = new WindowListener() { + + public void windowOpened(WindowEvent e) { + // nothing + } + + public void windowClosing(WindowEvent e) { + // nothing + } + + public void windowClosed(WindowEvent e) { + // nothing + } + + public void windowIconified(WindowEvent e) { + // nothing + } + + public void windowDeiconified(WindowEvent e) { + // nothing + } + + public void windowActivated(WindowEvent e) { + showExpansionWiimoteButton.setEnabled(false); + showExpansionWiimoteButton.setText("Hide Nunchuk"); + } + + public void windowDeactivated(WindowEvent e) { + showExpansionWiimoteButton.setEnabled(true); + showExpansionWiimoteButton.setText("Show Nunchuk"); + } + }; + + /** + * default constructor + */ + public WiiuseJGuiTest() { + initComponents(); + this.addWindowListener(new CloseGuiTestCleanly()); + } + + /** + * Creates new form WiiuseJGuiTest + */ + public WiiuseJGuiTest(Wiimote wiimote) { + initComponents(); + this.addWindowListener(new CloseGuiTestCleanly()); + if (wiimote != null) { + this.wiimote = wiimote; + registerListeners(); + initWiimote(); + isFirstStatusGot = false; + getStatusButtonMousePressed(null); + } + } + + /** + * Clear all views + */ + private void clearViews() { + ((IRPanel) irViewPanel).clearView(); + ((ButtonsEventPanel) buttonsPanel).clearView(); + ((OrientationPanel) motionSensingPanel).clearView(); + ((GForcePanel) gForcePanel).clearView(); + ((AccelerationPanel) accelerationPanel).clearView(); + } + + /** + * Unregister all listeners. + */ + private void unregisterListeners() { + wiimote.removeWiiMoteEventListeners((IRPanel) irViewPanel); + wiimote.removeWiiMoteEventListeners((ButtonsEventPanel) buttonsPanel); + wiimote + .removeWiiMoteEventListeners((OrientationPanel) motionSensingPanel); + wiimote.removeWiiMoteEventListeners((GForcePanel) gForcePanel); + wiimote + .removeWiiMoteEventListeners((AccelerationPanel) accelerationPanel); + wiimote.removeWiiMoteEventListeners(this); + } + + private void initWiimote() { + wiimote.deactivateContinuous(); + wiimote.deactivateSmoothing(); + wiimote.setScreenAspectRatio169(); + wiimote.setSensorBarBelowScreen(); + } + + /** + * Register all listeners + */ + private void registerListeners() { + wiimote.addWiiMoteEventListeners((IRPanel) irViewPanel); + wiimote.addWiiMoteEventListeners((ButtonsEventPanel) buttonsPanel); + wiimote.addWiiMoteEventListeners((OrientationPanel) motionSensingPanel); + wiimote.addWiiMoteEventListeners((GForcePanel) gForcePanel); + wiimote.addWiiMoteEventListeners((AccelerationPanel) accelerationPanel); + wiimote.addWiiMoteEventListeners(this); + + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + if (robot != null) { + if (arg0.isButtonAPressed()) { + robot.mousePress(InputEvent.BUTTON1_MASK); + + } + if (arg0.isButtonBPressed()) { + robot.mousePress(InputEvent.BUTTON2_MASK); + + } + if (arg0.isButtonOnePressed()) { + robot.mousePress(InputEvent.BUTTON3_MASK); + + } + if (arg0.isButtonAJustReleased()) { + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + } + if (arg0.isButtonBJustReleased()) { + robot.mouseRelease(InputEvent.BUTTON2_MASK); + + } + if (arg0.isButtonOneJustReleased()) { + robot.mouseRelease(InputEvent.BUTTON3_MASK); + + } + if (arg0.isButtonUpPressed()) {// mouse wheel up + robot.mouseWheel(-1); + } + if (arg0.isButtonDownPressed()) {// mouse wheel down + robot.mouseWheel(1); + } + + if (arg0.isButtonTwoPressed()) {// stop mouse control + mouseIRControlButtonMousePressed(null); + } + } + } + + public void onIrEvent(IREvent arg0) { + if (robot != null) {// if mouse control activated + robot.mouseMove(arg0.getX(), arg0.getY()); + } + if (statusIRRequested) { + xResolutionTextField.setText("" + arg0.getXVRes()); + yResolutionTextField.setText("" + arg0.getYVRes()); + statusIRRequested = false; + } + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + if (statusMotionRequested) {// Status requested + accelerationThresholdTextField.setText("" + + arg0.getAccelerationThreshold()); + orientationThresholdTextField.setText("" + + arg0.getOrientationThreshold()); + alphaSmoothingTextField.setText("" + arg0.getAlphaSmoothing()); + statusMotionRequested = false; + } + } + + public void onExpansionEvent(ExpansionEvent e) { + // nothing yet + } + + public void onStatusEvent(StatusEvent arg0) { + if (!isFirstStatusGot) { + if (arg0.isNunchukConnected()) { + showExpansionWiimoteButton.setEnabled(true); + showExpansionWiimoteButton.setText("Show Nunchuk"); + expansionFrame = new NunchukGuiTest(wiimote); + expansionFrame + .setDefaultCloseOperation(NunchukGuiTest.HIDE_ON_CLOSE); + expansionFrame.addWindowListener(buttonSetter); + isFirstStatusGot = true; + } + } + messageText.setText("Status received !"); + batteryLevelText.setText(arg0.getBatteryLevel() + " %"); + led1Button.setEnabled(arg0.isLed1Set()); + led2Button.setEnabled(arg0.isLed2Set()); + led3Button.setEnabled(arg0.isLed3Set()); + led4Button.setEnabled(arg0.isLed4Set()); + if (arg0.isNunchukConnected()) { + ((NunchukGuiTest) expansionFrame).requestThresholdsUpdate(); + } + // attachments + int eventType = arg0.getEventType(); + if (eventType == StatusEvent.WIIUSE_CLASSIC_CTRL_INSERTED) { + expansionText.setText("Classic control connected."); + } else if (eventType == StatusEvent.WIIUSE_CLASSIC_CTRL_REMOVED) { + expansionText.setText("Classic control removed."); + } else if (eventType == StatusEvent.WIIUSE_NUNCHUK_INSERTED) { + expansionText.setText("Nunchuk connected."); + } else if (eventType == StatusEvent.WIIUSE_NUNCHUK_REMOVED) { + expansionText.setText("Nunchuk removed."); + } else if (eventType == StatusEvent.WIIUSE_GUITAR_HERO_3_CTRL_INSERTED) { + expansionText.setText("Guitar Hero 3 control connected."); + } else if (eventType == StatusEvent.WIIUSE_GUITAR_HERO_3_CTRL_REMOVED) { + expansionText.setText("Guitar Hero 3 control removed."); + } + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + messageText.setText("Wiimote Disconnected !"); + unregisterListeners(); + clearViews(); + isFirstStatusGot = false; + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent e) { + messageText.setText("Nunchuk connected !"); + expansionText.setText("Expansion connected : Nunchuk."); + showExpansionWiimoteButton.setEnabled(true); + showExpansionWiimoteButton.setText("Show nunchuk"); + expansionFrame = new NunchukGuiTest(wiimote); + expansionFrame.setDefaultCloseOperation(NunchukGuiTest.HIDE_ON_CLOSE); + expansionFrame.addWindowListener(buttonSetter); + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent e) { + messageText.setText("Nunchuk disconnected !"); + expansionText.setText("No expansion connected."); + showExpansionWiimoteButton.setEnabled(false); + showExpansionWiimoteButton.setText("No expansion"); + if (expansionFrame != null) { + if (expansionFrame instanceof NunchukGuiTest) { + ((NunchukGuiTest) expansionFrame).unRegisterListeners(); + } + expansionFrame.setEnabled(false); + expansionFrame.dispose(); + expansionFrame = null; + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + leftPanel = new javax.swing.JPanel(); + irViewPanel = new IRPanel(); + jTabbedPane1 = new javax.swing.JTabbedPane(); + accelerationPanel = new AccelerationWiimoteEventPanel(); + motionSensingPanel = new OrientationWiimoteEventPanel(); + gForcePanel = new wiiusej.utils.GForceWiimoteEventPanel(); + rightPanel = new javax.swing.JPanel(); + fixedWiimotePanel = new javax.swing.JPanel(); + buttonsPanel = new ButtonsEventPanel(); + controlsPanel = new javax.swing.JPanel(); + activateRumbleIRPanel = new javax.swing.JPanel(); + toggleRumbleButton = new javax.swing.JButton(); + toggleIRTrackingButton = new javax.swing.JButton(); + activateMotionSensingPanel = new javax.swing.JPanel(); + toggleMotionSensingTrackingButton = new javax.swing.JButton(); + activateSmoothingContinuousPanel = new javax.swing.JPanel(); + toggleSmoothingButton = new javax.swing.JButton(); + toggleContinuousButton = new javax.swing.JButton(); + setLedsPanel = new javax.swing.JPanel(); + led1Button = new javax.swing.JButton(); + led2Button = new javax.swing.JButton(); + led3Button = new javax.swing.JButton(); + led4Button = new javax.swing.JButton(); + setLedsButton = new javax.swing.JButton(); + setAlphaSmoothingPanel = new javax.swing.JPanel(); + alphaSmoothingTextField = new javax.swing.JTextField(); + alphaSmoothingButton = new javax.swing.JButton(); + setOrientationThresholdPanel = new javax.swing.JPanel(); + orientationThresholdTextField = new javax.swing.JTextField(); + orientationThresholdButton = new javax.swing.JButton(); + setAccelerationThresholdPanel = new javax.swing.JPanel(); + accelerationThresholdTextField = new javax.swing.JTextField(); + accelerationThresholdButton = new javax.swing.JButton(); + getStatusPanel = new javax.swing.JPanel(); + getStatusButton = new javax.swing.JButton(); + batteryText = new javax.swing.JLabel(); + batteryLevelText = new javax.swing.JLabel(); + setIrSensitivyPanel = new javax.swing.JPanel(); + setIrSensitivySpinner = new javax.swing.JSpinner(); + setIrSensitivyButton = new javax.swing.JButton(); + setTimeoutButton = new javax.swing.JButton(); + setTimeoutPanel = new javax.swing.JPanel(); + normalTimeoutSpinner = new javax.swing.JSpinner(); + normalTimeoutText = new javax.swing.JLabel(); + expansionHandshakeTimeoutSpinner = new javax.swing.JSpinner(); + expansionHandshakeTimeoutText = new javax.swing.JLabel(); + setIRConfPanel = new javax.swing.JPanel(); + toggleSensorBarPositionButton = new javax.swing.JButton(); + toggleScreenAspectRatioButton = new javax.swing.JButton(); + setVirtualResolutionPanel = new javax.swing.JPanel(); + xLabel = new javax.swing.JLabel(); + xResolutionTextField = new javax.swing.JTextField(); + yLabel = new javax.swing.JLabel(); + yResolutionTextField = new javax.swing.JTextField(); + setVirtualResolutionButton = new javax.swing.JButton(); + startMouseControlPanel = new javax.swing.JPanel(); + mouseIRControlButton = new javax.swing.JButton(); + exPansionPanel = new javax.swing.JPanel(); + expansionText = new javax.swing.JLabel(); + showExpansionWiimoteButton = new javax.swing.JButton(); + showExpansionWiimoteButton.setEnabled(false); + messagesPanel = new javax.swing.JPanel(); + reconnectWiimotesButton = new javax.swing.JButton(); + messageLabelText = new javax.swing.JLabel(); + messageText = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setTitle("WiiuseJ Test GUI"); + setName("WiiuseJ Test GUI"); // NOI18N + + leftPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + irViewPanel.setBackground(new java.awt.Color(0, 0, 0)); + irViewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder( + new javax.swing.border.LineBorder(new java.awt.Color(0, 153, + 153), 2, true), "IR View", + javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, + javax.swing.border.TitledBorder.DEFAULT_POSITION, + new java.awt.Font("Tahoma", 0, 11), new java.awt.Color(255, 0, + 51))); + irViewPanel.setToolTipText("IREvent"); + + javax.swing.GroupLayout irViewPanelLayout = new javax.swing.GroupLayout( + irViewPanel); + irViewPanel.setLayout(irViewPanelLayout); + irViewPanelLayout.setHorizontalGroup(irViewPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 272, Short.MAX_VALUE)); + irViewPanelLayout.setVerticalGroup(irViewPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 299, Short.MAX_VALUE)); + + accelerationPanel.setToolTipText("MotionSensingEvent"); + + javax.swing.GroupLayout accelerationPanelLayout = new javax.swing.GroupLayout( + accelerationPanel); + accelerationPanel.setLayout(accelerationPanelLayout); + accelerationPanelLayout.setHorizontalGroup(accelerationPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 279, Short.MAX_VALUE)); + accelerationPanelLayout.setVerticalGroup(accelerationPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 213, Short.MAX_VALUE)); + + jTabbedPane1.addTab("Acceleration", accelerationPanel); + + javax.swing.GroupLayout motionSensingPanelLayout = new javax.swing.GroupLayout( + motionSensingPanel); + motionSensingPanel.setLayout(motionSensingPanelLayout); + motionSensingPanelLayout.setHorizontalGroup(motionSensingPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 279, Short.MAX_VALUE)); + motionSensingPanelLayout.setVerticalGroup(motionSensingPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 213, Short.MAX_VALUE)); + + jTabbedPane1.addTab("Orientation", motionSensingPanel); + + javax.swing.GroupLayout gForcePanelLayout = new javax.swing.GroupLayout( + gForcePanel); + gForcePanel.setLayout(gForcePanelLayout); + gForcePanelLayout.setHorizontalGroup(gForcePanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 279, Short.MAX_VALUE)); + gForcePanelLayout.setVerticalGroup(gForcePanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 213, Short.MAX_VALUE)); + + jTabbedPane1.addTab("GForce", gForcePanel); + + javax.swing.GroupLayout leftPanelLayout = new javax.swing.GroupLayout( + leftPanel); + leftPanel.setLayout(leftPanelLayout); + leftPanelLayout.setHorizontalGroup(leftPanelLayout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addComponent( + irViewPanel, javax.swing.GroupLayout.Alignment.TRAILING, + javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jTabbedPane1, + javax.swing.GroupLayout.DEFAULT_SIZE, 284, + Short.MAX_VALUE)); + leftPanelLayout + .setVerticalGroup(leftPanelLayout + .createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING) + .addGroup( + javax.swing.GroupLayout.Alignment.TRAILING, + leftPanelLayout + .createSequentialGroup() + .addComponent( + jTabbedPane1, + javax.swing.GroupLayout.PREFERRED_SIZE, + 238, + javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap( + javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent( + irViewPanel, + javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, + Short.MAX_VALUE))); + + jTabbedPane1.getAccessibleContext().setAccessibleName("Orientation"); + + rightPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + rightPanel.setLayout(new javax.swing.BoxLayout(rightPanel, + javax.swing.BoxLayout.LINE_AXIS)); + + fixedWiimotePanel.setMaximumSize(new java.awt.Dimension(120, 32767)); + fixedWiimotePanel.setMinimumSize(new java.awt.Dimension(120, 100)); + fixedWiimotePanel.setPreferredSize(new java.awt.Dimension(120, 100)); + fixedWiimotePanel.setRequestFocusEnabled(false); + fixedWiimotePanel.setLayout(null); + + buttonsPanel.setMaximumSize(new java.awt.Dimension(120, 484)); + buttonsPanel.setMinimumSize(new java.awt.Dimension(120, 484)); + buttonsPanel.setOpaque(false); + buttonsPanel.setPreferredSize(new java.awt.Dimension(120, 484)); + + javax.swing.GroupLayout buttonsPanelLayout = new javax.swing.GroupLayout( + buttonsPanel); + buttonsPanel.setLayout(buttonsPanelLayout); + buttonsPanelLayout.setHorizontalGroup(buttonsPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 120, Short.MAX_VALUE)); + buttonsPanelLayout.setVerticalGroup(buttonsPanelLayout + .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 484, Short.MAX_VALUE)); + + fixedWiimotePanel.add(buttonsPanel); + buttonsPanel.setBounds(0, 0, 120, 484); + + rightPanel.add(fixedWiimotePanel); + + controlsPanel.setMinimumSize(new java.awt.Dimension(100, 264)); + controlsPanel.setPreferredSize(new java.awt.Dimension(190, 264)); + controlsPanel.setLayout(new java.awt.GridLayout(16, 1)); + + toggleRumbleButton.setText("Activate Rumble"); + toggleRumbleButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleRumbleButtonMousePressed(evt); + } + }); + activateRumbleIRPanel.add(toggleRumbleButton); + + toggleIRTrackingButton.setText("Activate IR Tracking"); + toggleIRTrackingButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleIRTrackingButtonMousePressed(evt); + } + }); + activateRumbleIRPanel.add(toggleIRTrackingButton); + + controlsPanel.add(activateRumbleIRPanel); + + toggleMotionSensingTrackingButton + .setText("Activate motion sensing Tracking"); + toggleMotionSensingTrackingButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleMotionSensingTrackingButtonMousePressed(evt); + } + }); + activateMotionSensingPanel.add(toggleMotionSensingTrackingButton); + + controlsPanel.add(activateMotionSensingPanel); + + toggleSmoothingButton.setText("Activate Smoothing"); + toggleSmoothingButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleSmoothingButtonMousePressed(evt); + } + }); + activateSmoothingContinuousPanel.add(toggleSmoothingButton); + + toggleContinuousButton.setText("Activate Continuous"); + toggleContinuousButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleContinuousButtonMousePressed(evt); + } + }); + activateSmoothingContinuousPanel.add(toggleContinuousButton); + + controlsPanel.add(activateSmoothingContinuousPanel); + + led1Button.setText("Led1"); + led1Button.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + led1ButtonMousePressed(evt); + } + }); + setLedsPanel.add(led1Button); + + led2Button.setText("Led2"); + led2Button.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + led2ButtonMousePressed(evt); + } + }); + setLedsPanel.add(led2Button); + + led3Button.setText("Led3"); + led3Button.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + led3ButtonMousePressed(evt); + } + }); + setLedsPanel.add(led3Button); + + led4Button.setText("Led4"); + led4Button.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + led4ButtonMousePressed(evt); + } + }); + setLedsPanel.add(led4Button); + + setLedsButton.setText("Set leds"); + setLedsButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + setLedsButtonMousePressed(evt); + } + }); + setLedsPanel.add(setLedsButton); + + controlsPanel.add(setLedsPanel); + + alphaSmoothingTextField.setMinimumSize(new java.awt.Dimension(100, 20)); + alphaSmoothingTextField + .setPreferredSize(new java.awt.Dimension(100, 20)); + setAlphaSmoothingPanel.add(alphaSmoothingTextField); + + alphaSmoothingButton.setText("Set alpha smoothing"); + alphaSmoothingButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + alphaSmoothingButtonMousePressed(evt); + } + }); + setAlphaSmoothingPanel.add(alphaSmoothingButton); + + controlsPanel.add(setAlphaSmoothingPanel); + + orientationThresholdTextField.setMinimumSize(new java.awt.Dimension( + 100, 20)); + orientationThresholdTextField.setPreferredSize(new java.awt.Dimension( + 100, 20)); + setOrientationThresholdPanel.add(orientationThresholdTextField); + + orientationThresholdButton.setText("Set orientation threshold"); + orientationThresholdButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + orientationThresholdButtonMousePressed(evt); + } + }); + setOrientationThresholdPanel.add(orientationThresholdButton); + + controlsPanel.add(setOrientationThresholdPanel); + + accelerationThresholdTextField.setPreferredSize(new java.awt.Dimension( + 100, 20)); + setAccelerationThresholdPanel.add(accelerationThresholdTextField); + + accelerationThresholdButton.setText("Set acceleration threshold"); + accelerationThresholdButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + accelerationThresholdButtonMousePressed(evt); + } + }); + setAccelerationThresholdPanel.add(accelerationThresholdButton); + + controlsPanel.add(setAccelerationThresholdPanel); + + getStatusButton.setText("Get status"); + getStatusButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + getStatusButtonMousePressed(evt); + } + }); + getStatusPanel.add(getStatusButton); + + batteryText.setFont(new java.awt.Font("Tahoma", 0, 14)); + batteryText.setText("Battery level :"); + getStatusPanel.add(batteryText); + + batteryLevelText.setFont(new java.awt.Font("Arial", 0, 14)); + batteryLevelText.setText(" %"); + getStatusPanel.add(batteryLevelText); + + controlsPanel.add(getStatusPanel); + + setIrSensitivySpinner.setPreferredSize(new java.awt.Dimension(50, 18)); + setIrSensitivySpinner + .addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + setIrSensitivySpinnerStateChanged(evt); + } + }); + setIrSensitivyPanel.add(setIrSensitivySpinner); + + setIrSensitivyButton.setText("SetIrSensivity"); + setIrSensitivyButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + setIrSensitivyButtonMousePressed(evt); + } + }); + setIrSensitivyPanel.add(setIrSensitivyButton); + + setTimeoutButton.setText("Set timeouts in ms"); + setTimeoutButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + setTimeoutButtonMousePressed(evt); + } + }); + setIrSensitivyPanel.add(setTimeoutButton); + + controlsPanel.add(setIrSensitivyPanel); + + normalTimeoutSpinner.setPreferredSize(new java.awt.Dimension(40, 18)); + normalTimeoutSpinner + .addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + normalTimeoutSpinnerStateChanged(evt); + } + }); + setTimeoutPanel.add(normalTimeoutSpinner); + + normalTimeoutText.setText("Normal timeout"); + setTimeoutPanel.add(normalTimeoutText); + + expansionHandshakeTimeoutSpinner + .setPreferredSize(new java.awt.Dimension(40, 18)); + expansionHandshakeTimeoutSpinner + .addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + expansionHandshakeTimeoutSpinnerStateChanged(evt); + } + }); + setTimeoutPanel.add(expansionHandshakeTimeoutSpinner); + + expansionHandshakeTimeoutText.setText("Expansion handshake timeout"); + setTimeoutPanel.add(expansionHandshakeTimeoutText); + + controlsPanel.add(setTimeoutPanel); + + toggleSensorBarPositionButton.setText("Set sensor bar above"); + toggleSensorBarPositionButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleSensorBarPositionButtonMousePressed(evt); + } + }); + setIRConfPanel.add(toggleSensorBarPositionButton); + + toggleScreenAspectRatioButton.setText("Set screen aspect ratio 4/3"); + toggleScreenAspectRatioButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + toggleScreenAspectRatioButtonMousePressed(evt); + } + }); + setIRConfPanel.add(toggleScreenAspectRatioButton); + + controlsPanel.add(setIRConfPanel); + + xLabel.setText("X"); + setVirtualResolutionPanel.add(xLabel); + + xResolutionTextField.setMinimumSize(new java.awt.Dimension(40, 20)); + xResolutionTextField.setPreferredSize(new java.awt.Dimension(40, 20)); + setVirtualResolutionPanel.add(xResolutionTextField); + + yLabel.setText("Y"); + setVirtualResolutionPanel.add(yLabel); + + yResolutionTextField.setFocusTraversalPolicyProvider(true); + yResolutionTextField.setMinimumSize(new java.awt.Dimension(40, 20)); + yResolutionTextField.setPreferredSize(new java.awt.Dimension(40, 20)); + setVirtualResolutionPanel.add(yResolutionTextField); + + setVirtualResolutionButton.setText("Set virtual resolution"); + setVirtualResolutionButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + setVirtualResolutionButtonMousePressed(evt); + } + }); + setVirtualResolutionPanel.add(setVirtualResolutionButton); + + controlsPanel.add(setVirtualResolutionPanel); + + mouseIRControlButton.setText("Start infrared mouse control"); + mouseIRControlButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + mouseIRControlButtonMousePressed(evt); + } + }); + startMouseControlPanel.add(mouseIRControlButton); + + controlsPanel.add(startMouseControlPanel); + + expansionText.setText("No expansion connected."); + exPansionPanel.add(expansionText); + + showExpansionWiimoteButton.setText("No expansion connected"); + showExpansionWiimoteButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + showExpansionWiimoteButtonMousePressed(evt); + } + }); + exPansionPanel.add(showExpansionWiimoteButton); + + controlsPanel.add(exPansionPanel); + + reconnectWiimotesButton.setText("Reconnect wiimote"); + reconnectWiimotesButton + .addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + reconnectWiimotesButtonMousePressed(evt); + } + }); + messagesPanel.add(reconnectWiimotesButton); + + messageLabelText.setFont(new java.awt.Font("Tahoma", 0, 14)); + messageLabelText.setText("Message : "); + messagesPanel.add(messageLabelText); + + messageText.setFont(new java.awt.Font("Arial", 0, 14)); + messageText.setText("None"); + messagesPanel.add(messageText); + + controlsPanel.add(messagesPanel); + + rightPanel.add(controlsPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout( + getContentPane()); + getContentPane().setLayout(layout); + layout + .setHorizontalGroup(layout + .createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING) + .addGroup( + layout + .createSequentialGroup() + .addComponent( + leftPanel, + javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, + Short.MAX_VALUE) + .addPreferredGap( + javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent( + rightPanel, + javax.swing.GroupLayout.DEFAULT_SIZE, + 498, Short.MAX_VALUE))); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addComponent( + leftPanel, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(rightPanel, javax.swing.GroupLayout.DEFAULT_SIZE, + 573, Short.MAX_VALUE)); + + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit() + .getScreenSize(); + setBounds((screenSize.width - 800) / 2, (screenSize.height - 600) / 2, + 800, 600); + }// //GEN-END:initComponents + + private void toggleRumbleButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleRumbleButtonMousePressed + if (toggleRumbleButton.isEnabled()) { + wiimote.activateRumble(); + toggleRumbleButton.setEnabled(false); + toggleRumbleButton.setText("Deactivate Rumble"); + messageText.setText("Rumble activated"); + } else { + wiimote.deactivateRumble(); + toggleRumbleButton.setEnabled(true); + toggleRumbleButton.setText("Activate Rumble"); + messageText.setText("Rumble deactivated"); + } + }// GEN-LAST:event_toggleRumbleButtonMousePressed + + private void toggleIRTrackingButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleIRTrackingButtonMousePressed + if (toggleIRTrackingButton.isEnabled()) { + wiimote.activateIRTRacking(); + toggleIRTrackingButton.setEnabled(false); + toggleIRTrackingButton.setText("Deactivate IR Tracking"); + messageText.setText("IR Tracking activated"); + } else { + wiimote.deactivateIRTRacking(); + toggleIRTrackingButton.setEnabled(true); + toggleIRTrackingButton.setText("Activate IR Tracking"); + ((IRPanel) irViewPanel).onDisconnectionEvent(null); + messageText.setText("IR Tracking deactivated"); + } + }// GEN-LAST:event_toggleIRTrackingButtonMousePressed + + private void toggleMotionSensingTrackingButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleMotionSensingTrackingButtonMousePressed + if (toggleMotionSensingTrackingButton.isEnabled()) { + wiimote.activateMotionSensing(); + toggleMotionSensingTrackingButton.setEnabled(false); + toggleMotionSensingTrackingButton + .setText("Deactivate Motion Sensing"); + messageText.setText("Motion Sensing activated"); + } else { + wiimote.deactivateMotionSensing(); + toggleMotionSensingTrackingButton.setEnabled(true); + toggleMotionSensingTrackingButton + .setText("Activate Motion Sensing"); + ((OrientationPanel) motionSensingPanel).onDisconnectionEvent(null); + ((GForcePanel) gForcePanel).onDisconnectionEvent(null); + messageText.setText("Motion Sensing deactivated"); + } + }// GEN-LAST:event_toggleMotionSensingTrackingButtonMousePressed + + private void toggleSmoothingButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleSmoothingButtonMousePressed + if (toggleSmoothingButton.isEnabled()) { + wiimote.activateSmoothing(); + toggleSmoothingButton.setEnabled(false); + toggleSmoothingButton.setText("Deactivate Alpha Smoothing"); + messageText.setText("Alpha Smoothing activated"); + } else { + wiimote.deactivateSmoothing(); + toggleSmoothingButton.setEnabled(true); + toggleSmoothingButton.setText("Activate Alpha Smoothing"); + messageText.setText("Alpha Smoothing deactivated"); + } + }// GEN-LAST:event_toggleSmoothingButtonMousePressed + + private void toggleContinuousButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleContinuousButtonMousePressed + if (toggleContinuousButton.isEnabled()) { + wiimote.activateContinuous(); + toggleContinuousButton.setEnabled(false); + toggleContinuousButton.setText("Deactivate Continuous"); + messageText.setText("Continuous activated"); + } else { + wiimote.deactivateContinuous(); + toggleContinuousButton.setEnabled(true); + toggleContinuousButton.setText("Activate Continuous"); + messageText.setText("Continuous deactivated"); + } + }// GEN-LAST:event_toggleContinuousButtonMousePressed + + private void led1ButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_led1ButtonMousePressed + if (led1Button.isEnabled()) { + led1Button.setEnabled(false); + } else { + led1Button.setEnabled(true); + } + }// GEN-LAST:event_led1ButtonMousePressed + + private void led2ButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_led2ButtonMousePressed + if (led2Button.isEnabled()) { + led2Button.setEnabled(false); + } else { + led2Button.setEnabled(true); + } + }// GEN-LAST:event_led2ButtonMousePressed + + private void led3ButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_led3ButtonMousePressed + if (led3Button.isEnabled()) { + led3Button.setEnabled(false); + } else { + led3Button.setEnabled(true); + } + }// GEN-LAST:event_led3ButtonMousePressed + + private void led4ButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_led4ButtonMousePressed + if (led4Button.isEnabled()) { + led4Button.setEnabled(false); + } else { + led4Button.setEnabled(true); + } + }// GEN-LAST:event_led4ButtonMousePressed + + private void setLedsButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_setLedsButtonMousePressed + wiimote.setLeds(led1Button.isEnabled(), led2Button.isEnabled(), + led3Button.isEnabled(), led4Button.isEnabled()); + messageText.setText("Leds set"); + }// GEN-LAST:event_setLedsButtonMousePressed + + private void alphaSmoothingButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_alphaSmoothingButtonMousePressed + try { + float nb = Float.parseFloat(alphaSmoothingTextField.getText()); + wiimote.setAlphaSmoothingValue(nb); + messageText.setText("Alpha smoothing set to " + nb); + } catch (NumberFormatException e) { + messageText + .setText("Number is not a float, alpha smoothing not set !"); + } + }// GEN-LAST:event_alphaSmoothingButtonMousePressed + + private void orientationThresholdButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_orientationThresholdButtonMousePressed + try { + float nb = Float + .parseFloat(orientationThresholdTextField.getText()); + wiimote.setOrientationThreshold(nb); + messageText.setText("Orientation threshold set to " + nb); + } catch (NumberFormatException e) { + messageText + .setText("Number is not a float, orientation threshold not set !"); + } + }// GEN-LAST:event_orientationThresholdButtonMousePressed + + private void accelerationThresholdButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_accelerationThresholdButtonMousePressed + try { + int nb = Integer.parseInt(accelerationThresholdTextField.getText()); + wiimote.setAccelerationThreshold(nb); + messageText.setText("Acceleration threshold set to " + nb); + } catch (NumberFormatException e) { + messageText + .setText("Number is not an integer, acceleration threshold not set !"); + } + }// GEN-LAST:event_accelerationThresholdButtonMousePressed + + private void getStatusButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_getStatusButtonMousePressed + wiimote.getStatus(); + statusMotionRequested = true; + statusIRRequested = true; + if (expansionFrame instanceof NunchukGuiTest) { + ((NunchukGuiTest) expansionFrame).requestThresholdsUpdate(); + } + }// GEN-LAST:event_getStatusButtonMousePressed + + private void toggleSensorBarPositionButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleSensorBarPositionButtonMousePressed + if (toggleSensorBarPositionButton.isEnabled()) { + wiimote.setSensorBarBelowScreen(); + toggleSensorBarPositionButton.setEnabled(false); + toggleSensorBarPositionButton.setText("Set sensor bar below"); + messageText.setText("Sensor bar set above"); + } else { + wiimote.setSensorBarAboveScreen(); + toggleSensorBarPositionButton.setEnabled(true); + toggleSensorBarPositionButton.setText("Set sensor bar above"); + messageText.setText("Sensor bar set below"); + } + }// GEN-LAST:event_toggleSensorBarPositionButtonMousePressed + + private void toggleScreenAspectRatioButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_toggleScreenAspectRatioButtonMousePressed + if (toggleScreenAspectRatioButton.isEnabled()) { + wiimote.setScreenAspectRatio43(); + toggleScreenAspectRatioButton.setEnabled(false); + toggleScreenAspectRatioButton + .setText("Set screen aspect ratio 16/9"); + messageText.setText("creen aspect ratio to 4/3"); + } else { + wiimote.setScreenAspectRatio169(); + toggleScreenAspectRatioButton.setEnabled(true); + toggleScreenAspectRatioButton + .setText("Set screen aspect ratio 4/3"); + messageText.setText("Screen aspect ratio to 16/9"); + } + }// GEN-LAST:event_toggleScreenAspectRatioButtonMousePressed + + private void setVirtualResolutionButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_setVirtualResolutionButtonMousePressed + try { + int xres = Integer.parseInt(xResolutionTextField.getText()); + int yres = Integer.parseInt(yResolutionTextField.getText()); + wiimote.setVirtualResolution(xres, yres); + messageText.setText("Virtual resolution set to " + xres + "X" + + yres); + } catch (NumberFormatException e) { + messageText + .setText("A number in the virtual resolution is not an integer. Virtual resolution not set!"); + } + }// GEN-LAST:event_setVirtualResolutionButtonMousePressed + + private void mouseIRControlButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_mouseIRControlButtonMousePressed + if (mouseIRControlButton.isEnabled()) { + try { + mouseIRControlButton.setEnabled(false); + mouseIRControlButton.setText("Stop infrared mouse control"); + robot = new Robot(); + messageText.setText("Infrared mouse control started"); + } catch (AWTException ex) { + Logger.getLogger(WiiuseJGuiTest.class.getName()).log( + Level.SEVERE, null, ex); + } + } else { + mouseIRControlButton.setEnabled(true); + mouseIRControlButton.setText("Start infrared mouse control"); + robot = null; + messageText.setText("Infrared mouse control stopped"); + } + }// GEN-LAST:event_mouseIRControlButtonMousePressed + + private void normalTimeoutSpinnerStateChanged( + javax.swing.event.ChangeEvent evt) {// GEN-FIRST:event_normalTimeoutSpinnerStateChanged + String value = normalTimeoutSpinner.getValue().toString(); + boolean isInt = true; + int valueInt = 0; + try { + valueInt = Integer.parseInt(value); + } catch (NumberFormatException e) { + isInt = false; + messageText.setText("Wrong value for normal timeout."); + } + if (isInt) { + if (valueInt > 1000) { + normalTimeoutSpinner.setValue("1000"); + } else if (valueInt < 0) { + normalTimeoutSpinner.setValue("0"); + } + } + }// GEN-LAST:event_normalTimeoutSpinnerStateChanged + + private void expansionHandshakeTimeoutSpinnerStateChanged( + javax.swing.event.ChangeEvent evt) {// GEN-FIRST:event_expansionHandshakeTimeoutSpinnerStateChanged + String value = expansionHandshakeTimeoutSpinner.getValue().toString(); + boolean isInt = true; + int valueInt = 0; + try { + valueInt = Integer.parseInt(value); + } catch (NumberFormatException e) { + isInt = false; + messageText.setText("Wrong value for expansion handshake timeout."); + } + if (isInt) { + if (valueInt > 1000) { + expansionHandshakeTimeoutSpinner.setValue("1000"); + } else if (valueInt < 0) { + expansionHandshakeTimeoutSpinner.setValue("0"); + } + } + }// GEN-LAST:event_expansionHandshakeTimeoutSpinnerStateChanged + + private void setIrSensitivySpinnerStateChanged( + javax.swing.event.ChangeEvent evt) {// GEN-FIRST:event_setIrSensitivySpinnerStateChanged + String value = setIrSensitivySpinner.getValue().toString(); + boolean isInt = true; + int valueInt = 0; + try { + valueInt = Integer.parseInt(value); + } catch (NumberFormatException e) { + isInt = false; + messageText.setText("Wrong value for IR senstivity."); + } + if (isInt) { + if (valueInt > 5) { + setIrSensitivySpinner.setValue("1000"); + } else if (valueInt < 0) { + setIrSensitivySpinner.setValue("0"); + } + } + }// GEN-LAST:event_setIrSensitivySpinnerStateChanged + + private void setIrSensitivyButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_setIrSensitivyButtonMousePressed + String value = setIrSensitivySpinner.getValue().toString(); + boolean isInt = true; + int valueInt = 0; + try { + valueInt = Integer.parseInt(value); + } catch (NumberFormatException e) { + isInt = false; + messageText + .setText("Wrong value for IR sensitivity. It must be an int !"); + } + if (isInt) { + if (valueInt >= 1 && valueInt <= 5) { + wiimote.setIrSensitivity(valueInt); + messageText.setText("IR senstivity set to: " + valueInt + "."); + } else { + messageText + .setText("Wrong value for IR senstivity. It muset be between 1 and 5 !"); + } + } + }// GEN-LAST:event_setIrSensitivyButtonMousePressed + + private void setTimeoutButtonMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_setTimeoutButtonMousePressed + // get normal timeout + String value = normalTimeoutSpinner.getValue().toString(); + boolean isInt = true; + short valueInt = 0; + try { + valueInt = Short.parseShort(value); + } catch (NumberFormatException e) { + isInt = false; + messageText + .setText("Wrong value for normal timeout. It must be an int !"); + } + // get expansion handshake timeout + String value2 = expansionHandshakeTimeoutSpinner.getValue().toString(); + boolean isInt2 = true; + short valueInt2 = 0; + try { + valueInt2 = Short.parseShort(value2); + } catch (NumberFormatException e) { + isInt2 = false; + messageText + .setText("Wrong value for expansion handshake timeout. It must be an int !"); + } + if (isInt && isInt2) { + if (valueInt > 0 && valueInt2 > 0) { + wiimote.setTimeout(valueInt, valueInt2); + messageText.setText("Normal timeout set to: " + valueInt + + " and expansion handshake timeout set to: " + + valueInt2 + "!"); + } else { + messageText + .setText("Wrong value for one of the timeout value. It must be an integer > 0 !"); + } + } + }// GEN-LAST:event_setTimeoutButtonMousePressed + + private void reconnectWiimotesButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_reconnectWiimotesButtonMousePressed + // stop manager + WiiUseApiManager.shutdown(); + + // unregister previous wiimote + if (wiimote != null) { + onDisconnectionEvent(null); + } + + // Reset Gui + // remove frame for expansion + if (expansionFrame != null) { + if (expansionFrame instanceof NunchukGuiTest) { + ((NunchukGuiTest) expansionFrame).unRegisterListeners(); + } + expansionFrame.setEnabled(false); + expansionFrame.dispose(); + expansionFrame = null; + } + + // setup buttons In first state + toggleRumbleButton.setText("Activate Rumble"); + toggleRumbleButton.setEnabled(true); + toggleMotionSensingTrackingButton + .setText("Activate motion sensing Tracking"); + toggleMotionSensingTrackingButton.setEnabled(true); + toggleIRTrackingButton.setText("Activate IR Tracking"); + toggleIRTrackingButton.setEnabled(true); + toggleContinuousButton.setText("Activate Continuous"); + toggleContinuousButton.setEnabled(true); + toggleScreenAspectRatioButton.setText("Set screen aspect ratio 4/3"); + toggleScreenAspectRatioButton.setEnabled(true); + toggleSensorBarPositionButton.setText("Set sensor bar above"); + toggleSensorBarPositionButton.setEnabled(true); + toggleSmoothingButton.setText("Activate Smoothing"); + toggleSmoothingButton.setEnabled(true); + mouseIRControlButton.setText("Start infrared mouse control"); + mouseIRControlButton.setEnabled(true); + + // get wiimote + Wiimote[] listWiimote = WiiUseApiManager.getWiimotes(1, true); + if (listWiimote != null && listWiimote.length > 0) { + wiimote = listWiimote[0]; + + // registers listeners + registerListeners(); + initWiimote(); + + isFirstStatusGot = false; + getStatusButtonMousePressed(null); + } + }// GEN-LAST:event_reconnectWiimotesButtonMousePressed + + private void showExpansionWiimoteButtonMousePressed( + java.awt.event.MouseEvent evt) {// GEN-FIRST:event_showExpansionWiimoteButtonMousePressed + if (expansionFrame != null) { + if (showExpansionWiimoteButton.isEnabled()) {// expansion frame + // not shown + // show it + expansionFrame.setEnabled(true); + expansionFrame.setVisible(true); + showExpansionWiimoteButton.setEnabled(false); + showExpansionWiimoteButton.setText("Hide Nunchuk"); + messageText.setText("Nunchuk displayed !"); + } else {// already being shown + expansionFrame.setEnabled(false); + expansionFrame.setVisible(false); + showExpansionWiimoteButton.setEnabled(true); + showExpansionWiimoteButton.setText("Show Nunchuk"); + messageText.setText("Nunchuk hidden !"); + } + } + }// GEN-LAST:event_showExpansionWiimoteButtonMousePressed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel accelerationPanel; + private javax.swing.JButton accelerationThresholdButton; + private javax.swing.JTextField accelerationThresholdTextField; + private javax.swing.JPanel activateMotionSensingPanel; + private javax.swing.JPanel activateRumbleIRPanel; + private javax.swing.JPanel activateSmoothingContinuousPanel; + private javax.swing.JButton alphaSmoothingButton; + private javax.swing.JTextField alphaSmoothingTextField; + private javax.swing.JLabel batteryLevelText; + private javax.swing.JLabel batteryText; + private javax.swing.JPanel buttonsPanel; + private javax.swing.JPanel controlsPanel; + private javax.swing.JPanel exPansionPanel; + private javax.swing.JSpinner expansionHandshakeTimeoutSpinner; + private javax.swing.JLabel expansionHandshakeTimeoutText; + private javax.swing.JLabel expansionText; + private javax.swing.JPanel fixedWiimotePanel; + private javax.swing.JPanel gForcePanel; + private javax.swing.JButton getStatusButton; + private javax.swing.JPanel getStatusPanel; + private javax.swing.JPanel irViewPanel; + private javax.swing.JTabbedPane jTabbedPane1; + private javax.swing.JButton led1Button; + private javax.swing.JButton led2Button; + private javax.swing.JButton led3Button; + private javax.swing.JButton led4Button; + private javax.swing.JPanel leftPanel; + private javax.swing.JLabel messageLabelText; + private javax.swing.JLabel messageText; + private javax.swing.JPanel messagesPanel; + private javax.swing.JPanel motionSensingPanel; + private javax.swing.JButton mouseIRControlButton; + private javax.swing.JSpinner normalTimeoutSpinner; + private javax.swing.JLabel normalTimeoutText; + private javax.swing.JButton orientationThresholdButton; + private javax.swing.JTextField orientationThresholdTextField; + private javax.swing.JButton reconnectWiimotesButton; + private javax.swing.JPanel rightPanel; + private javax.swing.JPanel setAccelerationThresholdPanel; + private javax.swing.JPanel setAlphaSmoothingPanel; + private javax.swing.JPanel setIRConfPanel; + private javax.swing.JButton setIrSensitivyButton; + private javax.swing.JPanel setIrSensitivyPanel; + private javax.swing.JSpinner setIrSensitivySpinner; + private javax.swing.JButton setLedsButton; + private javax.swing.JPanel setLedsPanel; + private javax.swing.JPanel setOrientationThresholdPanel; + private javax.swing.JButton setTimeoutButton; + private javax.swing.JPanel setTimeoutPanel; + private javax.swing.JButton setVirtualResolutionButton; + private javax.swing.JPanel setVirtualResolutionPanel; + private javax.swing.JButton showExpansionWiimoteButton; + private javax.swing.JPanel startMouseControlPanel; + private javax.swing.JButton toggleContinuousButton; + private javax.swing.JButton toggleIRTrackingButton; + private javax.swing.JButton toggleMotionSensingTrackingButton; + private javax.swing.JButton toggleRumbleButton; + private javax.swing.JButton toggleScreenAspectRatioButton; + private javax.swing.JButton toggleSensorBarPositionButton; + private javax.swing.JButton toggleSmoothingButton; + private javax.swing.JLabel xLabel; + private javax.swing.JTextField xResolutionTextField; + private javax.swing.JLabel yLabel; + private javax.swing.JTextField yResolutionTextField; + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/AccelerationExpansionEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationExpansionEventPanel.java new file mode 100644 index 0000000..cb3021f --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationExpansionEventPanel.java @@ -0,0 +1,39 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.RawAcceleration; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; + +/** + * Panel to display Acceleration in a MotionSensingEvent from an expansion. + * + * @author guiguito + */ +public class AccelerationExpansionEventPanel extends AccelerationPanel { + + @Override + public RawAcceleration getRawAccelerationValue(GenericEvent e) { + if (e instanceof NunchukEvent) { + return ((NunchukEvent) e).getNunchukMotionSensingEvent() + .getRawAcceleration(); + } + return null; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/AccelerationPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationPanel.java new file mode 100644 index 0000000..6caa3b6 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationPanel.java @@ -0,0 +1,281 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; + +import wiiusej.values.RawAcceleration; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This panel is used to watch raw acceleration values from a + * MotionSensingEvent. + * + * @author guiguito + */ +public abstract class AccelerationPanel extends javax.swing.JPanel implements + WiimoteListener { + + private Image mImage;// image for double buffering + private Color xColor = Color.RED; + private Color yColor = Color.GREEN; + private Color zColor = Color.BLUE; + private Color backgroundColor = Color.WHITE; + private Color lineColor = Color.BLACK; + private ArrayList values = new ArrayList(); + + /** Creates new form AccelerationPanel */ + public AccelerationPanel() { + initComponents(); + } + + /** + * Constructor used to choose the colors used by the AccelerationPanel. + * + * @param bgColor + * background color. + * @param xColor + * x color. + * @param yColor + * y color. + * @param zColor + * z color. + * @param lColor + * line color. + */ + public AccelerationPanel(Color bgColor, Color xColor, Color yColor, + Color zColor, Color lColor) { + backgroundColor = bgColor; + this.xColor = xColor; + this.yColor = yColor; + this.zColor = zColor; + lineColor = lColor; + initComponents(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // draw medium line + int yLine = getHeight() - 25; + + g2.setPaint(lineColor); + g2.drawLine(0, yLine, getWidth(), yLine); + + RawAcceleration[] valuesArray = values.toArray(new RawAcceleration[0]); + + double unit = yLine / 255.0; + int previousX = 0; + int previousY = 0; + int previousZ = 0; + // draw curves + for (int i = 0; i < valuesArray.length && i < getWidth(); i++) { + RawAcceleration acceleration = valuesArray[i]; + // draw X + g2.setPaint(xColor); + int yDelta = (int) Math.round(unit * acceleration.getX()); + int y = -1 * yDelta + yLine; + g2.drawLine(i - 1, previousX, i, y); + g2.setTransform(new AffineTransform()); + previousX = y; + // draw Y + g2.setPaint(yColor); + yDelta = (int) Math.round(unit * acceleration.getY()); + y = -1 * yDelta + yLine; + g2.drawLine(i - 1, previousY, i, y); + g2.setTransform(new AffineTransform()); + previousY = y; + // draw Z + g2.setPaint(zColor); + yDelta = (int) Math.round(unit * acceleration.getZ()); + y = -1 * yDelta + yLine; + g2.drawLine(i - 1, previousZ, i, y); + g2.setTransform(new AffineTransform()); + previousZ = y; + } + + // draw legend + g2.setPaint(xColor); + g2.drawLine(5, getHeight() - 10, 25, getHeight() - 10); + g2.setPaint(yColor); + g2.drawLine(60, getHeight() - 10, 80, getHeight() - 10); + g2.setPaint(zColor); + g2.drawLine(120, getHeight() - 10, 140, getHeight() - 10); + + g2.setPaint(lineColor); + g2.drawString("X", 30, getHeight() - 5); + g2.drawString("Y", 85, getHeight() - 5); + g2.drawString("Z", 145, getHeight() - 5); + g2.drawString("0", 2, yLine - 5); + g2.drawString("255", 2, 15); + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing + } + + public void onIrEvent(IREvent arg0) { + // nothing + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + draw(arg0); + } + + public void onExpansionEvent(ExpansionEvent arg0) { + draw(arg0); + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // Clear points. + values.clear(); + repaint(); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) { + // nothing + } + + private void draw(GenericEvent arg0) { + if (values.size() >= getWidth()) { + // if there are as many values as pixels in the width + // clear points + values.clear(); + } + RawAcceleration rawAcceleration = getRawAccelerationValue(arg0); + if (rawAcceleration != null) + values.add(rawAcceleration); + repaint(); + } + + public abstract RawAcceleration getRawAccelerationValue(GenericEvent e); + + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getLineColor() { + return lineColor; + } + + public Color getXColor() { + return xColor; + } + + public Color getYColor() { + return yColor; + } + + public Color getZColor() { + return zColor; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + public void setXColor(Color xColor) { + this.xColor = xColor; + } + + public void setYColor(Color yColor) { + this.yColor = yColor; + } + + public void setZColor(Color zColor) { + this.zColor = zColor; + } + + public void clearView() { + values.clear(); + repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/AccelerationWiimoteEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationWiimoteEventPanel.java new file mode 100644 index 0000000..4e716de --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/AccelerationWiimoteEventPanel.java @@ -0,0 +1,37 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.RawAcceleration; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; + +/** + * Panel to display Acceleration in a MotionSensingEvent from a wiimote. + * @author guiguito + */ +public class AccelerationWiimoteEventPanel extends AccelerationPanel { + + @Override + public RawAcceleration getRawAccelerationValue(GenericEvent e) { + if (e instanceof MotionSensingEvent) { + return ((MotionSensingEvent) e).getRawAcceleration(); + } + return null; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/ButtonsEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/ButtonsEventPanel.java new file mode 100644 index 0000000..ba01ef4 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/ButtonsEventPanel.java @@ -0,0 +1,363 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Toolkit; +import java.awt.geom.AffineTransform; + +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This panel is used to see what buttons are pressed on the wiimote. It + * displays the result of last ButtonsEvent. + * + * @author guiguito + */ +public class ButtonsEventPanel extends javax.swing.JPanel implements + WiimoteListener { + + private Image mImage;// image for double buffering + private Image wiimoteImage;// image for double buffering + private WiimoteButtonsEvent buttons; + private Color pressedColor = Color.RED; + private Color heldColor = Color.ORANGE; + private Color releasedColor = Color.YELLOW; + private Shape shape; + + /** + * Default constructor. Red : button just pressed. Orange : button held. + * Yellow : button just released. + */ + public ButtonsEventPanel() { + Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); + java.net.URL url = ButtonsEventPanel.class + .getResource("/img/wiimote.png"); + wiimoteImage = toolkit.createImage(url); + shape = new java.awt.geom.Ellipse2D.Double(0, 0, 13, 13); + initComponents(); + } + + /** + * Constructor used to set colors and shape used. + * + * @param pressColor + * color of a button just pressed. + * @param hColor + * color of a button held. + * @param relColor + * color of a button just released. + * @param sh + * shape draw on the buttons. + */ + public ButtonsEventPanel(Color pressColor, Color hColor, Color relColor, + Shape sh) { + pressedColor = pressColor; + heldColor = hColor; + releasedColor = relColor; + shape = sh; + Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); + wiimoteImage = toolkit.createImage("img\\wiimote.png"); + shape = new java.awt.geom.Ellipse2D.Double(0, 0, 13, 13); + initComponents(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + // offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // draw buttons pushed + g2.drawImage(wiimoteImage, 0, 0, this); + g2.setTransform(new AffineTransform()); + + if (buttons != null) { + /* button ONE */ + if (buttons.isButtonOneJustPressed()) { + drawFunction(g2, pressedColor, 53, 353); + } + if (buttons.isButtonOneHeld()) { + drawFunction(g2, heldColor, 53, 353); + } + if (buttons.isButtonOneJustReleased()) { + drawFunction(g2, releasedColor, 53, 353); + } + + /* button TWO */ + if (buttons.isButtonTwoJustPressed()) { + drawFunction(g2, pressedColor, 53, 395); + } + if (buttons.isButtonTwoHeld()) { + drawFunction(g2, heldColor, 53, 395); + } + if (buttons.isButtonTwoJustReleased()) { + drawFunction(g2, releasedColor, 53, 395); + } + + /* button A */ + if (buttons.isButtonAJustPressed()) { + drawFunction(g2, pressedColor, 53, 150); + } + if (buttons.isButtonAHeld()) { + drawFunction(g2, heldColor, 53, 150); + } + if (buttons.isButtonAJustReleased()) { + drawFunction(g2, releasedColor, 53, 150); + } + + /* button B */ + if (buttons.isButtonBJustPressed()) { + drawFunction(g2, pressedColor, 16, 149); + } + if (buttons.isButtonBHeld()) { + drawFunction(g2, heldColor, 16, 149); + } + if (buttons.isButtonBJustReleased()) { + drawFunction(g2, releasedColor, 16, 149); + } + + /* button LEFT */ + if (buttons.isButtonLeftJustPressed()) { + drawFunction(g2, pressedColor, 33, 77); + } + if (buttons.isButtonLeftHeld()) { + drawFunction(g2, heldColor, 33, 77); + } + if (buttons.isButtonLeftJustReleased()) { + drawFunction(g2, releasedColor, 33, 77); + } + + /* button RIGHT */ + if (buttons.isButtonRightJustPressed()) { + drawFunction(g2, pressedColor, 73, 77); + } + if (buttons.isButtonRightHeld()) { + drawFunction(g2, heldColor, 73, 77); + } + if (buttons.isButtonRightJustReleased()) { + drawFunction(g2, releasedColor, 73, 77); + } + + /* button UP */ + if (buttons.isButtonUpJustPressed()) { + drawFunction(g2, pressedColor, 54, 60); + } + if (buttons.isButtonUpHeld()) { + drawFunction(g2, heldColor, 54, 60); + } + if (buttons.isButtonUpJustReleased()) { + drawFunction(g2, releasedColor, 54, 60); + } + + /* button DOWN */ + if (buttons.isButtonDownJustPressed()) { + drawFunction(g2, pressedColor, 54, 97); + } + if (buttons.isButtonDownHeld()) { + drawFunction(g2, heldColor, 54, 97); + } + if (buttons.isButtonDownJustReleased()) { + drawFunction(g2, releasedColor, 54, 97); + } + + /* button MINUS */ + if (buttons.isButtonMinusJustPressed()) { + drawFunction(g2, pressedColor, 20, 230); + } + if (buttons.isButtonMinusHeld()) { + drawFunction(g2, heldColor, 20, 230); + } + if (buttons.isButtonMinusJustReleased()) { + drawFunction(g2, releasedColor, 20, 230); + } + + /* button PLUS */ + if (buttons.isButtonPlusJustPressed()) { + drawFunction(g2, pressedColor, 86, 230); + } + if (buttons.isButtonPlusHeld()) { + drawFunction(g2, heldColor, 86, 230); + } + if (buttons.isButtonPlusJustReleased()) { + drawFunction(g2, releasedColor, 86, 230); + } + + /* button HOME */ + if (buttons.isButtonHomeJustPressed()) { + drawFunction(g2, pressedColor, 53, 230); + } + if (buttons.isButtonHomeHeld()) { + drawFunction(g2, heldColor, 53, 230); + } + if (buttons.isButtonHomeJustReleased()) { + drawFunction(g2, releasedColor, 53, 230); + } + + buttons = null; + } + + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * Function used to factorize code. + * + * @param g2 + * where to draw a shape. + * @param col + * color to use. + * @param x + * x coordinates. + * @param y + * y coordinates. + */ + private void drawFunction(Graphics2D g2, Color col, int x, int y) { + g2.setPaint(col); + g2.translate(x, y); + g2.draw(shape); + g2.fill(shape); + g2.setTransform(new AffineTransform()); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + setSize(wiimoteImage.getWidth(this), wiimoteImage.getHeight(this)); + buttons = arg0; + repaint(); + } + + public void onIrEvent(IREvent arg0) { + // nothing + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + // nothing + } + + public void onExpansionEvent(ExpansionEvent e) { + // nothing + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + buttons = null; + repaint(); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent e) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent e) { + // nothing + } + + public Color getHeldColor() { + return heldColor; + } + + public Color getPressedColor() { + return pressedColor; + } + + public Color getReleasedColor() { + return releasedColor; + } + + public Shape getShape() { + return shape; + } + + public void setHeldColor(Color heldColor) { + this.heldColor = heldColor; + } + + public void setPressedColor(Color pressedColor) { + this.pressedColor = pressedColor; + } + + public void setReleasedColor(Color releasedColor) { + this.releasedColor = releasedColor; + } + + public void setShape(Shape shape) { + this.shape = shape; + } + + public void clearView() { + buttons = null; + repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/GForceExpansionEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/GForceExpansionEventPanel.java new file mode 100644 index 0000000..d5852b0 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/GForceExpansionEventPanel.java @@ -0,0 +1,38 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.GForce; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; + +/** + * Panel to display GForce in a MotionSensingEvent from an expansion. + * + * @author guiguito + */ +public class GForceExpansionEventPanel extends GForcePanel{ + + @Override + public GForce getGForceValue(GenericEvent e) { + if (e instanceof NunchukEvent){ + return ((NunchukEvent)e).getNunchukMotionSensingEvent().getGforce(); + } + return null; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/GForcePanel.java b/WiiUseJ_0.12/src/wiiusej/utils/GForcePanel.java new file mode 100644 index 0000000..14de5f2 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/GForcePanel.java @@ -0,0 +1,282 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; + +import wiiusej.values.GForce; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This panel is used to watch gravity force values from a MotionSensingEvent. + * + * @author guiguito + */ +public abstract class GForcePanel extends javax.swing.JPanel implements + WiimoteListener { + + private Image mImage;// image for double buffering + private Color xColor = Color.RED; + private Color yColor = Color.GREEN; + private Color zColor = Color.BLUE; + private Color backgroundColor = Color.WHITE; + private Color lineColor = Color.BLACK; + private ArrayList values = new ArrayList(); + + /** + * Default constructor of the AccelerationPanel. + */ + public GForcePanel() { + initComponents(); + } + + /** + * Constructor used to choose the colors used by the AccelerationPanel. + * + * @param bgColor + * background color. + * @param xxColor + * color of the acceleration on X axis. + * @param yyColor + * color of the acceleration on Y axis. + * @param zzColor + * color of the acceleration on Z axis. + * @param lColor + * line color. + */ + public GForcePanel(Color bgColor, Color xxColor, Color yyColor, + Color zzColor, Color lColor) { + backgroundColor = bgColor; + xColor = xxColor; + yColor = yyColor; + zColor = zzColor; + lineColor = lColor; + initComponents(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // draw medium line + double yMiddleFloat = getHeight() / 2.0; + int yMiddle = (int) Math.round(yMiddleFloat); + + g2.setPaint(lineColor); + g2.drawLine(0, yMiddle, getWidth(), yMiddle); + + GForce[] valuesArray = values.toArray(new GForce[0]); + double unit = yMiddleFloat / 5.0; + int previousX = 0; + int previousY = 0; + int previousZ = 0; + // draw curves + for (int i = 0; i < valuesArray.length && i < getWidth(); i++) { + GForce gforce = valuesArray[i]; + // draw X + g2.setPaint(xColor); + int yDelta = (int) Math.round(unit * gforce.getX()); + int y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousX, i, y); + g2.setTransform(new AffineTransform()); + previousX = y; + // draw Y + g2.setPaint(yColor); + yDelta = (int) Math.round(unit * gforce.getY()); + y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousY, i, y); + g2.setTransform(new AffineTransform()); + previousY = y; + // draw Z + g2.setPaint(zColor); + yDelta = (int) Math.round(unit * gforce.getZ()); + y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousZ, i, y); + g2.setTransform(new AffineTransform()); + previousZ = y; + } + + // draw legend + g2.setPaint(xColor); + g2.drawLine(5, getHeight() - 10, 25, getHeight() - 10); + g2.setPaint(yColor); + g2.drawLine(60, getHeight() - 10, 80, getHeight() - 10); + g2.setPaint(zColor); + g2.drawLine(120, getHeight() - 10, 140, getHeight() - 10); + + g2.setPaint(lineColor); + g2.drawString("X", 30, getHeight() - 5); + g2.drawString("Y", 85, getHeight() - 5); + g2.drawString("Z", 145, getHeight() - 5); + g2.drawString("0", 2, yMiddle - 5); + g2.drawString("5", 2, 10); + g2.drawString("-5", 2, getHeight() - 15); + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing + } + + public void onIrEvent(IREvent arg0) { + // nothing + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + draw(arg0); + } + + public void onExpansionEvent(ExpansionEvent arg0) { + draw(arg0); + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // Clear points. + values.clear(); + repaint(); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) { + // nothing + } + + private void draw(GenericEvent arg0) { + if (values.size() >= getWidth()) { + // if there are as many values as pixels in the width + // clear points + values.clear(); + } + GForce gforce = getGForceValue(arg0); + if (gforce != null) + values.add(gforce); + repaint(); + } + + public abstract GForce getGForceValue(GenericEvent e); + + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getLineColor() { + return lineColor; + } + + public Color getXColor() { + return xColor; + } + + public Color getYColor() { + return yColor; + } + + public Color getZColor() { + return zColor; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + public void setXColor(Color xColor) { + this.xColor = xColor; + } + + public void setYColor(Color yColor) { + this.yColor = yColor; + } + + public void setZColor(Color zColor) { + this.zColor = zColor; + } + + public void clearView() { + values.clear(); + repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/GForceWiimoteEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/GForceWiimoteEventPanel.java new file mode 100644 index 0000000..1ae710e --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/GForceWiimoteEventPanel.java @@ -0,0 +1,37 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.GForce; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; + +/** + * Panel to display GForce in a MotionSensingEvent from a wiimote. + * + * @author guiguito + */ +public class GForceWiimoteEventPanel extends GForcePanel { + + @Override + public GForce getGForceValue(GenericEvent e) { + if (e instanceof MotionSensingEvent) { + return ((MotionSensingEvent) e).getGforce(); + } + return null; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/IRPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/IRPanel.java new file mode 100644 index 0000000..c826fee --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/IRPanel.java @@ -0,0 +1,253 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.AffineTransform; + +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This panel is used to see what the IR camera of the wiimote sees. + * + * @author guiguito + */ +public class IRPanel extends javax.swing.JPanel implements WiimoteListener { + + private static int MAX_NB_POINTS = 4; + private Color color = Color.YELLOW; + private Color backgroundColor = Color.BLACK; + private Color borderColor = Color.BLUE; + private Shape shape; + private Image mImage;// image for double buffering + private int[] xCoordinates; + private int[] yCoordinates; + private int nbPoints = -1; + + /** + * Default constructor for IR Panel. Background color : black. IR sources + * color : yellow. Border color of IR sources : blue. Shape of the IR + * sources : circle with a diameter of 10. + */ + public IRPanel() { + shape = new java.awt.geom.Ellipse2D.Double(0, 0, 10, 10); + initArrays(); + initComponents(); + } + + /** + * Constructor used to parameterize the IR panel. + * + * @param bgColor + * color. + * @param ptColor + * IR sources color. + * @param bdColor + * border color of IR sources. + * @param sh + * Shape of the IR sources. + */ + public IRPanel(Color bgColor, Color ptColor, Color bdColor, Shape sh) { + backgroundColor = bgColor; + color = ptColor; + borderColor = bdColor; + shape = sh; + initArrays(); + initComponents(); + } + + private void initArrays() { + xCoordinates = new int[MAX_NB_POINTS]; + yCoordinates = new int[MAX_NB_POINTS]; + for (int i = 0; i < MAX_NB_POINTS; i++) { + xCoordinates[i] = -1; + yCoordinates[i] = -1; + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // draw points + int i = 0; + while (i < nbPoints) { + double x = xCoordinates[i]; + double y = yCoordinates[i]; + + long xx = getWidth() - Math.round((double) getWidth() * x / 1024.0); + long yy = getHeight() + - Math.round((double) getHeight() * y / 768.0); + g2.translate(xx, yy); + + g2.setPaint(borderColor); + g2.draw(shape); + g2.setPaint(color); + g2.fill(shape); + + g2.setTransform(new AffineTransform()); + i++; + } + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing + repaint(); + } + + public void onIrEvent(IREvent arg0) { + // transfer points + wiiusej.values.IRSource[] points = arg0.getIRPoints(); + nbPoints = points.length; + for (int i = 0; i < points.length; i++) { + xCoordinates[i] = (int) points[i].getRx(); + yCoordinates[i] = (int) points[i].getRy(); + } + for (int i = points.length; i < MAX_NB_POINTS; i++) { + xCoordinates[i] = -1; + yCoordinates[i] = -1; + } + + // redraw panel + repaint(); + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + // nothing + } + + public void onExpansionEvent(ExpansionEvent e) { + // nothing + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // clear previous points + for (int i = 0; i < MAX_NB_POINTS; i++) { + xCoordinates[i] = -1; + yCoordinates[i] = -1; + } + // redraw panel + repaint(); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent e) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent e) { + // nothing + } + + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getBorderColor() { + return borderColor; + } + + public Color getColor() { + return color; + } + + public Shape getShape() { + return shape; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + public void setColor(Color color) { + this.color = color; + } + + public void setShape(Shape shape) { + this.shape = shape; + } + + public void clearView() { + initArrays(); + repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/JoystickEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/JoystickEventPanel.java new file mode 100644 index 0000000..6f04ce6 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/JoystickEventPanel.java @@ -0,0 +1,231 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.JoystickEvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * Panel to display joystick events. + * + * @author guiguito + */ +public abstract class JoystickEventPanel extends javax.swing.JPanel implements + WiimoteListener { + + private Image mImage;// image for double buffering + private Color backgroundColor = Color.BLACK; + private Color borderColor = Color.RED; + private Color pointColor = Color.RED; + private Shape shape = new java.awt.geom.Ellipse2D.Double(0, 0, 30, 30); + private JoystickEvent lastJoystickEvent = null; + + /** Creates new form JoystickPanel */ + public JoystickEventPanel() { + initComponents(); + } + + /** + * Constructor used to choose the colors used by the JoystickPanel. + * + * @param bgColor + * background color. + * @param pColor + * point color. + * @param bdColor + * border color for the shape. + * @param sh + * shape of what is drawn. + */ + public JoystickEventPanel(Color bgColor, Color pColor, Color bdColor, + Shape sh) { + backgroundColor = bgColor; + pointColor = pColor; + shape = sh; + borderColor = bdColor; + initComponents(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.setTransform(new AffineTransform()); + + // compute center + int xCenter = (int) Math.round(d.getWidth() / 2.0); + int yCenter = (int) Math.round(d.getHeight() / 2.0); + + // compute coordinates + if (lastJoystickEvent != null) { + double xAng = Math.sin(lastJoystickEvent.getAngle() * Math.PI + / 180.0) + * lastJoystickEvent.getMagnitude(); + double yAng = Math.cos(lastJoystickEvent.getAngle() * Math.PI + / 180.0) + * lastJoystickEvent.getMagnitude(); + int dx = (int) Math.round(shape.getBounds().getWidth() / 2); + int dy = (int) Math.round(shape.getBounds().getHeight() / 2); + double xTemp = xAng * (xCenter - dx * 2); + double yTemp = yAng * (yCenter - dy * 2); + int x = xCenter - dx + (int) xTemp; + int y = yCenter - dy - (int) yTemp; + // System.out.println("--------------------------------------------------------------------"); + // System.out.println(lastJoystickEvent); + // System.out.println("xCenter ,yCenter : "+xCenter+" , "+yCenter); + // System.out.println("xAng, yAng : "+xAng+" , "+yAng); + // System.out.println("dx, dy : "+dx+" , "+dy); + // System.out.println("xTemp, yTemp : "+xTemp+" , "+yTemp); + // System.out.println("x, y : "+x+" , "+y); + // shape + g2.translate(x, y); + g2.setPaint(borderColor); + g2.draw(shape); + g2.setPaint(pointColor); + g2.fill(shape); + } + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing + } + + public void onIrEvent(IREvent arg0) { + // nothing + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + // nothing + } + + public void onExpansionEvent(ExpansionEvent arg0) { + JoystickEvent joy = getJoystikEvent(arg0); + if (joy != null) { + lastJoystickEvent = joy; + } + repaint(); + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // nothing + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) { + // nothing + } + + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getPointColor() { + return pointColor; + } + + public Color getBorderColor() { + return borderColor; + } + + public Shape getShape() { + return shape; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public void setPointColor(Color pointColor) { + this.pointColor = pointColor; + } + + public void setBorderColor(Color borderColor) { + this.borderColor = borderColor; + } + + public void setShape(Shape shape) { + this.shape = shape; + } + + public abstract JoystickEvent getJoystikEvent(ExpansionEvent e); + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/NunchukJoystickEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/NunchukJoystickEventPanel.java new file mode 100644 index 0000000..a534751 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/NunchukJoystickEventPanel.java @@ -0,0 +1,37 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.JoystickEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; + +/** + * Panel to display nunchuk joystick events. + * + * @author guiguito + */ +public class NunchukJoystickEventPanel extends JoystickEventPanel { + + @Override + public JoystickEvent getJoystikEvent(ExpansionEvent e) { + if (e instanceof NunchukEvent) { + return ((NunchukEvent) e).getNunchukJoystickEvent(); + } + return null; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/OrientationExpansionEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/OrientationExpansionEventPanel.java new file mode 100644 index 0000000..f5e3856 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/OrientationExpansionEventPanel.java @@ -0,0 +1,38 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.Orientation; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; + +/** + * Panel to display Orientation in a MotionSensingEvent from an expansion. + * + * @author guiguito + */ +public class OrientationExpansionEventPanel extends OrientationPanel { + + @Override + public Orientation getOrientationValue(GenericEvent e) { + if (e instanceof NunchukEvent) { + return ((NunchukEvent) e).getNunchukMotionSensingEvent() + .getOrientation(); + } + return null; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/OrientationPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/OrientationPanel.java new file mode 100644 index 0000000..b298911 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/OrientationPanel.java @@ -0,0 +1,283 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.util.ArrayList; + +import wiiusej.values.Orientation; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.utils.WiimoteListener; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This panel is used to watch orientation values from a MotionSensingEvent. + * + * @author guiguito + */ +public abstract class OrientationPanel extends javax.swing.JPanel implements + WiimoteListener { + + private Image mImage;// image for double buffering + private Color rollColor = Color.RED; + private Color pitchColor = Color.GREEN; + private Color yawColor = Color.BLUE; + private Color backgroundColor = Color.WHITE; + private Color lineColor = Color.BLACK; + private ArrayList values = new ArrayList(); + + /** + * Default constructor. Background color : White. Roll color : Red. Pitch + * color : Green. Yaw color : Blue. + */ + public OrientationPanel() { + initComponents(); + } + + /** + * Constructor used to choose the colors used by the OrientationPanel. + * + * @param bgColor + * background color. + * @param rColor + * roll color. + * @param pColor + * pitch color. + * @param yColor + * yaw color. + * @param lColor + * line color. + */ + public OrientationPanel(Color bgColor, Color rColor, Color pColor, + Color yColor, Color lColor) { + backgroundColor = bgColor; + rollColor = rColor; + pitchColor = pColor; + yawColor = yColor; + lineColor = lColor; + initComponents(); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension d = getSize(); + checkOffScreenImage(); + Graphics offG = mImage.getGraphics(); + offG.setColor(backgroundColor); + offG.fillRect(0, 0, d.width, d.height); + Graphics2D g2 = (Graphics2D) mImage.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // draw medium line + double yMiddleFloat = getHeight() / 2.0; + int yMiddle = (int) Math.round(yMiddleFloat); + + g2.setPaint(lineColor); + g2.drawLine(0, yMiddle, getWidth(), yMiddle); + + Orientation[] valuesArray = values.toArray(new Orientation[0]); + double unit = yMiddleFloat / 180.0; + int previousRoll = 0; + int previousPitch = 0; + int previousYaw = 0; + // draw curves + for (int i = 0; i < valuesArray.length && i < getWidth(); i++) { + Orientation orientation = valuesArray[i]; + // draw roll + g2.setPaint(rollColor); + int yDelta = (int) Math.round(unit * orientation.getRoll()); + int y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousRoll, i, y); + g2.setTransform(new AffineTransform()); + previousRoll = y; + // draw pitch + g2.setPaint(pitchColor); + yDelta = (int) Math.round(unit * orientation.getPitch()); + y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousPitch, i, y); + g2.setTransform(new AffineTransform()); + previousPitch = y; + // draw yaw + g2.setPaint(yawColor); + yDelta = (int) Math.round(unit * orientation.getYaw()); + y = -1 * yDelta + yMiddle; + g2.drawLine(i - 1, previousYaw, i, y); + g2.setTransform(new AffineTransform()); + previousYaw = y; + } + + // draw legend + g2.setPaint(rollColor); + g2.drawLine(5, getHeight() - 10, 25, getHeight() - 10); + g2.setPaint(pitchColor); + g2.drawLine(60, getHeight() - 10, 80, getHeight() - 10); + g2.setPaint(yawColor); + g2.drawLine(120, getHeight() - 10, 140, getHeight() - 10); + + g2.setPaint(lineColor); + g2.drawString("Roll", 30, getHeight() - 5); + g2.drawString("Pitch", 85, getHeight() - 5); + g2.drawString("Yaw", 145, getHeight() - 5); + g2.drawString("0", 2, yMiddle - 5); + g2.drawString("180", 2, 10); + g2.drawString("-180", 2, getHeight() - 15); + // put offscreen image on the screen + g.drawImage(mImage, 0, 0, null); + } + + /** + * check if the mImage variable has been initialized. If it's not the case + * it initializes it with the dimensions of the panel. mImage is for double + * buffering. + */ + private void checkOffScreenImage() { + Dimension d = getSize(); + if (mImage == null || mImage.getWidth(null) != d.width + || mImage.getHeight(null) != d.height) { + mImage = createImage(d.width, d.height); + } + } + + public void onButtonsEvent(WiimoteButtonsEvent arg0) { + // nothing + } + + public void onIrEvent(IREvent arg0) { + // nothing + } + + public void onMotionSensingEvent(MotionSensingEvent arg0) { + draw(arg0); + } + + public void onExpansionEvent(ExpansionEvent arg0) { + draw(arg0); + } + + public void onStatusEvent(StatusEvent arg0) { + // nothing + } + + public void onDisconnectionEvent(DisconnectionEvent arg0) { + // Clear points. + values.clear(); + repaint(); + } + + public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) { + // nothing + } + + public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) { + // nothing + } + + private void draw(GenericEvent arg0) { + if (values.size() >= getWidth()) { + // if there are as many values as pixels in the width + // clear points + values.clear(); + } + Orientation orientation = getOrientationValue(arg0); + if (orientation != null) + values.add(orientation); + repaint(); + } + + public abstract Orientation getOrientationValue(GenericEvent e); + + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getLineColor() { + return lineColor; + } + + public Color getPitchColor() { + return pitchColor; + } + + public Color getRollColor() { + return rollColor; + } + + public Color getYawColor() { + return yawColor; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + + public void setPitchColor(Color pitchColor) { + this.pitchColor = pitchColor; + } + + public void setRollColor(Color rollColor) { + this.rollColor = rollColor; + } + + public void setYawColor(Color yawColor) { + this.yawColor = yawColor; + } + + public void clearView() { + values.clear(); + repaint(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 400, + Short.MAX_VALUE)); + layout.setVerticalGroup(layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 300, + Short.MAX_VALUE)); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables +} diff --git a/WiiUseJ_0.12/src/wiiusej/utils/OrientationWiimoteEventPanel.java b/WiiUseJ_0.12/src/wiiusej/utils/OrientationWiimoteEventPanel.java new file mode 100644 index 0000000..e38f3c9 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/utils/OrientationWiimoteEventPanel.java @@ -0,0 +1,38 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.utils; + +import wiiusej.values.Orientation; +import wiiusej.wiiusejevents.GenericEvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; + +/** + * Panel to display Orientation in a MotionSensingEvent from a wiimote. + * + * @author guiguito + */ +public class OrientationWiimoteEventPanel extends OrientationPanel { + + @Override + public Orientation getOrientationValue(GenericEvent e) { + if (e instanceof MotionSensingEvent) { + return ((MotionSensingEvent) e).getOrientation(); + } + return null; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/values/GForce.java b/WiiUseJ_0.12/src/wiiusej/values/GForce.java new file mode 100644 index 0000000..da79ed2 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/values/GForce.java @@ -0,0 +1,80 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.values; + +/** + * Represents gravity force on each axis. + * + * @author guiguito + */ +public class GForce { + + private float x; + private float y; + private float z; + + /** + * Default constructor; + */ + public GForce() { + x = 0; + y = 0; + z = 0; + } + + /** + * Constructor with gravity force on each axis. + * + * @param xx + * x value + * @param yy + * x value + * @param zz + * x value + */ + public GForce(float xx, float yy, float zz) { + x = xx; + y = yy; + z = zz; + } + + /** + * @return the x + */ + public float getX() { + return x; + } + + /** + * @return the y + */ + public float getY() { + return y; + } + + /** + * @return the z + */ + public float getZ() { + return z; + } + + @Override + public String toString() { + return "Gravity force : (" + x + ", " + y + "," + z + ")"; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/values/IRSource.java b/WiiUseJ_0.12/src/wiiusej/values/IRSource.java new file mode 100644 index 0000000..a738c05 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/values/IRSource.java @@ -0,0 +1,106 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.values; + +/** + * Class used for IR sources. + * + * @author guiguito + */ +public class IRSource { + + private int x; + private int y; + private short rx; + private short ry; + private short size; + + /** + * Build an IR source with all details. + * + * @param xx + * xx interpolated coordinates. + * @param yy + * yy interpolated coordinates. + * @param rxx + * raw X coordinate (0-1023). + * @param ryy + * raw Y coordinate (0-1023). + * @param si + * size of the IR dot (0-15). + */ + public IRSource(int xx, int yy, short rxx, short ryy, short si) { + x = xx; + y = yy; + rx = rxx; + ry = ryy; + size = si; + } + + /** + * Return x interpolated coordinates. + * + * @return the x + */ + public int getX() { + return x; + } + + /** + * Return y interpolated coordinates. + * + * @return the y + */ + public int getY() { + return y; + } + + /** + * Return raw X coordinate (0-1023). + * + * @return the rx + */ + public short getRx() { + return rx; + } + + /** + * Return raw Y coordinate (0-1023). + * + * @return the ry + */ + public short getRy() { + return ry; + } + + /** + * Return size of the IR dot (0-15). + * + * @return the size + */ + public short getSize() { + return size; + } + + @Override + public String toString() { + return "Interpolated coordinates (" + x + "," + y + + "), Raw coordinates(" + rx + "," + ry + "), source size : " + + size + ")"; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/values/Orientation.java b/WiiUseJ_0.12/src/wiiusej/values/Orientation.java new file mode 100644 index 0000000..124d890 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/values/Orientation.java @@ -0,0 +1,117 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.values; + +/** + * Class that represents the orientation of the wiimote. + * + * @author guiguito + */ +public class Orientation { + + private float roll; + private float pitch; + private float yaw; + private float a_roll; + private float a_pitch; + + /** + * Default constructor. + */ + public Orientation() { + roll = 0; + pitch = 0; + yaw = 0; + a_roll = 0; + a_pitch = 0; + } + + /** + * Contructor with raw, pitch , yaw. + * + * @param r + * roll (can be smoothed) + * @param p + * pitch (can be smoothed) + * @param y + * yaw + * @param ar + * absolute roll + * @param ap + * absolute pitch + */ + public Orientation(float r, float p, float y, float ar, float ap) { + roll = r; + pitch = p; + yaw = y; + a_roll = ar; + a_pitch = ap; + } + + /** + * Get the roll (can be smoothed). + * + * @return the roll + */ + public float getRoll() { + return roll; + } + + /** + * Get the pitch (can be smoothed). + * + * @return the pitch + */ + public float getPitch() { + return pitch; + } + + /** + * Get the yaw. + * + * @return the yaw + */ + public float getYaw() { + return yaw; + } + + /** + * Get absolute roll (can not be smoothed). + * + * @return the a_roll + */ + public float getARoll() { + return a_roll; + } + + /** + * Get absolute pitch (can not be smoothed). + * + * @return the a_pitch + */ + public float getAPitch() { + return a_pitch; + } + + @Override + public String toString() { + return "Orientation : (roll: " + roll + ", pitch: " + pitch + ", yaw: " + + yaw + ", absolute roll: " + a_roll + ", absolute pitch: " + + a_pitch + ")"; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/values/RawAcceleration.java b/WiiUseJ_0.12/src/wiiusej/values/RawAcceleration.java new file mode 100644 index 0000000..83f9578 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/values/RawAcceleration.java @@ -0,0 +1,81 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.values; + +/** + * Represents raw acceleration on each axis. + * + * @author guiguito + */ +public class RawAcceleration { + + private short x; + private short y; + private short z; + + /** + * Default constructor; + */ + public RawAcceleration() { + x = 0; + y = 0; + z = 0; + } + + /** + * Constructor with raw acceleration on each axis. + * + * @param xx + * x value + * @param yy + * x value + * @param zz + * x value + */ + public RawAcceleration(short xx, short yy, short zz) { + x = xx; + y = yy; + z = zz; + } + + /** + * @return the x + */ + public short getX() { + return x; + } + + /** + * @return the y + */ + public short getY() { + return y; + } + + /** + * @return the z + */ + public short getZ() { + return z; + } + + @Override + public String toString() { + return "Raw acceleration : (" + x + ", " + y + "," + z + ")"; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/GenericEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/GenericEvent.java new file mode 100644 index 0000000..18d8429 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/GenericEvent.java @@ -0,0 +1,59 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents; + +/** + * Abstract mother class representing an event with a wiimote id. + * + * @author guiguito + */ +public abstract class GenericEvent { + + /* ID */ + private int wiimoteId = -1; + + /** + * Construct the WiiUseApiEvent setting up the id. + * + * @param id + * the Wiimote id + */ + public GenericEvent(int id) { + wiimoteId = id; + } + + /** + * Get Wiimote ID + * + * @return the wiimote id. + */ + public int getWiimoteId() { + return wiimoteId; + } + + /** + * Set Wiimote ID + * + * @param wiimoteId + * id of the wiimote + */ + void setWiimoteId(int wiimoteId) { + this.wiimoteId = wiimoteId; + } + + public abstract String toString(); +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ButtonsEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ButtonsEvent.java new file mode 100644 index 0000000..d9705fa --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ButtonsEvent.java @@ -0,0 +1,128 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +import wiiusej.wiiusejevents.GenericEvent; + +/** + * Class which represents a buttons event. + * + * @author guiguito + */ +public abstract class ButtonsEvent extends GenericEvent { + + /* Buttons */ + private short buttonsJustPressed = 0; + private short buttonsJustReleased = 0; + private short buttonsHeld = 0; + + /** + * Constructor of the button Event. + * + * @param id + * id of the wiimote concerned. + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons just held. + */ + public ButtonsEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + super(id); + setAllButtons(buttonsJustPressed, buttonsJustReleased, buttonsHeld); + } + + /** + * Set all buttons in one method. + * + * @param buttonsJustPressed + * @param buttonsJustReleased + * @param buttonsHeld + */ + private void setAllButtons(short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + this.buttonsJustPressed = buttonsJustPressed; + this.buttonsJustReleased = buttonsJustReleased; + this.buttonsHeld = buttonsHeld; + } + + /** + * Get the short storing the buttons just pressed + * + * @return the short storing the buttons just pressed + */ + public short getButtonsJustPressed() { + return buttonsJustPressed; + } + + /** + * Get the short storing the buttons just released + * + * @return the short storing the buttons just released + */ + public short getButtonsJustReleased() { + return buttonsJustReleased; + } + + /** + * get the short storing the buttons held + * + * @return the short storing the buttons held + */ + public short getButtonsHeld() { + return buttonsHeld; + } + + /** **************** BUTTONS Methods ***************** */ + /* generic button functions */ + + protected boolean buttonTest(short buttonBitsDefinition, short buttons) { + return (buttons & buttonBitsDefinition) == buttonBitsDefinition; + } + + protected boolean isButtonJustPressed(short buttonBitsDefinition) { + return buttonTest(buttonBitsDefinition, buttonsJustPressed) + && !isButtonHeld(buttonBitsDefinition); + } + + protected boolean isButtonJustReleased(short buttonBitsDefinition) { + return buttonTest(buttonBitsDefinition, buttonsJustReleased); + } + + protected boolean isButtonHeld(short buttonBitsDefinition) { + return buttonTest(buttonBitsDefinition, buttonsHeld); + } + + protected boolean isButtonPressed(short buttonBitsDefinition) { + return isButtonHeld(buttonBitsDefinition) + || isButtonJustPressed(buttonBitsDefinition); + } + + @Override + public String toString() { + String out = ""; + /* Display buttons */ + out += "/******** Buttons ********/\n"; + out += "--- Buttons just pressed : " + buttonsJustPressed + "\n"; + out += "--- Buttons just released : " + buttonsJustReleased + "\n"; + out += "--- Buttons held : " + buttonsHeld + "\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ExpansionEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ExpansionEvent.java new file mode 100644 index 0000000..868f33c --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/ExpansionEvent.java @@ -0,0 +1,40 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +import wiiusej.wiiusejevents.GenericEvent; + +/** + * Mother Class of all expansions event. + * + * @author guiguito + */ +public abstract class ExpansionEvent extends GenericEvent { + + /** + * Constructor of an ExpansionEvent. + * + * @param id + * id of the wiimote to which the expansion is connected. + */ + public ExpansionEvent(int id) { + super(id); + } + + public abstract String toString(); + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/IREvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/IREvent.java new file mode 100644 index 0000000..1873a8c --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/IREvent.java @@ -0,0 +1,317 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +import wiiusej.values.IRSource; +import wiiusej.wiiusejevents.GenericEvent; + +/** + * Class which represents an IR event. + * + * @author guiguito + */ +public class IREvent extends GenericEvent { + + /* IR Tracking */ + private IRSource[] IRPoints; + private short indexPoints = 0; + private int x; + private int y; + private float z;// distance from the sensor bar + private int ax; + private int ay; + private int xVRes; + private int yVRes; + private int xOffset; + private int yOffset; + private short sensorBarPostion; + private short screenAsPectRatio; + private short irSensitivity; + private float distance; + + static private short WIIUSE_IR_ABOVE = 0; + static private short WIIUSE_IR_BELOW = 1; + static private short WIIUSE_SCREEN_RATIO_4_3 = 0; + static private short WIIUSE_SCREEN_RATIO_16_9 = 1; + + private static short NB_POINTS = 4;// number of points IR can track + + /** + * Constructor of IREvent with full infos. + * + * @param id + * d of the wiimote concerned. + * @param x + * calculated X coordinate. + * @param y + * calculated Y coordinate. + * @param z + * calculated distance. + * @param ax + * absolute X coordinate. + * @param ay + * absolute Y coordinate + * @param xVRes + * IR virtual screen x resolution. + * @param yVRes + * IR virtual screen y resolution. + * @param xOffset + * IR X correction offset. + * @param yOffset + * IR Y correction offset. + * @param sensorBarPostion + * aspect ratio of the screen. + * @param screenAsPectRatio + * IR sensor bar position. + * @param irSensitivity + * Sensitivity of the infrared camera. + * @param distance + * Pixel Distance between first two dots + */ + public IREvent(int id, int x, int y, float z, int ax, int ay, int xVRes, + int yVRes, int xOffset, int yOffset, short sensorBarPostion, + short screenAsPectRatio, short irSensitivity, float distance) { + super(id); + this.x = x; + this.y = y; + this.z = z; + this.ax = ax; + this.ay = ay; + this.xVRes = xVRes; + this.yVRes = yVRes; + this.xOffset = xOffset; + this.yOffset = yOffset; + this.sensorBarPostion = sensorBarPostion; + this.screenAsPectRatio = screenAsPectRatio; + this.irSensitivity = irSensitivity; + this.distance = distance; + IRPoints = new IRSource[NB_POINTS]; + } + + /** + * Get list of IR points. + * + * @return the list of 2D points + */ + public IRSource[] getIRPoints() { + return java.util.Arrays.copyOfRange(IRPoints, 0, indexPoints); + } + + /** + * Add IR Point in the list (Max 4 points) + * + * @param x + * x value + * @param y + * y value + * @param rx + * raw X coordinate (0-1023). + * @param ry + * raw Y coordinate (0-1023). + * @param size + * size of the IR dot (0-15). + */ + public void addIRpoint(int x, int y, short rx, short ry, short size) { + IRPoints[indexPoints] = new IRSource(x, y, rx, ry, size); + indexPoints++; + return; + } + + /** + * Return calculated X coordinate. + * + * @return the x + */ + public int getX() { + return x; + } + + /** + * Return calculated Y coordinate. + * + * @return the y + */ + public int getY() { + return y; + } + + /** + * Return calculated distance. + * + * @return the z + */ + public float getZ() { + return z; + } + + /** + * Return absolute X coordinate. + * + * @return the ax + */ + public int getAx() { + return ax; + } + + /** + * Return absolute Y coordinate. + * + * @return the ay + */ + public int getAy() { + return ay; + } + + /** + * Return IR virtual screen x resolution. + * + * @return the xVRes + */ + public int getXVRes() { + return xVRes; + } + + /** + * Return IR virtual screen y resolution. + * + * @return the yVRes + */ + public int getYVRes() { + return yVRes; + } + + /** + * Return IR X correction offset. + * + * @return the xOffset + */ + public int getXOffset() { + return xOffset; + } + + /** + * Return IR Y correction offset. + * + * @return the yOffset + */ + public int getYOffset() { + return yOffset; + } + + /** + * Return true if the sensor bar is above. + * + * @return true if the sensor bar is above. + */ + public boolean isSensorBarAbove() { + return sensorBarPostion == WIIUSE_IR_ABOVE; + } + + /** + * Return true if the sensor bar is below. + * + * @return true if the sensor bar is below. + */ + public boolean isSensorBarBelow() { + return sensorBarPostion == WIIUSE_IR_BELOW; + } + + /** + * Return true if screen aspect ratio set is 4/3. + * + * @return true if screen aspect ratio set is 4/3. + */ + public boolean isScreenAspectRatio43() { + return screenAsPectRatio == WIIUSE_SCREEN_RATIO_4_3; + } + + /** + * Return true if screen aspect ratio set is 16/9. + * + * @return true if screen aspect ratio set is 16/9. + */ + public boolean isScreenAspectRatio169() { + return screenAsPectRatio == WIIUSE_SCREEN_RATIO_16_9; + } + + /** + * Return aspect ratio of the screen. + * + * @return the screenAsPectRatio + */ + public short getScreenAsPectRatio() { + return screenAsPectRatio; + } + + /** + * The sensitivity of the IR camera can be turned up or down depending on + * your needs. Like the Wii, wiiusej and wiiuse can set the camera + * sensitivity to a degree between 1 (lowest) and 5 (highest). The default + * is 3. + * + * @return the irSensitivity + */ + public short getIrSensitivity() { + return irSensitivity; + } + + /** + * Pixel distance between first 2 dots. + * + * @return the distance between first 2 dots. + */ + public float getDistance() { + return distance; + } + + @Override + public String toString() { + String out = ""; + /* Display IR Tracking */ + out += "/******** IR Tracking ********/\n"; + out += "--- Active : true\n"; + out += "--- calculated X coordinate : " + x + "\n"; + out += "--- calculated Y coordinate : " + y + "\n"; + out += "--- calculated Z coordinate : " + z + "\n"; + out += "--- calculated distance : " + distance + "\n"; + out += "--- absolute X coordinate : " + ax + "\n"; + out += "--- absolute Y coordinate : " + ay + "\n"; + out += "--- IR virtual screen x resolution : " + xVRes + "\n"; + out += "--- IR virtual screen y resolution : " + yVRes + "\n"; + out += "--- IR X correction offset : " + xOffset + "\n"; + out += "--- IR Y correction offset : " + yOffset + "\n"; + out += "--- IR Sensitivity (between 1-5) : " + irSensitivity + "\n"; + if (isScreenAspectRatio43()) { + out += "--- aspect ratio of the screen : 4/3\n"; + } else if (isScreenAspectRatio169()) { + out += "--- aspect ratio of the screen : 16/9\n"; + } + if (isSensorBarAbove()) { + out += "--- IR sensor bar position. : Above\n"; + } else if (isSensorBarBelow()) { + out += "--- IR sensor bar position. : Below\n"; + } + out += "--- Seen points\n"; + for (int i = 0; i < IRPoints.length; i++) { + if (IRPoints[i] != null) { + out += IRPoints[i].toString(); + } + } + out += "\n"; + return out; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/JoystickEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/JoystickEvent.java new file mode 100644 index 0000000..5dc7f2f --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/JoystickEvent.java @@ -0,0 +1,135 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +import wiiusej.wiiusejevents.GenericEvent; + +/** + * Class that stores values on a joystick Event. + * + * @author guiguito + */ +public class JoystickEvent extends GenericEvent { + + private float angle; + private float magnitude; + private short[] max; + private short[] min; + private short[] center; + + /** + * Constructor of a JoystickEvent. + * + * @param id + * id of the wiimote connected. + * @param angle + * angle the joystick is being held. + * @param magnitude + * magnitude of the joystick (range 0-1). + * @param max1 + * maximum joystick value 1. + * @param max2 + * maximum joystick value 2. + * @param min1 + * minimum joystick value 1. + * @param min2 + * minimum joystick value 2. + * @param center1 + * center joystick value 1. + * @param center2 + * center joystick value 2. + */ + public JoystickEvent(int id, float angle, float magnitude, short max1, + short max2, short min1, short min2, short center1, short center2) { + super(id); + this.angle = angle; + this.magnitude = magnitude; + max = new short[2]; + max[0] = max1; + max[1] = max2; + min = new short[2]; + min[0] = min1; + min[1] = min2; + center = new short[2]; + center[0] = center1; + center[1] = center2; + } + + /** + * Get angle the joystick is being held. + * + * @return the angle angle the joystick. + */ + public float getAngle() { + return angle; + } + + /** + * Get magnitude of the joystick (range 0-1). + * + * @return the magnitude magnitude of the joystick. + */ + public float getMagnitude() { + return magnitude; + } + + /** + * Maximum joystick values. + * + * @return the max + */ + public short[] getMax() { + return max; + } + + /** + * Minimum joystick values. + * + * @return the min + */ + public short[] getMin() { + return min; + } + + /** + * Center joystick values. + * + * @return the center + */ + public short[] getCenter() { + return center; + } + + /* + * (non-Javadoc) + * + * @see wiiusej.wiiusejevents.GenericEvent#toString() + */ + @Override + public String toString() { + String out = ""; + /* Display IR Tracking */ + out += "/******** Joystick ********/\n"; + out += "--- angle : " + angle + "\n"; + out += "--- magnitude : " + magnitude + "\n"; + out += "--- maximum values : " + max[0] + "," + max[1] + "\n"; + out += "--- minimum values : " + min[0] + "," + min[1] + "\n"; + out += "--- center values : " + center[0] + "," + center[1] + "\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/MotionSensingEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/MotionSensingEvent.java new file mode 100644 index 0000000..0945a48 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/MotionSensingEvent.java @@ -0,0 +1,203 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +import wiiusej.values.GForce; +import wiiusej.values.Orientation; +import wiiusej.values.RawAcceleration; +import wiiusej.wiiusejevents.GenericEvent; + +/** + * Class which represents a motion sensing event. + * + * @author guiguito + */ +public class MotionSensingEvent extends GenericEvent { + + /* Motion Sensing */ + private Orientation orientation; + private GForce gforce; + private RawAcceleration acceleration; + + private float orientationThreshold = 0; + private int accelerationThreshold = 0; + private float alphaSmoothing = 0; + private boolean isSmoothingActive = false; + + /** + * Constructor for a Motion Sensing Event. + * + * @param id + * id of the wiimote concerned. + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + */ + public MotionSensingEvent(int id, float orientationThreshold, + int accelerationThreshold, boolean smoothingState, + float alphaSmooth, float r, float p, float ya, float ar, float ap, + float x, float y, float z, short xx, short yy, short zz) { + super(id); + this.orientationThreshold = orientationThreshold; + this.accelerationThreshold = accelerationThreshold; + this.isSmoothingActive = smoothingState; + this.alphaSmoothing = alphaSmooth; + setOrientationAndGforce(r, p, ya, ar, ap, x, y, z, xx, yy, zz); + } + + /** + * Set orientation, gravity force and raw acceleration. + * + * @param r + * roll + * @param p + * pitch + * @param ya + * yaw + * @param ar + * absolute roll + * @param ap + * absolute pitch + * @param x + * gravity force on x axis + * @param y + * gravity force on y axis + * @param z + * gravity force on z axis + * @param xx + * raw acceleration on x axis + * @param yy + * raw acceleration on y axis + * @param zz + * raw acceleration on z axis + */ + private void setOrientationAndGforce(float r, float p, float ya, float ar, + float ap, float x, float y, float z, short xx, short yy, short zz) { + this.orientation = new Orientation(r, p, ya, ar, ap); + this.gforce = new GForce(x, y, z); + this.acceleration = new RawAcceleration(xx, yy, zz); + } + + /** + * @return the orientation + */ + public Orientation getOrientation() { + return orientation; + } + + /** + * Get the gravity force. + * + * @return the gforce + */ + public GForce getGforce() { + return gforce; + } + + /** + * Get the raw acceleration. + * + * @return the raw acceleration + */ + public RawAcceleration getRawAcceleration() { + return acceleration; + } + + /** + * Get orientation threshold. + * + * @return the orientationThreshold + */ + public float getOrientationThreshold() { + return orientationThreshold; + } + + /** + * Get acceleration threshold. + * + * @return the accelerationThreshold + */ + public int getAccelerationThreshold() { + return accelerationThreshold; + } + + /** + * Get alpha smoothing. + * + * @return the alphaSmoothing + */ + public float getAlphaSmoothing() { + return alphaSmoothing; + } + + /** + * Tell if the option SMOOTHING is activated. + * + * @return the isSmoothingActive + */ + public boolean isSmoothingActive() { + return isSmoothingActive; + } + + @Override + public String toString() { + String out = ""; + /* Motion sensing */ + out += "/******** Motion sensing ********/\n"; + out += "--- Motion sensing : true \n"; + out += "--- Orientation threshold value ? : " + orientationThreshold + + "\n"; + out += "--- Acceleration threshold value ? : " + accelerationThreshold + + "\n"; + out += "--- Alpha smoothing threshold value ? : " + alphaSmoothing + + "\n"; + out += "--- Smoothing ? : " + isSmoothingActive + "\n"; + out += "--- " + orientation + "\n"; + out += "--- " + gforce + "\n"; + out += "--- " + acceleration + "\n"; + return out; + } +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukButtonsEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukButtonsEvent.java new file mode 100644 index 0000000..b6584d6 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukButtonsEvent.java @@ -0,0 +1,90 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +/** + * Class which represents a buttons event for a generic event. It means buttons + * from a wiimote. + * + * @author guiguito + */ +public class NunchukButtonsEvent extends ButtonsEvent { + + private static short NUNCHUK_BUTTON_Z = 0x01; + private static short NUNCHUK_BUTTON_C = 0x02; + private static short NUNCHUK_BUTTON_ALL = 0x03; + + /** + * Constructor of the nunchuk button Event. + * + * @param id + * id of the wiimote. + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons just pressed. + */ + public NunchukButtonsEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + super(id, buttonsJustPressed, buttonsJustReleased, buttonsHeld); + } + + /* Button Z */ + + public boolean isButtonZJustPressed() { + return isButtonJustPressed(NUNCHUK_BUTTON_Z); + } + + public boolean isButtonZJustReleased() { + return isButtonJustReleased(NUNCHUK_BUTTON_Z); + } + + public boolean isButtonZeHeld() { + return isButtonHeld(NUNCHUK_BUTTON_Z); + } + + public boolean isButtonZPressed() { + return isButtonPressed(NUNCHUK_BUTTON_Z); + } + + /* Button Z */ + + public boolean isButtonCJustPressed() { + return isButtonJustPressed(NUNCHUK_BUTTON_C); + } + + public boolean isButtonCJustReleased() { + return isButtonJustReleased(NUNCHUK_BUTTON_C); + } + + public boolean isButtonCHeld() { + return isButtonHeld(NUNCHUK_BUTTON_C); + } + + public boolean isButtonCPressed() { + return isButtonPressed(NUNCHUK_BUTTON_C); + } + + @Override + public String toString() { + return "/******** Buttons for Nunchuk Event ********/\n" + + super.toString(); + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukEvent.java new file mode 100644 index 0000000..eec7b97 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/NunchukEvent.java @@ -0,0 +1,169 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +/** + * This class represents the values from the joystick and its events. + * + * @author guiguito + */ +public class NunchukEvent extends ExpansionEvent { + + NunchukButtonsEvent buttonsEvent; + MotionSensingEvent nunchukMotionSensingEvent; + JoystickEvent nunchukJoystickEvent; + + /** + * Constructor of NunchukEvent. + * + * @param id + * id of the wiimote. + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons just pressed. + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + * @param angle + * angle the joystick is being held. + * @param magnitude + * magnitude of the joystick (range 0-1). + * @param max1 + * maximum joystick value 1. + * @param max2 + * maximum joystick value 2. + * @param min1 + * minimum joystick value 1. + * @param min2 + * minimum joystick value 2. + * @param center1 + * center joystick value 1. + * @param center2 + * center joystick value 2. + */ + public NunchukEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld, + float orientationThreshold, int accelerationThreshold, + boolean smoothingState, float alphaSmooth, float r, float p, + float ya, float ar, float ap, float x, float y, float z, short xx, + short yy, short zz, float angle, float magnitude, short max1, + short max2, short min1, short min2, short center1, short center2) { + super(id); + buttonsEvent = new NunchukButtonsEvent(id, buttonsJustPressed, + buttonsJustReleased, buttonsHeld); + nunchukMotionSensingEvent = new MotionSensingEvent(id, + orientationThreshold, accelerationThreshold, smoothingState, + alphaSmooth, r, p, ya, ar, ap, x, y, z, xx, yy, zz); + nunchukJoystickEvent = new JoystickEvent(id, angle, magnitude, max1, + max2, min1, min2, center1, center2); + } + + /** + * Tell if there is a nunchuk motion sensing Event. + * + * @return TRUE if there is a nunchuk motion sensing event, false otherwise. + */ + public boolean isThereMotionSensingEvent() { + return nunchukMotionSensingEvent != null; + } + + /** + * Tell if there is a nunchuk joystick event. + * + * @return TRUE if there is a nunchuk joystick event, false otherwise. + */ + public boolean isThereNunchukJoystickEvent() { + return nunchukJoystickEvent != null; + } + + /** + * Get joystick buttons event. + * + * @return the joystick buttons event if there is one or null. + */ + public NunchukButtonsEvent getButtonsEvent() { + return buttonsEvent; + } + + /** + * Get the nunchuk motion sensing event. + * + * @return the nunchuk motion sensing event if there is one or null. + */ + public MotionSensingEvent getNunchukMotionSensingEvent() { + return nunchukMotionSensingEvent; + } + + /** + * Get the nunchuk joystick event. + * + * @return the nunchuk Joystick Event if there is one or null. + */ + public JoystickEvent getNunchukJoystickEvent() { + return nunchukJoystickEvent; + } + + /* + * (non-Javadoc) + * + * @see wiiusej.wiiusejevents.GenericEvent#toString() + */ + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** Nunchuk EVENT : WIIMOTE ID :" + getWiimoteId() + + " ********/\n"; + out += buttonsEvent; + out += nunchukJoystickEvent; + out += nunchukMotionSensingEvent; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/WiimoteButtonsEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/WiimoteButtonsEvent.java new file mode 100644 index 0000000..106fc1c --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/physicalevents/WiimoteButtonsEvent.java @@ -0,0 +1,267 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.physicalevents; + +/** + * Class which represents a buttons event for a generic event. It means buttons + * from a wiimote. + * + * @author guiguito + */ +public class WiimoteButtonsEvent extends ButtonsEvent { + + /* Buttons MACRO */ + private static short WIIMOTE_BUTTON_TWO = 0x0001; + private static short WIIMOTE_BUTTON_ONE = 0x0002; + private static short WIIMOTE_BUTTON_B = 0x0004; + private static short WIIMOTE_BUTTON_A = 0x0008; + private static short WIIMOTE_BUTTON_MINUS = 0x0010; + private static short WIIMOTE_BUTTON_ZACCEL_BIT6 = 0x0020; + private static short WIIMOTE_BUTTON_ZACCEL_BIT7 = 0x0040; + private static short WIIMOTE_BUTTON_HOME = 0x0080; + private static short WIIMOTE_BUTTON_LEFT = 0x0100; + private static short WIIMOTE_BUTTON_RIGHT = 0x0200; + private static short WIIMOTE_BUTTON_DOWN = 0x0400; + private static short WIIMOTE_BUTTON_UP = 0x0800; + private static short WIIMOTE_BUTTON_PLUS = 0x1000; + private static short WIIMOTE_BUTTON_ZACCEL_BIT4 = 0x2000; + private static short WIIMOTE_BUTTON_ZACCEL_BIT5 = 0x4000; + private static int WIIMOTE_BUTTON_UNKNOWN = 0x8000; + private static short WIIMOTE_BUTTON_ALL = 0x1F9F; + + /** + * Constructor of the wiimote button Event. + * + * @param id + * id of the wiimote. + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons held. + */ + public WiimoteButtonsEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + super(id, buttonsJustPressed, buttonsJustReleased, buttonsHeld); + } + + /* Button ONE */ + + public boolean isButtonOneJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_ONE); + } + + public boolean isButtonOneJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_ONE); + } + + public boolean isButtonOneHeld() { + return isButtonHeld(WIIMOTE_BUTTON_ONE); + } + + public boolean isButtonOnePressed() { + return isButtonPressed(WIIMOTE_BUTTON_ONE); + } + + /* Button TWO */ + + public boolean isButtonTwoJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_TWO); + } + + public boolean isButtonTwoJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_TWO); + } + + public boolean isButtonTwoHeld() { + return isButtonHeld(WIIMOTE_BUTTON_TWO); + } + + public boolean isButtonTwoPressed() { + return isButtonPressed(WIIMOTE_BUTTON_TWO); + } + + /* Button A */ + + public boolean isButtonAJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_A); + } + + public boolean isButtonAJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_A); + } + + public boolean isButtonAHeld() { + return isButtonHeld(WIIMOTE_BUTTON_A); + } + + public boolean isButtonAPressed() { + return isButtonPressed(WIIMOTE_BUTTON_A); + } + + /* Button B */ + + public boolean isButtonBJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_B); + } + + public boolean isButtonBJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_B); + } + + public boolean isButtonBHeld() { + return isButtonHeld(WIIMOTE_BUTTON_B); + } + + public boolean isButtonBPressed() { + return isButtonPressed(WIIMOTE_BUTTON_B); + } + + /* Button LEFT */ + + public boolean isButtonLeftJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_LEFT); + } + + public boolean isButtonLeftJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_LEFT); + } + + public boolean isButtonLeftHeld() { + return isButtonHeld(WIIMOTE_BUTTON_LEFT); + } + + public boolean isButtonLeftPressed() { + return isButtonPressed(WIIMOTE_BUTTON_LEFT); + } + + /* Button RIGHT */ + + public boolean isButtonRightJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_RIGHT); + } + + public boolean isButtonRightJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_RIGHT); + } + + public boolean isButtonRightHeld() { + return isButtonHeld(WIIMOTE_BUTTON_RIGHT); + } + + public boolean isButtonRightPressed() { + return isButtonPressed(WIIMOTE_BUTTON_RIGHT); + } + + /* Button UP */ + + public boolean isButtonUpJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_UP); + } + + public boolean isButtonUpJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_UP); + } + + public boolean isButtonUpHeld() { + return isButtonHeld(WIIMOTE_BUTTON_UP); + } + + public boolean isButtonUpPressed() { + return isButtonPressed(WIIMOTE_BUTTON_UP); + } + + /* Button DOWN */ + + public boolean isButtonDownJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_DOWN); + } + + public boolean isButtonDownJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_DOWN); + } + + public boolean isButtonDownHeld() { + return isButtonHeld(WIIMOTE_BUTTON_DOWN); + } + + public boolean isButtonDownPressed() { + return isButtonPressed(WIIMOTE_BUTTON_DOWN); + } + + /* Button - */ + + public boolean isButtonMinusJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_MINUS); + } + + public boolean isButtonMinusJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_MINUS); + } + + public boolean isButtonMinusHeld() { + return isButtonHeld(WIIMOTE_BUTTON_MINUS); + } + + public boolean isButtonMinusPressed() { + return isButtonPressed(WIIMOTE_BUTTON_MINUS); + } + + /* Button + */ + + public boolean isButtonPlusJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_PLUS); + } + + public boolean isButtonPlusJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_PLUS); + } + + public boolean isButtonPlusHeld() { + return isButtonHeld(WIIMOTE_BUTTON_PLUS); + } + + public boolean isButtonPlusPressed() { + return isButtonPressed(WIIMOTE_BUTTON_PLUS); + } + + /* Button HOME */ + + public boolean isButtonHomeJustPressed() { + return isButtonJustPressed(WIIMOTE_BUTTON_HOME); + } + + public boolean isButtonHomeJustReleased() { + return isButtonJustReleased(WIIMOTE_BUTTON_HOME); + } + + public boolean isButtonHomeHeld() { + return isButtonHeld(WIIMOTE_BUTTON_HOME); + } + + public boolean isButtonHomePressed() { + return isButtonPressed(WIIMOTE_BUTTON_HOME); + } + + @Override + public String toString() { + return "/******** Buttons for Wiimote generic Event ********/\n" + + super.toString(); + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/EventsGatherer.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/EventsGatherer.java new file mode 100644 index 0000000..31ed13a --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/EventsGatherer.java @@ -0,0 +1,355 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.utils; + +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; +import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent; +import wiiusej.wiiusejevents.wiiuseapievents.WiimoteEvent; + +/** + * This class is used to gather events during a call to the Wiiuse API. + * + * @author guiguito + */ +public class EventsGatherer { + + private WiiUseApiEvent[] events; + private int index = 0; + private WiimoteEvent genericEvent = null; + + /** + * Create EventsGatherer. + * + * @param nbWiimotes + * nb wiimotes (nb a of events possible in a call to Wiiuse API). + */ + public EventsGatherer(int nbWiimotes) { + events = new WiiUseApiEvent[nbWiimotes]; + } + + /** + * Add an event to the array. + * + * @param e + * the event to add. + */ + private void addEvent(WiiUseApiEvent e) { + events[index] = e; + index++; + } + + /** + * Prepare a wiimote event to add. + * + * @param id + * id of the wiimote. + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons held. + */ + public void prepareWiiMoteEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + genericEvent = new WiimoteEvent(id, buttonsJustPressed, + buttonsJustReleased, buttonsHeld); + } + + /** + * Prepare an IR event to populate. + * + * @param x + * calculated X coordinate. + * @param y + * calculated Y coordinate. + * @param z + * calculated distance. + * @param ax + * absolute X coordinate. + * @param ay + * absolute Y coordinate. + * @param xVRes + * IR virtual screen x resolution. + * @param yVRes + * IR virtual screen y resolution. + * @param xOffset + * IR X correction offset. + * @param yOffset + * IR Y correction offset. + * @param sensorBarPostion + * aspect ratio of the screen. + * @param screenAsPectRatio + * IR sensor bar position. + * @param irSensitivity + * Sensitivity of the infrared camera. + * @param distance + * Pixel Distance between first two dots. + */ + public void prepareIRevent(int x, int y, float z, int ax, int ay, + int xVRes, int yVRes, int xOffset, int yOffset, + short sensorBarPostion, short screenAsPectRatio, + short irSensitivity, float distance) { + genericEvent.prepareIRevent(x, y, z, ax, ay, xVRes, yVRes, xOffset, + yOffset, sensorBarPostion, screenAsPectRatio, irSensitivity, + distance); + + } + + /** + * Add an IR point to the WiiMoteEvent prepared. + * + * @param x + * x coordinates. + * @param y + * y coordinates. + * @param rx + * raw X coordinate (0-1023). + * @param ry + * raw Y coordinate (0-1023). + * @param size + * size of the IR dot (0-15). + */ + public void addIRPointToPreparedWiiMoteEvent(int x, int y, short rx, + short ry, short size) { + if (genericEvent != null) { + genericEvent.addIRpoint(x, y, rx, ry, size); + } + } + + /** + * Set orientation and gravity force of the prepared event. + * + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + */ + public void addMotionSensingValues(float orientationThreshold, + int accelerationThreshold, boolean smoothingState, + float alphaSmooth, float r, float p, float ya, float ar, float ap, + float x, float y, float z, short xx, short yy, short zz) { + if (genericEvent != null) { + genericEvent.setMotionSensingEvent(orientationThreshold, + accelerationThreshold, smoothingState, alphaSmooth, r, p, + ya, ar, ap, x, y, z, xx, yy, zz); + } + } + + /** + * Set a NunchukEvent to the prepared . + * + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons just pressed. + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + * @param angle + * angle the joystick is being held. + * @param magnitude + * magnitude of the joystick (range 0-1). + * @param max1 + * maximum joystick value 1. + * @param max2 + * maximum joystick value 2. + * @param min1 + * minimum joystick value 1. + * @param min2 + * minimum joystick value 2. + * @param center1 + * center joystick value 1. + * @param center2 + * center joystick value 2. + */ + public void addNunchunkEventToPreparedWiimoteEvent( + short buttonsJustPressed, short buttonsJustReleased, + short buttonsHeld, float orientationThreshold, + int accelerationThreshold, boolean smoothingState, + float alphaSmooth, float r, float p, float ya, float ar, float ap, + float x, float y, float z, short xx, short yy, short zz, + float angle, float magnitude, short max1, short max2, short min1, + short min2, short center1, short center2) { + if (genericEvent != null) { + genericEvent.setNunchukEvent(buttonsJustPressed, + buttonsJustReleased, buttonsHeld, orientationThreshold, + accelerationThreshold, smoothingState, alphaSmooth, r, p, + ya, ar, ap, x, y, z, xx, yy, zz, angle, magnitude, max1, + max2, min1, min2, center1, center2); + } + } + + /** + * Add the prepared WiimoteEvent to the gatherer. + */ + public void addWiimoteEvent() { + if (genericEvent != null) { + addEvent(genericEvent); + genericEvent = null; + } + } + + /** + * Add a StatusEvent to the gatherer. + * + * @param id + * id of the wiimote. + * @param connect + * true if the wiimote is connected. + * @param batt + * battery level. + * @param led + * status of leds. + * @param speak + * speakers status. + * @param attach + * attachment status. + * @param rumbleState + * true if rumble is active. + * @param continuousState + * true if continuous flag is activated. + * @param irState + * true if ir is active. + * @param motionSensingState + * true if accelerometer is active. + */ + public void addStatusEvent(int id, boolean connect, float batt, short led, + boolean speak, int attach, boolean rumbleState, + boolean continuousState, boolean irState, boolean motionSensingState) { + StatusEvent evt = new StatusEvent(id, connect, batt, led, speak, + attach, rumbleState, continuousState, irState, + motionSensingState); + addEvent(evt); + } + + /** + * Add a DisconnectionEvent to the gatherer. + * + * @param id + * id of the wiimote. + */ + public void addDisconnectionEvent(int id) { + DisconnectionEvent evt = new DisconnectionEvent(id); + addEvent(evt); + } + + /** + * Add a NunchukInsertedEvent to the gatherer. + * + * @param id + * id of the wiimote. + */ + public void addNunchukInsertedEvent(int id) { + NunchukInsertedEvent evt = new NunchukInsertedEvent(id); + addEvent(evt); + } + + /** + * Add a NunchukRemovedEvent to the gatherer. + * + * @param id + * id of the wiimote. + */ + public void addNunchukRemovedEvent(int id) { + NunchukRemovedEvent evt = new NunchukRemovedEvent(id); + addEvent(evt); + } + + /** + * Return an array containing the events. + * + * @return events received. + */ + public WiiUseApiEvent[] getEvents() { + return java.util.Arrays.copyOfRange(events, 0, index); + } + + /** + * Clear the gatherer and remove objects. + */ + public void clearEvents() { + for (int i = 0; i < events.length; i++) { + events[i] = null; + } + genericEvent = null; + index = 0; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiiUseApiListener.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiiUseApiListener.java new file mode 100644 index 0000000..ee1ce80 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiiUseApiListener.java @@ -0,0 +1,37 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.utils; + +import wiiusej.wiiusejevents.wiiuseapievents.WiiUseApiEvent; + +/** + * This is the interface to implement to listen to events from the wiiuse API. + * + * @author guiguito + */ +public interface WiiUseApiListener extends java.util.EventListener { + + /** + * Method called when a WiiUseApiEvent occurs. A WiiUseApiEvent can be : - + * WiimoteEvent (Storing ButtonsEvent and eventually IREvent and + * MotionSensingEvent) - StatusEvent - DisconnectionEvent + * + * @param e + */ + void onWiiUseApiEvent(WiiUseApiEvent e); + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiimoteListener.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiimoteListener.java new file mode 100644 index 0000000..d066516 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/utils/WiimoteListener.java @@ -0,0 +1,107 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.utils; + +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; +import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent; +import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent; + +/** + * This is the interface to implement to listen to events from wiimotes. The + * differents methods are called in this order : onButtonsEvent, onIrEvent, + * onMotionSensingEvent, onExpansionEvent, onStatusEvent, onDisconnectionEvent + * onNunchukInsertedEvent, onNunchukRemovedEvent. + * + * @author guiguito + */ +public interface WiimoteListener extends java.util.EventListener { + + /** + * Method called on a button Event. + * + * @param e + * the buttonEvent with the last informations about the buttons + * of the wiimote. + */ + void onButtonsEvent(WiimoteButtonsEvent e); + + /** + * Method called when an IR event occurs. + * + * @param e + * the IREvent with the IR points seen. + */ + void onIrEvent(IREvent e); + + /** + * Method called when a motion sensing event occurs. + * + * @param e + * the motion sensing event with orientation and acceleration. + */ + void onMotionSensingEvent(MotionSensingEvent e); + + /** + * Method called when an expansion event occurs. + * + * @param e + * the expansion event occured. + */ + void onExpansionEvent(ExpansionEvent e); + + /** + * Method called on a status event. A status event occurs when : - we ask it - + * an expansion controller has been plugged - an expansion controller has + * been unplugged This is where you can get the different values of the + * parameters setup on your wiimote. + * + * @param e + * the status event. + */ + void onStatusEvent(StatusEvent e); + + /** + * This is the method called when a disconnection event occurs. A + * disconnection event happens when : - there are no battery left - the + * wiimote has just been turned off - the connection is dropped + * + * @param e + * the disconnection event. + */ + void onDisconnectionEvent(DisconnectionEvent e); + + /** + * This is the method called when a NunchukInsertedEvent occurs. + * + * @param e + * the NunchukInsertedEvent. + */ + void onNunchukInsertedEvent(NunchukInsertedEvent e); + + /** + * This is the method called when a NunchukRemovedEvent occurs. + * + * @param e + * the NunchukRemovedEvent. + */ + void onNunchukRemovedEvent(NunchukRemovedEvent e); +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/DisconnectionEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/DisconnectionEvent.java new file mode 100644 index 0000000..1c844c7 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/DisconnectionEvent.java @@ -0,0 +1,45 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +/** + * Class representing a disconnection event. + * + * @author guiguito + */ +public class DisconnectionEvent extends WiiUseApiEvent { + + /** + * Construct the DisconnectionEvent setting up the id. + * + * @param id + * the Wiimote id + */ + public DisconnectionEvent(int id) { + super(id, WiiUseApiEvent.DISCONNECTION_EVENT); + } + + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** DISCONNECTION EVENT : WIIMOTE ID :" + + super.getWiimoteId() + " ********/\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukInsertedEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukInsertedEvent.java new file mode 100644 index 0000000..6aff636 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukInsertedEvent.java @@ -0,0 +1,51 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +/** + * Event that represents the connection of a nunchuk to a wiimote. + * + * @author guiguito + * + */ +public class NunchukInsertedEvent extends WiiUseApiEvent { + + /** + * Construct the NunchukInsertedEvent setting up the id. + * + * @param id + * id of the wiimote. + */ + public NunchukInsertedEvent(int id) { + super(id, WIIUSE_NUNCHUK_INSERTED); + } + + /* + * (non-Javadoc) + * + * @see wiiusej.wiiusejevents.WiiUseApiEvent#toString() + */ + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** NUNCHUK INSERTED EVENT : WIIMOTE ID :" + + super.getWiimoteId() + " ********/\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukRemovedEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukRemovedEvent.java new file mode 100644 index 0000000..c9c585d --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/NunchukRemovedEvent.java @@ -0,0 +1,50 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +/** + * Event that represents the connection of a nunchuk to a wiimote. + * + * @author guiguito + */ +public class NunchukRemovedEvent extends WiiUseApiEvent { + + /** + * Construct the NunchukInsertedEvent setting up the id. + * + * @param id + * id of the wiimote. + */ + public NunchukRemovedEvent(int id) { + super(id, WIIUSE_NUNCHUK_REMOVED); + } + + /* + * (non-Javadoc) + * + * @see wiiusej.wiiusejevents.WiiUseApiEvent#toString() + */ + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** NUNCHUK REMOVED EVENT : WIIMOTE ID :" + + super.getWiimoteId() + " ********/\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/StatusEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/StatusEvent.java new file mode 100644 index 0000000..d200bb7 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/StatusEvent.java @@ -0,0 +1,293 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +/** + * Class used to represent a status event. This class is used to know what are + * the settings of the wiimote. + * + * @author guiguito + */ +public class StatusEvent extends WiiUseApiEvent { + + protected static short WIIMOTE_LED_1 = 1; + protected static short WIIMOTE_LED_2 = 2; + protected static short WIIMOTE_LED_3 = 4; + protected static short WIIMOTE_LED_4 = 8; + + /* ATTACHMENT CONSTANTS */ + + private static short EXP_NONE = 0; + private static short EXP_NUNCHUK = 1; + private static short EXP_CLASSIC = 2; + private static short EXP_GUITAR_HERO_3 = 3; + + /* Status variables */ + private boolean connected = false; + + private float batteryLevel = -1; + + private short leds = 0; + + private boolean isSpeakerEnabled = false; + + private int attachment = 0; + + private boolean isRumbleActive = false; + + private boolean isContinuousActive = false; + + private boolean isIrActive = false; + + private boolean isMotionSensingActive = false; + + /** + * Construct the StatusEvent setting up the id. + * + * @param id + * the Wiimote id + */ + public StatusEvent(int id) { + super(id, WiiUseApiEvent.STATUS_EVENT); + } + + /** + * Build a StatusEvent with all fields set. + * + * @param id + * id of the wiimote + * @param connect + * true if the wiimote is connected + * @param batt + * battery level + * @param led + * status of leds + * @param speak + * speakers status + * @param attach + * attachment status + * @param rumbleState + * true if rumble is active + * @param continuousState + * true if continuous flag is activated + * @param irState + * true if ir is active + * @param motionSensingState + * true if accelerometer is active + */ + public StatusEvent(int id, boolean connect, float batt, short led, + boolean speak, int attach, boolean rumbleState, + boolean continuousState, boolean irState, boolean motionSensingState) { + super(id, WiiUseApiEvent.STATUS_EVENT); + connected = connect; + this.batteryLevel = batt; + this.leds = led; + this.isSpeakerEnabled = speak; + this.attachment = attach; + isRumbleActive = rumbleState; + isContinuousActive = continuousState; + isIrActive = irState; + isMotionSensingActive = motionSensingState; + } + + /** + * True if the wiimote is connected false otherwise. + * + * @return return the connected status. + */ + public boolean isConnected() { + return connected; + } + + /** + * Get battery level. + * + * @return battery level. 1 = 100% + */ + public float getBatteryLevel() { + return batteryLevel; + } + + /** + * Get status of the leds . + * + * @return a short representing LEDS turned on. + */ + public short getLeds() { + return leds; + } + + /** + * Tells if the given led is turned on according to the leds status int. + * + * @param led + * the int encoding a led. + * @return true if the led is turned on false otherwise. + */ + private boolean ledStatusCheck(short led) { + if ((leds & led) > 0) { + return true; + } else { + return false; + } + } + + /** + * Get led1 status. + * + * @return true if the led is set. + */ + public boolean isLed1Set() { + return ledStatusCheck(WIIMOTE_LED_1); + } + + /** + * Get led2 status. + * + * @return true if the led is set. + */ + public boolean isLed2Set() { + return ledStatusCheck(WIIMOTE_LED_2); + } + + /** + * Get led3 status. + * + * @return true if the led is set. + */ + public boolean isLed3Set() { + return ledStatusCheck(WIIMOTE_LED_3); + } + + /** + * Get led4 status. + * + * @return true if the led is set. + */ + public boolean isLed4Set() { + return ledStatusCheck(WIIMOTE_LED_4); + } + + /** + * Tell if the speaker is enable for this wiimote + * + * @return TRUE if it enabled false otherwise + */ + public boolean isSpeakerEnabled() { + return isSpeakerEnabled; + } + + /** + * Get the int representing the attachment type. + * + * @return value of the Attachment Type + */ + public int getAttachment() { + return attachment; + } + + /** + * Get the status of rumble. + * + * @return true if the rumble is active false otherwise + */ + public boolean isRumbleActive() { + return isRumbleActive; + } + + /** + * Tell if the CONTINUOUS option is activated. + * + * @return the isContinuousActive + */ + public boolean isContinuousActive() { + return isContinuousActive; + } + + /** + * Tell if the IR Tracking is active. + * + * @return TRUE if it is active or false otherwise. + */ + public boolean isIrActive() { + return isIrActive; + } + + /** + * Get the flag indicating if the motion sensing is active. + * + * @return true if the motion sensing is active false otherwise + */ + public boolean isMotionSensingActive() { + return isMotionSensingActive; + } + + /** + * Tells if an attachment is connected. + * + * @return true if anything is connected to the wiimote false otherwise. + */ + public boolean isAttachmentConnected() { + return attachment == EXP_NONE; + } + + /** + * Tells if a nunchuk is connected. + * + * @return true if a nunchuk is connected to the wiimote false otherwise. + */ + public boolean isNunchukConnected() { + return attachment == EXP_NUNCHUK; + } + + /** + * Tells if a classic controller is connected. + * + * @return true if a classic controller is connected to the wiimote false otherwise. + */ + public boolean isClassicControllerConnected() { + return attachment == EXP_CLASSIC; + } + + /** + * Tells if a guitar hero controller is connected. + * + * @return true if a guitar hero controllerr is connected to the wiimote false otherwise. + */ + public boolean isGuitarHeroConnected() { + return attachment == EXP_GUITAR_HERO_3; + } + + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** STATUS EVENT : WIIMOTE ID :" + + super.getWiimoteId() + " ********/\n"; + out += "--- connected : " + connected + "\n"; + out += "--- Battery level : " + batteryLevel + "\n"; + out += "--- Leds : " + leds + "\n"; + out += "--- Speaker enabled : " + isSpeakerEnabled + "\n"; + out += "--- Attachment ? : " + attachment + "\n"; + out += "--- Rumble ? : " + isRumbleActive + "\n"; + out += "--- Continuous ? : " + isContinuousActive + "\n"; + out += "--- IR active ? : " + isIrActive + "\n"; + out += "--- Motion sensing active ? : " + isMotionSensingActive + "\n"; + return out; + } + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiiUseApiEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiiUseApiEvent.java new file mode 100644 index 0000000..0527b13 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiiUseApiEvent.java @@ -0,0 +1,66 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +import wiiusej.wiiusejevents.GenericEvent; + +/** + * This class describes the structure of an event from the WiiUse API event. + * + * @author guiguito + */ +public abstract class WiiUseApiEvent extends GenericEvent{ + + public static int NONE_EVENT = 0; + public static int GENERIC_EVENT = 1; + public static int STATUS_EVENT = 2; + public static int DISCONNECTION_EVENT = 3; + public static int WIIUSE_READ_DATA = 4; + public static int WIIUSE_NUNCHUK_INSERTED = 5; + public static int WIIUSE_NUNCHUK_REMOVED = 6; + public static int WIIUSE_CLASSIC_CTRL_INSERTED = 7; + public static int WIIUSE_CLASSIC_CTRL_REMOVED = 8; + public static int WIIUSE_GUITAR_HERO_3_CTRL_INSERTED = 9; + public static int WIIUSE_GUITAR_HERO_3_CTRL_REMOVED = 10; + + /* Event Type */ + private int eventType; + + /** + * Construct the WiiUseApiEvent setting up the id. + * + * @param id + * the Wiimote id + * @param type + * type of the event + */ + public WiiUseApiEvent(int id, int type) { + super(id); + eventType = type; + } + + /** + * Get the event type. + * @return the eventType + */ + public int getEventType() { + return eventType; + } + + public abstract String toString(); + +} diff --git a/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiimoteEvent.java b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiimoteEvent.java new file mode 100644 index 0000000..04c1840 --- /dev/null +++ b/WiiUseJ_0.12/src/wiiusej/wiiusejevents/wiiuseapievents/WiimoteEvent.java @@ -0,0 +1,345 @@ +/** + * This file is part of WiiuseJ. + * + * WiiuseJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * WiiuseJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WiiuseJ. If not, see . + */ +package wiiusej.wiiusejevents.wiiuseapievents; + +import wiiusej.wiiusejevents.physicalevents.ExpansionEvent; +import wiiusej.wiiusejevents.physicalevents.IREvent; +import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent; +import wiiusej.wiiusejevents.physicalevents.NunchukEvent; +import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent; + +/** + * Class that is a bean to be filled by the wiiuse API on an event that occurs + * on a wiimote. + * + * @author guiguito + */ +public class WiimoteEvent extends WiiUseApiEvent { + + WiimoteButtonsEvent buttonsEvent = null; + IREvent infraredEvent = null; + MotionSensingEvent motionSensingEvent = null; + ExpansionEvent expansionEvent = null; + + /** + * Construct the Wiimote setting up the id. + * + * @param id + * the Wiimote id + */ + public WiimoteEvent(int id) { + super(id, WiiUseApiEvent.GENERIC_EVENT); + } + + /** + * Construct the Wiimote setting up the id and the buttons. + * + * @param id + * the Wiimote id + * @param buttonsJustPressed + * buttons just pressed + * @param buttonsJustReleased + * buttons just released + * @param buttonsHeld + * buttons held + */ + public WiimoteEvent(int id, short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld) { + super(id, WiiUseApiEvent.GENERIC_EVENT); + buttonsEvent = new WiimoteButtonsEvent(id, buttonsJustPressed, + buttonsJustReleased, buttonsHeld); + } + + /** + * Tell if there is an IR Event. + * + * @return TRUE if there is an IR event. + */ + public boolean isThereIrEvent() { + return infraredEvent != null; + } + + /** + * Tell if there is a motion sensing Event. + * + * @return TRUE if there is a motion sensing event. + */ + public boolean isThereMotionSensingEvent() { + return motionSensingEvent != null; + } + + /** + * Tell if there is an expansion Event. + * + * @return TRUE if there is an expansion event. + */ + public boolean isThereExpansionEvent() { + return expansionEvent != null; + } + + /** + * Get buttons event. + * + * @return the buttons event. + */ + public WiimoteButtonsEvent getButtonsEvent() { + return buttonsEvent; + } + + /** + * Get the IR event. + * + * @return the IR event if there is one or null. + */ + public IREvent getIREvent() { + return infraredEvent; + } + + /** + * Get the motion sensing event. + * + * @return the motion sensing event if there is one or null. + */ + public MotionSensingEvent getMotionSensingEvent() { + return motionSensingEvent; + } + + /** + * Get the expansion event. + * + * @return the expansion event if there is one or null. + */ + public ExpansionEvent getExpansionEvent() { + return expansionEvent; + } + + /** + * Prepare an IR event to populate. + * + * @param x + * calculated X coordinate. + * @param y + * calculated Y coordinate. + * @param z + * calculated distance. + * @param ax + * absolute X coordinate. + * @param ay + * absolute Y coordinate + * @param xVRes + * IR virtual screen x resolution. + * @param yVRes + * IR virtual screen y resolution. + * @param xOffset + * IR X correction offset. + * @param yOffset + * IR Y correction offset. + * @param sensorBarPostion + * aspect ratio of the screen. + * @param screenAsPectRatio + * IR sensor bar position. + * @param irSensitivity + * Sensitivity of the infrared camera. + * @param distance + * Pixel Distance between first two dots + */ + public void prepareIRevent(int x, int y, float z, int ax, int ay, + int xVRes, int yVRes, int xOffset, int yOffset, + short sensorBarPostion, short screenAsPectRatio, + short irSensitivity, float distance) { + if (infraredEvent == null) { + infraredEvent = new IREvent(getWiimoteId(), x, y, z, ax, ay, xVRes, + yVRes, xOffset, yOffset, sensorBarPostion, + screenAsPectRatio, irSensitivity, distance); + } + } + + /** + * Add an IR point to the generic event. Create an IR Event if it's not + * created yet. + * + * @param x + * x coordinates. + * @param y + * y coordinates + * @param rx + * raw X coordinate (0-1023). + * @param ry + * raw Y coordinate (0-1023). + * @param size + * size of the IR dot (0-15). + */ + public void addIRpoint(int x, int y, short rx, short ry, short size) { + if (infraredEvent != null) + infraredEvent.addIRpoint(x, y, rx, ry, size); + } + + /** + * Set the Motion Sensing Event. + * + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + */ + public void setMotionSensingEvent(float orientationThreshold, + int accelerationThreshold, boolean smoothingState, + float alphaSmooth, float r, float p, float ya, float ar, float ap, + float x, float y, float z, short xx, short yy, short zz) { + motionSensingEvent = new MotionSensingEvent(getWiimoteId(), + orientationThreshold, accelerationThreshold, smoothingState, + alphaSmooth, r, p, ya, ar, ap, x, y, z, xx, yy, zz); + } + + /** + * Set a NunchukEvent for the expansion event. + * + * @param buttonsJustPressed + * buttons just pressed. + * @param buttonsJustReleased + * buttons just released. + * @param buttonsHeld + * buttons just pressed. + * @param orientationThreshold + * value of the minimum angle between two events with the + * accelerometer. + * @param accelerationThreshold + * value of the value variation between two events with the + * accelerometer. + * @param smoothingState + * true if smoothing flag is activated. + * @param alphaSmooth + * value of the alpha smoothing parameter. + * @param r + * roll. + * @param p + * pitch. + * @param ya + * yaw. + * @param ar + * absolute roll. + * @param ap + * absolute pitch. + * @param x + * gravity force on x axis. + * @param y + * gravity force on y axis. + * @param z + * gravity force on z axis. + * @param xx + * raw acceleration on x axis. + * @param yy + * raw acceleration on y axis. + * @param zz + * raw acceleration on z axis. + * @param angle + * angle the joystick is being held. + * @param magnitude + * magnitude of the joystick (range 0-1). + * @param max1 + * maximum joystick value 1. + * @param max2 + * maximum joystick value 2. + * @param min1 + * minimum joystick value 1. + * @param min2 + * minimum joystick value 2. + * @param center1 + * center joystick value 1. + * @param center2 + * center joystick value 2. + */ + public void setNunchukEvent(short buttonsJustPressed, + short buttonsJustReleased, short buttonsHeld, + float orientationThreshold, int accelerationThreshold, + boolean smoothingState, float alphaSmooth, float r, float p, + float ya, float ar, float ap, float x, float y, float z, short xx, + short yy, short zz, float angle, float magnitude, short max1, + short max2, short min1, short min2, short center1, short center2) { + expansionEvent = new NunchukEvent(getWiimoteId(), buttonsJustPressed, + buttonsJustReleased, buttonsHeld, orientationThreshold, + accelerationThreshold, smoothingState, alphaSmooth, r, p, ya, + ar, ap, x, y, z, xx, yy, zz, angle, magnitude, max1, max2, + min1, min2, center1, center2); + } + + public void setClassicControllerEvent() { + // @TODO + } + + @Override + public String toString() { + String out = ""; + /* Status */ + out += "/*********** GENERIC EVENT : WIIMOTE ID :" + getWiimoteId() + + " ********/\n"; + + out += buttonsEvent; + + if (infraredEvent != null) { + out += infraredEvent; + } else { + out += "/******** IR Tracking ********/\n"; + out += "--- Active : false\n"; + } + + if (motionSensingEvent != null) { + out += motionSensingEvent; + } else { + out += "/******** Motion sensing ********/\n"; + out += "--- Motion sensing : false \n"; + } + + if (expansionEvent != null) { + out += expansionEvent; + } else { + out += "/******** Expansion ********/\n"; + out += "--- No expansion connected \n"; + } + + return out; + } + +} diff --git a/WiiUseJ_0.12/wiiuse.dll b/WiiUseJ_0.12/wiiuse.dll new file mode 100644 index 0000000000000000000000000000000000000000..a7e228c8743a1ff5cd537f1670304e79c2f46c2b GIT binary patch literal 114688 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 r0_7Gcw?MfC$}LcCfpQC!TcF$m