/* ----------------------------------------------------------------------------- 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 ViewerNavigation = [ VNAV_inst : PInstance, VNAV_shell : SO3_OBJECT, VNAV_camShell : SO3_OBJECT, VNAV_camShell2 : SO3_OBJECT, VNAV_camera : SO3_OBJECT, VNAV_body : SO3_PHYSICBODY, VNAV_move : [[F F F] [F F F] F], VNAV_lControls : [[S [[F F F] [F F F] F I]] r1], VNAV_fFov : F, VNAV_fDist : F, VNAV_tDistLimit : [F F], VNAV_bPan : I, VNAV_bRevertY : I, VNAV_bUseViewLimits : I, VNAV_fSpeed : F, VNAV_fInertia : F, VNAV_fInertiaValues : [F F], VNAV_tCamLimit : [[F F I] [F F I]], VNAV_lPressedKeys : [[I I] r1], VNAV_cbInterpolate : fun [ViewerNavigation V3Dsession F] I, VNAV_bShowUnitScale : I, VNAV_sResourceGroup : S, VNAV_mUnitScale : SO3_OBJECT, VNAV_mUnitScaleMaterial : SO3_MATERIAL, VNAV_mUnitScaleTexture : SO3_TEXTURE, VNAV_mUnitScaleBuffer : AlphaBitmap, VNAV_fLastScale : F, VNAV_camOffset : [F I F I], VNAV_bState : I ]mkViewerNavigation;; typeof defUnitScaleFont = ObjBTFont;; fun applyOffset(navstr, vw, vh)= let (itof vh) /. (itof vw) -> ratio in let SO3CameraGetFOVy navstr.VNAV_camera -> fovy in let navstr.VNAV_camOffset -> [xoff xoffmode yoff yoffmode] in let if (!xoffmode) then xoff else (xoff /. 100.0) *. (itof vw) -> xoff in let if (!yoffmode) then yoff else (yoff /. 100.0) *. (itof vh) -> yoff in let ((xoff /. (itof vw)) /. ratio) *. fovy *. 0.5 -> ox in let (yoff /. (itof vh)) *. fovy *. 0.5 -> oy in SO3CameraSetFrustumOffset navstr.VNAV_camera (-.ox) oy; 0;; fun updateUnitScaleIndicator(navstr)= //mode orthographic if (navstr.VNAV_fFov != 0.0) then nil else let V3DgetOrthographicScale navstr.VNAV_camera -> scale in ( if (!navstr.VNAV_bShowUnitScale) || (navstr.VNAV_fLastScale == scale) then nil else ( //update position and unit scale let scale *. 0.25 -> oscale in let if (scale <=. 0.04) then [oscale strcat (itoa (ftoi ((scale *. 1000.0) *. 0.25)))" mm"] else if (scale <=. 4.0) then [oscale strcat (itoa (ftoi ((scale *. 100.0) *. 0.25)))" cm"] else if (scale <=. 40.0) then [oscale strcat (let (itoa (ftoi (scale *. 10.0) *. 0.25)) -> m10 in strcatn (substr m10 0 ((strlen m10) - 1))::"."::(substr m10 ((strlen m10) - 1) 1)::nil) " m"] else if (scale <=. 4000.0) then [oscale strcat (itoa (ftoi scale *. 0.25))" m"] else [oscale strcat (itoa (ftoi ((scale *. 0.001) *. 0.25)))" km"] -> [uscale sscale] in let _GETalphaBitmaps navstr.VNAV_mUnitScaleBuffer -> [bmp bmp8] in ( _FILLbitmap bmp 0xffffff; _FILLbitmap8 bmp8 0; SO3ObjectSetScale navstr.VNAV_mUnitScale [uscale uscale uscale]; _BTDRAWtextAreaAlphaBitmap navstr.VNAV_mUnitScaleBuffer defUnitScaleFont [0 0 512 120] [0 0] BT_TEXT_HORIZ_CENTERED|BT_TEXT_VERT_TOP 0x000000 255 sscale; SO3TextureBlitAlpha navstr.VNAV_mUnitScaleTexture navstr.VNAV_mUnitScaleBuffer; set navstr.VNAV_fLastScale = scale; ); ); //unit scale position let SO3CameraGetViewport navstr.VNAV_camera -> viewport in let SO3ViewportGetPixelPositionSize viewport -> [_ _ vw vh] in let ((itof vw) /. (itof vh)) *. scale -> wscale in SO3ObjectSetPosition navstr.VNAV_mUnitScale [wscale *. 0.35 ((-.0.45) *. scale) (-.1.0 -. scale)]; 0; ); 0;; fun zoomTarget(navstr, dist)= SO3ObjectSetPosition navstr.VNAV_camShell [0.0 0.0 dist]; V3DsetOrthographicScale navstr.VNAV_camera dist; 0;; fun computeControls(navstr, ftime, fspeed)= let [ftime ftime ftime] -> vtime in 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] -> ang in // cam data let [0.0 0.0 0.0] -> cvec in let [0.0 0.0 0.0] -> cang in let 0.0 -> ycam in let 0 -> angOverride in ( let sizelist navstr.VNAV_lControls -> size in let 0 -> i in while i < size do ( let nth_list navstr.VNAV_lControls i -> [_ tcontrol] in let tcontrol -> [nvec nang nycam mode] in ( if (mode == 1) then // accumulator ( set vec = addVectorF vec nvec; set ang = addVectorF ang nang; set ycam = ycam +. nycam; //reset control mutate tcontrol <- [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 mode]; 0; ) else if (mode == 2) || (mode == 3) then // override angle ( set angOverride = 1; set vec = addVectorF vec nvec; set cang = nang; set ycam = ycam +. nycam; //reset control mutate tcontrol <- [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 mode]; 0; ) else ( set avec = addVectorF avec nvec; set aang = addVectorF aang nang; set ycam = ycam +. nycam; 0; ) ); set i = i + 1; ); // compute speed and time let navstr.VNAV_move -> [kvec kang dist] in ( set ycam = (ycam +. dist) *. fspeed *. ftime; set avec = (addVectorF avec kvec); set aang = (addVectorF aang kang); set avec = multiplyVectorF multiplyVectorF avec vtime vspeed; let aang -> [pitch yaw roll] in set aang = multiplyVectorF multiplyVectorF multiplyVectorF [(SO3MathsDegreeToRadian pitch) (SO3MathsDegreeToRadian yaw) (SO3MathsDegreeToRadian roll)] vspeed vtime [90.0 90.0 90.0]; let cang -> [pitch yaw roll] in set cang = [(SO3MathsDegreeToRadian pitch) (SO3MathsDegreeToRadian yaw) (SO3MathsDegreeToRadian roll)]; ); let ang -> [ax ay az] in set ang = [(SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian ay) (SO3MathsDegreeToRadian az)]; [(addVectorF avec vec) (addVectorF aang ang) cang angOverride ycam]; );; fun interpolateData(navstr, sessionstr, ftime, p)= let p -> [[fromvec fromquat fromdist] [tovec toquat todist] coef] in let 4.0 -> interpolatetime in let if ((coef +. (interpolatetime *. ftime)) >. 1.0) then 1.0 else if ((coef +. (interpolatetime *. ftime)) <. 0.0) then 0.0 else (coef +. (interpolatetime *. ftime)) -> ncoef in if (coef == 1.0) then ( set navstr.VNAV_cbInterpolate = nil; SO3ObjectSetOrientation navstr.VNAV_shell toquat; SO3ObjectSetPosition navstr.VNAV_shell tovec; zoomTarget navstr todist; 0; ) else ( let SO3MathsQuatInterpolate fromquat toquat ncoef 1 -> tang in SO3ObjectSetOrientation navstr.VNAV_shell tang; let multiplyVectorF (subVectorF tovec fromvec) [coef coef coef] -> transvec in let addVectorF fromvec transvec -> posvec in SO3ObjectSetPosition navstr.VNAV_shell posvec; let (todist -. fromdist) *. coef -> transdist in let fromdist +. transdist -> transdist in zoomTarget navstr transdist; mutate p <- [_ _ ncoef]; 0; ); 0;; fun dataChanged(navstr)= let SO3ObjectGetPosition navstr.VNAV_shell -> [vx vy vz] in let SO3ObjectGetOrientation navstr.VNAV_shell -> [ax ay az aw] in let getVectorLengthF SO3ObjectGetPosition navstr.VNAV_camShell -> d in SendPluginEvent navstr.VNAV_inst "Data changed" (strbuild ((XMLgetShortFloatToString vx)::(XMLgetShortFloatToString vy)::(XMLgetShortFloatToString vz)::nil)::((XMLgetShortFloatToString ax)::(XMLgetShortFloatToString ay)::(XMLgetShortFloatToString az)::(XMLgetShortFloatToString aw)::nil)::((XMLgetShortFloatToString d)::nil)::nil) nil; 0;; fun vNavCameraPan(sessionstr, navstr, x, y) = let SO3CameraGetViewport navstr.VNAV_camera -> viewport in let SO3CameraGetFOVy navstr.VNAV_camera -> fovy in let if fovy <=. 0.0 then 0.000001 else fovy -> fovy in let if V3DgetOrthographicMode navstr.VNAV_camera then 1.0 else fovy -> fovy in let SO3ViewportGetPixelPositionSize viewport -> [vx vy vw vh] in let if (vw <= 0) then 1 else vw -> vw in let if (vh <= 0) then 1 else vh -> vh in let getVectorLengthF SO3ObjectGetPosition navstr.VNAV_camShell -> dist in let ((itof vw)) /. atan fovy -> dx in let ((-.dist *. ((itof vw))) /. dx /. ((itof vh))) -> coef in let (itof x) *. coef -> mx in let (itof y) *. coef -> my in let [mx my 0.0] -> vect in ( SO3ObjectTranslate navstr.VNAV_shell vect SO3_LOCAL_TS; ); 0;; fun pitchCamera(navstr, ang, absolute)= if (absolute) then ( V3DsetObjectOrientationDeg navstr.VNAV_camShell2 [0.0 (SO3MathsRadianToDegree ang) 0.0]; 0; ) else ( let if navstr.VNAV_bRevertY then -. ang else ang -> ang in let SO3MathsQuatToEulerYXZ (SO3ObjectGetOrientation navstr.VNAV_shell) -> [ax ay _] in let navstr.VNAV_tCamLimit -> [[lx lx2 xstate] [ly ly2 ystate]] in if (navstr.VNAV_bUseViewLimits && ((ax +. ang) <. lx) && xstate) then ( SO3ObjectSetOrientation navstr.VNAV_shell SO3MathsEulerYXZToQuat [lx ay 0.0]; 0; ) else if (navstr.VNAV_bUseViewLimits && ((ax +. ang) >. lx2) && xstate) then ( SO3ObjectSetOrientation navstr.VNAV_shell SO3MathsEulerYXZToQuat [lx2 ay 0.0]; 0; ) else ( SO3ObjectRotatePitch navstr.VNAV_shell ang SO3_LOCAL_TS; 0; ); ); 0;; fun rollCamera(navstr, ang, absolute)= if (absolute) then ( V3DsetObjectOrientationDeg navstr.VNAV_camera [0.0 0.0 (SO3MathsRadianToDegree ang)]; 0; ) else ( SO3ObjectRotateRoll navstr.VNAV_camera ang SO3_LOCAL_TS; 0; ); 0;; fun rollCameraShell(navstr, ang, absolute)= if (absolute) then ( V3DsetObjectOrientationDeg navstr.VNAV_shell [0.0 0.0 (SO3MathsRadianToDegree ang)]; 0; ) else ( SO3ObjectRotateRoll navstr.VNAV_shell ang SO3_LOCAL_TS; 0; ); 0;; fun yawCamera(navstr, ang, absolute)= if (absolute) then ( SO3ObjectRotateYaw navstr.VNAV_camShell ang SO3_LOCAL_TS; 0; ) else ( // dot not always return the yaw from the good axis let SO3MathsQuatToEulerYXZ (SO3ObjectGetOrientation navstr.VNAV_shell) -> [ax ay _] in let navstr.VNAV_tCamLimit -> [[lx lx2 xstate] [ly ly2 ystate]] in if (navstr.VNAV_bUseViewLimits && ((ay +. ang) <. ly) && ystate) then ( SO3ObjectSetOrientation navstr.VNAV_shell SO3MathsEulerYXZToQuat [ax ly 0.0]; 0; ) else if (navstr.VNAV_bUseViewLimits && ((ay +. ang) >. ly2) && ystate) then ( SO3ObjectSetOrientation navstr.VNAV_shell SO3MathsEulerYXZToQuat [ax ly2 0.0]; 0; ) else ( SO3ObjectRotateYaw navstr.VNAV_shell ang if (navstr.VNAV_bUseViewLimits) then SO3_PARENT_TS else SO3_LOCAL_TS; 0; ); ); 0;; fun cbVnavKeyDown(inst, viewstr, key, ascode, navstr)= if VUIisFocusedInput then nil else ( let _keybdstate -> ctrlstate in let navstr.VNAV_move -> [vec ang dist] in let 1.0 -> v in let 1.0 -> a in if (switch navstr.VNAV_lPressedKeys key) != nil then nil else ( let if key == 328 then // UP if ctrlstate & 2 && navstr.VNAV_bPan then -.v else -.a else if key == 336 then // DOWN if ctrlstate & 2 && navstr.VNAV_bPan then v else a else nil -> pitch in let if key == 331 then // LEFT if ctrlstate & 2 && navstr.VNAV_bPan then v else a else if key == 333 then // RIGHT if ctrlstate & 2 && navstr.VNAV_bPan then -.v else -.a else nil -> yaw in ( if pitch == nil then nil else if ctrlstate & 2 && navstr.VNAV_bPan then mutate vec <- [_ (-.pitch) _] else mutate ang <- [pitch _ _]; if yaw == nil then nil else if ctrlstate & 2 && navstr.VNAV_bPan then mutate vec <- [-.yaw _ _] else mutate ang <- [_ yaw _]; ); set navstr.VNAV_lPressedKeys = [key (if ctrlstate == nil then 0 else ctrlstate)]::navstr.VNAV_lPressedKeys; ); ); 0;; fun cbVnavKeyUp(inst, viewstr, key, navstr)= if VUIisFocusedInput then nil else ( let navstr.VNAV_move -> [vec ang dist] in let switch navstr.VNAV_lPressedKeys key -> ctrlstate in ( set navstr.VNAV_lPressedKeys = (remove_idx_from_list navstr.VNAV_lPressedKeys key); // UP & DOWN if (key != 328) && (key != 336) then nil else if ctrlstate & 2 && navstr.VNAV_bPan then mutate vec <- [_ 0.0 _] else mutate ang <- [0.0 _ _]; // LEFT & RIGHT if (key != 331) && (key != 333) then nil else if ctrlstate & 2 && navstr.VNAV_bPan then mutate vec <- [0.0 _ _] else mutate ang <- [_ 0.0 _]; ); ); 0;; fun cbVnavPreRender(inst, sessionstr, etime, navstr)= let sessionstr.V3D_sessionView -> viewstr in let maxf 0.000001 ((itof etime) /. 1000.0) -> ftime in //milliseconds let ftime /. 1000.0 -> fsec in //seconds let computeControls navstr fsec navstr.VNAV_fSpeed -> [vec [pitch yaw roll] cang angOverride dist] in let 0 -> datastate in ( if (navstr.VNAV_cbInterpolate == nil) then nil else exec navstr.VNAV_cbInterpolate with [navstr sessionstr fsec]; if (!navstr.VNAV_bState) then nil else ( let navstr.VNAV_fInertiaValues -> [xib yib] in let if navstr.VNAV_fInertia == 0.0 then 1.0 else minf 1.0 (fsec *. 180.0 /. (navstr.VNAV_fInertia)) -> inertia in let [(if xib == 0.0 || xib == nil then 0.0 else (xib -. (xib *. inertia))) (if yib == 0.0 || yib == nil then 0.0 else (yib -. (yib *. inertia)))] -> [iax iay] in ( set navstr.VNAV_fInertiaValues = [(pitch +. iax) (yaw +. iay)]; ( pitchCamera navstr (pitch +. SO3MathsDegreeToRadian iax) 0; yawCamera navstr (yaw +. SO3MathsDegreeToRadian iay) 0; if (!angOverride) then nil else let cang -> [cpitch cyaw croll] in ( pitchCamera navstr cpitch 1; yawCamera navstr cyaw 1; rollCamera navstr croll 1; ); if (zeroVectorF [pitch yaw roll]) then nil else set datastate = 1; ); ); let SO3ObjectGetDerivedDirectionAxis navstr.VNAV_camera vec -> vec in SO3ObjectTranslate navstr.VNAV_shell vec SO3_WORLD_TS; SO3ObjectTranslate navstr.VNAV_camShell [0.0 0.0 dist] SO3_LOCAL_TS; let SO3ObjectGetPosition navstr.VNAV_camShell -> [cx cy cz] in let getVectorLengthF [cx cy cz] -> dist in let navstr.VNAV_tDistLimit -> [mindist maxdist] in if (dist <. mindist) then ( zoomTarget navstr mindist; ) else if (dist >. maxdist) then ( zoomTarget navstr maxdist; ) else V3DsetOrthographicScale navstr.VNAV_camera dist; //update unit scale content updateUnitScaleIndicator navstr; if ((zeroVectorF vec) && dist == 0.0) then nil else set datastate = 1; if (viewstr.V3D_bVRpointer) then nil else ( let V3DgetCursorTrans viewstr -> curstrans in if curstrans == nil then nil else // avoid object axis handler to move the camera let sessionstr.V3D_selectedAxis -> [axisstr _] in if ((axisstr != nil) && axisstr.V3D_iAxisMode) then nil else let curstrans -> [dx dy] in // Camera rotation on mouse drag if (viewstr.V3D_iMoveClickStatus == 1) then ( let V3DgetViewSize viewstr -> [iWinW iWinH] in let V3DgetLastMouseMove viewstr 0 -> [mx my] in let V3DgetLastMouseClick viewstr 0 -> [cx cy] in let [(mx-cx) (cy-my)] -> [dx dy] in let 1.0 /. ((itof iWinW) /. 2.0) *. (itof dx) *. (fsec *. 180.0) -> fdx in let 1.0 /. ((itof iWinH) /. 2.0) *. (itof dy) *. (fsec *. 180.0) -> fdy in //let (1.0 /. (((itof iWinW * 2) /. ((itof dx) +. 0.000001)) +. 0.000001)) *. navstr.VNAV_fSpeed *. (fsec *. 90.0) -> fdx in //let (1.0 /. (((itof iWinH * 2) /. ((itof dy) +. 0.000001)) +. 0.000001)) *. navstr.VNAV_fSpeed *. (fsec *. 90.0) -> fdy in ( set navstr.VNAV_fInertiaValues = [(-. fdy) (-. fdx)]; pitchCamera navstr SO3MathsDegreeToRadian (-. fdy) 0; yawCamera navstr SO3MathsDegreeToRadian (-. fdx) 0; set datastate = 1; ); ) else if ((viewstr.V3D_iMoveClickStatus == 2) && !navstr.VNAV_bUseViewLimits) then ( let V3DgetViewSize viewstr -> [iWinW iWinH] in let V3DgetLastMouseMove viewstr 0 -> [mx my] in let V3DgetLastMouseClick viewstr 0 -> [cx cy] in let [(mx-cx) (cy-my)] -> [dx dy] in let 1.0 /. ((itof iWinW) /. 2.0) *. (itof dx) -> fdx in let 1.0 /. ((itof iWinH) /. 2.0) *. (itof dy) -> fdy in let (fdx +. fdy) /. 2.0 -> roll in rollCameraShell navstr SO3MathsDegreeToRadian roll 0; set datastate = 1; ) else nil; if (viewstr.V3D_iMoveClickStatus != 16) || (!navstr.VNAV_bPan) then nil else ( let V3DgetLastMouseMove viewstr 0 -> [mx my] in let V3DgetLastMouseClick viewstr 0 -> [cx cy] in let V3DgetLastMouseRender viewstr 0 -> [rx ry] in let [(mx-cx) (cy-my)] -> [dx dy] in let if rx == nil then cx else rx -> mvx in let if ry == nil then cy else ry -> mvy in let [(mx-mvx) (mvy-my)] -> [dx dy] in vNavCameraPan c3dXsession navstr dx dy; set datastate = 1; ); ); if !datastate then nil else dataChanged navstr; ); ); 0;; fun cbVnavWheel(inst, viewstr, x, y, delta, btn, navstr)= let getVectorLengthF SO3ObjectGetPosition navstr.VNAV_camShell -> z in let if iGlobalUnit > 1 then ((itof iGlobalUnit) /. 10.0) else (itof iGlobalUnit) -> unitdiv in ( let ((itof -delta) *. (((absf z) +. 10.0) /. (100.0 /. unitdiv)) ) -> zm in if zm <. 0.0 && z <=. 0.0 then nil else let (z +. zm) -> dist in let navstr.VNAV_tDistLimit -> [mindist maxdist] in let if (dist <. mindist) then mindist else if (dist >. maxdist) then maxdist else dist -> dist in ( zoomTarget navstr dist; //update unit scale content updateUnitScaleIndicator navstr; dataChanged navstr; ); ); 0;; fun deleteOb(inst, navstr)= let SO3ObjectGetChildren navstr.VNAV_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; ); V3DdelCamera c3dXsession navstr.VNAV_camera; SO3ObjectDestroy navstr.VNAV_camShell; SO3ObjectDestroy navstr.VNAV_camShell2; SO3ObjectDestroy navstr.VNAV_shell; // destroy unit scale SO3ObjectDestroy navstr.VNAV_mUnitScale; // delete material and texture SO3MaterialDestroy navstr.VNAV_mUnitScaleMaterial; SO3TextureDestroy navstr.VNAV_mUnitScaleTexture; _DSalphaBitmap navstr.VNAV_mUnitScaleBuffer; SO3GroupDelete (V3DgetSession c3dXsession) navstr.VNAV_sResourceGroup; V3DenableNavigate c3dXsession 1; 0;; fun cbChangeData(inst, from, action, param, reply, navstr)= let strextr param -> l in let hd l -> sv in let hd tl l -> sa in let atof hd (hd tl tl l) -> todist in let [atof(nth_list sv 0) atof(nth_list sv 1) atof(nth_list sv 2)] -> tovec in let [atof(nth_list sa 0) atof(nth_list sa 1) atof(nth_list sa 2) atof(nth_list sa 3)] -> toquat in let SO3ObjectGetPosition navstr.VNAV_shell -> fromvec in let SO3ObjectGetOrientation navstr.VNAV_shell -> fromquat in let getVectorLengthF SO3ObjectGetPosition navstr.VNAV_camShell -> fromdist in ( set navstr.VNAV_cbInterpolate = mkfun4 @interpolateData [[fromvec fromquat fromdist] [tovec toquat todist] 0.0]; /*SO3ObjectSetPosition navstr.VNAV_shell tovec; SO3ObjectSetOrientation navstr.VNAV_shell toquat; SO3ObjectSetPosition navstr.VNAV_camera [0.0 0.0 todist];*/ 0; ); 0;; fun cbResizeCtrl(inst, viewstr, vw, vh, navstr)= applyOffset navstr vw vh; 0;; fun cbControl(inst, from, action, param, reply, navstr)= //get the input control from the link let if reply == nil then "control" else reply -> reply in let switchstr navstr.VNAV_lControls reply -> icontrol in ( // if not already int the list we add it if (icontrol != nil) then nil else ( set navstr.VNAV_lControls = [reply [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 0]]::navstr.VNAV_lControls; set icontrol = switchstr navstr.VNAV_lControls reply; //addLogMessage strcat "add control " 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 then mutate icontrol <- [[vx vy vz] [ax ay az] 0.0 imode] else // accumulator mutate icontrol <- [(addVectorF ovec [vx 0.0 vz]) (addVectorF oang [ax ay az]) (ycam +. vy) imode]; ); ); 0;; fun cbControlDist(inst, from, action, param, reply, navstr)= //get the input control from the link let if reply == nil then "controldist" else reply -> reply in let switchstr navstr.VNAV_lControls reply -> icontrol in ( // if not already in the list we add it if (icontrol != nil) then nil else ( set navstr.VNAV_lControls = [reply [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0 0]]::navstr.VNAV_lControls; set icontrol = switchstr navstr.VNAV_lControls reply; //addLogMessage strcat "add control " reply; ); let atof param -> dist in ( mutate icontrol <- [_ _ dist 0]; ); ); 0;; fun cbSetPosition(inst, from, action, param, reply, navstr)= let strextr param -> l in let hd l -> sv in let hd tl l -> sa in let atof hd (hd tl tl l) -> dist 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 ( SO3ObjectSetPosition navstr.VNAV_shell vec; if dist == nil then nil else zoomTarget navstr dist; let ang -> [ax ay az] 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 ( SO3ObjectSetOrientation navstr.VNAV_shell (SO3MathsEulerYXZToQuat [(SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian ay) (SO3MathsDegreeToRadian az)]); ); SO3ObjectSetOrientation navstr.VNAV_camShell [0.0 0.0 0.0 1.0]; //reset controls set navstr.VNAV_lControls = nil; //update unit scale content updateUnitScaleIndicator navstr; dataChanged navstr; ); 0;; fun cbSetGlobalPosition(inst, from, action, param, reply, navstr)= let strextr param -> l in let hd l -> sv in let hd tl l -> sa in let [(nth_list sv 0) (nth_list sv 1) (nth_list sv 2)] -> [svx svy svz] in let if ((!strcmp svx "") || (!strcmp svx "_") || ((atof svx) == nil)) then nil else atof svx -> vx in let if ((!strcmp svy "") || (!strcmp svy "_") || ((atof svy) == nil)) then nil else atof svy -> vy in let if ((!strcmp svz "") || (!strcmp svz "_") || ((atof svz) == nil)) then nil else atof svz -> vz in let [(nth_list sa 0) (nth_list sa 1) (nth_list sa 2)] -> [sax say saz] in let if ((!strcmp sax "") || (!strcmp sax "_") || ((atof sax) == nil)) then nil else atof sax -> ax in let if ((!strcmp say "") || (!strcmp say "_") || ((atof say) == nil)) then nil else atof say -> ay in let if ((!strcmp saz "") || (!strcmp saz "_") || ((atof saz) == nil)) then nil else atof saz -> az in let if (vx == nil || vy == nil || vz == nil) then SO3ObjectGetGlobalPosition navstr.VNAV_camera else [vx vy vz] -> vec in let if (ax == nil || ay == nil || az == nil) then SO3ObjectGetGlobalOrientation navstr.VNAV_camera else SO3MathsEulerYXZToQuat [(SO3MathsDegreeToRadian ax) (SO3MathsDegreeToRadian ay) (SO3MathsDegreeToRadian az)] -> quat in let getVectorLengthF SO3ObjectGetPosition navstr.VNAV_camShell -> dist in let SO3MathsQuatGetDirection quat [0.0 0.0 (-.1.0)] -> dir in ( SO3ObjectSetOrientation navstr.VNAV_shell quat; SO3ObjectSetPosition navstr.VNAV_shell addVectorF vec (multiplyVectorF dir [dist dist dist]); SO3ObjectSetOrientation navstr.VNAV_camShell [0.0 0.0 0.0 1.0]; //reset controls set navstr.VNAV_lControls = nil; //update unit scale content updateUnitScaleIndicator navstr; dataChanged navstr; ); 0;; fun cbSetDistance(inst, from, action, param, reply, navstr)= if param == nil then nil else let (atof param) -> dist in let navstr.VNAV_tDistLimit -> [mindist maxdist] in let if (dist <. mindist) then mindist else if (dist >. maxdist) then maxdist else dist -> dist in zoomTarget navstr dist; dataChanged navstr; 0;; fun cbCameraShell(inst, from, action, param, reply, navstr)= let SO3ObjectGetName navstr.VNAV_shell -> shellname in SendPluginEvent inst "Camera shell" shellname nil; 0;; fun cbEnable(inst, from, action, param, reply, navstr)= if (!(V3DgetNavigateControlState c3dXsession)) then nil else ( setPluginInstanceCbKeyDown inst mkfun5 @cbVnavKeyDown navstr; setPluginInstanceCbKeyUp inst mkfun4 @cbVnavKeyUp navstr; setPluginInstanceCbWheel inst mkfun7 @cbVnavWheel navstr; setPluginInstanceCbScenePreRender inst mkfun4 @cbVnavPreRender navstr; set navstr.VNAV_lControls = nil; ); set navstr.VNAV_bState = 1; 0;; fun cbDisable(inst, from, action, param, reply, navstr)= set navstr.VNAV_bState = 0; setPluginInstanceCbKeyDown inst nil; setPluginInstanceCbKeyUp inst nil; setPluginInstanceCbWheel inst nil; setPluginInstanceCbScenePreRender inst nil; 0;; fun cbNavigationControlState(inst, sessionstr, state, navstr)= if (!state) then ( let navstr.VNAV_bState -> prevstate in ( cbDisable inst nil nil nil nil navstr; set navstr.VNAV_bState = prevstate; ); ) else ( if !navstr.VNAV_bState then nil else cbEnable inst nil nil nil nil navstr; ); 0;; fun getAngleLimit(minp, maxp, miny, maxy)= let if (minp == 180.0) && (maxp == 180.0) then 0 else 1 -> mp in let if (miny == 180.0) && (maxy == 180.0) then 0 else 1 -> my in let if (minp == 180.0) && mp then -.179.5 else -.minp -> minp in let if (maxp == 180.0) && mp then 179.5 else maxp -> maxp in let if (miny == 180.0) && my then -.179.5 else -.miny -> miny in let if (maxy == 180.0) && my then 179.5 else maxy -> maxy in [[(SO3MathsDegreeToRadian minp) (SO3MathsDegreeToRadian maxp) mp] [(SO3MathsDegreeToRadian miny) (SO3MathsDegreeToRadian maxy) my]];; fun cbActiveCamera(inst, from, action, param, reply, navstr)= V3DsetDefaultCamera c3dXsession navstr.VNAV_camera; if (!navstr.VNAV_bState) then nil else cbEnable inst from action param reply navstr; 0;; fun cbDeactivateCamera(inst, from, action, param, reply, navstr)= V3DremoveDefaultCamera c3dXsession navstr.VNAV_camera; let navstr.VNAV_bState -> prevstate in ( cbDisable inst from action param reply navstr; set navstr.VNAV_bState = prevstate; ); 0;; fun cbCameraFov(inst, from, action, param, reply, navstr)= if ((atof param) == nil) then nil else ( set navstr.VNAV_fFov = (atof param); SO3CameraSetFOVy navstr.VNAV_camera SO3MathsDegreeToRadian (atof param); //mode orthographic if (navstr.VNAV_fFov == 0.0) then ( V3DsetOrthographicMode navstr.VNAV_camera 1; if (!navstr.VNAV_bShowUnitScale) then nil else SO3ObjectSetVisible navstr.VNAV_mUnitScale 1 1; ) else ( V3DsetOrthographicMode navstr.VNAV_camera 0; SO3ObjectSetVisible navstr.VNAV_mUnitScale 0 0; ); updateUnitScaleIndicator navstr; ); 0;; fun cbCameraClipping(inst, from, action, param, reply, navstr)= 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 navstr.VNAV_camera near; SO3CameraSetFarClipDistance navstr.VNAV_camera far; ); 0;; fun cbSetUnitScaleState(inst, from, action, param, reply, navstr)= let XMLgetBoolValue param 0 -> state in ( set navstr.VNAV_bShowUnitScale = state; if (navstr.VNAV_fFov != 0.0) then nil else SO3ObjectSetVisible navstr.VNAV_mUnitScale state state; ); updateUnitScaleIndicator navstr; 0;; fun cbSetLimitsState(inst, from, action, param, reply, navstr)= let XMLgetBoolValue param 1 -> state in set navstr.VNAV_bUseViewLimits = state; if (!navstr.VNAV_bUseViewLimits) then nil else rollCameraShell navstr 0.0 1; 0;; fun cbSetCameraOffset(inst, from, action, param, reply, navstr)= if param == nil then nil else let strextr param -> lp in let (nth_list (hd lp) 0) -> sx in let (nth_list (hd lp) 1) -> sy in let (V3DgetDefaultViewport (V3DgetSessionView c3dXsession)) -> viewportstr in let SO3ViewportGetPixelPositionSize viewportstr.V3D_viewport -> [_ _ vw vh] in ( let 0 -> xpercent in let if (!strcmp "%" (substr sx ((strlen sx) - 1) 1)) then ( set xpercent = 1; atof sx; ) else atof sx -> px in let 0 -> ypercent in let if (!strcmp "%" (substr sy ((strlen sy) - 1) 1)) then ( set ypercent = 1; atof sy; ) else atof sy -> py in let [(if px == nil then 0.0 else px) (if py == nil then 0.0 else py)] -> [px py] in ( mutate navstr.VNAV_camOffset <- [px xpercent py ypercent]; applyOffset navstr vw vh; ); ); 0;; fun newOb(inst)= V3DenableNavigate c3dXsession 0; let atoi (getPluginInstanceParam inst "initcam") -> initcam in let if initcam == nil then 1 else initcam -> initcam in let atoi (getPluginInstanceParam inst "init") -> init in let if init == nil then 1 else init -> init in let atof (getPluginInstanceParam inst "posx") -> posx in let if posx == nil then 0.0 else posx -> posx in let atof (getPluginInstanceParam inst "posy") -> posy in let if posy == nil then 0.0 else posy -> posy in let atof (getPluginInstanceParam inst "posz") -> posz in let if posz == nil then 0.0 else posz -> posz in let atof (getPluginInstanceParam inst "angx") -> angx in let atof (getPluginInstanceParam inst "angy") -> angy in let atof (getPluginInstanceParam inst "angz") -> angz in let atof (getPluginInstanceParam inst "minp") -> minp in let atof (getPluginInstanceParam inst "maxp") -> maxp in let atof (getPluginInstanceParam inst "miny") -> miny in let atof (getPluginInstanceParam inst "maxy") -> maxy in let atof (getPluginInstanceParam inst "angz") -> angz in let atof (getPluginInstanceParam inst "dist") -> dist in let atof (getPluginInstanceParam inst "mindist") -> mindist in let atof (getPluginInstanceParam inst "maxdist") -> maxdist in let atoi (getPluginInstanceParam inst "reverty") -> reverty in let if (reverty == nil) then 0 else reverty -> reverty in let atoi (getPluginInstanceParam inst "pan") -> pan in let if angx == nil then 0.0 else angx -> angx in let if angy == nil then 0.0 else angy -> angy in let if angz == nil then 0.0 else angz -> angz in let if minp == nil then 180.0 else minp -> minp in let if maxp == nil then 180.0 else maxp -> maxp in let if miny == nil then 180.0 else miny -> miny in let if maxy == nil then 180.0 else maxy -> maxy in let if dist == nil then 5.0 else dist -> dist in let if mindist == nil then 0.0 else mindist -> mindist in let if maxdist == nil then 100000.0 else maxdist -> maxdist in let atof (getPluginInstanceParam inst "fovy") -> fovy in let if fovy == nil then 45.0 else fovy -> fovy in let atof (getPluginInstanceParam inst "nclip") -> nclip in let if nclip == nil then 0.01 else nclip -> nclip in let atof (getPluginInstanceParam inst "fclip") -> fclip in let if fclip == nil then 10000.0 else fclip -> fclip in let atof (getPluginInstanceParam inst "xoff") -> xoff in let if xoff == nil then 0.0 else xoff -> xoff in let atoi (getPluginInstanceParam inst "xoffmode") -> xoffmode in let if xoffmode == nil then 0 else xoffmode -> xoffmode in let atof (getPluginInstanceParam inst "yoff") -> yoff in let if yoff == nil then 0.0 else yoff -> yoff in let atoi (getPluginInstanceParam inst "yoffmode") -> yoffmode in let if yoffmode == nil then 0 else yoffmode -> yoffmode in let atof (getPluginInstanceParam inst "speed") -> speed in let if speed == nil then 10.0 else speed -> speed in let atof (getPluginInstanceParam inst "inertia") -> inertia in let if inertia == nil then 0.0 else inertia *. 10.0 -> inertia in let atoi (getPluginInstanceParam inst "showunitscale") -> showunitscale in let if showunitscale == nil then 1 else showunitscale -> showunitscale in let atoi (getPluginInstanceParam inst "uselimits") -> useviewlimits in let if useviewlimits == nil then 1 else useviewlimits -> useviewlimits in let V3DaddShell c3dXsession strcat (getPluginInstanceName inst) "_ViewerNav_dummy" nil nil [posx posy posz] [0.0 0.0 0.0 1.0] -> shell in let V3DaddShell c3dXsession strcat (getPluginInstanceName inst) "_ViewerNav_cam_dummy" nil nil [0.0 0.0 0.0] [0.0 0.0 0.0 1.0] -> camshell in let V3DaddShell c3dXsession strcat (getPluginInstanceName inst) "_ViewerNav_cam_dummy2" nil nil [0.0 0.0 0.0] [0.0 0.0 0.0 1.0] -> camshell2 in let V3DaddCamera c3dXsession strcat (getPluginInstanceName inst) "_ViewerNav_camera" -> cam in let getAngleLimit maxp minp miny maxy -> anglimit in let mkViewerNavigation [inst shell camshell camshell2 cam nil [[0.0 0.0 0.0] [0.0 0.0 0.0] 0.0] nil fovy dist [mindist maxdist] pan reverty useviewlimits speed inertia nil anglimit nil nil showunitscale nil nil nil nil nil nil [xoff xoffmode yoff yoffmode] init] -> navstr in ( SO3ObjectLink cam camshell2; SO3ObjectLink camshell2 camshell; SO3ObjectLink camshell shell; zoomTarget navstr dist; V3DsetCamera cam 1.0 (SO3MathsDegreeToRadian fovy) nclip fclip; //mode orthographic if (navstr.VNAV_fFov == 0.0) then V3DsetOrthographicMode navstr.VNAV_camera 1 else V3DsetOrthographicMode navstr.VNAV_camera 0; V3DsetOrthographicScale cam dist; SO3ObjectSetOrientation navstr.VNAV_shell (SO3MathsEulerYXZToQuat [(SO3MathsDegreeToRadian angx) (SO3MathsDegreeToRadian angy) (SO3MathsDegreeToRadian angz)]); SO3ObjectSetOrientation navstr.VNAV_camShell [0.0 0.0 0.0 1.0]; let (V3DgetDefaultViewport (V3DgetSessionView c3dXsession)) -> viewportstr in let SO3ViewportGetPixelPositionSize viewportstr.V3D_viewport -> [_ _ vw vh] in applyOffset navstr vw vh; //unit scale object //load resources set navstr.VNAV_sResourceGroup = strcat (getPluginInstanceName inst) "_UnitGroup"; SO3GroupCreate (V3DgetSession c3dXsession) navstr.VNAV_sResourceGroup; let strcatn (getPluginDirectory (getInstancePlugin inst))::"/res/"::"scale_indicator.mesh"::nil -> meshpath in let strcatn (getPluginDirectory (getInstancePlugin inst))::"/res/"::"scale_indicator.material"::nil -> matpath in ( V3DaddResource c3dXsession matpath navstr.VNAV_sResourceGroup SO3_RESOURCE_MATERIAL; V3DaddResource c3dXsession meshpath navstr.VNAV_sResourceGroup SO3_RESOURCE_MESH; set navstr.VNAV_mUnitScale = SO3SceneLoadEntity (V3DgetSession c3dXsession) navstr.VNAV_sResourceGroup (strcat (getPluginInstanceName inst) "/unitScale") (_checkpack meshpath); //SO3ObjectSetOrientation navstr.VNAV_mUnitScale [0.0 1.0 0.0 0.0]; set navstr.VNAV_mUnitScaleMaterial = SO3SceneGetMaterial (V3DgetSession c3dXsession) navstr.VNAV_sResourceGroup "sci_scale_value"; SO3MaterialSetIgnoreSlicePlane navstr.VNAV_mUnitScaleMaterial 1; SO3MaterialSetIgnoreSlicePlane (SO3SceneGetMaterial (V3DgetSession c3dXsession) navstr.VNAV_sResourceGroup "sci_scale_indicator") 1; SO3ObjectSetCastShadows navstr.VNAV_mUnitScale 0; SO3ObjectSetRenderQueue navstr.VNAV_mUnitScale 51; SO3ObjectLink navstr.VNAV_mUnitScale navstr.VNAV_camera; SO3ObjectSetPosition navstr.VNAV_mUnitScale [0.0 (-.0.0) (-.2.0)]; // ignore mouse SO3ObjectSetMouseClick navstr.VNAV_mUnitScale 0; //texture let [512 120] -> [tw th] in ( set navstr.VNAV_mUnitScaleTexture = SO3TextureCreate (V3DgetSession c3dXsession) (strcat (getPluginInstanceName inst) "/unitScaleTex") nil navstr.VNAV_sResourceGroup tw th; set navstr.VNAV_mUnitScaleBuffer = _CRalphaBitmap _channel (_FILLbitmap (_CRbitmap _channel tw th) 0xffffff) (_FILLbitmap8 (_CRbitmap8 _channel tw th) 0) nil nil; SO3MaterialSetTexture navstr.VNAV_mUnitScaleMaterial navstr.VNAV_mUnitScaleTexture 0 0 0; if (defUnitScaleFont != nil) then nil else set defUnitScaleFont = _CRBTfont _channel "sans" 55 BT_FONT_BOLD|BT_FONT_FILLED|BT_FONT_ANTIALIAS 1.0; SO3EntitySetMaterial navstr.VNAV_mUnitScale navstr.VNAV_mUnitScaleMaterial 0; ); if ((navstr.VNAV_fFov == 0.0) && navstr.VNAV_bShowUnitScale) then SO3ObjectSetVisible navstr.VNAV_mUnitScale 1 1 else SO3ObjectSetVisible navstr.VNAV_mUnitScale 0 0; //update unit scale content updateUnitScaleIndicator navstr; ); setPluginInstanceCbDel inst mkfun2 @deleteOb navstr; setPluginInstanceCbNavigateControlState inst mkfun4 @cbNavigationControlState navstr; PluginRegisterAction inst "Control" mkfun6 @cbControl navstr; PluginRegisterAction inst "Control distance" mkfun6 @cbControlDist navstr; PluginRegisterAction inst "Set position" mkfun6 @cbSetPosition navstr; PluginRegisterAction inst "Set distance" mkfun6 @cbSetDistance navstr; PluginRegisterAction inst "Set global position" mkfun6 @cbSetGlobalPosition navstr; PluginRegisterAction inst "Get camera shell" mkfun6 @cbCameraShell navstr; PluginRegisterAction inst "Change data" mkfun6 @cbChangeData navstr; PluginRegisterAction inst "Enable control" mkfun6 @cbEnable navstr; PluginRegisterAction inst "Disable control" mkfun6 @cbDisable navstr; PluginRegisterAction inst "Active camera" mkfun6 @cbActiveCamera navstr; PluginRegisterAction inst "Deactivate camera" mkfun6 @cbDeactivateCamera navstr; PluginRegisterAction inst "Set camera FOV" mkfun6 @cbCameraFov navstr; PluginRegisterAction inst "Set camera clipping" mkfun6 @cbCameraClipping navstr; PluginRegisterAction inst "Set unit scale state" mkfun6 @cbSetUnitScaleState navstr; PluginRegisterAction inst "Set view limits state" mkfun6 @cbSetLimitsState navstr; PluginRegisterAction inst "Set camera offset" mkfun6 @cbSetCameraOffset navstr; // keep for retro compatibility PluginRegisterAction inst "Enable" mkfun6 @cbEnable navstr; PluginRegisterAction inst "Disable" mkfun6 @cbDisable navstr; if (!initcam) then nil else cbActiveCamera inst nil nil nil nil navstr; if (!initcam || !init) then nil else cbEnable inst nil nil nil nil navstr; setPluginInstanceCbResizeView inst mkfun5 @cbResizeCtrl navstr; ); 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;