public static void animeClearner(VNController game)
        {
            Console.WriteLine(String.Format("animeClearner: start collapse anime from Act%d", game.aniIndex - 1));
            // stop scene anime timer if exists
            if (game.scnAnimeTID != -1)
            {
                game.clear_timer(game.scnAnimeTID);
            }
            game.scnAnimeTID = -1;
            // stop cam anime timer if exists
            if (game.camAnimeTID != -1)
            {
                game.clear_timer(game.camAnimeTID);
            }
            game.camAnimeTID = -1;
            // collapse current and rest animes/acts into one act script
            var actScript = scriptCollapser(game.aniList);

            Console.WriteLine("animeClearner collapsed act: " + script2string(actScript));
            // call act to do collapsed script
            act(game, actScript);
        }
 public static object animeUpdater(VNController game, object dt, object time, float duration)
 {
     try
     {
         // calculate progress
         if (time > duration)
         {
             time = duration;
         }
         var asProgress = time2progress(time, duration, game.curAnimeEff);
         // handle special system command
         if (game.curAnimeAct.Keys.Contains("sys"))
         {
             if (game.curAnimeAct["sys"].Contains("wait_anime"))
             {
                 if (sys_wait_anime(game, game.curAnimeAct["sys"]["wait_anime"]))
                 {
                     //print "stop anime here time = %f"%time
                     game.clear_timer(game.scnAnimeTID, true);
                 }
             }
         }
         if (game.curAnimeAct.Keys.Contains("sys"))
         {
             if (game.curAnimeAct["sys"].Contains("wait_voice"))
             {
                 if (sys_wait_voice(game, game.curAnimeAct["sys"]["wait_voice"]))
                 {
                     //print "stop by voice at time = %f"%time
                     game.clear_timer(game.scnAnimeTID, true);
                 }
             }
         }
         // set script
         var actScript = new Dictionary <object, object>
         {
         };
         foreach (var tgt in game.curAnimeAct)
         {
             actScript[tgt] = new Dictionary <object, object>
             {
             };
             foreach (var fnc in game.curAnimeAct[tgt])
             {
                 var rangeParam = game.curAnimeAct[tgt][fnc];
                 if (rangeParam is tuple)
                 {
                     actScript[tgt][fnc] = paramInterpolater(rangeParam[0], rangeParam[1], asProgress);
                 }
                 else
                 {
                     actScript[tgt][fnc] = rangeParam;
                 }
             }
         }
         // send to act
         //print actScript
         act(game, actScript);
         // sync with ScriptHelper
         if (_sh != null)
         {
             _sh.animeTime = time;
         }
     }
     catch (Exception e)
     {
         traceback.print_exc();
         Console.WriteLine("animeUpdater error:", e.ToString());
     }
 }