/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com
Copyright (c) 2012 I-maginer
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt
-----------------------------------------------------------------------------
*/
/*
Version : 1.0
First version : 05/08/2010
Author : Bourineau Bastien
*/
struct ObjJoyPadStr = [
PJOY_inst : PInstance,
PJOY_joypad : ObjJoypad,
PJOY_iIndex : I,
PJOY_control : [[F F F] [F F F]],
PJOY_lPrevAxis : [[F F] [F F] [F F] [F F] [F F]],
PJOY_lBtnState : [[I I] r1],
PJOY_iLstickState : I,
PJOY_iRstickState : I,
PJOY_bUpdated : I,
PJOY_bControl : I,
PJOY_bLstick : I,
PJOY_bRstick : I,
PJOY_bLz : I,
PJOY_bRz : I,
PJOY_bPov : I,
PJOY_bSlider : I
]mkObjJoyPadStr;;
/*! \brief Callback on instance destruction
*
* Prototype: fun [PInstance ObjJoypad] I
*
* \param PInstance : destroyed plugIT instance
* \param ObjJoypad : joypad object
*
* \return I : 0
**/
fun deleteOb(inst, obstr)=
setPluginInstanceCbPreRender inst nil;
_CloseJoypad obstr.PJOY_joypad;
0;;
fun cbJoyPreRender(inst, viewstr, obstr)=
if (!obstr.PJOY_bUpdated) then nil else
let obstr.PJOY_control -> [[vx vy vz] [ax ay az]] in
(
SendPluginEvent inst "Control" (strbuild ((ftoa vx)::(ftoa vy)::(ftoa -.vz)::nil)::((ftoa ay)::(ftoa ax)::(ftoa az)::nil)::nil) inst.INST_sName;
set obstr.PJOY_bUpdated = 0;
);
0;;
// for infos on pov values see : http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.dijoystate2(VS.85).aspx
fun cbJoypadData(joypad, obstr, stick1, lzaxis, stick2, rzaxis, pov, sliders, lbtn)=
let obstr.PJOY_inst -> inst in
let obstr.PJOY_control -> [v a] in
let 0.4 -> deadzone in
(
let stick1 -> [jx1 jy1] in
let (itof jx1) /. 1000.0 -> jfx1 in
let if ((absf jfx1) <=. deadzone) then 0.0 else (if (jfx1 <. 0.0) then (jfx1 +. deadzone) else (jfx1 -. deadzone)) /. (1.0 -. deadzone) -> jfx1 in
let (itof jy1) /. 1000.0 -> jfy1 in
let if ((absf jfy1) <=. deadzone) then 0.0 else (if (jfy1 <. 0.0) then (jfy1 +. deadzone) else (jfy1 -. deadzone)) /. (1.0 -. deadzone) -> jfy1 in
let stick2 -> [jx2 jy2] in
let (itof jx2) /. 1000.0 -> jfx2 in
let if ((absf jfx2) <=. deadzone) then 0.0 else (if (jfx2 <. 0.0) then (jfx2 +. deadzone) else (jfx2 -. deadzone)) /. (1.0 -. deadzone) -> jfx2 in
let (itof jy2) /. 1000.0 -> jfy2 in
let if ((absf jfy2) <=. deadzone) then 0.0 else (if (jfy2 <. 0.0) then (jfy2 +. deadzone) else (jfy2 -. deadzone)) /. (1.0 -. deadzone) -> jfy2 in
let (itof lzaxis) /. 1000.0 -> lfzaxis in
let if ((absf lfzaxis) <=. deadzone) then 0.0 else (if (lfzaxis <. 0.0) then (lfzaxis +. deadzone) else (lfzaxis -. deadzone)) /. (1.0 -. deadzone) -> lfzaxis in
let (itof rzaxis) /. 1000.0 -> rfzaxis in
let if ((absf rfzaxis) <=. deadzone) then 0.0 else (if (rfzaxis <. 0.0) then (rfzaxis +. deadzone) else (rfzaxis -. deadzone)) /. (1.0 -. deadzone) -> rfzaxis in
let sliders -> [slx sly] in
let (itof slx) /. 1000.0 -> sslx in
let if ((absf sslx) <=. deadzone) then 0.0 else (if (sslx <. 0.0) then (sslx +. deadzone) else (sslx -. deadzone)) /. (1.0 -. deadzone) -> sslx in
let (itof sly) /. 1000.0 -> ssly in
let if ((absf ssly) <=. deadzone) then 0.0 else (if (ssly <. 0.0) then (ssly +. deadzone) else (ssly -. deadzone)) /. (1.0 -. deadzone) -> ssly in
let pov -> [pov1 pov2 pov3 pov4] in
let if (pov1 == -1) then
[0.0 0.0]
else if (pov1 == 0) then
[0.0 1.0]
else if (pov1 == 4500) then
[1.0 1.0]
else if (pov1 == 9000) then
[1.0 0.0]
else if (pov1 == 13500) then
[1.0 (-.1.0)]
else if (pov1 == 18000) then
[0.0 (-.1.0)]
else if (pov1 == 22500) then
[(-.1.0) (-.1.0)]
else if (pov1 == 27000) then
[(-.1.0) 0.0]
else if (pov1 == 31500) then
[(-.1.0) 1.0]
else
[0.0 0.0]
-> [povx povy] in
(
mutate a <-[-.((maxf jfx1 jfx2) +. (minf jfx1 jfx2)) (-.jfy2) _];
mutate v <-[povx povy (-.jfy1)];
let obstr.PJOY_lPrevAxis -> [[pjfx1 pjfy1] [pjfx2 pjfy2] [plfzaxis prfzaxis] [ppovx ppovy] [pslx psly]] in
(
if ((!obstr.PJOY_bLstick) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (jfx1 -. pjfx1)) <=. 0.001) && ((absf (jfy1 -. pjfy1)) <=. 0.001))) then nil else
SendPluginEvent inst "Left stick" strcatn (ftoa jfx1)::" "::(ftoa jfy1)::nil nil;
if ((!obstr.PJOY_bRstick) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (jfx2 -. pjfx2)) <=. 0.001) && ((absf (jfy2 -. pjfy2)) <=. 0.001))) then nil else
SendPluginEvent inst "Right stick" strcatn (ftoa jfx2)::" "::(ftoa jfy2)::nil nil;
let if (obstr.PJOY_lPrevAxis == nil) then
0
else if (jfx1 <. (-.0.7)) then //left
-1
else if (jfx1 >. 0.7) then //right
1
else if (jfy1 <. (-.0.7)) then //up
2
else if (jfy1 >. 0.7) then //down
-2
else
0
-> ladir in
(
if (obstr.PJOY_iLstickState == ladir) then nil else
if (ladir == 0) then
SendPluginEvent inst "Left stick center" nil nil
else if (ladir == (-1)) then
SendPluginEvent inst "Left stick left" nil nil
else if (ladir == 1) then
SendPluginEvent inst "Left stick right" nil nil
else if (ladir == (-2)) then
SendPluginEvent inst "Left stick down" nil nil
else if (ladir == 2) then
SendPluginEvent inst "Left stick up" nil nil
else nil;
set obstr.PJOY_iLstickState = ladir;
);
let if (obstr.PJOY_lPrevAxis == nil) then
0
else if (jfx2 <. (-.0.7)) then //left
-1
else if (jfx2 >. 0.7) then //right
1
else if (jfy2 <. (-.0.7)) then //up
2
else if (jfy2 >. 0.7) then //down
-2
else
0
-> radir in
(
if (obstr.PJOY_iRstickState == radir) then nil else
if (radir == 0) then
SendPluginEvent inst "Right stick center" nil nil
else if (radir == (-1)) then
SendPluginEvent inst "Right stick left" nil nil
else if (radir == 1) then
SendPluginEvent inst "Right stick right" nil nil
else if (radir == (-2)) then
SendPluginEvent inst "Right stick down" nil nil
else if (radir == 2) then
SendPluginEvent inst "Right stick up" nil nil
else nil;
set obstr.PJOY_iRstickState = radir;
);
if ((!obstr.PJOY_bLz) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (lfzaxis -. plfzaxis)) <=. 0.001))) then nil else
SendPluginEvent inst "LZ axis" (ftoa lfzaxis) nil;
if ((!obstr.PJOY_bRz) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (rfzaxis -. prfzaxis)) <=. 0.001))) then nil else
SendPluginEvent inst "RZ axis" (ftoa rfzaxis) nil;
if ((!obstr.PJOY_bSlider) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (sslx -. pslx)) <=. 0.001) && ((absf (ssly -. psly)) <=. 0.001))) then nil else
SendPluginEvent inst "Slider axis" strcatn (ftoa sslx)::" "::(ftoa ssly)::nil nil;
if ((!obstr.PJOY_bPov) || ((obstr.PJOY_lPrevAxis != nil) && ((absf (povx -. ppovx)) == 0.0) && ((absf (povy -. ppovy)) == 0.0))) then nil else
SendPluginEvent inst "Pov" strcatn (ftoa povx)::" "::(ftoa povy)::nil nil;
if ((obstr.PJOY_lPrevAxis != nil) && ((absf (povx -. ppovx)) == 0.0)) then nil else
if (povx >. 0.0) then
SendPluginEvent inst "Pov right" nil nil
else if (povx <. 0.0) then
SendPluginEvent inst "Pov left" nil nil
else nil;
if ((obstr.PJOY_lPrevAxis != nil) && ((absf (povy -. ppovy)) == 0.0)) then nil else
if (povy >. 0.0) then
SendPluginEvent inst "Pov up" nil nil
else if (povy <. 0.0) then
SendPluginEvent inst "Pov down" nil nil
else nil;
if ((obstr.PJOY_lPrevAxis != nil) && ((povx != ppovx) || (povy != ppovy)) && ((povx == 0.0) && (povy == 0.0))) then
SendPluginEvent inst "Pov center" nil nil
else nil;
);
set obstr.PJOY_lPrevAxis = [[jfx1 jfy1] [jfx2 jfy2] [lfzaxis rfzaxis] [povx povy] [sslx ssly]];
);
if obstr.PJOY_lBtnState != nil then nil else
(
let sizelist lbtn -> size in
let 0 -> i in
while (i < size) do
(
set obstr.PJOY_lBtnState = [i (nth_list lbtn i)]::obstr.PJOY_lBtnState;
set i = i + 1;
);
set obstr.PJOY_lBtnState = revertlist obstr.PJOY_lBtnState;
);
let sizelist lbtn -> size in
let 0 -> i in
while (i < size) do
(
let (nth_list lbtn i) -> curstate in
(
if !curstate then nil else
SendPluginEvent inst strcat "Button " (itoa i+1) nil nil;
let switch obstr.PJOY_lBtnState i -> btnstate in
if (btnstate == curstate) then nil else
(
if curstate then
SendPluginEvent inst strcatn "Button "::(itoa i+1)::" down"::nil nil nil
else
SendPluginEvent inst strcatn "Button "::(itoa i+1)::" up"::nil nil nil;
);
//update btn states
let nth_list obstr.PJOY_lBtnState i -> btn in
mutate btn <- [_ curstate];
);
set i = i + 1;
);
);
set obstr.PJOY_bUpdated = 1;
0;;
fun cbStartRumble(inst, from, action, param, rep, obstr)=
let strextr param -> lp in
let if (atof (nth_list (hd lp) 0)) == nil then 0.5 else (atof (nth_list (hd lp) 0)) -> intensity in
_StartJoypadRumble obstr.PJOY_joypad intensity;
0;;
fun cbStopRumble(inst, from, action, param, rep, obstr)=
_StopJoypadRumble obstr.PJOY_joypad;
0;;
fun cbConnect(inst, from, action, param, rep, obstr)=
if (obstr.PJOY_joypad != nil) then nil else
(
let _OpenJoypadEx _channel obstr.PJOY_iIndex @cbJoypadData obstr -> joypad in
set obstr.PJOY_joypad = joypad;
if (obstr.PJOY_joypad == nil) || (!obstr.PJOY_bControl) then nil else
setPluginInstanceCbPreRender inst mkfun3 @cbJoyPreRender obstr;
);
0;;
fun cbDisconnect(inst, from, action, param, rep, obstr)=
setPluginInstanceCbPreRender inst nil;
_CloseJoypad obstr.PJOY_joypad;
set obstr.PJOY_joypad = nil;
0;;
fun cbSetDeviceIndex(inst, from, action, param, rep, obstr)=
if ((atoi param) == nil) then nil else
(
set obstr.PJOY_iIndex = atoi param;
if (obstr.PJOY_joypad == nil) then nil else
(
cbDisconnect inst nil nil nil nil obstr;
cbConnect inst nil nil nil nil obstr;
);
);
0;;
/*! \brief Callback on new plugIT instance
*
* Read the parameters from editor values and connect the joypad
*
* Prototype: fun [PInstance] I
*
* \param PInstance : plugIT instance
*
* \return I : 0
**/
fun newOb(inst)=
let atoi (getPluginInstanceParam inst "index") -> index in
let if index == nil then 0 else index -> index in
let atoi (getPluginInstanceParam inst "init") -> init in
let if init == nil then 1 else init -> init in
let (IsInEditor inst) || IsEventLinked inst "Control" -> bcontrol in
let (IsInEditor inst) || IsEventLinked inst "Left stick" -> blstick in
let (IsInEditor inst) || IsEventLinked inst "Right stick" -> brstick in
let (IsInEditor inst) || IsEventLinked inst "LZ axis" -> blz in
let (IsInEditor inst) || IsEventLinked inst "RZ axis" -> brz in
let (IsInEditor inst) || IsEventLinked inst "Pov" -> bpov in
let (IsInEditor inst) || IsEventLinked inst "Slider axis" -> bslider in
let mkObjJoyPadStr [inst nil index [[0.0 0.0 0.0] [0.0 0.0 0.0]] nil nil 0 0 0 bcontrol blstick brstick blz brz bpov bslider] -> obstr in
(
if (!init) then nil else
cbConnect inst nil nil nil nil obstr;
PluginRegisterAction inst "Connect" mkfun6 @cbConnect obstr;
PluginRegisterAction inst "Disconnect" mkfun6 @cbDisconnect obstr;
PluginRegisterAction inst "Set device index" mkfun6 @cbSetDeviceIndex obstr;
PluginRegisterAction inst "Start rumble" mkfun6 @cbStartRumble obstr;
PluginRegisterAction inst "Stop rumble" mkfun6 @cbStopRumble obstr;
setPluginInstanceCbDel inst mkfun2 @deleteOb obstr;
);
0;;
/*! \brief Global plugIT function to initialize the plugIT callbacks
*
* Prototype: fun [S] I
*
* \param S : plugIT file path
*
* \return I : 0
**/
fun IniPlug(file)=
PlugRegister @newOb nil;
setPluginEditor @dynamicedit;
0;;