/* ----------------------------------------------------------------------------- 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 ObjPhysMouseStr = [ PMOUSE_inst : PInstance, PMOUSE_obj : SO3_OBJECT, PMOUSE_body : SO3_PHYSICBODY, PMOUSE_contraint : SO3_PHYSICCONTRAINT, PMOUSE_grabMaterial : SO3_PHYSICMATERIAL, PMOUSE_fDist : F, PMOUSE_fMass : F, PMOUSE_fFriction : F, PMOUSE_tLimits : [F F], PMOUSE_tSpring : [F F], PMOUSE_bUseSpring : I, PMOUSE_iMouseButton : I, PMOUSE_lastDist : F, PMOUSE_lastBody : SO3_PHYSICBODY, PMOUSE_bLimitangle : I, PMOUSE_state : I ]mkObjPhysMouseStr;; fun releaseGrap(obstr)= setPluginInstanceCbScenePreRenderPhysic obstr.PMOUSE_inst nil; SO3PhysicsContraintDestroy obstr.PMOUSE_contraint; SO3BodyDestroy obstr.PMOUSE_body; SO3ObjectDestroy obstr.PMOUSE_obj; SO3BodySetType obstr.PMOUSE_lastBody ((SO3BodyGetType obstr.PMOUSE_lastBody) & ~(1)) & ~(2); set obstr.PMOUSE_body = nil; set obstr.PMOUSE_obj = nil; set obstr.PMOUSE_contraint = nil; set obstr.PMOUSE_lastBody = nil; 0;; fun deleteOb(inst, obstr)= releaseGrap obstr; setPluginInstanceCbInputClick inst nil; setPluginInstanceCbInputUnClick inst nil; SO3PhysicsMaterialDestroy obstr.PMOUSE_grabMaterial; 0;; fun cbMousePreRender(inst, sessionstr, etime, obstr)= let sessionstr.V3D_sessionView -> viewstr in let V3DgetDefaultViewport viewstr -> viewportstr in let SO3ViewportGetCamera viewportstr.V3D_viewport -> camera in let V3DgetLastMouseMove viewstr 0 -> [mx my] in let SO3ViewportGetWorldPosFromPixelPosition viewportstr.V3D_viewport mx my obstr.PMOUSE_lastDist -> [pos dir] in ( if (pos == nil) then nil else SO3BodyMoveTo obstr.PMOUSE_body pos 0.3; if (!obstr.PMOUSE_bLimitangle) then nil else let SO3ObjectGetGlobalOrientation camera -> cquat in SO3BodyRotateTo obstr.PMOUSE_body cquat 0.90; 0; ); 0;; // 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 if (((SO3BodyGetType tbody) & 1) || ((SO3BodyGetType tbody) & 4) || (SO3BodyGetIgnoreCollision tbody) || (SO3BodyGetFluid tbody)) then nil else ( set body = tbody; set dist = tdist; set normal = tnormal; ); set lray = tl lray; ); [body dist normal] );; fun grabObj(obstr, id, btn, pdata)= if (!obstr.PMOUSE_state) then nil else ( let pdata -> [obj mat _ pos _ dist] in let V3DgetSessionView c3dXsession -> viewstr in let if dist <=. 0.0 then 1000.0 else dist -> dist in let V3DgetDefaultViewport viewstr -> viewportstr in let SO3ViewportGetCamera viewportstr.V3D_viewport -> camera in let V3DgetLastMouseMove viewstr 0 -> [mx my] in let SO3ViewportGetWorldPosFromPixelPosition viewportstr.V3D_viewport mx my 0.15 -> [src dir] in let getValidRay SO3PhysicsRayCastExt (V3DgetSession c3dXsession) src dir (dist +. 1.0) -> [tbody cdist normal] in let getVectorDistanceF (SO3ObjectGetGlobalPosition camera) pos -> ncdist in let [cdist cdist cdist] -> vpdist in let if (tbody == nil) || (((cdist +. 0.15) >. dist) && ((SO3SceneNodeGetBody obj) != nil)) then [(SO3SceneNodeGetBody obj) ncdist pos] else [tbody (cdist +. 0.15) (addVectorF src (multiplyVectorF dir vpdist))] -> [tbody cdist pos] in let SO3BodyGetMassMatrix tbody -> [mass _] in let if (obstr.PMOUSE_fDist == 0.0) then 1 else if (cdist >. obstr.PMOUSE_fDist) then 0 else 1 -> closedist in let SO3ObjectGetGlobalOrientation camera -> cquat in if (((btn != obstr.PMOUSE_iMouseButton) && (btn != -1)) || (tbody == nil) || (mass <=. 0.0) || !closedist) then nil else ( releaseGrap obstr; set obstr.PMOUSE_lastBody = tbody; set obstr.PMOUSE_obj = V3DaddShell c3dXsession strcat (getPluginInstanceName obstr.PMOUSE_inst) "_PhysicMouse_dummy" nil nil pos cquat; let SO3ObjectGetBoundingBoxInfo SO3BodyGetSceneNode tbody 0 -> [bbox _ _] in let if (bbox == nil) then 0.025 else let bbox -> [sx sy sz] in (maxf maxf sx maxf sy sz 0.1) /. 4.0 -> bsize in set obstr.PMOUSE_body = SO3BodyCreateEllipsoid obstr.PMOUSE_obj [bsize bsize bsize]; SO3BodySetMaterial obstr.PMOUSE_body obstr.PMOUSE_grabMaterial; SO3BodySetMass obstr.PMOUSE_body if (obstr.PMOUSE_fMass != 0.0) then obstr.PMOUSE_fMass /. mass else mass; SO3BodySetAutoSleep obstr.PMOUSE_body 0; SO3BodySetGravityEnable obstr.PMOUSE_body 0; SO3BodySetIgnoreCollision obstr.PMOUSE_body 1; SO3BodySetType obstr.PMOUSE_body 1; SO3BodySetType tbody (SO3BodyGetType tbody) | 1 | 2; set obstr.PMOUSE_lastDist = cdist; set obstr.PMOUSE_contraint = SO3PhysicsContraintCreateSlider (V3DgetSession c3dXsession) obstr.PMOUSE_body tbody pos [0.0 1.0 0.0] 1 obstr.PMOUSE_bUseSpring; let obstr.PMOUSE_tLimits -> [minl maxl] in SO3PhysicsContraintSetSliderLimits obstr.PMOUSE_contraint minl maxl; let obstr.PMOUSE_tSpring -> [strenght damping] in SO3PhysicsContraintSetSliderSpring obstr.PMOUSE_contraint strenght damping; SO3PhysicsContraintSetSliderFriction obstr.PMOUSE_contraint obstr.PMOUSE_fFriction; SO3PhysicsContraintSetCollisionState obstr.PMOUSE_contraint 0; let (SO3ObjectGetName SO3BodyGetSceneNode tbody) -> bname in ( cbPlugGeneric 21 bname nil; SendPluginEvent obstr.PMOUSE_inst "Grabed" bname nil; ); setPluginInstanceCbScenePreRenderPhysic obstr.PMOUSE_inst mkfun4 @cbMousePreRender obstr; ); ); 0;; fun cbInputClick(inst, viewstr, id, x, y, btn, pdata, obstr)= grabObj obstr id btn pdata; 0;; fun cbInputUnClick(inst, viewstr, id, x, y, btn, pdata, obstr)= if (obstr.PMOUSE_contraint == nil) then nil else ( SendPluginEvent obstr.PMOUSE_inst "Ungrabed" nil nil; cbPlugGeneric 22 (SO3ObjectGetName (SO3BodyGetSceneNode obstr.PMOUSE_lastBody)) nil; ); releaseGrap obstr; 0;; fun cbGrab(inst, from, action, param, reply, obstr)= let V3DgetSessionView c3dXsession -> viewstr in let V3DgetLastMouseData viewstr 0 -> [_ _ obj mat _ _ pos _ dist] in grabObj obstr 0 (-1) [obj mat nil pos nil dist]; 0;; fun cbUngrab(inst, from, action, param, reply, obstr)= if (obstr.PMOUSE_contraint == nil) then nil else ( SendPluginEvent obstr.PMOUSE_inst "Ungrabed" nil nil; cbPlugGeneric 22 (SO3ObjectGetName (SO3BodyGetSceneNode obstr.PMOUSE_lastBody)) nil; ); releaseGrap obstr; 0;; fun cbEnable(inst, from, action, param, reply, obstr)= set obstr.PMOUSE_state = 1; 0;; fun cbDisable(inst, from, action, param, reply, obstr)= if (obstr.PMOUSE_contraint == nil) then nil else ( SendPluginEvent obstr.PMOUSE_inst "Ungrabed" nil nil; cbPlugGeneric 22 (SO3ObjectGetName (SO3BodyGetSceneNode obstr.PMOUSE_lastBody)) nil; ); releaseGrap obstr; set obstr.PMOUSE_state = 0; 0;; fun newOb(inst)= let atof (getPluginInstanceParam inst "friction") -> friction in let atof (getPluginInstanceParam inst "mindist") -> mindist in let atof (getPluginInstanceParam inst "maxdist") -> maxdist in let atof (getPluginInstanceParam inst "strength") -> strength in let atof (getPluginInstanceParam inst "damping") -> damping in let atoi (getPluginInstanceParam inst "usespring") -> usespring in let atof (getPluginInstanceParam inst "dist") -> dist in let atof (getPluginInstanceParam inst "mass") -> mass in let (atoi (getPluginInstanceParam inst "mousebtn")) + 1 -> mousebtn in let atoi (getPluginInstanceParam inst "limitangle") -> limitangle in let if (limitangle == nil) then 0 else limitangle -> limitangle in let atoi (getPluginInstanceParam inst "init") -> init in let SO3PhysicsGetMaterial (V3DgetSession c3dXsession) "mousegrab" -> gmat in let if gmat == nil then SO3PhysicsMaterialCreate (V3DgetSession c3dXsession) "mousegrab" else gmat -> gmat in let mkObjPhysMouseStr [inst nil nil nil gmat dist mass friction [mindist maxdist] [strength damping] usespring mousebtn nil nil limitangle init] -> obstr in ( //avoid collision with camera let V3DgetAvatarMaterial c3dXsession -> avmat in ( SO3PhysicsMaterialSetDefaultCollidable gmat avmat 0; SO3PhysicsMaterialSetDefaultCollidable gmat gmat 0; ); setPluginInstanceCbInputClick inst mkfun8 @cbInputClick obstr; setPluginInstanceCbInputUnClick inst mkfun8 @cbInputUnClick obstr; PluginRegisterAction inst "Enable" mkfun6 @cbEnable obstr; PluginRegisterAction inst "Disable" mkfun6 @cbDisable obstr; PluginRegisterAction inst "Grab" mkfun6 @cbGrab obstr; PluginRegisterAction inst "Ungrab" mkfun6 @cbUngrab obstr; setPluginInstanceCbDel inst mkfun2 @deleteOb obstr; ); 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;