/* ----------------------------------------------------------------------------- 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 PlugAnimSwitch = [ PANIMSWITCH_inst : PInstance, PANIMSWITCH_defaultAnim : V3Danim, PANIMSWITCH_defaultLoop : I, PANIMSWITCH_prevAnims : [V3Danim r1], PANIMSWITCH_currentAnim : V3Danim, PANIMSWITCH_targetAnim : V3Danim, PANIMSWITCH_nextAnim : V3Danim, PANIMSWITCH_fSpeed : F, PANIMSWITCH_iTick : I, PANIMSWITCH_bAuto : I, PANIMSWITCH_bEnable : I, PANIMSWITCH_bWaitEnd : I, PANIMSWITCH_lastAnimEvent : V3Danim ]mkPlugAnimSwitch;; fun isAnimInList(l, anim)= if (l == nil) then 0 else let l -> [elt next] in if (elt == anim) then 1 else isAnimInList tl l anim;; fun deleteOb(inst, panimstr)= V3DsetAnimationLoop panimstr.PANIMSWITCH_defaultAnim panimstr.PANIMSWITCH_defaultLoop; while (panimstr.PANIMSWITCH_prevAnims != nil) do ( V3DstopAnimation hd panimstr.PANIMSWITCH_prevAnims; set panimstr.PANIMSWITCH_prevAnims = tl panimstr.PANIMSWITCH_prevAnims; ); V3DstopAnimation panimstr.PANIMSWITCH_currentAnim; V3DstopAnimation panimstr.PANIMSWITCH_defaultAnim; V3DstopAnimation panimstr.PANIMSWITCH_targetAnim; setPluginInstanceCbPreRender inst nil; 0;; fun cbGetAnimTransition(inst, view3d, panimstr)= let (itof (_tickcount - panimstr.PANIMSWITCH_iTick)) -> deltatime in let panimstr.PANIMSWITCH_currentAnim -> canim in ( if ((panimstr.PANIMSWITCH_targetAnim == nil) || (panimstr.PANIMSWITCH_targetAnim == panimstr.PANIMSWITCH_currentAnim)) then nil else ( let V3DgetAnimationWeight panimstr.PANIMSWITCH_currentAnim -> weight1 in let V3DgetAnimationWeight panimstr.PANIMSWITCH_targetAnim -> weight2 in ( let panimstr.PANIMSWITCH_prevAnims -> lanims in while (lanims != nil) do ( let hd lanims -> oanim in let V3DgetAnimationWeight oanim -> oweight in ( if (oweight == 0.0) then nil else let if (panimstr.PANIMSWITCH_fSpeed == 0.0) then 0.0 else oweight -. (deltatime /. panimstr.PANIMSWITCH_fSpeed) -> noweight in ( V3DsetAnimationWeight oanim (SO3MathsClampValue noweight 0.0 1.0); if (!V3DgetAnimationState oanim) || (noweight >. 0.0) then nil else ( V3DsetAnimationPosition oanim V3DgetAnimationLength oanim; V3DpauseAnimation oanim; set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims oanim; ); ); ); set lanims = tl lanims; ); if (weight1 == 0.0) || (panimstr.PANIMSWITCH_targetAnim == nil) then nil else let if (panimstr.PANIMSWITCH_fSpeed == 0.0) then 0.0 else weight1 -. (deltatime /. panimstr.PANIMSWITCH_fSpeed) -> nweight in ( V3DsetAnimationWeight panimstr.PANIMSWITCH_currentAnim (SO3MathsClampValue nweight 0.0 1.0); if (!V3DgetAnimationState panimstr.PANIMSWITCH_currentAnim) || (nweight >. 0.0) then nil else ( V3DsetAnimationPosition panimstr.PANIMSWITCH_currentAnim V3DgetAnimationLength panimstr.PANIMSWITCH_currentAnim; V3DpauseAnimation panimstr.PANIMSWITCH_currentAnim; ); ); if (weight2 >=. 1.0) then nil else let if (panimstr.PANIMSWITCH_fSpeed == 0.0) then 1.0 else weight2 +. (deltatime /. panimstr.PANIMSWITCH_fSpeed) -> nweight in ( V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim (SO3MathsClampValue nweight 0.0 1.0); ); let (weight1 <=. 0.0) && (weight2 >=. 1.0) && panimstr.PANIMSWITCH_prevAnims == nil -> end in if !end then nil else ( set panimstr.PANIMSWITCH_currentAnim = panimstr.PANIMSWITCH_targetAnim; set panimstr.PANIMSWITCH_targetAnim = nil; /*let V3DgetAnimationLoop panimstr.PANIMSWITCH_currentAnim -> loop in if (!loop || (panimstr.PANIMSWITCH_nextAnim == nil)) then nil else ( setPluginInstanceCbPreRender inst nil; set panimstr.PANIMSWITCH_iTick = nil; );*/ ); ); ); // when an animation is not in loop we get back to the default animation before the animation end let (V3DgetAnimationLength panimstr.PANIMSWITCH_currentAnim) -. (V3DgetAnimationPosition panimstr.PANIMSWITCH_currentAnim) -> trest in let if (panimstr.PANIMSWITCH_currentAnim != panimstr.PANIMSWITCH_targetAnim) then if (trest >. (if (panimstr.PANIMSWITCH_fSpeed == 0.0) then 0.0 else (panimstr.PANIMSWITCH_fSpeed /. 1000.0))) then 0 else 1 else if (trest >=. 0.1) then 0 else 1 -> timetochange in if (!timetochange) then nil else ( let V3DgetAnimationLoop panimstr.PANIMSWITCH_currentAnim -> loop in if (panimstr.PANIMSWITCH_bAuto && (!loop) && (panimstr.PANIMSWITCH_nextAnim == nil) && ((panimstr.PANIMSWITCH_targetAnim == nil) || (panimstr.PANIMSWITCH_currentAnim == panimstr.PANIMSWITCH_targetAnim))) then ( // reset to default anim set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_currentAnim; set panimstr.PANIMSWITCH_targetAnim = panimstr.PANIMSWITCH_defaultAnim; if (panimstr.PANIMSWITCH_fSpeed == 0.0) then nil else V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim 0.0; V3DsetAnimationPosition panimstr.PANIMSWITCH_targetAnim 0.0; V3DplayAnimation panimstr.PANIMSWITCH_targetAnim; 0; ) else if (panimstr.PANIMSWITCH_nextAnim != nil) then ( if (panimstr.PANIMSWITCH_targetAnim == nil) then nil else ( set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_targetAnim; set panimstr.PANIMSWITCH_currentAnim = panimstr.PANIMSWITCH_targetAnim; ); set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_nextAnim; set panimstr.PANIMSWITCH_targetAnim = panimstr.PANIMSWITCH_nextAnim; if (panimstr.PANIMSWITCH_currentAnim == panimstr.PANIMSWITCH_targetAnim) then nil else if (((V3DgetAnimationWeight panimstr.PANIMSWITCH_targetAnim) != 1.0) || (panimstr.PANIMSWITCH_fSpeed == 0.0)) then nil else V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim 0.0; if (V3DgetAnimationLoop panimstr.PANIMSWITCH_targetAnim) then nil else V3DsetAnimationPosition panimstr.PANIMSWITCH_targetAnim 0.0; V3DplayAnimation panimstr.PANIMSWITCH_targetAnim; set panimstr.PANIMSWITCH_nextAnim = nil; 0; ); //let V3DgetAnimationLoop canim -> loop in if (canim == panimstr.PANIMSWITCH_lastAnimEvent) then nil else ( // manage the instantiate case where the ressource name is rewritten let canim.V3D_sAnimName -> animname in let strcat (strreplace inst.INST_groupstr.GRP_project.PRJ_sName " " "_") "." -> basename in let if (!strcmp basename (substr animname 0 (strlen basename))) then substr animname (strlen basename) 1024 else animname -> evtname in SendPluginEvent inst strcat evtname " end" nil nil; set panimstr.PANIMSWITCH_lastAnimEvent = canim; ); 0; ); ); set panimstr.PANIMSWITCH_iTick = _tickcount; 0;; fun cbSwitchAnimation(inst, from, action, param, rep, p)= let p -> [anim panimstr] in if (!panimstr.PANIMSWITCH_bEnable) then nil else ( if (panimstr.PANIMSWITCH_lastAnimEvent != anim) then nil else set panimstr.PANIMSWITCH_lastAnimEvent = nil; if (panimstr.PANIMSWITCH_bWaitEnd) then ( set panimstr.PANIMSWITCH_nextAnim = anim; if (panimstr.PANIMSWITCH_iTick != nil) then nil else set panimstr.PANIMSWITCH_iTick = _tickcount; setPluginInstanceCbPreRender inst mkfun3 @cbGetAnimTransition panimstr; 0; ) else if (anim == panimstr.PANIMSWITCH_targetAnim) || ((panimstr.PANIMSWITCH_targetAnim == nil) && (anim == panimstr.PANIMSWITCH_currentAnim)) then nil else ( // when we call a new switch before a transition end we force the target animation to weight 1.0 if (panimstr.PANIMSWITCH_targetAnim == nil) then nil else ( if (((V3DgetAnimationWeight panimstr.PANIMSWITCH_targetAnim) != 0.0) || (panimstr.PANIMSWITCH_fSpeed == 0.0)) then nil else V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim 1.0; if (isAnimInList panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_currentAnim) then nil else set panimstr.PANIMSWITCH_prevAnims = panimstr.PANIMSWITCH_currentAnim::panimstr.PANIMSWITCH_prevAnims; if (!isAnimInList panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_targetAnim) then nil else set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims panimstr.PANIMSWITCH_targetAnim; set panimstr.PANIMSWITCH_currentAnim = panimstr.PANIMSWITCH_targetAnim; ); if (!isAnimInList panimstr.PANIMSWITCH_prevAnims anim) then nil else set panimstr.PANIMSWITCH_prevAnims = remove_from_list panimstr.PANIMSWITCH_prevAnims anim; set panimstr.PANIMSWITCH_targetAnim = anim; if (((V3DgetAnimationWeight panimstr.PANIMSWITCH_targetAnim) != 1.0) || (panimstr.PANIMSWITCH_fSpeed == 0.0)) then nil else V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim 0.0; if (V3DgetAnimationLoop panimstr.PANIMSWITCH_targetAnim) then nil else V3DsetAnimationPosition panimstr.PANIMSWITCH_targetAnim 0.0; V3DplayAnimation panimstr.PANIMSWITCH_targetAnim; if (panimstr.PANIMSWITCH_iTick != nil) then nil else set panimstr.PANIMSWITCH_iTick = _tickcount; setPluginInstanceCbPreRender inst mkfun3 @cbGetAnimTransition panimstr; 0; ); 0; ); 0;; fun cbEnable(inst, from, action, param, rep, panimstr)= if (panimstr.PANIMSWITCH_bEnable) then nil else ( // force loop mode for default animation if (!panimstr.PANIMSWITCH_bAuto) then nil else V3DsetAnimationLoop panimstr.PANIMSWITCH_defaultAnim 1; V3DsetAnimationWeight panimstr.PANIMSWITCH_defaultAnim 1.0; V3DsetAnimationPosition panimstr.PANIMSWITCH_defaultAnim 0.0; V3DplayAnimation panimstr.PANIMSWITCH_defaultAnim; set panimstr.PANIMSWITCH_currentAnim = panimstr.PANIMSWITCH_defaultAnim; set panimstr.PANIMSWITCH_targetAnim = nil; set panimstr.PANIMSWITCH_bEnable = 1; set panimstr.PANIMSWITCH_prevAnims = nil; set panimstr.PANIMSWITCH_nextAnim = nil; set panimstr.PANIMSWITCH_iTick = nil; set panimstr.PANIMSWITCH_lastAnimEvent = nil; ); 0;; fun cbDisable(inst, from, action, param, rep, panimstr)= if (!panimstr.PANIMSWITCH_bEnable) then nil else ( setPluginInstanceCbPreRender inst nil; while (panimstr.PANIMSWITCH_prevAnims != nil) do ( let hd panimstr.PANIMSWITCH_prevAnims -> panim in ( V3DstopAnimation panim; V3DsetAnimationWeight panim 1.0; V3DsetAnimationPosition panim 0.0; ); set panimstr.PANIMSWITCH_prevAnims = tl panimstr.PANIMSWITCH_prevAnims; ); V3DstopAnimation panimstr.PANIMSWITCH_currentAnim; V3DsetAnimationWeight panimstr.PANIMSWITCH_currentAnim 1.0; V3DsetAnimationPosition panimstr.PANIMSWITCH_currentAnim 0.0; V3DstopAnimation panimstr.PANIMSWITCH_targetAnim; V3DsetAnimationWeight panimstr.PANIMSWITCH_targetAnim 1.0; V3DsetAnimationPosition panimstr.PANIMSWITCH_targetAnim 0.0; V3DstopAnimation panimstr.PANIMSWITCH_defaultAnim; V3DsetAnimationWeight panimstr.PANIMSWITCH_defaultAnim 1.0; V3DsetAnimationPosition panimstr.PANIMSWITCH_defaultAnim 0.0; set panimstr.PANIMSWITCH_bEnable = 0; ); 0;; fun loadAnimations(inst, panimstr)= let 0 -> i in let getPluginInstanceParam inst (strcat "animation_" (itoa i)) -> elem in while (elem != nil) do ( //keep default also //if (!strcmp elem panimstr.PANIMSWITCH_defaultAnim.V3D_sAnimName) then nil else let V3DgetAnimationByName c3dXsession elem -> anim in // manage the instantiate case where the ressource name is rewritten let strcat (strreplace inst.INST_groupstr.GRP_project.PRJ_sName " " "_") "." -> basename in let if (!strcmp basename (substr elem 0 (strlen basename))) then substr elem (strlen basename) 1024 else elem -> actname in ( PluginRegisterAction inst actname mkfun6 @cbSwitchAnimation [anim panimstr]; ); set i = i + 1; set elem = getPluginInstanceParam inst (strcat "animation_" (itoa i)); ); 0;; fun newOb(inst)= let getPluginInstanceParam inst "defaultAnim" -> defanim in let atoi (getPluginInstanceParam inst "autoSwitch") -> autoswitch in let if autoswitch == nil then 1 else autoswitch -> autoswitch in let atoi (getPluginInstanceParam inst "init") -> init in let if init == nil then 1 else init -> init in let atof (getPluginInstanceParam inst "transitionSpeed") -> speed in let if speed == nil then 200.0 else speed -> speed in let atoi (getPluginInstanceParam inst "waitend") -> waitend in let if waitend == nil then 0 else waitend -> waitend in let V3DgetAnimationByName c3dXsession defanim -> defanimstr in let V3DgetAnimationLoop defanimstr -> loop in let mkPlugAnimSwitch [inst defanimstr loop nil defanimstr nil nil speed nil autoswitch 0 waitend nil] -> panimstr in ( loadAnimations inst panimstr; PluginRegisterAction inst "Default" mkfun6 @cbSwitchAnimation [defanimstr panimstr]; PluginRegisterAction inst "Enable" mkfun6 @cbEnable panimstr; PluginRegisterAction inst "Disable" mkfun6 @cbDisable panimstr; if (!init) then nil else cbEnable inst nil nil nil nil panimstr; setPluginInstanceCbDel inst mkfun2 @deleteOb panimstr; ); 0;; fun IniPlug(file)= PlugRegister @newOb nil; setPluginEditor @dynamicedit; 0;;