/* ----------------------------------------------------------------------------- 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 ----------------------------------------------------------------------------- */ struct WalkSound = [ WSND_sPath : S, WSND_asSound : ObjAudio, WSND_iTimeStep : I, WSND_iTick : I ]mkWalkSound;; struct BasicNavigation = [ BNAV_sGroupName : S, BNAV_avBase : SO3_OBJECT, BNAV_shell : SO3_OBJECT, BNAV_camera : SO3_OBJECT, BNAV_neckShell : SO3_OBJECT, BNAV_camShell : SO3_OBJECT, BNAV_collShell : SO3_OBJECT, BNAV_shellBody : SO3_PHYSICBODY, BNAV_camBody : SO3_PHYSICBODY, BNAV_contraint : SO3_PHYSICCONTRAINT, BNAV_qLastOrientation : [F F F F], BNAV_vTargetTrans : [F F F], BNAV_vTargetPos : [F F F], BNAV_bTargetSwitch : I, BNAV_pos : [[F F F] [F F F]], BNAV_move : [[F F F] [F F F]], BNAV_mouseMove : [F F], BNAV_lastVelocity : [F F F], BNAV_lControls : [[S [[F F F] [F F F] F I I]] r1], BNAV_bHasMoved : I, BNAV_fFov : F, BNAV_fWalkSpeed : F, BNAV_fRunSpeed : F, BNAV_bShiftMode : I, BNAV_fMass : F, BNAV_fJumpForce : F, BNAV_bJumping : I, BNAV_fCamHeight : F, BNAV_fLastYPos : F, BNAV_fLastYRef : F, BNAV_tCamLimit : [F F], BNAV_lPressedKeys : [[I I] r1], BNAV_bHideMouse : I, BNAV_bShiftState : I, BNAV_bFocus : I, BNAV_bIgnoreNextMove : I, BNAV_bFlyMode : I, BNAV_bCrouchState : I, BNAV_bLastCrouchState : I, BNAV_bKeyboard : I, BNAV_bDisableDefControl : I, BNAV_bMouse : I, BNAV_leftPoint : [I I I], BNAV_rightPoint : [I I I], BNAV_sLastMaterial : S, BNAV_iContactCount : I, BNAV_iAirTick : I, BNAV_bInAir : I, BNAV_fInAirMaxVelocity : F, BNAV_curState : S, BNAV_lWSound : [[S WalkSound] r1], BNAV_jumpSound : ObjAudio, BNAV_hitSound : ObjAudio, BNAV_slideSound : ObjAudio, BNAV_bState : I, BNAV_bFreeHead : I, BNAV_bAutoHead : I, BNAV_iTick : I, BNAV_iNbUpDetections : I, BNAV_bHeadRangeState : I, BNAV_bShowFeetPos : I, BNAV_vTranslate : [F F F], BNAV_bSendFeetPosition : I, BNAV_bSendHeadPosition : I, BNAV_bSendHipPosition : I ]mkBasicNavigation;; var fNeckOutdistance = 0.25;; var fNeckMindistance = 0.15;; fun playHitSound(bnavstr, impact)= let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> pos in let SO3ObjectGetDerivedDirectionAxis bnavstr.BNAV_neckShell [0.0 0.0 1.0] -> dir in ( _AudioSetPosition bnavstr.BNAV_hitSound pos dir; let min (ftoi (impact *. 100.0)) 100 -> vol in _AudioSetVolume bnavstr.BNAV_hitSound vol; if (_AudioIsPlaying bnavstr.BNAV_hitSound) then nil else ( _AudioPlay3d bnavstr.BNAV_hitSound 0.8 0; ); ); 0;; fun playJumpSound(bnavstr)= let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> pos in let SO3ObjectGetDerivedDirectionAxis bnavstr.BNAV_neckShell [0.0 0.0 1.0] -> dir in ( _AudioSetPosition bnavstr.BNAV_jumpSound pos dir; _AudioPlay3d bnavstr.BNAV_jumpSound 0.8 0; ); 0;; fun computeControls(sessionstr, bnavstr, vnbsec, fspeed)= let [fspeed fspeed fspeed] -> vspeed in // analogic data let [0.0 0.0 0.0] -> avec in let [0.0 0.0 0.0] -> aang in // real data let [0.0 0.0 0.0] -> vec in let [0.0 0.0 0.0] -> hvec in let [0.0 0.0 0.0] -> ang in let 0.0 -> ycam in let 0 -> angOverride in let 0 -> addCamHeight in let 0 -> havedata in ( let sizelist bnavstr.BNAV_lControls -> size in let 0 -> i in while i < size do ( let nth_list bnavstr.BNAV_lControls i -> [_ tcontrol] in let tcontrol -> [nvec nang nycam mode newdata] in if (!newdata && mode != 0) then nil else ( if ((mode == 1) || (mode == 4)) then // accumulator ( set vec = addVectorF vec nvec; if (angOverride) then nil else set ang = addVectorF ang nang; set ycam = ycam +. nycam; if (mode != 4) then nil else // add cam height set addCamHeight = 1; //reset control mutate tcontrol <- [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 mode 0]; 0; ) else if (mode == 2) || (mode == 3) then // override angle ( set angOverride = 1; set hvec = addVectorF hvec nvec; set ang = nang; if (mode == 2) then set ycam = ycam +. nycam else ( set addCamHeight = 0; set ycam = nycam; ); //reset control mutate tcontrol <- [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 mode 0]; 0; ) else ( set avec = addVectorF avec nvec; set aang = addVectorF aang nang; mutate tcontrol <- [_ _ _ _ 0]; 0; ); set havedata = 1; ); set i = i + 1; ); // compute speed and time let if bnavstr.BNAV_bDisableDefControl then [[0.0 0.0 0.0] [0.0 0.0 0.0]] else bnavstr.BNAV_move -> [kvec kang] in let if bnavstr.BNAV_bDisableDefControl then [0.0 0.0] else bnavstr.BNAV_mouseMove -> [mx my] in ( set avec = multiplyVectorF multiplyVectorF (addVectorF avec kvec) vnbsec [2.0 2.0 2.0]; //2 meter per second ? set aang = multiplyVectorF multiplyVectorF (addVectorF addVectorF aang kang [my mx 0.0]) vnbsec [90.0 90.0 90.0]; //90 degree per second ? set avec = multiplyVectorF avec vspeed; if (zeroVectorF bnavstr.BNAV_vTranslate) then nil else set avec = addVectorF avec (multiplyVectorF bnavstr.BNAV_vTranslate vspeed); let aang -> [pitch yaw roll] in set aang = [(SO3MathsDegreeToRadian pitch) (SO3MathsDegreeToRadian yaw) (SO3MathsDegreeToRadian roll)]; ); let ang -> [ax ay az] in set ang = [(SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian ay) (SO3MathsDegreeToRadian az)]; let ang -> [ax ay az] in let aang -> [pitch yaw roll] in let if (angOverride) then [ax (ay +. yaw) az] else (addVectorF aang ang) -> fang in [(addVectorF avec vec) hvec fang ycam angOverride addCamHeight havedata]; );; // ignore avatar bodies and disabled bodies fun getValidRay(lray)= let nil -> body in let 0.0 -> dist in let [0.0 1.0 0.0] -> normal in ( while ((lray != nil) && (body == nil)) do ( let hd lray -> [tbody tdist tnormal] in ( let SO3PhysicsGetMaterialName (SO3BodyGetMaterial tbody) -> bmat in if (((SO3BodyGetType tbody) & 1) || (SO3BodyGetIgnoreCollision tbody) || (SO3BodyGetFluid tbody) || (!strcmp bmat "ignore")) then nil else ( set body = tbody; set dist = tdist; set normal = tnormal; ); ); set lray = tl lray; ); [body dist normal] );; fun cbNavKeyDown(inst, viewstr, key, ascode, bnavstr)= if VUIisFocusedInput then nil else ( if (!bnavstr.BNAV_bFocus) then nil else ( let bnavstr.BNAV_move -> [vec ang] in if ((switch bnavstr.BNAV_lPressedKeys key) != nil) then nil else ( let if (!strcmpi KEYBgetCurrentKeyboardType "azerty") then "Z" else "W" -> upkey in let "S" -> downkey in let if (!strcmpi KEYBgetCurrentKeyboardType "azerty") then "Q" else "A" -> leftkey in let "D" -> rightkey in let if ((key == (KEYBgetKeyNumber "UPARROW")) || (key == (KEYBgetKeyNumber upkey))) then // UP -.1.0 else if ((key == (KEYBgetKeyNumber "DOWNARROW")) || (key == (KEYBgetKeyNumber downkey))) then // DOWN 1.0 else nil -> z in let if (key == (KEYBgetKeyNumber leftkey)) then // STRAFE LEFT -.1.0 else if (key == (KEYBgetKeyNumber rightkey)) then // STRAFE RIGHT 1.0 else nil -> x in let if (key == (KEYBgetKeyNumber "LEFTARROW")) then // TURN LEFT 1.0 else if (key == (KEYBgetKeyNumber "RIGHTARROW")) then // TURN RIGHT -.1.0 else nil -> yaw in ( if z == nil then nil else mutate vec <- [_ _ z]; if x == nil then nil else mutate vec <- [x _ _]; if yaw == nil then nil else mutate ang <- [_ yaw _]; ); if !(_keybdstate & 2) then nil else set bnavstr.BNAV_bCrouchState = 1; set bnavstr.BNAV_lPressedKeys = [key ascode]::bnavstr.BNAV_lPressedKeys; ); if ((key == (KEYBgetKeyNumber "SPACE")) && (!bnavstr.BNAV_bJumping)) then // SPACE ( let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> [gx gy gz] in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (gy +. 0.1) gz] [0.0 (-.1.0) 0.0] 0.15 -> [body dist normal] in if ((body == nil) || (dist >. ((bnavstr.BNAV_fCamHeight /. 2.0) +. 0.1))) && (strcmpi "Climbing" bnavstr.BNAV_curState) then nil else ( set bnavstr.BNAV_bJumping = 1; set bnavstr.BNAV_curState = "Jumping"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; SO3BodyAddImpulse bnavstr.BNAV_shellBody [0.0 bnavstr.BNAV_fJumpForce 0.0] [gx gy gz]; playJumpSound bnavstr; ); ) else nil; if (!(_keybdstate & 4) && (key != 1)) then nil else ( if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor viewstr 1; set bnavstr.BNAV_bFocus = 0; set bnavstr.BNAV_lastVelocity = [0.0 0.0 0.0]; set bnavstr.BNAV_lPressedKeys = nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; set bnavstr.BNAV_mouseMove = [0.0 0.0]; let SO3BodyGetVelocity bnavstr.BNAV_shellBody -> [velx vely velz] in SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 vely 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; ); ); ); 0;; fun cbNavKeyUp(inst, viewstr, key, bnavstr)= if VUIisFocusedInput then nil else ( if (!bnavstr.BNAV_bFocus) then nil else ( let bnavstr.BNAV_move -> [vec ang] in let switch bnavstr.BNAV_lPressedKeys key -> ascode in let if (!strcmpi KEYBgetCurrentKeyboardType "azerty") then "Z" else "W" -> upkey in let "S" -> downkey in let if (!strcmpi KEYBgetCurrentKeyboardType "azerty") then "Q" else "A" -> leftkey in let "D" -> rightkey in ( set bnavstr.BNAV_lPressedKeys = (remove_idx_from_list bnavstr.BNAV_lPressedKeys key); // UP & DOWN if ((key != (KEYBgetKeyNumber "UPARROW")) && (key != (KEYBgetKeyNumber upkey)) && (key != (KEYBgetKeyNumber "DOWNARROW")) && (key != (KEYBgetKeyNumber downkey))) then nil else ( let if ((isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber "UPARROW")) || (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber upkey))) then // UP -.1.0 else if ((isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber "DOWNARROW")) || (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber downkey))) then // DOWN 1.0 else 0.0 -> nv in mutate vec <- [_ _ nv]; ); // STRAFE LEFT RIGHT if (key != (KEYBgetKeyNumber leftkey)) && (key != (KEYBgetKeyNumber rightkey)) then nil else ( let if (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber leftkey)) then // STRAFE LEFT -.1.0 else if (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber rightkey)) then // STRAFE RIGHT 1.0 else 0.0 -> nv in mutate vec <- [nv _ _]; ); // TURN LEFT & RIGHT if (key != (KEYBgetKeyNumber "LEFTARROW")) && (key != (KEYBgetKeyNumber "RIGHTARROW")) then nil else ( let if (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber "LEFTARROW")) then 1.0 else if (isT1InList bnavstr.BNAV_lPressedKeys (KEYBgetKeyNumber "RIGHTARROW")) then -.1.0 else 0.0 -> na in mutate ang <- [_ na _]; ); if (key != (KEYBgetKeyNumber "SPACE")) then nil else // SPACE set bnavstr.BNAV_bJumping = 0; //uncrouch if (_keybdstate & 2) then nil else set bnavstr.BNAV_bCrouchState = 0; ); ); ); 0;; fun yawCamera(bnavstr, ang, absolute)= if (absolute) then ( V3DsetObjectOrientationDeg bnavstr.BNAV_neckShell [0.0 (SO3MathsRadianToDegree ang) 0.0]; 0; ) else ( SO3ObjectRotateYaw bnavstr.BNAV_neckShell ang SO3_LOCAL_TS; 0; ); 0;; fun rollCamera(bnavstr, ang, absolute)= if (absolute) then ( V3DsetObjectOrientationDeg bnavstr.BNAV_camera [0.0 0.0 (SO3MathsRadianToDegree ang)]; 0; ) else ( SO3ObjectRotateRoll bnavstr.BNAV_camera ang SO3_LOCAL_TS; 0; ); 0;; fun pitchCamera(bnavstr, ang, absolute)= let SO3MathsQuatToEulerPYR SO3ObjectGetOrientation bnavstr.BNAV_camShell -> [ax _ _] in if (absolute) then ( V3DsetObjectOrientationDeg bnavstr.BNAV_camShell [0.0 (SO3MathsRadianToDegree ang) 0.0]; 0; ) else let bnavstr.BNAV_tCamLimit -> [lx lx2] in let if (absolute) then ang else (ax +. ang) -> tang in ( if (tang <. lx) then ( V3DsetObjectOrientationDeg bnavstr.BNAV_camShell [0.0 (SO3MathsRadianToDegree lx) 0.0]; 0; ) else if (tang >. lx2) then ( V3DsetObjectOrientationDeg bnavstr.BNAV_camShell [0.0 (SO3MathsRadianToDegree lx2) 0.0]; 0; ) else ( SO3ObjectRotatePitch bnavstr.BNAV_camShell ang SO3_LOCAL_TS; 0; ); ); 0;; fun cbCursorClick(inst, viewstr, x, y, btn, bnavstr)= if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor viewstr 0; set bnavstr.BNAV_bFocus = 1; 0;; // multi touch fun cbAddCursor(inst, viewstr, id, x, y, bnavstr)= if (bnavstr.BNAV_bKeyboard) then ( set bnavstr.BNAV_mouseMove = [0.0 0.0]; // right of the screen for rotations and left for translations let (V3DgetDefaultViewport viewstr) -> viewportstr in let SO3ViewportGetPixelPositionSize viewportstr.V3D_viewport -> [_ _ vw vh] in if (x >= (vw / 2)) && (bnavstr.BNAV_rightPoint == nil) then set bnavstr.BNAV_rightPoint = [id x y] else if (x < (vw / 2)) && (bnavstr.BNAV_leftPoint == nil) then set bnavstr.BNAV_leftPoint = [id x y] else nil; set bnavstr.BNAV_bMouse = 0; 0; ) else ( if (bnavstr.BNAV_bDisableDefControl) then nil else V3DcenterMouseCursor viewstr; 0; ); 0;; fun cbUpdateCursor(inst, viewstr, id, x, y, vx, vy, bnavstr)= //do not use touch for navigation if a widget is used, it can be used as a control if (bnavstr.BNAV_bKeyboard) then ( let c3dXsession -> sessionstr in let sessionstr.V3D_sessionView -> viewstr in let (V3DWidgetCtrlHasFocus viewstr) -> widgetctrl in if (widgetctrl != nil) && (SO3WidgetGetMouseEnable widgetctrl) && ((SO3WidgetGetMode widgetctrl) != 3) /*&& (SO3WidgetIsMouseOver widgetctrl)*/ then nil else ( set bnavstr.BNAV_mouseMove = [0.0 0.0]; set bnavstr.BNAV_bMouse = 0; let bnavstr.BNAV_leftPoint -> [lid _ _] in let bnavstr.BNAV_rightPoint -> [rid _ _] in let bnavstr.BNAV_move -> [vec ang] in let (V3DgetDefaultViewport viewstr) -> viewportstr in let SO3ViewportGetPixelPositionSize viewportstr.V3D_viewport -> [_ _ vw vh] in let (itof (vw / 4)) -> xscratio in let (itof vh / 4) -> yscratio in if (id == lid) then ( let bnavstr.BNAV_leftPoint -> [_ ox oy] in let ((itof (ox - x)) /. xscratio) *. (-.1.0) -> nx in let if nx >. 1.0 then 1.0 else if nx <. (-.1.0) then (-.1.0) else nx -> nx in let ((itof (oy - y)) /. yscratio) *. (-.1.0) -> ny in let if ny >. 1.0 then 1.0 else if ny <. (-.1.0) then (-.1.0) else ny -> ny in let if ((absf nx) <. 0.05) then 0.0 else nx -> nx in let if ((absf ny) <. 0.05) then 0.0 else ny -> ny in mutate vec <- [nx _ ny]; ) else if (id == rid) then ( let bnavstr.BNAV_rightPoint -> [_ ox oy] in let ((itof (ox - x)) /. xscratio) -> nx in let if nx >. 1.0 then 1.0 else if nx <. (-.1.0) then (-.1.0) else nx -> nx in let ((itof (oy - y)) /. yscratio) -> ny in let if ny >. 1.0 then 1.0 else if ny <. (-.1.0) then (-.1.0) else ny -> ny in let if ((absf nx) <. 0.05) then 0.0 else nx -> nx in let if ((absf ny) <. 0.05) then 0.0 else ny -> ny in mutate ang <- [ny nx _]; ) else nil; ); 0; ) else ( if (bnavstr.BNAV_bDisableDefControl) then nil else V3DcenterMouseCursor viewstr; 0; ); 0;; fun cbRemoveCursor(inst, viewstr, id, bnavstr)= if (bnavstr.BNAV_bKeyboard) then ( let bnavstr.BNAV_leftPoint -> [lid _ _] in let bnavstr.BNAV_rightPoint -> [rid _ _] in let bnavstr.BNAV_move -> [vec ang] in if (id == lid) then ( mutate vec <- [0.0 _ 0.0]; set bnavstr.BNAV_leftPoint = nil; ) else if (id == rid) then ( mutate ang <- [0.0 0.0 _]; set bnavstr.BNAV_rightPoint = nil; ) else nil; if (bnavstr.BNAV_leftPoint != nil || bnavstr.BNAV_rightPoint != nil) then nil else ( set bnavstr.BNAV_mouseMove = [0.0 0.0]; V3DcenterMouseCursor viewstr; set bnavstr.BNAV_bMouse = 1; ); 0; ) else ( if (bnavstr.BNAV_bDisableDefControl) then nil else V3DcenterMouseCursor viewstr; 0; ); 0;; fun cbNavPreRender2(inst, sessionstr, etime, bnavstr)= //update Y rotation on camera independently of physics if (!V3DphysGetState c3dXsession) then nil else ( let sessionstr.V3D_sessionView -> viewstr in let (V3DWidgetCtrlHasFocus viewstr) -> widgetctrl in let if (widgetctrl != nil) && (SO3WidgetGetMouseEnable widgetctrl) && ((SO3WidgetGetMode widgetctrl) != 3) /*&& (SO3WidgetIsMouseOver widgetctrl)*/ && bnavstr.BNAV_bMouse then 1 else 0 -> disablenavig in if (disablenavig) /*|| (!bnavstr.BNAV_bFocus)*/ then nil else SO3ObjectSetGlobalOrientation bnavstr.BNAV_neckShell bnavstr.BNAV_qLastOrientation; ); //sync camera height with collshell if (!bnavstr.BNAV_bFreeHead) then SO3ObjectSetPosition bnavstr.BNAV_neckShell (SO3ObjectGetPosition bnavstr.BNAV_collShell) else ( //use translation to keep physics behaviors let SO3ObjectGetPosition bnavstr.BNAV_neckShell -> [_ oy _] in SO3ObjectTranslate bnavstr.BNAV_neckShell [0.0 (bnavstr.BNAV_fLastYPos -. oy) 0.0] SO3_WORLD_TS; if (bnavstr.BNAV_vTargetTrans == nil) then nil else ( let SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell -> cpos in let addVectorF cpos bnavstr.BNAV_vTargetTrans -> nvpos in SO3ObjectSetGlobalPosition bnavstr.BNAV_neckShell nvpos; set bnavstr.BNAV_vTargetTrans = nil; ); if (bnavstr.BNAV_vTargetPos == nil) then nil else ( let SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell -> [nx ny nz] in let bnavstr.BNAV_vTargetPos -> [tx ty tz] in SO3ObjectSetGlobalPosition bnavstr.BNAV_neckShell [tx ny tz]; set bnavstr.BNAV_vTargetPos = nil; ); if (!V3DphysGetState c3dXsession) then nil else let subVectorF (SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell) (SO3ObjectGetGlobalPosition bnavstr.BNAV_collShell) -> colldiff in let getVectorLengthF colldiff -> neckdist in if (neckdist >=. fNeckOutdistance) then ( if (bnavstr.BNAV_bHeadRangeState < 20) then ( set bnavstr.BNAV_bHeadRangeState = bnavstr.BNAV_bHeadRangeState + 1; ) else if (bnavstr.BNAV_bHeadRangeState > 21) then nil else ( SendPluginEvent inst "Head out of range" nil nil; set bnavstr.BNAV_bHeadRangeState = bnavstr.BNAV_bHeadRangeState + 1; if (bnavstr.BNAV_bShowFeetPos) then nil else SO3ObjectSetVisible bnavstr.BNAV_avBase 1 0; ); ) else if ((neckdist <. fNeckOutdistance) && bnavstr.BNAV_bHeadRangeState) then ( set bnavstr.BNAV_bHeadRangeState = 0; SendPluginEvent inst "Head in range" nil nil; if (bnavstr.BNAV_bShowFeetPos) then nil else SO3ObjectSetVisible bnavstr.BNAV_avBase 0 0; ) else nil; ); 0;; fun cbNavPreRender(inst, sessionstr, etime, bnavstr)= set bnavstr.BNAV_iTick = bnavstr.BNAV_iTick + etime; let (1000000 / SO3WorldGetFPS sessionstr.V3D_session) -> phystime in if ((V3DphysGetState c3dXsession) && (bnavstr.BNAV_iTick < phystime)) then nil else ( let itof (SO3WorldGetFPS sessionstr.V3D_session) -> pfps in let maxf 0.000001 (itof (bnavstr.BNAV_iTick / 1000)) -> ftime in //milliseconds let ftime /. 1000.0 -> nbsec in let [nbsec nbsec nbsec] -> vnbsec in let sessionstr.V3D_sessionView -> viewstr in let (V3DWidgetCtrlHasFocus viewstr) -> widgetctrl in let if (widgetctrl != nil) && (SO3WidgetGetMouseEnable widgetctrl) && ((SO3WidgetGetMode widgetctrl) != 3) /*&& (SO3WidgetIsMouseOver widgetctrl)*/ && bnavstr.BNAV_bMouse then 1 else 0 -> disablenavig in // manage the case that a widget get the focus if (disablenavig) /*|| (!bnavstr.BNAV_bFocus)*/ then ( set bnavstr.BNAV_lastVelocity = [0.0 0.0 0.0]; set bnavstr.BNAV_lPressedKeys = nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; let SO3BodyGetVelocity bnavstr.BNAV_shellBody -> [velx vely velz] in SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 vely 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; 0; ) else ( //mouse camera let sessionstr.V3D_selectedAxis -> [axisstr _] in if (!bnavstr.BNAV_bMouse || !bnavstr.BNAV_bFocus || bnavstr.BNAV_bDisableDefControl || ((axisstr != nil) && axisstr.V3D_iAxisMode)) then nil else let _GETscreenPos -> [mx my] in ( V3DcenterMouseCursor viewstr; let _GETscreenPos -> [ox oy] in let [(ox - mx) (oy - my)] -> [nmx nmy] in let [((itof nmx) /. ftime) *. 0.4 ((itof nmy) /. ftime) *. 0.4] -> mmove in set bnavstr.BNAV_mouseMove = mmove; ); let if (((_keybdstate & 1) || bnavstr.BNAV_bShiftState) && !bnavstr.BNAV_bShiftMode) then 1 else if (((_keybdstate & 1) || bnavstr.BNAV_bShiftState) && bnavstr.BNAV_bShiftMode) then 0 else if bnavstr.BNAV_bShiftMode then 1 else 0 -> isrunning in let if (isrunning) then bnavstr.BNAV_fRunSpeed else bnavstr.BNAV_fWalkSpeed -> speed in let computeControls sessionstr bnavstr vnbsec speed -> [vec hvec [pitch yaw roll] ycam angOverride addCamHeight havedata] in let bnavstr.BNAV_bHasMoved -> hasmoved in ( set bnavstr.BNAV_bHasMoved = 0; if (V3DphysGetState c3dXsession) then ( // for stairs / climb let V3DphysGetGravity c3dXsession -> gravity in let bnavstr.BNAV_fMass *. pfps -> msp in let [msp msp msp] -> vmsp in let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> gpos in let SO3ObjectGetGlobalOrientation (if bnavstr.BNAV_bFlyMode then bnavstr.BNAV_camShell else bnavstr.BNAV_neckShell) -> gquat in let SO3MathsQuatAdd gquat (SO3MathsEulerXYZToQuat [yaw 0.0 0.0]) -> gquat in let addVectorF vec hvec -> mnvec in let SO3MathsQuatGetDirection gquat (addVectorF mnvec (multiplyVectorF (normalizeVectorF mnvec) [0.20 0.0 0.20])) -> mtvec in let gpos -> [gpx gpy gpz] in let addVectorF gpos mtvec -> [gx gy gz] in let if bnavstr.BNAV_bFlyMode then nil else getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (gy +. 0.5) gz] [1.0 0.0 1.0] 1.5 -> [ftbody ftdist _] in let if ((ftdist >. 0.0) && (ftdist <. 0.30)) then [nil 0.0 [0.0 0.0 0.0]] else getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (gy +. 1.0) gz] [0.0 (-.1.0) 0.0] 1.0 -> [ntbody ntdist [_ nty _]] in let if ((nty != nil) && (nty <. 0.65)) then 0.0 else ntdist -> ntdist in let if (ntbody == nil) then SO3PhysicsGetMaterialName SO3BodyGetMaterial ftbody else SO3PhysicsGetMaterialName SO3BodyGetMaterial ntbody -> climbmat in let if climbmat == nil then bnavstr.BNAV_sLastMaterial else climbmat -> climbmat in let if ((strfindi "climb" climbmat 0) != nil) then 1 else 0 -> climb in let if ((strfindi "stairs" climbmat 0) != nil) then 1 else 0 -> stairs in let if (bnavstr.BNAV_fMass >. 0.0) && (!bnavstr.BNAV_bFlyMode) && (!climb) then [1.0 0.0 1.0] else [1.0 1.0 1.0] -> vmul in let SO3ObjectGetGlobalOrientation (if bnavstr.BNAV_bFlyMode || climb then bnavstr.BNAV_camShell else bnavstr.BNAV_neckShell) -> pquat in let SO3MathsQuatAdd pquat (SO3MathsEulerXYZToQuat [yaw 0.0 0.0]) -> pquat in let SO3MathsQuatGetDirection pquat multiplyVectorF vec vmul -> mvec in let SO3MathsQuatGetDirection pquat multiplyVectorF hvec vmul -> hmvec in //let addVectorF gpos mvec -> gmove in // for normal and slide mode let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gpx (gpy +. 1.0) gpz] [0.0 (-.1.0) 0.0] 2.0 -> [tbody tdist [cnx cny cnz]] in let SO3PhysicsGetMaterialName SO3BodyGetMaterial tbody -> slidemat in let if ((strfindi "climb" slidemat 0) != nil) then 1 else climb -> sclimb in let if ((strfindi "stairs" slidemat 0) != nil) then 1 else stairs -> sstairs in let SO3BodyGetVelocity bnavstr.BNAV_shellBody -> [velx vely velz] in let (1.0 -. ntdist) -> nydist in let if (nydist >. 0.01) && (nydist <=. 0.50) then nydist else 0.0 -> nydist in let divideVectorF mvec vnbsec -> mvel in let if ((tbody != nil) && (tdist <. 1.1)) || (ntbody != nil) then 1 else 0 -> touch in // sliding ? let if ((cny <. 0.8) && !sclimb && !sstairs && !bnavstr.BNAV_bFlyMode && (!vectorIsZeroF gravity)) then 1 else 0 -> slide in // need to move to slide let if (slide && ((absf velx) <. 0.01) && ((absf velz) <. 0.01)) then 0 else slide -> slide in // cannot move in the air let if (!touch && (bnavstr.BNAV_sLastMaterial == nil) && !sclimb && !bnavstr.BNAV_bFlyMode && (!vectorIsZeroF gravity) && !slide) then 1 else 0 -> inair in let if slide then [velx 0.0 velz] else /*if inair then [velx 0.0 velz] else*/ mvel -> mvel in let if (bnavstr.BNAV_fMass >. 0.0) && (!bnavstr.BNAV_bFlyMode) && (!climb) then vely else 0.0 -> nvely in let SO3MathsQuatGetDirection (SO3MathsQuatAdd (SO3ObjectGetGlobalOrientation bnavstr.BNAV_neckShell) (SO3MathsEulerXYZToQuat [yaw 0.0 0.0])) [1.0 1.0 1.0] -> snddir in ( //climb stairs if (sclimb || sclimb || (zeroVectorF vec) || (nydist == 0.0)) then nil else ( //set nvely = nvely +. ((nydist /. nbsec) *. 0.5); set bnavstr.BNAV_iNbUpDetections = bnavstr.BNAV_iNbUpDetections + 1; if (bnavstr.BNAV_iNbUpDetections < 5) then nil else ( //addLogMessage strcatn "Move up : "::(ftoa nydist)::" "::(ftoa nty)::nil; SO3ObjectTranslate bnavstr.BNAV_shell [0.0 nydist 0.0] SO3_WORLD_TS; set bnavstr.BNAV_iNbUpDetections = 0; ); ); if (!slide) then ( if (strcmpi "Sliding" bnavstr.BNAV_curState) then nil else _AudioStop bnavstr.BNAV_slideSound; 0; ) else ( _AudioSetPosition bnavstr.BNAV_jumpSound gpos snddir; if (!strcmpi "Sliding" bnavstr.BNAV_curState) then nil else ( set bnavstr.BNAV_curState = "Sliding"; _AudioPlay3d bnavstr.BNAV_slideSound 0.8 1; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); set bnavstr.BNAV_fInAirMaxVelocity = minf bnavstr.BNAV_fInAirMaxVelocity nvely; 0; ); if (inair == bnavstr.BNAV_bInAir) then ( if (!inair) then nil else ( if (!strcmpi "Falling" bnavstr.BNAV_curState) || ((_tickcount - bnavstr.BNAV_iAirTick) < 300) then nil else ( set bnavstr.BNAV_curState = "Falling"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); set bnavstr.BNAV_fInAirMaxVelocity = minf bnavstr.BNAV_fInAirMaxVelocity nvely; ); 0; ) else ( set bnavstr.BNAV_bInAir = inair; if (!inair) then ( if ((_tickcount - bnavstr.BNAV_iAirTick) < 300) then nil else ( let (absf bnavstr.BNAV_fInAirMaxVelocity) /. 10.0 -> vol in playHitSound bnavstr vol; SendPluginEvent inst "Hit velocity" ftoa (absf bnavstr.BNAV_fInAirMaxVelocity) nil; ); 0; ) else ( set bnavstr.BNAV_fInAirMaxVelocity = nvely; set bnavstr.BNAV_iAirTick = _tickcount; 0; ); ); if ((!hasmoved) && (zeroVectorF vec) && (zeroVectorF hvec) && !inair && !slide && !sclimb) then //disabled ( if (!strcmpi "Idle" bnavstr.BNAV_curState) then nil else ( set bnavstr.BNAV_curState = "Idle"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); 0; ) else ( if (zeroVectorF vec) then nil else set bnavstr.BNAV_bHasMoved = 1; let [velx vely velz] -> curvel in let divideVectorF hmvec vnbsec -> hmvel in let [0.0 0.0 0.0] -> dvel in let !(zeroVectorF hmvec) -> mvhead in ( let SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell -> gneckpos in let multiplyVectorF (subVectorF gneckpos (SO3ObjectGetGlobalPosition bnavstr.BNAV_shell)) [1.0 0.0 1.0] -> neckdiff in let multiplyVectorF subVectorF gneckpos (SO3ObjectGetGlobalPosition bnavstr.BNAV_collShell) [1.0 0.0 1.0] -> colldiff in let getVectorLengthF colldiff -> nlenght in ( let getVectorLengthF [velx 0.0 velz] -> vlenght in let (vlenght >. 0.8) -> outside in if ((bnavstr.BNAV_bFreeHead && ((nlenght <=. fNeckMindistance) || outside)) || bnavstr.BNAV_bHasMoved) then ( if (!bnavstr.BNAV_bHasMoved && (zeroVectorF bnavstr.BNAV_lastVelocity)) then nil else /*let if (slide || climb || bnavstr.BNAV_bTargetSwitch) then mvel else let if (bnavstr.BNAV_bHeadRangeState) then 0.05 else 0.01 -> coef in let multiplyVectorF (divideVectorF neckdiff vnbsec) [coef coef coef] -> hdiffvel in addVectorF hdiffvel mvel -> tovel in*/ set dvel = mvel; if (!bnavstr.BNAV_bTargetSwitch || bnavstr.BNAV_bHasMoved) then ( set bnavstr.BNAV_vTargetTrans = hmvec; ) else if (bnavstr.BNAV_bTargetSwitch) then ( set bnavstr.BNAV_bTargetSwitch = 0; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 nvely 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 nvely 0.0]; let addVectorF (SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell) hmvec -> tovec in set bnavstr.BNAV_vTargetPos = tovec; ) else nil; 0; ) else ( //force body to neck pos direction if (!mvhead && !climb) then nil else ( let multiplyVectorF (divideVectorF neckdiff vnbsec) [0.02 0.02 0.02] -> hdiffvel in let addVectorF hdiffvel hmvel -> tovel in let getVectorLengthF tovel -> lenght in if (lenght == 0.0) then nil else ( set dvel = tovel; if (!mvhead) then nil else ( let addVectorF (SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell) hmvec -> tovec in set bnavstr.BNAV_vTargetPos = tovec; ); set bnavstr.BNAV_bTargetSwitch = 1; ); ); 0; ); let getVectorLengthF dvel -> vlenght in if (vlenght == 0.0) then nil else ( let subVectorF (addVectorF dvel [0.0 nvely 0.0]) curvel -> nvel in let multiplyVectorF nvel vmsp -> dforce in let minf vlenght (pfps /. nbsec) -> maxlenght in let multiplyVectorF divideVectorF dforce [vlenght vlenght vlenght] [maxlenght maxlenght maxlenght] -> nforce in SO3BodyAddForce bnavstr.BNAV_shellBody nforce; ); set bnavstr.BNAV_lastVelocity = mvel; ); ); // stop the physic body on motion stop if (!bnavstr.BNAV_bHasMoved && hasmoved && (bnavstr.BNAV_bFlyMode || !inair)) then ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 nvely 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 nvely 0.0]; ) else nil; if (slide || climb || inair || !(zeroVectorF vec) || !touch || (!strcmp bnavstr.BNAV_curState "Jumping")) then nil else if (!strcmpi "Idle" bnavstr.BNAV_curState) then nil else ( set bnavstr.BNAV_curState = "Idle"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); //walk sound if (inair || slide || !touch || (zeroVectorF vec)) then nil else ( if (climb) then ( if (!strcmpi "Climbing" bnavstr.BNAV_curState) then nil else ( set bnavstr.BNAV_curState = "Climbing"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); ) else if ((isrunning && (!strcmpi "Running" bnavstr.BNAV_curState)) || (!isrunning && (!strcmpi "Walking" bnavstr.BNAV_curState))) then nil else ( set bnavstr.BNAV_curState = if (isrunning) then "Running" else "Walking"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); let if climb then climbmat else if touch then SO3PhysicsGetMaterialName SO3BodyGetMaterial tbody else nil -> matname in ( let switchstr bnavstr.BNAV_lWSound matname -> sndstr in let if (sndstr == nil) then switchstr bnavstr.BNAV_lWSound "default" else sndstr -> sndstr in ( _AudioSetPosition sndstr.WSND_asSound gpos snddir; let addVectorF mvec hvec -> [mvx mvy mvz] in if ((absf mvx) +. (absf mvy) +. (absf mvz)) <. (0.1 /. ftime) then nil else let ftoi ((itof sndstr.WSND_iTimeStep) /. ((speed +. 0.001) /. 1.8)) -> step in if ((sndstr.WSND_iTick != nil) && ((_tickcount - sndstr.WSND_iTick) < step)) then nil else ( _AudioPlay3d sndstr.WSND_asSound 0.8 0; //_AudioSetPitch sndstr.WSND_asSound speed /. 2.0; set sndstr.WSND_iTick = _tickcount; ); ); ); ); ); if (bnavstr.BNAV_vTranslate == nil) then nil else ( let addVectorF (SO3MathsQuatGetDirection pquat bnavstr.BNAV_vTranslate) [0.0 nydist 0.0] -> mtvec in if (slide) then nil else ( let mtvec -> [mvx mvy mvz] in let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> [gx gy gz] in let SO3ObjectGetGlobalPosition bnavstr.BNAV_camera -> [_ cgy _] in let (getVectorLengthF (multiplyVectorF mtvec [1.0 0.0 1.0])) +. 0.4 -> raylength in let multiplyVectorF mtvec [1.0 0.0 1.0] -> raydir in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (gy +. 0.5) gz] raydir raylength -> [ftbody ftdist _] in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (cgy +. 0.1) gz] raydir raylength -> [cftbody cftdist _] in let maxf 0.0 ((maxf ftdist cftdist) -. 0.4) -> ftdist in let if ((ftbody == nil) && (cftbody == nil)) then mtvec else addVectorF (multiplyVectorF (normalizeVectorF mtvec) [ftdist 0.0 ftdist]) [0.0 mvy 0.0] -> mtvec in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) (addVectorF [gx (gy +. 1.0) gz] (multiplyVectorF mtvec [1.0 0.0 1.0])) [0.0 (-.1.0) 0.0] 2.0 -> [ntbody ntdist [_ cny _]] in let mtvec -> [mvx mvy mvz] in let if (ntbody == nil) then mtvec else addVectorF (multiplyVectorF (normalizeVectorF mtvec) [0.0 (1.0 -. ntdist) 0.0]) [mvx 0.0 mvz] -> mtvec in ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; set bnavstr.BNAV_vTargetTrans = nil; set bnavstr.BNAV_vTargetPos = nil; //reset neck offset let SO3ObjectGetPosition bnavstr.BNAV_neckShell -> [_ nky _] in SO3ObjectSetPosition bnavstr.BNAV_neckShell [0.0 nky 0.0]; SO3ObjectTranslate bnavstr.BNAV_shell mtvec SO3_WORLD_TS; SO3BodySetInitialState bnavstr.BNAV_shellBody; SO3BodySetInitialState bnavstr.BNAV_camBody; //reset control set bnavstr.BNAV_lControls = nil; //reset contacts set bnavstr.BNAV_iContactCount = 0; set bnavstr.BNAV_vTranslate = nil; ); ); ); ); SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; set bnavstr.BNAV_qLastOrientation = SO3MathsQuatAdd bnavstr.BNAV_qLastOrientation (SO3MathsEulerXYZToQuat [yaw 0.0 0.0]); 0; ) else ( if (bnavstr.BNAV_bFlyMode) then let SO3MathsQuatGetDirection (SO3MathsQuatAdd (SO3ObjectGetGlobalOrientation bnavstr.BNAV_camShell) (SO3MathsEulerXYZToQuat [yaw 0.0 0.0])) addVectorF vec hvec -> mvec in SO3ObjectTranslate bnavstr.BNAV_shell mvec SO3_WORLD_TS else let SO3MathsQuatGetDirection (SO3MathsQuatAdd (SO3ObjectGetGlobalOrientation bnavstr.BNAV_neckShell) (SO3MathsEulerXYZToQuat [yaw 0.0 0.0])) addVectorF vec hvec -> mvec in SO3ObjectTranslate bnavstr.BNAV_shell mvec SO3_WORLD_TS; yawCamera bnavstr yaw 0; if (bnavstr.BNAV_vTranslate == nil) then nil else ( //reset neck offset let SO3ObjectGetPosition bnavstr.BNAV_neckShell -> [_ nky _] in SO3ObjectSetPosition bnavstr.BNAV_neckShell [0.0 nky 0.0]; set bnavstr.BNAV_vTranslate = nil; //reset control set bnavstr.BNAV_lControls = nil; ); 0; ); pitchCamera bnavstr pitch angOverride; rollCamera bnavstr roll angOverride; if (!havedata && (bnavstr.BNAV_bLastCrouchState == bnavstr.BNAV_bCrouchState)) then nil else let if (!addCamHeight) then ( if (ycam == 0.0) then bnavstr.BNAV_fCamHeight else ycam ) else ( if (bnavstr.BNAV_fLastYPos == 0.0) then bnavstr.BNAV_fCamHeight +. ycam else bnavstr.BNAV_fLastYPos +. ycam ) -> dscpos in ( let if bnavstr.BNAV_bCrouchState then maxf 0.0 dscpos -. (bnavstr.BNAV_fCamHeight *. 0.4) else dscpos -> dhpos in ( if (V3DphysGetState c3dXsession) then ( let maxf (-.bnavstr.BNAV_fCamHeight *. 0.5) (dhpos -. bnavstr.BNAV_fCamHeight) -> dhpos in SO3PhysicsContraintSetSliderLimits bnavstr.BNAV_contraint dhpos dhpos; 0; ) else ( SO3ObjectSetPosition bnavstr.BNAV_collShell [0.0 dhpos 0.0]; 0; ); set bnavstr.BNAV_bLastCrouchState = bnavstr.BNAV_bCrouchState; set bnavstr.BNAV_fLastYPos = dhpos; ); ); 0; ); ); set bnavstr.BNAV_iTick = 0; if (!bnavstr.BNAV_bSendFeetPosition && !bnavstr.BNAV_bSendHeadPosition && !bnavstr.BNAV_bSendHipPosition) then nil else ( if (!bnavstr.BNAV_bSendFeetPosition) then nil else let SO3ObjectGetPosition bnavstr.BNAV_shell -> [px py pz] in let SO3MathsQuatToEulerDegreePYR (SO3ObjectGetOrientation bnavstr.BNAV_shell) -> [fax fay faz] in SendPluginEvent inst "Feet position" strcatn (strcatnSep (ftoa px)::(ftoa py)::(ftoa pz)::nil " ")::"\n"::(strcatnSep (ftoa fax)::(ftoa fay)::(ftoa faz)::nil " ")::nil nil; if (!bnavstr.BNAV_bSendHeadPosition) then nil else let SO3ObjectGetGlobalPosition bnavstr.BNAV_camShell -> [px py pz] in let SO3MathsQuatToEulerDegreePYR (SO3ObjectGetGlobalOrientation bnavstr.BNAV_camShell) -> [fax fay faz] in SendPluginEvent inst "Head position" strcatn (strcatnSep (ftoa px)::(ftoa py)::(ftoa pz)::nil " ")::"\n"::(strcatnSep (ftoa fax)::(ftoa fay)::(ftoa faz)::nil " ")::nil nil; if (!bnavstr.BNAV_bSendHipPosition) then nil else let SO3ObjectGetPosition bnavstr.BNAV_shell -> [_ sy _] in let SO3ObjectGetGlobalPosition bnavstr.BNAV_neckShell -> [nx ny nz] in let sy +. ((ny -. sy) *. 0.65) -> py in let SO3MathsQuatToEulerDegreePYR SO3ObjectGetGlobalOrientation bnavstr.BNAV_neckShell -> [fax fay faz] in SendPluginEvent inst "Hip position" strcatn (strcatnSep (ftoa nx)::(ftoa py)::(ftoa nz)::nil " ")::"\n"::(strcatnSep (ftoa fax)::(ftoa fay)::(ftoa faz)::nil " ")::nil nil; ); ); 0;; fun deleteOb(inst, bnavstr)= let SO3ObjectGetChildren bnavstr.BNAV_camera -> lchild in let sizelist lchild -> size in let 0 -> i in while i < size do ( let nth_list lchild i -> child in SO3ObjectUnlink child; set i = i + 1; ); let sizelist bnavstr.BNAV_lWSound -> size in let 0 -> i in while i < size do ( let nth_list bnavstr.BNAV_lWSound i -> [mat sndstr] in _DSAudio sndstr.WSND_asSound; set i = i + 1; ); _DSAudio bnavstr.BNAV_jumpSound; _DSAudio bnavstr.BNAV_hitSound; _DSAudio bnavstr.BNAV_slideSound; setPluginInstanceCbScenePreRenderPhysic inst nil; setPluginInstanceCbScenePreRender2 inst nil; if (bnavstr.BNAV_bDisableDefControl) then nil else ( setPluginInstanceCbKeyDown inst nil; setPluginInstanceCbKeyUp inst nil; setPluginInstanceCbClick inst nil; setPluginInstanceCbFocusView inst nil; setPluginInstanceCbKillFocusView inst nil; setPluginInstanceCbTouchPointAdd inst nil; setPluginInstanceCbTouchPointRemove inst nil; setPluginInstanceCbTouchPointUpdate inst nil; ); let c3dXsession -> sessionstr in if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor sessionstr.V3D_sessionView 1; SO3ObjectDestroy bnavstr.BNAV_avBase; SO3GroupDelete (V3DgetSession c3dXsession) bnavstr.BNAV_sGroupName; V3DdelCamera c3dXsession bnavstr.BNAV_camera; SO3ObjectDestroy bnavstr.BNAV_neckShell; SO3ObjectDestroy bnavstr.BNAV_camShell; SO3ObjectDestroy bnavstr.BNAV_shell; V3DenableNavigate c3dXsession 1; set bnavstr.BNAV_lControls = nil; 0;; fun cbRotateView(inst, from, action, param, reply, bnavstr)= if ((!bnavstr.BNAV_bState) || (param == nil)) then nil else ( if (V3DphysGetState c3dXsession) then ( SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; set bnavstr.BNAV_qLastOrientation = SO3MathsQuatAdd bnavstr.BNAV_qLastOrientation (SO3MathsEulerXYZToQuat [SO3MathsDegreeToRadian (atof param) 0.0 0.0]); 0; ) else ( yawCamera bnavstr SO3MathsDegreeToRadian (atof param) 0; 0; ); ); 0;; fun cbTranslateView(inst, from, action, param, reply, bnavstr)= if ((!bnavstr.BNAV_bState) || (param == nil)) then nil else ( let strextr param -> l in let hd l -> sv in let [atof(nth_list sv 0) atof(nth_list sv 1) atof(nth_list sv 2)] -> vec in set bnavstr.BNAV_vTranslate = vec; ); 0;; fun cbShiftKey(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bShiftState = if (atoi param) == nil then 0 else (atoi param); 0;; fun cbCtrlKey(inst, from, action, param, reply, bnavstr)= let if (atoi param) == nil then 0 else (atoi param) -> nstate in set bnavstr.BNAV_bCrouchState = nstate; 0;; fun cbJump(inst, from, action, param, reply, bnavstr)= let SO3ObjectGetGlobalPosition bnavstr.BNAV_shell -> [gx gy gz] in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) [gx (gy +. 0.1) gz] [0.0 (-.1.0) 0.0] 0.15 -> [body dist normal] in if (bnavstr.BNAV_bJumping) || (((body == nil) || (dist >. ((bnavstr.BNAV_fCamHeight /. 2.0) +. 0.05))) && (strcmpi "Climbing" bnavstr.BNAV_curState)) then nil else ( set bnavstr.BNAV_curState = "Jumping"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; SO3BodyAddImpulse bnavstr.BNAV_shellBody [0.0 bnavstr.BNAV_fJumpForce 0.0] [gx gy gz]; playJumpSound bnavstr; ); 0;; fun cbControl(inst, from, action, param, reply, bnavstr)= //get the input control from the link let if reply == nil then "control" else reply -> reply in let switchstr bnavstr.BNAV_lControls reply -> icontrol in ( // if not already int the list we add it if (icontrol != nil) then nil else ( set bnavstr.BNAV_lControls = [reply [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 0 1]]::bnavstr.BNAV_lControls; set icontrol = switchstr bnavstr.BNAV_lControls reply; ); let strextr param -> l in let hd l -> sv in let hd tl l -> sa in let hd (hd tl tl l) -> mode in let icontrol -> [ovec oang ycam _ _] in let ovec -> [ovx ovy ovz] in let oang -> [oax oay oaz] in let if mode == nil then 0 else atoi mode -> imode in let [(nth_list sv 0) (nth_list sv 1) (nth_list sv 2)] -> [svx svy svz] in let [(if (!strcmp "_" svx) || (svx == nil) then ovx else (atof svx)) (if (!strcmp "_" svy) || (svy == nil) then ovy else (atof svy)) (if (!strcmp "_" svz) || (svz == nil) then ovz else (atof svz))] -> [vx vy vz] in let [(nth_list sa 0) (nth_list sa 1) (nth_list sa 2)] -> [sax say saz] in let [(if (!strcmp "_" sax) || (sax == nil) then oax else (atof sax)) (if (!strcmp "_" say) || (say == nil) then oay else (atof say)) (if (!strcmp "_" saz) || (saz == nil) then oaz else (atof saz))] -> [ax ay az] in ( if ((imode == 1) || (imode == 4)) then // accumulator mutate icontrol <- [(addVectorF ovec [vx 0.0 vz]) (addVectorF oang [ax ay az]) (ycam +. vy) imode 1] else if (imode == 2) || (imode == 3) then ( //update the head position in real time if (!bnavstr.BNAV_bAutoHead) then nil else set bnavstr.BNAV_bFreeHead = 1; // override orientation mutate icontrol <- [(addVectorF ovec [vx 0.0 vz]) [ax ay az] (if (imode == 2) then (ycam +. vy) else vy) imode 1] ) else mutate icontrol <- [[vx vy vz] [ax ay az] 0.0 imode 1]; ); ); 0;; fun cbSetPosition(inst, from, action, param, reply, bnavstr)= let strextr param -> l in let hd l -> sv in let hd tl l -> sa in let [atof(nth_list sv 0) atof(nth_list sv 1) atof(nth_list sv 2)] -> vec in let [atof(nth_list sa 0) atof(nth_list sa 1) atof(nth_list sa 2)] -> ang in ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; let ang -> [ax ay az] in if (ang == nil) || ((ax == nil) && (ay == nil) && (az == nil)) then nil else ( SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; let if ax == nil then 0.0 else ax -> ax in let if ay == nil then 0.0 else ay -> ay in let if az == nil then 0.0 else az -> az in ( set bnavstr.BNAV_qLastOrientation = (SO3MathsEulerXYZToQuat [(SO3MathsDegreeToRadian ay) 0.0 0.0]); set bnavstr.BNAV_vTargetTrans = nil; set bnavstr.BNAV_vTargetPos = nil; SO3ObjectSetGlobalOrientation bnavstr.BNAV_neckShell (SO3MathsEulerXYZToQuat [(SO3MathsDegreeToRadian ay) 0.0 0.0]); SO3ObjectSetOrientation bnavstr.BNAV_camShell (SO3MathsEulerXYZToQuat [0.0 (SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian az)]); ); ); //reset neck offset let SO3ObjectGetPosition bnavstr.BNAV_neckShell -> [_ nky _] in SO3ObjectSetPosition bnavstr.BNAV_neckShell [0.0 nky 0.0]; SO3ObjectSetPosition bnavstr.BNAV_shell vec; SO3BodySetInitialState bnavstr.BNAV_shellBody; SO3BodySetInitialState bnavstr.BNAV_camBody; //reset control set bnavstr.BNAV_lControls = nil; //reset contacts set bnavstr.BNAV_iContactCount = 0; V3DcameraTeleport (V3DgetSessionView c3dXsession) bnavstr.BNAV_camera; ); 0;; fun cbGetPosition(inst, from, action, param, reply, bnavstr)= let SO3ObjectGetPosition bnavstr.BNAV_shell -> [px py pz] in let SO3MathsQuatToEulerXYZ (SO3ObjectGetGlobalOrientation bnavstr.BNAV_neckShell) -> [ay _ _] in let SO3MathsQuatToEulerXYZ (SO3ObjectGetOrientation bnavstr.BNAV_camShell) -> [_ ax az] in ( SendPluginEvent inst "Position" strcatn (strcatnSep (ftoa px)::(ftoa py)::(ftoa pz)::nil " ")::"\n"::(strcatnSep (ftoa (SO3MathsRadianToDegree ax))::(ftoa (SO3MathsRadianToDegree ay))::(ftoa (SO3MathsRadianToDegree az))::nil " ")::nil nil; ); 0;; fun cbSetAngleLimit(inst, from, action, param, reply, bnavstr)= if param == nil then nil else let bnavstr.BNAV_tCamLimit -> [_ otlimit] in let strextr param -> l in let SO3MathsDegreeToRadian (atof (nth_list (hd l) 0)) -> blimit in let SO3MathsDegreeToRadian (atof (nth_list (hd l) 1)) -> tlimit in if blimit == nil && tlimit == nil then nil else let if tlimit == nil then otlimit else tlimit -> tlimit in ( set bnavstr.BNAV_tCamLimit = [blimit tlimit]; ); 0;; fun cbSetWalkSpeed(inst, from, action, param, reply, bnavstr)= if (atof param) == nil then nil else set bnavstr.BNAV_fWalkSpeed = atof param; 0;; fun cbSetRunSpeed(inst, from, action, param, reply, bnavstr)= if (atof param) == nil then nil else set bnavstr.BNAV_fRunSpeed = atof param; 0;; fun cbFocus(inst, viewstr, bnavstr)= if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor viewstr 0; set bnavstr.BNAV_bFocus = 1; 0;; fun cbKillFocus(inst, viewstr, bnavstr)= if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor viewstr 1; set bnavstr.BNAV_bFocus = 0; set bnavstr.BNAV_lastVelocity = [0.0 0.0 0.0]; set bnavstr.BNAV_lPressedKeys = nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; set bnavstr.BNAV_mouseMove = [0.0 0.0]; let SO3BodyGetVelocity bnavstr.BNAV_shellBody -> [velx vely velz] in SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 vely 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; 0;; fun cbEnableKeyboard(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bKeyboard = 1; if (!bnavstr.BNAV_bState || !(V3DgetNavigateControlState c3dXsession)) then nil else ( setPluginInstanceCbKeyDown inst mkfun5 @cbNavKeyDown bnavstr; setPluginInstanceCbKeyUp inst mkfun4 @cbNavKeyUp bnavstr; ); 0;; fun cbDisableKeyboard(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bKeyboard = 0; set bnavstr.BNAV_lPressedKeys = nil; setPluginInstanceCbKeyDown inst nil; setPluginInstanceCbKeyUp inst nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; 0;; fun cbEnableDefaultInputs(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bDisableDefControl = 0; set bnavstr.BNAV_bMouse = 1; if (!bnavstr.BNAV_bKeyboard) then nil else ( setPluginInstanceCbKeyDown inst mkfun5 @cbNavKeyDown bnavstr; setPluginInstanceCbKeyUp inst mkfun4 @cbNavKeyUp bnavstr; ); setPluginInstanceCbTouchPointAdd inst mkfun6 @cbAddCursor bnavstr; setPluginInstanceCbTouchPointRemove inst mkfun4 @cbRemoveCursor bnavstr; setPluginInstanceCbTouchPointUpdate inst mkfun8 @cbUpdateCursor bnavstr; setPluginInstanceCbClick inst mkfun6 @cbCursorClick bnavstr; setPluginInstanceCbFocusView inst mkfun3 @cbFocus bnavstr; setPluginInstanceCbKillFocusView inst mkfun3 @cbKillFocus bnavstr; 0;; fun cbDisableDefaultInputs(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bDisableDefControl = 1; set bnavstr.BNAV_bMouse = 0; setPluginInstanceCbKeyDown inst nil; setPluginInstanceCbKeyUp inst nil; setPluginInstanceCbClick inst nil; setPluginInstanceCbFocusView inst nil; setPluginInstanceCbKillFocusView inst nil; setPluginInstanceCbTouchPointAdd inst nil; setPluginInstanceCbTouchPointRemove inst nil; setPluginInstanceCbTouchPointUpdate inst nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; 0;; fun cbEnable(inst, from, action, param, reply, bnavstr)= let c3dXsession -> sessionstr in if (!(V3DgetNavigateControlState sessionstr)) then nil else ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; set bnavstr.BNAV_lControls = nil; if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor sessionstr.V3D_sessionView 0; V3DcenterMouseCursor (sessionstr.V3D_sessionView); setPluginInstanceCbScenePreRenderPhysic inst mkfun4 @cbNavPreRender bnavstr; setPluginInstanceCbScenePreRender2 inst mkfun4 @cbNavPreRender2 bnavstr; if (bnavstr.BNAV_bDisableDefControl) then nil else ( if (!bnavstr.BNAV_bKeyboard) then nil else ( setPluginInstanceCbKeyDown inst mkfun5 @cbNavKeyDown bnavstr; setPluginInstanceCbKeyUp inst mkfun4 @cbNavKeyUp bnavstr; ); setPluginInstanceCbTouchPointAdd inst mkfun6 @cbAddCursor bnavstr; setPluginInstanceCbTouchPointRemove inst mkfun4 @cbRemoveCursor bnavstr; setPluginInstanceCbTouchPointUpdate inst mkfun8 @cbUpdateCursor bnavstr; setPluginInstanceCbClick inst mkfun6 @cbCursorClick bnavstr; setPluginInstanceCbFocusView inst mkfun3 @cbFocus bnavstr; setPluginInstanceCbKillFocusView inst mkfun3 @cbKillFocus bnavstr; ); V3DphysEnableBody bnavstr.BNAV_shellBody 1; V3DphysEnableBody bnavstr.BNAV_camBody 1; SO3BodySetGravityEnable bnavstr.BNAV_shellBody !bnavstr.BNAV_bFlyMode; SO3BodySetGravityEnable bnavstr.BNAV_camBody !bnavstr.BNAV_bFlyMode; SO3BodySetIgnoreCollision bnavstr.BNAV_shellBody 0; SO3BodySetIgnoreCollision bnavstr.BNAV_camBody 0; set bnavstr.BNAV_iAirTick = _tickcount; set bnavstr.BNAV_bInAir = 1; set bnavstr.BNAV_iTick = 0; SO3ObjectSetVisible bnavstr.BNAV_avBase bnavstr.BNAV_bShowFeetPos 0; set bnavstr.BNAV_curState = "Idle"; SendPluginEvent inst bnavstr.BNAV_curState nil nil; ); set bnavstr.BNAV_bState = 1; 0;; fun cbDisable(inst, from, action, param, reply, bnavstr)= let c3dXsession -> sessionstr in ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; if (!bnavstr.BNAV_bHideMouse) then nil else V3DshowCursor sessionstr.V3D_sessionView 1; setPluginInstanceCbScenePreRenderPhysic inst nil; setPluginInstanceCbScenePreRender2 inst nil; if (bnavstr.BNAV_bDisableDefControl) then nil else ( setPluginInstanceCbKeyDown inst nil; setPluginInstanceCbKeyUp inst nil; setPluginInstanceCbClick inst nil; setPluginInstanceCbFocusView inst nil; setPluginInstanceCbKillFocusView inst nil; setPluginInstanceCbTouchPointAdd inst nil; setPluginInstanceCbTouchPointRemove inst nil; setPluginInstanceCbTouchPointUpdate inst nil; ); SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; V3DphysEnableBody bnavstr.BNAV_shellBody 0; V3DphysEnableBody bnavstr.BNAV_camBody 0; SO3BodySetGravityEnable bnavstr.BNAV_shellBody 0; SO3BodySetGravityEnable bnavstr.BNAV_camBody 0; SO3BodySetIgnoreCollision bnavstr.BNAV_shellBody 1; SO3BodySetIgnoreCollision bnavstr.BNAV_camBody 1; SO3ObjectSetVisible bnavstr.BNAV_avBase 0 0; set bnavstr.BNAV_lPressedKeys = nil; set bnavstr.BNAV_move = [[0.0 0.0 0.0] [0.0 0.0 0.0]]; set bnavstr.BNAV_bState = 0; set bnavstr.BNAV_lControls = nil; set bnavstr.BNAV_iTick = 0; ); 0;; fun cbNavigationControlState(inst, sessionstr, state, bnavstr)= if (!state) then ( let bnavstr.BNAV_bState -> prevstate in ( cbDisable inst nil nil nil nil bnavstr; set bnavstr.BNAV_bState = prevstate; ); ) else ( if !bnavstr.BNAV_bState then nil else cbEnable inst nil nil nil nil bnavstr; ); 0;; fun cbSetPlayerMass(inst, from, action, param, reply, bnavstr)= let atof param -> mass in let if mass == nil then 0.0 else mass -> mass in ( set bnavstr.BNAV_fMass = mass; SO3BodySetMass bnavstr.BNAV_shellBody if mass <=. 0.0 then 0.0 else mass *. 0.8; SO3BodySetMass bnavstr.BNAV_camBody mass *. 0.2; ); 0;; fun cbLookAtObject(inst, from, action, param, reply, bnavstr)= let V3DgetObjectByName c3dXsession param -> objsrc in if objsrc == nil then nil else ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; let SO3ObjectGetGlobalPosition bnavstr.BNAV_camera -> src in let SO3ObjectGetGlobalPosition objsrc -> target in let lookAtPYR src target 1 -> [ax ay az] in ( set bnavstr.BNAV_qLastOrientation = (SO3MathsEulerXYZToQuat [ay 0.0 0.0]); set bnavstr.BNAV_vTargetTrans = nil; set bnavstr.BNAV_vTargetPos = nil; SO3ObjectSetGlobalOrientation bnavstr.BNAV_neckShell (SO3MathsEulerXYZToQuat [ay 0.0 0.0]); SO3ObjectSetOrientation bnavstr.BNAV_camShell (SO3MathsEulerXYZToQuat [0.0 ax 0.0]); ); ); 0;; fun cbLookAtPos(inst, from, action, param, reply, bnavstr)= let strextr param -> l in let hd l -> sv in let [atof(nth_list sv 0) atof(nth_list sv 1) atof(nth_list sv 2)] -> target in if (target == nil) then nil else ( SO3BodySetForce bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetForce bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetVelocity bnavstr.BNAV_camBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_shellBody [0.0 0.0 0.0]; SO3BodySetOmega bnavstr.BNAV_camBody [0.0 0.0 0.0]; let SO3ObjectGetGlobalPosition bnavstr.BNAV_camera -> src in let lookAtPYR src target 1 -> [ax ay az] in ( set bnavstr.BNAV_qLastOrientation = (SO3MathsEulerXYZToQuat [ay 0.0 0.0]); set bnavstr.BNAV_vTargetTrans = nil; set bnavstr.BNAV_vTargetPos = nil; SO3ObjectSetGlobalOrientation bnavstr.BNAV_neckShell (SO3MathsEulerXYZToQuat [ay 0.0 0.0]); SO3ObjectSetOrientation bnavstr.BNAV_camShell (SO3MathsEulerXYZToQuat [0.0 ax 0.0]); ); ); 0;; fun cbActiveCamera(inst, from, action, param, reply, bnavstr)= V3DsetDefaultCamera c3dXsession bnavstr.BNAV_camera; V3DcameraTeleport (V3DgetSessionView c3dXsession) bnavstr.BNAV_camera; if (!bnavstr.BNAV_bState) then nil else cbEnable inst from action param reply bnavstr; 0;; fun cbDeactivateCamera(inst, from, action, param, reply, bnavstr)= V3DremoveDefaultCamera c3dXsession bnavstr.BNAV_camera; let bnavstr.BNAV_bState -> prevstate in ( cbDisable inst from action param reply bnavstr; set bnavstr.BNAV_bState = prevstate; ); 0;; fun cbCameraFocalLength(inst, from, action, param, reply, bnavstr)= if ((atof param) == nil) then nil else SO3CameraSetFocalLength bnavstr.BNAV_camera (atof param); 0;; fun cbCameraFov(inst, from, action, param, reply, bnavstr)= if ((atof param) == nil) then nil else ( set bnavstr.BNAV_fFov = (atof param); SO3CameraSetFOVy bnavstr.BNAV_camera SO3MathsDegreeToRadian (atof param); ); 0;; fun cbCameraClipping(inst, from, action, param, reply, bnavstr)= if ((atof param) == nil) then nil else let hd strextr param -> l in let atof (hd l) -> near in let atof (hd tl l) -> far in ( SO3CameraSetNearClipDistance bnavstr.BNAV_camera near; SO3CameraSetFarClipDistance bnavstr.BNAV_camera far; ); 0;; fun cbEnableFlyMode(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bFlyMode = 1; SO3BodySetGravityEnable bnavstr.BNAV_shellBody 0; SO3BodySetGravityEnable bnavstr.BNAV_camBody 0; 0;; fun cbDisableFlyMode(inst, from, action, param, reply, bnavstr)= set bnavstr.BNAV_bFlyMode = 0; SO3BodySetGravityEnable bnavstr.BNAV_shellBody 1; SO3BodySetGravityEnable bnavstr.BNAV_camBody 1; 0;; fun cbGeneric(inst, type, value, param, bnavstr)= let (SO3ObjectGetName bnavstr.BNAV_shell) -> objname in if (strcmpi objname value) then nil else ( let strextr param -> lparam in let strcatnSep hd lparam " " -> secondBodyName in let strcatnSep hd tl lparam " " -> matname1 in let strcatnSep hd tl tl lparam " " -> matname2 in let if (!strcmp "avatar" matname1) then matname2 else matname1 -> material in let hd tl tl tl lparam -> spos in let [atof (hd spos) atof (hd tl spos) atof (hd tl tl spos)] -> pos in let hd tl tl tl tl lparam -> snormal in let [atof (hd snormal) atof (hd tl snormal) atof (hd tl tl snormal)] -> normal in let hd tl tl tl tl tl lparam -> sforce in let [atof (hd sforce) atof (hd tl sforce) atof (hd tl tl sforce)] -> force in let atof (hd hd tl tl tl tl tl tl lparam) -> normalspeed in if (type == 16) then // "Ray intersect in" 0 else if (type == 17) then // "Ray intersect out" 0 else if (type == 18) then // "Contact" 0 else if (type == 19) then // "Overlap started" ( set bnavstr.BNAV_iContactCount = bnavstr.BNAV_iContactCount + 1; set bnavstr.BNAV_sLastMaterial = material; let if ((strfindi "climb" material 0) != nil) then 1 else 0 -> climb in if (bnavstr.BNAV_bFlyMode || !climb) then nil else ( SO3BodySetGravityEnable bnavstr.BNAV_shellBody 0; SO3BodySetGravityEnable bnavstr.BNAV_camBody 0; ); 0; ) else if (type == 20) then // "Overlap stopped" ( set bnavstr.BNAV_iContactCount = bnavstr.BNAV_iContactCount - 1; if (bnavstr.BNAV_iContactCount >= 0) then nil else set bnavstr.BNAV_iContactCount = 0; let if ((strfindi "climb" material 0) != nil) then 1 else 0 -> climb in if (bnavstr.BNAV_bFlyMode || !climb) then nil else ( SO3BodySetGravityEnable bnavstr.BNAV_shellBody 1; SO3BodySetGravityEnable bnavstr.BNAV_camBody 1; ); if (bnavstr.BNAV_iContactCount > 0) then nil else set bnavstr.BNAV_sLastMaterial = nil; 0; ) else if (type == 21) then // "Grabed" 0 else if (type == 22) then // "Ungrabed" 0 else nil; ); 0;; fun cbPhysCollision(scene, bnavstr, body1, body2, pos, normal, force, normalspeed)= 0;; fun cbPhysOverlapStarted(scene, bnavstr, body1, body2)= if (body1 != bnavstr.BNAV_shellBody) && (body2 != bnavstr.BNAV_shellBody) then nil else ( set bnavstr.BNAV_iContactCount = bnavstr.BNAV_iContactCount + 1; set bnavstr.BNAV_sLastMaterial = "default"; ); 0;; fun cbPhysOverlapEnded(scene, bnavstr, body1, body2)= if (body1 != bnavstr.BNAV_shellBody) && (body2 != bnavstr.BNAV_shellBody) then nil else ( set bnavstr.BNAV_iContactCount = bnavstr.BNAV_iContactCount - 1; if (bnavstr.BNAV_iContactCount >= 0) then nil else set bnavstr.BNAV_iContactCount = 0; if (bnavstr.BNAV_iContactCount != 0) then nil else ( set bnavstr.BNAV_sLastMaterial = nil; ); ); 0;; fun loadWalkSounds(inst, bnavstr)= let nil -> ndata in let 0 -> i in ( let getPluginInstanceParam inst (strcat "mat_" (itoa i)) -> mat in let getPluginInstanceParam inst (strcat "snd_" (itoa i)) -> sound in while (mat != nil) do ( let _CRAudio _channel strcatn (getPluginInstanceName inst)::"_walk_"::mat::nil (_checkpack sound) 0 -> wsnd in let mkWalkSound [sound wsnd 400 nil] -> sdnstr in ( _AudioEnableSoundEffect wsnd 1; _AudioSetVolume wsnd 100; _AudioSetCone wsnd 360 360 10; set bnavstr.BNAV_lWSound = [mat sdnstr]::bnavstr.BNAV_lWSound; ); set i = i + 1; set mat = getPluginInstanceParam inst (strcat "mat_" (itoa i)); set sound = getPluginInstanceParam inst (strcat "snd_" (itoa i)); ); // default sound if (switchstr bnavstr.BNAV_lWSound "default") != nil then nil else let strcatn (getPluginDirectory (getInstancePlugin inst))::"/medias/"::"step_default.ogg"::nil -> path in let _CRAudio _channel strcatn (getPluginInstanceName inst)::"_walk_"::"default"::nil (_checkpack path) 0 -> wsnd in let mkWalkSound [path wsnd 400 nil] -> sdnstr in ( _AudioSetVolume wsnd 100; _AudioSetCone wsnd 360 360 10; set bnavstr.BNAV_lWSound = ["default" sdnstr]::bnavstr.BNAV_lWSound; ); ); 0;; fun loadSound(inst, bnavstr)= //let strcatn (getPluginDirectory (getInstancePlugin inst))::"/medias/"::"slide.ogg"::nil -> path in let (getPluginInstanceParam inst "sndslide") -> path in if ((_checkpack path) == nil) then nil else let _CRAudio _channel strcatn (getPluginInstanceName inst)::"_slide"::nil (_checkpack path) 0 -> wsnd in ( _AudioSetVolume wsnd 100; _AudioSetCone wsnd 360 360 10; set bnavstr.BNAV_slideSound = wsnd; ); //let strcatn (getPluginDirectory (getInstancePlugin inst))::"/medias/"::"hit.ogg"::nil -> path in let (getPluginInstanceParam inst "sndhit") -> path in if ((_checkpack path) == nil) then nil else let _CRAudio _channel strcatn (getPluginInstanceName inst)::"_hit"::nil (_checkpack path) 0 -> wsnd in ( _AudioSetVolume wsnd 100; _AudioSetCone wsnd 360 360 10; set bnavstr.BNAV_hitSound = wsnd; ); //let strcatn (getPluginDirectory (getInstancePlugin inst))::"/medias/"::"jump.ogg"::nil -> path in let (getPluginInstanceParam inst "sndjump") -> path in if ((_checkpack path) == nil) then nil else let _CRAudio _channel strcatn (getPluginInstanceName inst)::"_jump"::nil (_checkpack path) 0 -> wsnd in ( _AudioSetVolume wsnd 100; _AudioSetCone wsnd 360 360 10; set bnavstr.BNAV_jumpSound = wsnd; ); loadWalkSounds inst bnavstr; 0;; fun newOb(inst)= V3DenableNavigate c3dXsession 0; let atof (getPluginInstanceParam inst "wspeed") -> wspeed in let atof (getPluginInstanceParam inst "rspeed") -> rspeed in let atof (getPluginInstanceParam inst "cameraheight") -> camheight in let atof (getPluginInstanceParam inst "jumpforce") -> jumpforce in let atof (getPluginInstanceParam inst "mass") -> mass in let atoi (getPluginInstanceParam inst "shiftmode") -> shiftmode in let atof (getPluginInstanceParam inst "posx") -> posx in let atof (getPluginInstanceParam inst "posy") -> posy in let atof (getPluginInstanceParam inst "posz") -> posz in let atof (getPluginInstanceParam inst "angx") -> ax in let atof (getPluginInstanceParam inst "angy") -> ay in let atof (getPluginInstanceParam inst "angz") -> az in let atof (getPluginInstanceParam inst "fovy") -> fovy in let atof (getPluginInstanceParam inst "nclip") -> nclip in let atof (getPluginInstanceParam inst "fclip") -> fclip in let atof (getPluginInstanceParam inst "focalelength") -> focalelength in let atof (getPluginInstanceParam inst "maxlookup") -> maxlookup in let atof (getPluginInstanceParam inst "maxlookdown") -> maxlookdown in let atoi (getPluginInstanceParam inst "hidemouse") -> hidemouse in let atoi (getPluginInstanceParam inst "enable") -> enable in let atoi (getPluginInstanceParam inst "keyboard") -> keyboard in let atoi (getPluginInstanceParam inst "flymode") -> flymode in let atoi (getPluginInstanceParam inst "feetpos") -> feetpos in let atoi (getPluginInstanceParam inst "initcam") -> initcam in let atoi (getPluginInstanceParam inst "disabledefcontrol") -> disabledefcontrol in let atoi (getPluginInstanceParam inst "freehead") -> freehead in let if initcam == nil then 1 else initcam -> initcam in let if wspeed == nil then 1.0 else wspeed -> wspeed in let if rspeed == nil then 2.0 else rspeed -> rspeed in let if camheight == nil then 1.60 else camheight -> camheight in let if jumpforce == nil then 5.0 else jumpforce -> jumpforce in let if mass == nil then 60.0 else mass -> mass in let if shiftmode == nil then 0 else shiftmode -> shiftmode in let if posx == nil then 0.0 else posx -> posx in let if posy == nil then 0.0 else posy -> posy in let if posz == nil then 0.0 else posz -> posz in let if ax == nil then 0.0 else ax -> ax in let if ay == nil then 0.0 else ay -> ay in let if az == nil then 0.0 else az -> az in let if fovy == nil then 45.0 else fovy -> fovy in let if nclip == nil then 0.1 else nclip -> nclip in let if fclip == nil then 10000.0 else fclip -> fclip in let if focalelength == nil then 1.0 else focalelength -> focalelength in let if maxlookup == nil then SO3MathsDegreeToRadian 80.0 else SO3MathsDegreeToRadian maxlookup -> maxlookup in let if maxlookdown == nil then SO3MathsDegreeToRadian -.85.0 else SO3MathsDegreeToRadian maxlookdown -> maxlookdown in let if hidemouse == nil then 1 else hidemouse -> hidemouse in let if flymode == nil then 0 else flymode -> flymode in let if feetpos == nil then 0 else feetpos -> feetpos in let if enable == nil then 1 else enable -> enable in let if keyboard == nil then 1 else keyboard -> keyboard in let if disabledefcontrol == nil then 0 else disabledefcontrol -> disabledefcontrol in let if freehead == nil then 1 else freehead -> freehead in let (IsInEditor inst) || IsEventLinked inst "Feet position" -> bfeetpos in let (IsInEditor inst) || IsEventLinked inst "Head position" -> bheadpos in let (IsInEditor inst) || IsEventLinked inst "Hip position" -> bhippos in let 0.20 -> bodyradius in let (strreplace (getPluginInstanceName inst) " " "_") -> instname in let V3DaddShell c3dXsession strcat instname "_FPSNav_dummy" nil nil [posx posy posz] [0.0 0.0 0.0 1.0] -> shell in //let SO3BodyCreateCapsule shell 0.20 camheight -> body in let SO3BodyCreateCapsuleExt shell bodyradius (camheight /. 1.8) [0.0 (camheight /. 3.6) 0.0] [0.0 0.0 0.0 1.0] -> body in let V3DaddShell c3dXsession strcat instname "_FPSNav_coll_dummy" nil nil [0.0 camheight 0.0] [0.0 0.0 0.0 1.0] -> collshell in let V3DaddShell c3dXsession strcat instname "_FPSNav_neck_dummy" nil nil [0.0 camheight 0.0] [0.0 0.0 0.0 1.0] -> neckshell in let V3DaddShell c3dXsession strcat instname "_FPSNav_cam_dummy" nil nil [0.0 0.0 0.0] [0.0 0.0 0.0 1.0] -> camshell in let SO3BodyCreateCapsuleExt collshell (bodyradius *. 0.8) (camheight /. 2.5) [0.0 (-. camheight /. 10.0) 0.0] [0.0 0.0 0.0 1.0] -> cambody in let V3DaddCamera c3dXsession strcat instname "_FPSNav_camera" -> cam in let strcat (getPluginInstanceName inst) "_Group" -> grpname in let mkBasicNavigation [grpname nil shell cam neckshell camshell collshell body cambody nil nil nil nil 0 [[posx posy posz] [ax ay az]] [[0.0 0.0 0.0] [0.0 0.0 0.0]] [0.0 0.0] [0.0 0.0 0.0] nil 0 fovy wspeed rspeed shiftmode mass jumpforce 0 camheight 0.0 0.0 [maxlookdown maxlookup] nil hidemouse 0 1 0 flymode 0 0 keyboard disabledefcontrol !disabledefcontrol nil nil nil 0 0 1 0.0 "Idle" nil nil nil nil enable 0 freehead 0 0 0 feetpos nil bfeetpos bheadpos bhippos] -> bnavstr in ( SO3ObjectSetNavigationType shell SO3_NAVIGATION_CYLINDER_OBSTACLE; SO3ObjectSetNavigationSize shell 0.20 camheight; let strcat (getPluginInstanceName inst) "_Group" -> grpname in let strcatn (getPluginDirectory (getInstancePlugin inst))::"/res/"::"avbase.mesh"::nil -> meshpath in let strcatn (getPluginDirectory (getInstancePlugin inst))::"/res/"::"avbase.material"::nil -> matpath in ( SO3GroupCreate (V3DgetSession c3dXsession) grpname; V3DaddResource c3dXsession matpath grpname SO3_RESOURCE_MATERIAL; V3DaddResource c3dXsession meshpath grpname SO3_RESOURCE_MESH; set bnavstr.BNAV_avBase = SO3SceneLoadEntity (V3DgetSession c3dXsession) grpname (strcatn "base_mesh_"::instname::nil) (_checkpack meshpath); SO3ObjectSetRenderQueue bnavstr.BNAV_avBase 65; SO3ObjectSetCastShadows bnavstr.BNAV_avBase 0; ); SO3BodySetLinearDamping body 0.0; SO3BodySetAngularDamping body [0.0 0.0 0.0]; SO3BodyCreateBasicJointUpVector body [0.0 1.0 0.0]; SO3BodySetContiniousCollisionMode body 1; SO3BodySetType body 1; SO3BodySetLinearDamping cambody 0.0; SO3BodySetAngularDamping cambody [0.0 0.0 0.0]; SO3BodySetContiniousCollisionMode cambody 1; SO3BodySetType cambody 1; SO3BodySetType cambody 1; let V3DgetAvatarMaterial c3dXsession -> mat1 in let V3DgetDefaultMaterial c3dXsession -> mat2 in ( SO3CbMaterialOverlapStarted mat1 mat2 @cbPhysOverlapStarted bnavstr; SO3CbMaterialOverlapEnded mat1 mat2 @cbPhysOverlapEnded bnavstr; SO3CbMaterialCollision mat1 mat2 @cbPhysCollision bnavstr; ); V3DphysSetBodyMaterial c3dXsession body "avatar"; V3DphysSetBodyMaterial c3dXsession cambody "avatar"; SO3ObjectLink bnavstr.BNAV_avBase shell; SO3ObjectSetVisible bnavstr.BNAV_avBase 0 0; SO3ObjectLink collshell shell; SO3ObjectLink neckshell shell; SO3ObjectLink camshell neckshell; SO3ObjectLink cam camshell; V3DsetCamera cam focalelength (SO3MathsDegreeToRadian fovy) nclip fclip; set bnavstr.BNAV_contraint = SO3PhysicsContraintCreateSlider (V3DgetSession c3dXsession) cambody body SO3ObjectGetGlobalPosition bnavstr.BNAV_camShell [0.0 1.0 0.0] 1 1; ( SO3PhysicsContraintSetSliderLimits bnavstr.BNAV_contraint 0.0 0.0; SO3PhysicsContraintSetCollisionState bnavstr.BNAV_contraint 0; SO3PhysicsContraintSetSliderFriction bnavstr.BNAV_contraint 10.0; SO3PhysicsContraintSetSliderSpring bnavstr.BNAV_contraint 2000.0 300.0; ); set bnavstr.BNAV_qLastOrientation = (SO3MathsEulerXYZToQuat [(SO3MathsDegreeToRadian ay) 0.0 0.0]); SO3ObjectSetGlobalOrientation bnavstr.BNAV_neckShell (SO3MathsEulerXYZToQuat [(SO3MathsDegreeToRadian ay) 0.0 0.0]); SO3ObjectSetOrientation bnavstr.BNAV_camShell (SO3MathsEulerXYZToQuat [0.0 (SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian az)]); SO3BodySetInitialState body; SO3BodySetInitialState cambody; SO3BodySetMass body if mass <=. 0.0 then 0.0 else mass *. 0.8; SO3BodySetMass cambody mass *. 0.2; SO3BodySetAutoSleep body 0; SO3BodySetAutoSleep cambody 0; SO3BodySetFreeze body 0; SO3BodySetFreeze cambody 0; setPluginInstanceCbDel inst mkfun2 @deleteOb bnavstr; setPluginInstanceCbNavigateControlState inst mkfun4 @cbNavigationControlState bnavstr; PluginRegisterAction inst "Control" mkfun6 @cbControl bnavstr; PluginRegisterAction inst "Enable control" mkfun6 @cbEnable bnavstr; PluginRegisterAction inst "Disable control" mkfun6 @cbDisable bnavstr; PluginRegisterAction inst "Rotate view" mkfun6 @cbRotateView bnavstr; PluginRegisterAction inst "Translate view" mkfun6 @cbTranslateView bnavstr; PluginRegisterAction inst "Enable keyboard" mkfun6 @cbEnableKeyboard bnavstr; PluginRegisterAction inst "Disable keyboard" mkfun6 @cbDisableKeyboard bnavstr; PluginRegisterAction inst "Enable default inputs" mkfun6 @cbEnableDefaultInputs bnavstr; PluginRegisterAction inst "Disable default inputs" mkfun6 @cbDisableDefaultInputs bnavstr; PluginRegisterAction inst "Set position" mkfun6 @cbSetPosition bnavstr; PluginRegisterAction inst "Get position" mkfun6 @cbGetPosition bnavstr; PluginRegisterAction inst "Set angle limit" mkfun6 @cbSetAngleLimit bnavstr; PluginRegisterAction inst "Jump" mkfun6 @cbJump bnavstr; PluginRegisterAction inst "Shift key" mkfun6 @cbShiftKey bnavstr; PluginRegisterAction inst "Ctrl key" mkfun6 @cbCtrlKey bnavstr; PluginRegisterAction inst "Set walk speed" mkfun6 @cbSetWalkSpeed bnavstr; PluginRegisterAction inst "Set run speed" mkfun6 @cbSetRunSpeed bnavstr; PluginRegisterAction inst "Active camera" mkfun6 @cbActiveCamera bnavstr; PluginRegisterAction inst "Deactivate camera" mkfun6 @cbDeactivateCamera bnavstr; PluginRegisterAction inst "Set camera FOV" mkfun6 @cbCameraFov bnavstr; PluginRegisterAction inst "Set camera clipping" mkfun6 @cbCameraClipping bnavstr; PluginRegisterAction inst "Set camera focal length" mkfun6 @cbCameraFocalLength bnavstr; PluginRegisterAction inst "Enable fly mode" mkfun6 @cbEnableFlyMode bnavstr; PluginRegisterAction inst "Disable fly mode" mkfun6 @cbDisableFlyMode bnavstr; PluginRegisterAction inst "Set player mass" mkfun6 @cbSetPlayerMass bnavstr; PluginRegisterAction inst "Look at object" mkfun6 @cbLookAtObject bnavstr; PluginRegisterAction inst "Look at position" mkfun6 @cbLookAtPos bnavstr; // keep for retro compatibility PluginRegisterAction inst "Enable" mkfun6 @cbEnable bnavstr; PluginRegisterAction inst "Disable" mkfun6 @cbDisable bnavstr; loadSound inst bnavstr; setPluginInstanceCbGeneric inst mkfun5 @cbGeneric bnavstr; if (!initcam) then nil else ( V3DsetDefaultCamera c3dXsession bnavstr.BNAV_camera; V3DcameraTeleport (V3DgetSessionView c3dXsession) bnavstr.BNAV_camera; ); if (!initcam || !enable) then cbDisable inst nil nil nil nil bnavstr else cbEnable inst nil nil nil nil bnavstr; ); 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;