/* ----------------------------------------------------------------------------- This source file is part of OpenSpace3D For the latest info, see http://www.openspace3d.com Copyright (c) 2020 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 PlugVPointerStr = [ PVPTR_inst : PInstance, PVPTR_sGroupName : S, PVPTR_sSrcName : S, PVPTR_iSrcMode : I, PVPTR_iShowRay : I, PVPTR_bAutoClick : I, PVPTR_fAutoClickDist : F, PVPTR_iLastAutoClick : I, PVPTR_pGrabBody : SO3_PHYSICBODY, PVPTR_pGrabJoint : SO3_PHYSICCONTRAINT, PVPTR_pGrabbedBody : SO3_PHYSICBODY, PVPTR_bGrab : I, PVPTR_oPointerSrc : SO3_OBJECT, PVPTR_oPointer : SO3_OBJECT, PVPTR_oRayDummy : SO3_OBJECT, PVPTR_oRay1 : SO3_OBJECT, PVPTR_oRay2 : SO3_OBJECT, PVPTR_oTarget : SO3_OBJECT, PVPTR_matRay : SO3_MATERIAL, PVPTR_bState : I, PVPTR_iLastBtn : I, PVPTR_tLastCursorPos : [I I] ]mkPlugVPointerStr;; fun isAnInvalidBody(obstr, body)= let SO3BodyGetMassMatrix body -> [mass _] in let SO3PhysicsGetMaterialName (SO3BodyGetMaterial body) -> bmat in let SO3BodyGetType body -> btype in if ((!strcmp bmat "nograb") || (!strcmp bmat "ignore") || (btype & 4) || (btype & 1) || (SO3BodyGetIgnoreCollision body) || (body == (SO3SceneNodeGetBody obstr.PVPTR_oPointerSrc)) || (obstr.PVPTR_pGrabBody == body) || (SO3BodyGetFluid body)) && !(btype & 2) then 1 else 0;; fun getValidRay(lray, obstr, cbtest)= 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 (exec cbtest with [obstr tbody]) then nil else ( set body = tbody; set dist = tdist; set normal = tnormal; ); set lray = tl lray; ); [body dist normal] );; fun setObjectRenderQueue(l, queue, sons)= if l == nil then nil else let hd l -> obj in ( if (!sons) then nil else setObjectRenderQueue (SO3ObjectGetChildren obj) queue sons; SO3ObjectSetRenderQueue obj queue; setObjectRenderQueue (tl l) queue sons; ); 0;; fun cbPreRender(inst, viewstr, obstr)= //update virtual pointer on widgets SO3VirtualPointerUpdate obstr.PVPTR_oPointer; let SO3VirtualPointerGetId obstr.PVPTR_oPointer -> id in let V3DgetDefaultViewport (V3DgetSessionView c3dXsession) -> viewportstr in let SO3VirtualPointerHasWidgetUnder obstr.PVPTR_oPointer -> foundwidget in ( SO3ObjectSetVisible obstr.PVPTR_oRayDummy (obstr.PVPTR_bState && ((obstr.PVPTR_iShowRay == 1) || ((obstr.PVPTR_iShowRay == 2) && foundwidget))) 1; SO3ObjectSetVisible obstr.PVPTR_oTarget 0 0; //update data for mouse let SO3VirtualPointerGetRayInfos obstr.PVPTR_oPointer -> [session obj mat subid p3d puv dist] in let p3d -> [px py pz] in let dist -. 0.05 -> dist in let SO3ObjectGetFlags obj -> obflag in let SO3ViewportGetPixelPositionFromWorldPos viewportstr.V3D_viewport p3d -> cursorpos in ( set obstr.PVPTR_tLastCursorPos = cursorpos; let if (foundwidget) then 71 else 66 -> rdpriority in setObjectRenderQueue obstr.PVPTR_oPointerSrc::nil rdpriority 1; //scale laser SO3ObjectSetGlobalScale obstr.PVPTR_oRayDummy [1.0 1.0 (maxf 0.0 ((SO3VirtualPointerGetlength obstr.PVPTR_oPointer) -. 0.04))]; let obstr.PVPTR_tLastCursorPos -> [cx cy] in ( cbV3DviewPointerUpdate viewstr id [(SO3ObjectGetGlobalPosition obstr.PVPTR_oPointer) (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointer)] cx cy obstr.PVPTR_iLastBtn [obj mat subid p3d puv dist]; //control virtual pointer on widgets SO3VirtualPointerSendMove obstr.PVPTR_oPointer obstr.PVPTR_iLastBtn; cbV3DPointerMove viewstr id [(SO3ObjectGetGlobalPosition obstr.PVPTR_oPointer) (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointer)] cx cy obstr.PVPTR_iLastBtn [obj mat subid p3d puv dist]; SendPluginEvent inst "Pointer move" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); let obstr.PVPTR_iLastAutoClick -> lclick in if (!obstr.PVPTR_bAutoClick || (!(obflag & iNodeFlagClick) && !(obflag & iNodeFlagVUI) && !foundwidget)) then nil else if ((dist >. obstr.PVPTR_fAutoClickDist) || ((lclick != nil) && ((_tickcount - lclick) < 1000))) then ( if ((dist >. (obstr.PVPTR_fAutoClickDist +. 0.02)) && ((lclick != nil) && ((_tickcount - lclick) > 100))) then set obstr.PVPTR_iLastAutoClick = nil else nil; ) else ( SO3VirtualPointerSendClick obstr.PVPTR_oPointer 1; cbV3DviewPointerClick viewstr id [(SO3ObjectGetGlobalPosition obstr.PVPTR_oPointer) (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointer)] cx cy 1 [obj mat subid p3d puv dist]; SendPluginEvent inst "Left click" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); SO3VirtualPointerSendUnClick obstr.PVPTR_oPointer 1; cbV3DviewPointerUnClick viewstr id cx cy 1 [obj mat subid p3d puv dist]; SendPluginEvent inst "Left unclick" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); set obstr.PVPTR_iLastAutoClick = _tickcount; ); ); ); //physic raycast if ((obstr.PVPTR_iSrcMode == 0) && obstr.PVPTR_bGrab && (obstr.PVPTR_pGrabbedBody == nil)) then let normalizeVectorF (SO3MathsQuatGetDirection (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointerSrc) [0.0 0.0 (-.1.0)]) -> dest in let addVectorF (SO3ObjectGetGlobalPosition obstr.PVPTR_oPointerSrc) (multiplyVectorF dest [0.01 0.01 0.01]) -> src in let getValidRay (SO3PhysicsRayCastExt (V3DgetSession c3dXsession) src dest 0.20) obstr @isAnInvalidBody -> [rbody cdist rnormal] in let SO3SceneNodeGetBody obstr.PVPTR_oPointerSrc -> srcbody in ( if (rbody == nil) then nil else ( //check if the grabbed object can have a mass after it has been grabbed / otherwise ignore it let SO3BodyGetMassMatrix rbody -> [mass _] in if (mass <=. 0.0) then nil else ( if (srcbody != nil) then nil else ( set obstr.PVPTR_pGrabBody = SO3BodyCreateEllipsoid obstr.PVPTR_oPointerSrc [0.05 0.05 0.05]; SO3BodySetType obstr.PVPTR_pGrabBody 1; V3DphysSetBodyMaterial c3dXsession obstr.PVPTR_pGrabBody "avatar"; let SO3BodyGetMassMatrix rbody -> [mass _] in SO3BodySetMass obstr.PVPTR_pGrabBody minf 2.0 (mass *. 10.0); SO3BodySetAutoSleep obstr.PVPTR_pGrabBody 0; SO3BodySetGravityEnable obstr.PVPTR_pGrabBody 0; SO3BodySetIgnoreCollision obstr.PVPTR_pGrabBody 1; ); set obstr.PVPTR_pGrabJoint = SO3PhysicsContraintCreateSlider (V3DgetSession c3dXsession) (SO3SceneNodeGetBody obstr.PVPTR_oPointerSrc) rbody (SO3ObjectGetGlobalPosition obstr.PVPTR_oPointerSrc) [0.0 1.0 0.0] 1 0; SO3PhysicsContraintSetSliderLimits obstr.PVPTR_pGrabJoint 0.0 0.0; SO3PhysicsContraintSetCollisionState obstr.PVPTR_pGrabJoint 0; // if the body father have a body we limits the joint stiffness let SO3SceneNodeGetBody (SO3ObjectGetParent SO3BodyGetSceneNode rbody) -> pbody in let SO3BodyGetMassMatrix pbody -> [pmass _] in let if ((pbody != nil) && (pmass >. 0.0)) then 0.8 else 1.0 -> stiff in SO3PhysicsContraintSetStiffness obstr.PVPTR_pGrabJoint stiff; SO3BodySetType rbody (SO3BodyGetType rbody) | 1 | 2; //set obstr.PVPTR_bGrab = 0; set obstr.PVPTR_pGrabbedBody = rbody; ); // grab the object let SO3ObjectGetName (SO3BodyGetSceneNode rbody) -> grabbedname in ( cbPlugGeneric 21 grabbedname nil; SendPluginEvent obstr.PVPTR_inst "Grab" grabbedname (itoa id); ); ); 0; ) else ( let SO3BodyGetMassMatrix obstr.PVPTR_pGrabbedBody -> [gmass _] in if (!obstr.PVPTR_bGrab && (obstr.PVPTR_pGrabbedBody != nil) || (gmass == 0.0)) then ( let SO3SceneNodeGetBody obstr.PVPTR_oPointerSrc -> srcbody in let SO3BodyGetVelocity srcbody -> lastvel in let SO3BodyGetOmega srcbody -> lastomega in ( SO3PhysicsContraintDestroy obstr.PVPTR_pGrabJoint; SO3BodyDestroy obstr.PVPTR_pGrabBody; set obstr.PVPTR_pGrabJoint = nil; set obstr.PVPTR_pGrabBody = nil; // ungrab the object let SO3ObjectGetName (SO3BodyGetSceneNode obstr.PVPTR_pGrabbedBody) -> grabbedname in ( SO3BodySetType obstr.PVPTR_pGrabbedBody ((SO3BodyGetType obstr.PVPTR_pGrabbedBody) & ~(1)) & ~(2); cbPlugGeneric 22 grabbedname nil; SendPluginEvent obstr.PVPTR_inst "Ungrab" grabbedname (itoa id); ); SO3BodySetVelocity obstr.PVPTR_pGrabbedBody lastvel; SO3BodySetOmega obstr.PVPTR_pGrabbedBody lastomega; ); set obstr.PVPTR_pGrabbedBody = nil; ) else nil; 0; ); ); 0;; fun cbGrab(inst, from, action, param, reply, p)= let p -> [obstr state] in set obstr.PVPTR_bGrab = state; 0;; fun cbEnable(inst, from, action, param, reply, p)= let p -> [obstr state] in if (obstr.PVPTR_bState == state) then nil else ( set obstr.PVPTR_bState = state; setPluginInstanceCbPreRender obstr.PVPTR_inst mkfun3 @cbPreRender obstr; if (state) then ( SO3ObjectSetVisible obstr.PVPTR_oRayDummy (obstr.PVPTR_iShowRay == 1) 1; SO3ObjectSetVisible obstr.PVPTR_oTarget 0 0; SO3VirtualPointerSetEnable obstr.PVPTR_oPointer 1; ) else ( SO3ObjectSetVisible obstr.PVPTR_oRayDummy 0 1; SO3ObjectSetVisible obstr.PVPTR_oTarget 0 0; SO3VirtualPointerSetEnable obstr.PVPTR_oPointer 0; ); /* let V3DgetSessionView c3dXsession -> viewstr in V3DsetVrPointerState viewstr state; */ ); 0;; fun cbChangeCamera(inst, viewstr, sessionstr, camera, obstr)= let V3DgetCameraByType sessionstr camera obstr.PVPTR_iSrcMode -> obj in ( SO3ObjectSetMouseClick obstr.PVPTR_oPointerSrc 1; let SO3BodyGetMassMatrix obstr.PVPTR_pGrabbedBody -> [gmass _] in if (!obstr.PVPTR_bGrab && (obstr.PVPTR_pGrabbedBody != nil) || (gmass == 0.0)) then ( let SO3SceneNodeGetBody obstr.PVPTR_oPointerSrc -> srcbody in let SO3BodyGetVelocity srcbody -> lastvel in let SO3BodyGetOmega srcbody -> lastomega in ( SO3PhysicsContraintDestroy obstr.PVPTR_pGrabJoint; SO3BodyDestroy obstr.PVPTR_pGrabBody; set obstr.PVPTR_pGrabJoint = nil; set obstr.PVPTR_pGrabBody = nil; // ungrab the object let SO3ObjectGetName (SO3BodyGetSceneNode obstr.PVPTR_pGrabbedBody) -> grabbedname in let SO3VirtualPointerGetId obstr.PVPTR_oPointer -> id in ( SO3BodySetType obstr.PVPTR_pGrabbedBody ((SO3BodyGetType obstr.PVPTR_pGrabbedBody) & ~(1)) & ~(2); cbPlugGeneric 22 grabbedname nil; SendPluginEvent obstr.PVPTR_inst "Ungrab" grabbedname (itoa id); ); SO3BodySetVelocity obstr.PVPTR_pGrabbedBody lastvel; SO3BodySetOmega obstr.PVPTR_pGrabbedBody lastomega; ); set obstr.PVPTR_pGrabbedBody = nil; set obstr.PVPTR_bGrab = 0; ) else nil; set obstr.PVPTR_oPointerSrc = obj; SO3ObjectSetMouseClick obstr.PVPTR_oPointerSrc 0; SO3ObjectLink obstr.PVPTR_oPointer obstr.PVPTR_oPointerSrc; SO3ObjectLink obstr.PVPTR_oRayDummy obstr.PVPTR_oPointerSrc; setObjectRenderQueue obstr.PVPTR_oPointerSrc::nil 66 1; ); 0;; fun loadVirtualPointer(obstr)= let V3DgetObjectByName c3dXsession obstr.PVPTR_sSrcName -> raysrc in if (raysrc == nil) then nil else let V3DgetObjectTypeByName obstr.PVPTR_sSrcName -> iobjmode in let SO3VirtualPointerCreate (V3DgetSession c3dXsession) strcat obstr.PVPTR_sSrcName "pointer" -> lvpointer in let SO3MaterialCreate (V3DgetSession c3dXsession) (strcat obstr.PVPTR_sSrcName "ray.material") obstr.PVPTR_sGroupName -> lmatray in let SO3SceneNodeCreate (V3DgetSession c3dXsession) (strcat obstr.PVPTR_sSrcName ".shell") -> lray in let SO3PlaneCreate (V3DgetSession c3dXsession) obstr.PVPTR_sGroupName (strcat obstr.PVPTR_sSrcName ".ray1") [0.005 1.0] nil nil -> lobray1 in let SO3PlaneCreate (V3DgetSession c3dXsession) obstr.PVPTR_sGroupName (strcat obstr.PVPTR_sSrcName ".ray2") [0.005 1.0] nil nil -> lobray2 in ( SO3VirtualPointerSetMaxLength lvpointer 10.0; set obstr.PVPTR_oPointerSrc = raysrc; set obstr.PVPTR_oPointer = lvpointer; set obstr.PVPTR_matRay = lmatray; set obstr.PVPTR_oRayDummy = lray; set obstr.PVPTR_oRay1 = lobray1; set obstr.PVPTR_oRay2 = lobray2; set obstr.PVPTR_iSrcMode = iobjmode; let V3DgetAvatarMaterial c3dXsession -> mat2 in let strcatn (getPluginDirectory (getInstancePlugin obstr.PVPTR_inst))::"/res/"::"raybase.mesh"::nil -> meshpath in let strcatn (getPluginDirectory (getInstancePlugin obstr.PVPTR_inst))::"/res/"::"raybase.material"::nil -> matpath in ( if (obstr.PVPTR_oPointer == nil) then nil else ( V3DaddResource c3dXsession matpath obstr.PVPTR_sGroupName SO3_RESOURCE_MATERIAL; V3DaddResource c3dXsession meshpath obstr.PVPTR_sGroupName SO3_RESOURCE_MESH; SO3VirtualPointerSetEnable obstr.PVPTR_oPointer 0; ); //link virtual pointer to objects if (obstr.PVPTR_oPointer == nil) then ( addLogMessage strcat "Virtual pointer creation failed on object " obstr.PVPTR_sSrcName; 0; ) else ( set obstr.PVPTR_oTarget = SO3SceneLoadEntity (V3DgetSession c3dXsession) obstr.PVPTR_sGroupName (strcat obstr.PVPTR_sSrcName ".raybase") (_checkpack meshpath); SO3ObjectSetMouseClick obstr.PVPTR_oPointerSrc 0; SO3ObjectSetVisible obstr.PVPTR_oTarget 0 0; SO3ObjectSetRenderQueue obstr.PVPTR_oTarget 65; SO3ObjectSetCastShadows obstr.PVPTR_oTarget 0; SO3ObjectLink obstr.PVPTR_oPointer obstr.PVPTR_oPointerSrc; SO3ObjectSetPosition obstr.PVPTR_oPointer [0.0 0.0 0.001]; SO3MaterialSetReceiveShadows lmatray 0; SO3MaterialSetAmbient lmatray make_rgba 255 0 0 96; SO3MaterialSetDiffuse lmatray make_rgba 255 0 0 96; SO3MaterialSetSelfIllumination lmatray make_rgba 255 0 0 96; SO3MaterialSetIgnoreSlicePlane lmatray 1; SO3MaterialSetPassCullingEnable lmatray 0 0 0; SO3MaterialSetPassDepthFunction lmatray 0 0 SO3_COMPARE_FUNCTION_ALWAYS_PASS; SO3EntitySetMaterial lobray1 lmatray 0; SO3EntitySetMaterial lobray2 lmatray 0; SO3ObjectSetCastShadows lobray1 0; SO3ObjectSetCastShadows lobray2 0; SO3ObjectSetMouseClick lobray1 0; SO3ObjectSetMouseClick lobray2 0; SO3ObjectLink lobray1 lray; SO3ObjectLink lobray2 lray; SO3ObjectLink lray obstr.PVPTR_oPointerSrc; SO3ObjectSetOrientation lobray1 [1.0 0.0 0.0 0.0]; //90° on X SO3ObjectSetOrientation lobray2 SO3MathsQuatAdd [1.0 0.0 0.0 0.0] [0.0 0.0 0.5 0.5]; //90° on X and Z SO3ObjectSetPosition lobray1 [0.0 0.0 (-.0.5)]; SO3ObjectSetPosition lobray2 [0.0 0.0 (-.0.5)]; setObjectRenderQueue obstr.PVPTR_oPointerSrc::nil 66 1; if (iobjmode == 0) then nil else setPluginInstanceCbCameraChange obstr.PVPTR_inst mkfun5 @cbChangeCamera obstr; 0; ); ); );; fun cbSendClick(inst, from, action, param, reply, p)= let p -> [obstr btn] in let V3DgetSessionView c3dXsession -> viewstr in let SO3VirtualPointerGetRayInfos obstr.PVPTR_oPointer -> [session obj mat subid p3d puv dist] in let SO3VirtualPointerGetId obstr.PVPTR_oPointer -> id in let p3d -> [px py pz] in let dist -. 0.05 -> dist in let obstr.PVPTR_tLastCursorPos -> [cx cy] in let if (btn == 1) then "Left" else if (btn == 2) then "Right" else "Middle" -> btnname in ( SO3VirtualPointerSendClick obstr.PVPTR_oPointer btn; cbV3DviewPointerClick viewstr id [(SO3ObjectGetGlobalPosition obstr.PVPTR_oPointer) (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointer)] cx cy btn [obj mat subid p3d puv dist]; SendPluginEvent inst strcat btnname " click" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); SO3VirtualPointerSendUnClick obstr.PVPTR_oPointer btn; cbV3DviewPointerUnClick viewstr id cx cy btn [obj mat subid p3d puv dist]; SendPluginEvent inst strcat btnname " unclick" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); set obstr.PVPTR_iLastBtn = 0; ); 0;; fun cbSendButtonDown(inst, from, action, param, reply, p)= let p -> [obstr btn] in let V3DgetSessionView c3dXsession -> viewstr in let SO3VirtualPointerGetRayInfos obstr.PVPTR_oPointer -> [session obj mat subid p3d puv dist] in let SO3VirtualPointerGetId obstr.PVPTR_oPointer -> id in let p3d -> [px py pz] in let dist -. 0.05 -> dist in let obstr.PVPTR_tLastCursorPos -> [cx cy] in let if (btn == 1) then "Left" else if (btn == 2) then "Right" else "Middle" -> btnname in ( set obstr.PVPTR_iLastBtn = btn; SO3VirtualPointerSendClick obstr.PVPTR_oPointer btn; cbV3DviewPointerClick viewstr id [(SO3ObjectGetGlobalPosition obstr.PVPTR_oPointer) (SO3ObjectGetGlobalOrientation obstr.PVPTR_oPointer)] cx cy btn [obj mat subid p3d puv dist]; SendPluginEvent inst strcat btnname " click" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); ); 0;; fun cbSendButtonUp(inst, from, action, param, reply, p)= let p -> [obstr btn] in let V3DgetSessionView c3dXsession -> viewstr in let SO3VirtualPointerGetRayInfos obstr.PVPTR_oPointer -> [session obj mat subid p3d puv dist] in let SO3VirtualPointerGetId obstr.PVPTR_oPointer -> id in let p3d -> [px py pz] in let dist -. 0.05 -> dist in let obstr.PVPTR_tLastCursorPos -> [cx cy] in let if (btn == 1) then "Left" else if (btn == 2) then "Right" else "Middle" -> btnname in ( set obstr.PVPTR_iLastBtn = 0; SO3VirtualPointerSendUnClick obstr.PVPTR_oPointer btn; cbV3DviewPointerUnClick viewstr id cx cy btn [obj mat subid p3d puv dist]; SendPluginEvent inst strcat btnname " unclick" strcatn (ftoa px)::" "::(ftoa py)::" "::(ftoa pz)::nil (itoa id); ); 0;; fun deleteOb(inst, obstr)= setPluginInstanceCbPreRender inst nil; setPluginInstanceCbCameraChange inst nil; SO3PhysicsContraintDestroy obstr.PVPTR_pGrabJoint; SO3BodyDestroy obstr.PVPTR_pGrabBody; SO3ObjectDestroy obstr.PVPTR_oPointer; SO3ObjectDestroy obstr.PVPTR_oRay1; SO3ObjectDestroy obstr.PVPTR_oRay2; SO3ObjectDestroy obstr.PVPTR_oRayDummy; SO3ObjectDestroy obstr.PVPTR_oTarget; SO3MaterialDestroy obstr.PVPTR_matRay; SO3ObjectSetMouseClick obstr.PVPTR_oPointerSrc 1; SO3GroupDelete (V3DgetSession c3dXsession) obstr.PVPTR_sGroupName; /* if (!obstr.PVPTR_bState) then nil else let V3DgetSessionView c3dXsession -> viewstr in V3DsetVrPointerState viewstr 0; */ 0;; fun newOb(inst)= let atoi (getPluginInstanceParam inst "showray") -> showray in let if (showray == nil) then 1 else showray -> showray in let getPluginInstanceParam inst "raysrc" -> raysrc in let atoi (getPluginInstanceParam inst "autoclick") -> autoclick in let if (autoclick == nil) then 0 else autoclick -> autoclick in let atof (getPluginInstanceParam inst "autoclickdist") -> autoclickdist in let if (autoclickdist == nil) then 0.05 else autoclickdist -> autoclickdist in let atoi(getPluginInstanceParam inst "init") -> init in let if init == nil then 1 else init -> init in let strcat (getPluginInstanceName inst) "_Group" -> groupname in let mkPlugVPointerStr [inst groupname raysrc 0 showray autoclick autoclickdist 0 nil nil nil 0 nil nil nil nil nil nil nil 0 0 nil] -> obstr in ( SO3GroupCreate (V3DgetSession c3dXsession) obstr.PVPTR_sGroupName; loadVirtualPointer obstr; cbEnable inst nil nil nil nil [obstr init]; PluginRegisterAction inst "Enable" mkfun6 @cbEnable [obstr 1]; PluginRegisterAction inst "Disable" mkfun6 @cbEnable [obstr 0]; PluginRegisterAction inst "Grab" mkfun6 @cbGrab [obstr 1]; PluginRegisterAction inst "UnGrab" mkfun6 @cbGrab [obstr 0]; PluginRegisterAction inst "Left click" mkfun6 @cbSendClick [obstr 1]; PluginRegisterAction inst "Right click" mkfun6 @cbSendClick [obstr 2]; PluginRegisterAction inst "Middle click" mkfun6 @cbSendClick [obstr 3]; PluginRegisterAction inst "Left button down" mkfun6 @cbSendButtonDown [obstr 1]; PluginRegisterAction inst "Right button down" mkfun6 @cbSendButtonDown [obstr 2]; PluginRegisterAction inst "Middle button down" mkfun6 @cbSendButtonDown [obstr 3]; PluginRegisterAction inst "Left button up" mkfun6 @cbSendButtonUp [obstr 1]; PluginRegisterAction inst "Right button up" mkfun6 @cbSendButtonUp [obstr 1]; PluginRegisterAction inst "Middle button up" mkfun6 @cbSendButtonUp [obstr 1]; //PluginRegisterAction inst "Double click" mkfun6 @cbSendDbCLick obstr; setPluginInstanceCbDel inst mkfun2 @deleteOb obstr; ); 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;