3D Audio GSoC:
[blender-staging.git] / source / blender / blenkernel / intern / scene.c
index dd2a3143d3d641aab444d4c680d7a801fe657d04..12e81e8296e26a2f5d1716b2bda6cdfb7c1a4926 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/scene.c
+ *  \ingroup bke
+ */
+
+
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #ifndef WIN32 
 #include <unistd.h>
 #else
 #include <io.h>
 #endif
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_group_types.h"
+#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_anim.h"
 #include "BKE_animsys.h"
 #include "BKE_scene.h"
 #include "BKE_sequencer.h"
 #include "BKE_world.h"
-#include "BKE_utildefines.h"
+
 #include "BKE_sound.h"
 
 //XXX #include "BIF_previewrender.h"
 //XXX #include "BIF_editseq.h"
 
-#ifndef DISABLE_PYTHON
-#include "BPY_extern.h"
-#endif
-
-#include "BLI_math.h"
-#include "BLI_blenlib.h"
-
 //XXX #include "nla.h"
 
 #ifdef WIN32
@@ -111,7 +112,7 @@ void free_qtcodecdata(QuicktimeCodecData *qcd)
        }
 }
 
-Scene *copy_scene(Main *bmain, Scene *sce, int type)
+Scene *copy_scene(Scene *sce, int type)
 {
        Scene *scen;
        ToolSettings *ts;
@@ -133,7 +134,6 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
                
                id_us_plus((ID *)scen->world);
                id_us_plus((ID *)scen->set);
-               id_us_plus((ID *)scen->ima);
                id_us_plus((ID *)scen->gm.dome.warptext);
 
                scen->ed= NULL;
@@ -174,9 +174,12 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
                BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces));
                BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers));
                BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets));
-               
-               scen->nodetree= ntreeCopyTree(sce->nodetree, 0);
-               
+
+               if(sce->nodetree) {
+                       scen->nodetree= ntreeCopyTree(sce->nodetree); /* copies actions */
+                       ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
+               }
+
                obase= sce->base.first;
                base= scen->base.first;
                while(base) {
@@ -201,6 +204,10 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
                scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms);
        }
        
+       if(sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */
+               scen->r.ffcodecdata.properties= IDP_CopyProperty(sce->r.ffcodecdata.properties);
+       }
+
        /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations
         * are done outside of blenkernel with ED_objects_single_users! */
 
@@ -208,16 +215,25 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
        if(type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
                ID_NEW(scen->camera);
        }
+       
+       /* before scene copy */
+       sound_create_scene(scen);
 
        /* world */
        if(type == SCE_COPY_FULL) {
+               BKE_copy_animdata_id_action((ID *)scen);
                if(scen->world) {
                        id_us_plus((ID *)scen->world);
                        scen->world= copy_world(scen->world);
+                       BKE_copy_animdata_id_action((ID *)scen->world);
                }
-       }
 
-       sound_create_scene(scen);
+               if(sce->ed) {
+                       scen->ed= MEM_callocN( sizeof(Editing), "addseq");
+                       scen->ed->seqbasep= &scen->ed->seqbase;
+                       seqbase_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL);
+               }
+       }
 
        return scen;
 }
@@ -307,14 +323,15 @@ void free_scene(Scene *sce)
        sound_destroy_scene(sce);
 }
 
-Scene *add_scene(char *name)
+Scene *add_scene(const char *name)
 {
+       Main *bmain= G.main;
        Scene *sce;
        ParticleEditSettings *pset;
        int a;
 
-       sce= alloc_libblock(&G.main->scene, ID_SCE, name);
-       sce->lay= 1;
+       sce= alloc_libblock(&bmain->scene, ID_SCE, name);
+       sce->lay= sce->layact= 1;
        
        sce->r.mode= R_GAMMA|R_OSA|R_SHADOW|R_SSS|R_ENVMAP|R_RAYTRACE;
        sce->r.cfra= 1;
@@ -327,26 +344,42 @@ Scene *add_scene(char *name)
        sce->r.yasp= 1;
        sce->r.xparts= 8;
        sce->r.yparts= 8;
-       sce->r.size= 25;
+       sce->r.mblur_samples= 1;
+       sce->r.filtertype= R_FILTER_MITCH;
+       sce->r.size= 50;
        sce->r.planes= 24;
+       sce->r.imtype= R_PNG;
        sce->r.quality= 90;
+       sce->r.displaymode= R_OUTPUT_AREA;
        sce->r.framapto= 100;
        sce->r.images= 100;
        sce->r.framelen= 1.0;
-       sce->r.frs_sec= 25;
+       sce->r.blurfac= 0.5;
+       sce->r.frs_sec= 24;
        sce->r.frs_sec_base= 1;
+       sce->r.edgeint= 10;
        sce->r.ocres = 128;
        sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT;
+       sce->r.gauss= 1.0;
+       
+       /* deprecated but keep for upwards compat */
+       sce->r.postgamma= 1.0;
+       sce->r.posthue= 0.0;
+       sce->r.postsat= 1.0;
        
        sce->r.bake_mode= 1;    /* prevent to include render stuff here */
-       sce->r.bake_filter= 8;
+       sce->r.bake_filter= 2;
        sce->r.bake_osa= 5;
        sce->r.bake_flag= R_BAKE_CLEAR;
        sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT;
-
        sce->r.scemode= R_DOCOMP|R_DOSEQ|R_EXTENSION;
-       sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_SCENE|R_STAMP_CAMERA|R_STAMP_RENDERTIME;
+       sce->r.stamp= R_STAMP_TIME|R_STAMP_FRAME|R_STAMP_DATE|R_STAMP_CAMERA|R_STAMP_SCENE|R_STAMP_FILENAME|R_STAMP_RENDERTIME;
        sce->r.stamp_font_id= 12;
+       sce->r.fg_stamp[0]= sce->r.fg_stamp[1]= sce->r.fg_stamp[2]= 0.8f;
+       sce->r.fg_stamp[3]= 1.0f;
+       sce->r.bg_stamp[0]= sce->r.bg_stamp[1]= sce->r.bg_stamp[2]= 0.0f;
+       sce->r.bg_stamp[3]= 0.25f;
+       sce->r.raytrace_options = R_RAYTRACE_USE_INSTANCES;
 
        sce->r.seq_prev_type= OB_SOLID;
        sce->r.seq_rend_type= OB_SOLID;
@@ -388,6 +421,7 @@ Scene *add_scene(char *name)
        sce->toolsettings->jointrilimit = 0.8f;
 
        sce->toolsettings->selectmode= SCE_SELECT_VERTEX;
+       sce->toolsettings->uv_selectmode= UV_SELECT_VERTEX;
        sce->toolsettings->normalsize= 0.1;
        sce->toolsettings->autokey_mode= U.autokey_mode;
 
@@ -431,16 +465,20 @@ Scene *add_scene(char *name)
                pset->brush[a].count= 10;
        }
        pset->brush[PE_BRUSH_CUT].strength= 100;
-       
-       sce->jumpframe = 10;
+
        sce->r.ffcodecdata.audio_mixrate = 44100;
+       sce->r.ffcodecdata.audio_volume = 1.0f;
+       sce->r.ffcodecdata.audio_bitrate = 192;
+       sce->r.ffcodecdata.audio_channels = 2;
 
-       sce->audio.distance_model = 2.0;
-       sce->audio.doppler_factor = 1.0;
-       sce->audio.speed_of_sound = 343.3;
+       BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine));
 
-       strcpy(sce->r.backbuf, "//backbuf");
-       strcpy(sce->r.pic, U.renderdir);
+       sce->audio.distance_model = 2.0f;
+       sce->audio.doppler_factor = 1.0f;
+       sce->audio.speed_of_sound = 343.3f;
+       sce->audio.volume = 1.0f;
+
+       BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic));
 
        BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
        sce->r.osa= 8;
@@ -459,8 +497,8 @@ Scene *add_scene(char *name)
        sce->gm.dome.resbuf = 1.0f;
        sce->gm.dome.tilt = 0;
 
-       sce->gm.xplay= 800;
-       sce->gm.yplay= 600;
+       sce->gm.xplay= 640;
+       sce->gm.yplay= 480;
        sce->gm.freqplay= 60;
        sce->gm.depth= 32;
 
@@ -493,7 +531,7 @@ Base *object_in_scene(Object *ob, Scene *sce)
        return NULL;
 }
 
-void set_scene_bg(Scene *scene)
+void set_scene_bg(Main *bmain, Scene *scene)
 {
        Scene *sce;
        Base *base;
@@ -503,14 +541,18 @@ void set_scene_bg(Scene *scene)
        int flag;
        
        /* check for cyclic sets, for reading old files but also for definite security (py?) */
-       scene_check_setscene(scene);
+       scene_check_setscene(bmain, scene);
        
+       /* can happen when switching modes in other scenes */
+       if(scene->obedit && !(scene->obedit->mode & OB_MODE_EDIT))
+               scene->obedit= NULL;
+
        /* deselect objects (for dataselect) */
-       for(ob= G.main->object.first; ob; ob= ob->id.next)
+       for(ob= bmain->object.first; ob; ob= ob->id.next)
                ob->flag &= ~(SELECT|OB_FROMGROUP);
 
        /* group flags again */
-       for(group= G.main->group.first; group; group= group->id.next) {
+       for(group= bmain->group.first; group; group= group->id.next) {
                go= group->gobject.first;
                while(go) {
                        if(go->ob) go->ob->flag |= OB_FROMGROUP;
@@ -519,12 +561,12 @@ void set_scene_bg(Scene *scene)
        }
 
        /* sort baselist */
-       DAG_scene_sort(scene);
+       DAG_scene_sort(bmain, scene);
        
        /* ensure dags are built for sets */
        for(sce= scene->set; sce; sce= sce->set)
                if(sce->theDag==NULL)
-                       DAG_scene_sort(sce);
+                       DAG_scene_sort(bmain, sce);
 
        /* copy layers and flags from bases to objects */
        for(base= scene->base.first; base; base= base->next) {
@@ -546,18 +588,17 @@ void set_scene_bg(Scene *scene)
 }
 
 /* called from creator.c */
-void set_scene_name(char *name)
+Scene *set_scene_name(Main *bmain, const char *name)
 {
-       Scene *sce;
-
-       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
-               if (BLI_streq(name, sce->id.name+2)) {
-                       set_scene_bg(sce);
-                       return;
-               }
+       Scene *sce= (Scene *)find_id("SC", name);
+       if(sce) {
+               set_scene_bg(bmain, sce);
+               printf("Scene switch: '%s' in file: '%s'\n", name, G.main->name);
+               return sce;
        }
-       
-       //XXX error("Can't find scene: %s", name);
+
+       printf("Can't find scene: '%s' in file: '%s'\n", name, G.main->name);
+       return NULL;
 }
 
 void unlink_scene(Main *bmain, Scene *sce, Scene *newsce)
@@ -571,7 +612,7 @@ void unlink_scene(Main *bmain, Scene *sce, Scene *newsce)
                        sce1->set= NULL;
        
        /* check all sequences */
-       clear_scene_in_allseqs(sce);
+       clear_scene_in_allseqs(bmain, sce);
 
        /* check render layer nodes in other scenes */
        clear_scene_in_nodes(bmain, sce);
@@ -587,7 +628,7 @@ void unlink_scene(Main *bmain, Scene *sce, Scene *newsce)
 /* used by metaballs
  * doesnt return the original duplicated object, only dupli's
  */
-int next_object(Scene *scene, int val, Base **base, Object **ob)
+int next_object(Scene **scene, int val, Base **base, Object **ob)
 {
        static ListBase *duplilist= NULL;
        static DupliObject *dupob;
@@ -616,17 +657,21 @@ int next_object(Scene *scene, int val, Base **base, Object **ob)
 
                        /* the first base */
                        if(fase==F_START) {
-                               *base= scene->base.first;
+                               *base= (*scene)->base.first;
                                if(*base) {
                                        *ob= (*base)->object;
                                        fase= F_SCENE;
                                }
                                else {
                                        /* exception: empty scene */
-                                       if(scene->set && scene->set->base.first) {
-                                               *base= scene->set->base.first;
-                                               *ob= (*base)->object;
-                                               fase= F_SET;
+                                       while((*scene)->set) {
+                                               (*scene)= (*scene)->set;
+                                               if((*scene)->base.first) {
+                                                       *base= (*scene)->base.first;
+                                                       *ob= (*base)->object;
+                                                       fase= F_SCENE;
+                                                       break;
+                                               }
                                        }
                                }
                        }
@@ -636,11 +681,14 @@ int next_object(Scene *scene, int val, Base **base, Object **ob)
                                        if(*base) *ob= (*base)->object;
                                        else {
                                                if(fase==F_SCENE) {
-                                                       /* scene is finished, now do the set */
-                                                       if(scene->set && scene->set->base.first) {
-                                                               *base= scene->set->base.first;
-                                                               *ob= (*base)->object;
-                                                               fase= F_SET;
+                                                       /* (*scene) is finished, now do the set */
+                                                       while((*scene)->set) {
+                                                               (*scene)= (*scene)->set;
+                                                               if((*scene)->base.first) {
+                                                                       *base= (*scene)->base.first;
+                                                                       *ob= (*base)->object;
+                                                                       break;
+                                                               }
                                                        }
                                                }
                                        }
@@ -655,7 +703,7 @@ int next_object(Scene *scene, int val, Base **base, Object **ob)
                                                this enters eternal loop because of 
                                                makeDispListMBall getting called inside of group_duplilist */
                                                if((*base)->object->dup_group == NULL) {
-                                                       duplilist= object_duplilist(scene, (*base)->object);
+                                                       duplilist= object_duplilist((*scene), (*base)->object);
                                                        
                                                        dupob= duplilist->first;
 
@@ -691,6 +739,10 @@ int next_object(Scene *scene, int val, Base **base, Object **ob)
                }
        }
        
+       /* if(ob && *ob) {
+               printf("Scene: '%s', '%s'\n", (*scene)->id.name+2, (*ob)->id.name+2);
+       } */
+
        /* reset recursion test */
        in_next_object= 0;
        
@@ -782,39 +834,6 @@ char *scene_find_last_marker_name(Scene *scene, int frame)
        return best_marker ? best_marker->name : NULL;
 }
 
-/* markers need transforming from different parts of the code so have
- * a generic function to do this */
-int scene_marker_tfm_translate(Scene *scene, int delta, int flag)
-{
-       TimeMarker *marker;
-       int tot= 0;
-
-       for (marker= scene->markers.first; marker; marker= marker->next) {
-               if ((marker->flag & flag) == flag) {
-                       marker->frame += delta;
-                       tot++;
-               }
-       }
-
-       return tot;
-}
-
-int scene_marker_tfm_extend(Scene *scene, int delta, int flag, int frame, char side)
-{
-       TimeMarker *marker;
-       int tot= 0;
-
-       for (marker= scene->markers.first; marker; marker= marker->next) {
-               if ((marker->flag & flag) == flag) {
-                       if((side=='L' && marker->frame < frame) || (side=='R' && marker->frame >= frame)) {
-                               marker->frame += delta;
-                               tot++;
-                       }
-               }
-       }
-
-       return tot;
-}
 
 Base *scene_add_base(Scene *sce, Object *ob)
 {
@@ -849,7 +868,7 @@ void scene_select_base(Scene *sce, Base *selbase)
 }
 
 /* checks for cycle, returns 1 if it's all OK */
-int scene_check_setscene(Scene *sce)
+int scene_check_setscene(Main *bmain, Scene *sce)
 {
        Scene *scene;
        int a, totscene;
@@ -857,7 +876,7 @@ int scene_check_setscene(Scene *sce)
        if(sce->set==NULL) return 1;
        
        totscene= 0;
-       for(scene= G.main->scene.first; scene; scene= scene->id.next)
+       for(scene= bmain->scene.first; scene; scene= scene->id.next)
                totscene++;
        
        for(a=0, scene=sce; scene->set; scene=scene->set, a++) {
@@ -872,96 +891,134 @@ int scene_check_setscene(Scene *sce)
        return 1;
 }
 
-/* This (evil) function is needed to cope with two legacy Blender rendering features
-* mblur (motion blur that renders 'subframes' and blurs them together), and fields 
-* rendering. Thus, the use of ugly globals from object.c
-*/
-// BAD... EVIL... JUJU...!!!!
-// XXX moved here temporarily
-float frame_to_float (Scene *scene, int cfra)          /* see also bsystem_time in object.c */
+/* This function is needed to cope with fractional frames - including two Blender rendering features
+* mblur (motion blur that renders 'subframes' and blurs them together), and fields rendering. */
+
+/* see also bsystem_time in object.c */
+float BKE_curframe(Scene *scene)
+{
+       float ctime = scene->r.cfra;
+       ctime+= scene->r.subframe;
+       ctime*= scene->r.framelen;      
+
+       return ctime;
+}
+
+/* drivers support/hacks 
+ *     - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
+ *     - these are always run since the depsgraph can't handle non-object data
+ *     - these happen after objects are all done so that we can read in their final transform values,
+ *       though this means that objects can't refer to scene info for guidance...
+ */
+static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
 {
-       extern float bluroffs;  /* bad stuff borrowed from object.c */
-       extern float fieldoffs;
-       float ctime;
+       float ctime = BKE_curframe(scene);
        
-       ctime= (float)cfra;
-       ctime+= bluroffs+fieldoffs;
-       ctime*= scene->r.framelen;
+       /* scene itself */
+       if (scene->adt && scene->adt->drivers.first) {
+               BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
+       }
        
-       return ctime;
+       /* world */
+       // TODO: what about world textures? but then those have nodes too...
+       if (scene->world) {
+               ID *wid = (ID *)scene->world;
+               AnimData *adt= BKE_animdata_from_id(wid);
+               
+               if (adt && adt->drivers.first)
+                       BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
+       }
+       
+       /* nodes */
+       if (scene->nodetree) {
+               ID *nid = (ID *)scene->nodetree;
+               AnimData *adt= BKE_animdata_from_id(nid);
+               
+               if (adt && adt->drivers.first)
+                       BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
+       }
 }
 
-static void scene_update_newframe(Scene *sce, unsigned int lay)
+static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
 {
        Base *base;
-       Object *ob;
        
-       for(base= sce->base.first; base; base= base->next) {
-               ob= base->object;
+       
+       scene->customdata_mask= scene_parent->customdata_mask;
+
+       /* sets first, we allow per definition current scene to have
+          dependencies on sets, but not the other way around. */
+       if (scene->set)
+               scene_update_tagged_recursive(bmain, scene->set, scene_parent);
+       
+       /* scene objects */
+       for (base= scene->base.first; base; base= base->next) {
+               Object *ob= base->object;
                
-               object_handle_update(sce, ob);   // bke_object.h
+               object_handle_update(scene_parent, ob);
                
-               /* only update layer when an ipo */
-                       // XXX old animation system
-               //if(ob->ipo && has_ipo_code(ob->ipo, OB_LAY) ) {
-               //      base->lay= ob->lay;
-               //}
+               if(ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
+                       group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
+                       
+               /* always update layer, so that animating layers works */
+               base->lay= ob->lay;
        }
+       
+       /* scene drivers... */
+       scene_update_drivers(bmain, scene);
+
+       /* update sound system animation */
+       sound_update_scene(bmain, scene);
 }
 
 /* this is called in main loop, doing tagged updates before redraw */
-void scene_update_tagged(Scene *scene)
+void scene_update_tagged(Main *bmain, Scene *scene)
 {
-       Scene *sce;
-       Base *base;
-       float ctime = frame_to_float(scene, scene->r.cfra); 
+       DAG_ids_flush_tagged(bmain);
+
+       scene->physics_settings.quick_cache_step= 0;
 
        /* update all objects: drivers, matrices, displists, etc. flags set
           by depgraph or manual, no layer check here, gets correct flushed */
 
-       /* sets first, we allow per definition current scene to have
-          dependencies on sets, but not the other way around. */
-       if(scene->set) {
-               for(SETLOOPER(scene->set, base))
-                       object_handle_update(scene, base->object);
-       }
-       
-       for(base= scene->base.first; base; base= base->next) {
-               object_handle_update(scene, base->object);
-       }
+       scene_update_tagged_recursive(bmain, scene, scene);
 
        /* recalc scene animation data here (for sequencer) */
        {
                AnimData *adt= BKE_animdata_from_id(&scene->id);
-
-               if(adt && (adt->recalc & ADT_RECALC_ANIM))
-                       BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, 0);
+               float ctime = BKE_curframe(scene);
+               
+               if (adt && (adt->recalc & ADT_RECALC_ANIM))
+                       BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
        }
-
-       BKE_ptcache_quick_cache_all(scene);
+       
+       if (scene->physics_settings.quick_cache_step)
+               BKE_ptcache_quick_cache_all(bmain, scene);
 
        /* in the future this should handle updates for all datablocks, not
           only objects and scenes. - brecht */
 }
 
 /* applies changes right away, does all sets too */
-void scene_update_for_newframe(Scene *sce, unsigned int lay)
+void scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
 {
-       float ctime = frame_to_float(sce, sce->r.cfra);
+       float ctime = BKE_curframe(sce);
        Scene *sce_iter;
+
+       sound_set_cfra(sce->r.cfra);
        
        /* clear animation overrides */
        // XXX TODO...
 
        for(sce_iter= sce; sce_iter; sce_iter= sce_iter->set) {
                if(sce_iter->theDag==NULL)
-                       DAG_scene_sort(sce_iter);
+                       DAG_scene_sort(bmain, sce_iter);
        }
 
 
        /* Following 2 functions are recursive
-        * so dont call within 'scene_update_newframe' */
-       DAG_scene_update_flags(sce, lay);   // only stuff that moves or needs display still
+        * so dont call within 'scene_update_tagged_recursive' */
+       DAG_scene_update_flags(bmain, sce, lay, TRUE);   // only stuff that moves or needs display still
 
        /* All 'standard' (i.e. without any dependencies) animation is handled here,
         * with an 'local' to 'macro' order of evaluation. This should ensure that
@@ -969,15 +1026,11 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay)
         * can be overridden by settings from Scene, which owns the Texture through a hierarchy
         * such as Scene->World->MTex/Texture) can still get correctly overridden.
         */
-       BKE_animsys_evaluate_all_animation(G.main, ctime);
+       BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
        /*...done with recusrive funcs */
 
-
-       /* sets first, we allow per definition current scene to have dependencies on sets */
-       for(sce_iter= sce->set; sce_iter; sce_iter= sce_iter->set)
-               scene_update_newframe(sce_iter, lay);
-
-       scene_update_newframe(sce, lay);
+       /* object_handle_update() on all objects, groups and sets */
+       scene_update_tagged_recursive(bmain, sce, sce);
 }
 
 /* return default layer, also used to patch old files */
@@ -1031,3 +1084,26 @@ float get_render_aosss_error(RenderData *r, float error)
                return error;
 }
 
+/* helper function for the SETLOOPER macro */
+Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+{
+       if(base && base->next) {
+               /* common case, step to the next */
+               return base->next;
+       }
+       else if(base==NULL && (*sce_iter)->base.first) {
+               /* first time looping, return the scenes first base */
+               return (Base *)(*sce_iter)->base.first;
+       }
+       else {
+               /* reached the end, get the next base in the set */
+               while((*sce_iter= (*sce_iter)->set)) {
+                       base= (Base *)(*sce_iter)->base.first;
+                       if(base) {
+                               return base;
+                       }
+               }
+       }
+
+       return NULL;
+}