Timeline addition: Display cached frames
authorMatt Ebb <matt@mke3.net>
Tue, 22 Jun 2010 02:29:52 +0000 (02:29 +0000)
committerMatt Ebb <matt@mke3.net>
Tue, 22 Jun 2010 02:29:52 +0000 (02:29 +0000)
This started off doing pointcache debugging but it's also very useful for users too.
Previously it was very hard to see the state of the system when you're working caches
such as physics point cache - is it baked? which frames are cached? is it out of date?

Now, for better feedback, cached frames are drawn for the active object at the bottom
of the timeline - a semitransparent area shows the entire cache extents, and more
solid blocks on top show the frames that are cached. Darker versions indicate it's
using a disk cache.

It can be disabled in general in the timeline View -> Caches menu, or by each individual
system that can be shown.

There's still a bit to do on this, behaviour needs to be clarified still eg. deciding what
shows when it's out of date, or when it's been played back but not cached, etc. etc.
Part of this is due to a lack of definition in the point cache system itself, so we should
try and clean up/clarify this behaviour and what it means to users, at the same time.

Also would be interested in extending this to other caches such as fluid cache,
sequencer memory cache etc. in the future, too.

12 files changed:
release/scripts/ui/space_time.py
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_screen_types.h
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_pointcache.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_time/space_time.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_space.c
source/blender/windowmanager/WM_types.h

index 00bdcf7..9469a72 100644 (file)
@@ -98,10 +98,32 @@ class TIME_MT_view(bpy.types.Menu):
         layout.prop(st, "show_cframe_indicator")
         layout.prop(st, "only_selected")
 
+        layout.separator()
+        
+        layout.menu("TIME_MT_cache")
+        
         layout.separator()
 
         layout.operator("marker.camera_bind")
+        
+class TIME_MT_cache(bpy.types.Menu):
+    bl_label = "Cache"
+
+    def draw(self, context):
+        layout = self.layout
+
+        st = context.space_data
+
+        layout.prop(st, "show_cache")
+
+        layout.separator()
 
+        col = layout.column()
+        col.enabled = st.show_cache
+        col.prop(st, "cache_softbody")
+        col.prop(st, "cache_particles")
+        col.prop(st, "cache_cloth")
+        col.prop(st, "cache_smoke")
 
 class TIME_MT_frame(bpy.types.Menu):
     bl_label = "Frame"
@@ -171,6 +193,7 @@ class TIME_MT_autokey(bpy.types.Menu):
 classes = [
     TIME_HT_header,
     TIME_MT_view,
+    TIME_MT_cache,
     TIME_MT_frame,
     TIME_MT_autokey,
     TIME_MT_playback]
index cff9397..718ccf9 100644 (file)
@@ -10857,14 +10857,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                SpaceLink *sl;
                                for (sl= sa->spacedata.first; sl; sl= sl->next) {
                                        if (sl->spacetype == SPACE_NODE) {
-                                               SpaceNode *snode;
-
-                                               snode= (SpaceNode *)sl;
+                                               SpaceNode *snode= (SpaceNode *)sl;
+                                               
                                                if (snode->v2d.minzoom > 0.09f)
                                                        snode->v2d.minzoom= 0.09f;
                                                if (snode->v2d.maxzoom < 2.31f)
                                                        snode->v2d.maxzoom= 2.31f;
                                        }
+                                       else if (sl->spacetype == SPACE_TIME) {
+                                               SpaceTime *stime= (SpaceTime *)sl;
+                                               
+                                               /* enable all cache display */
+                                               stime->cache_display |= TIME_CACHE_DISPLAY;
+                                               stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES);
+                                               stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE);
+                                       }
                                }
                        }
                }
index 4a4c546..21a8fa7 100644 (file)
@@ -97,8 +97,8 @@ void  ED_screen_set_scene(struct bContext *C, struct Scene *scene);
 void   ED_screen_delete_scene(struct bContext *C, struct Scene *scene);
 void   ED_screen_set_subwinactive(struct wmWindow *win, struct wmEvent *event);
 void   ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
-void   ED_screen_animation_timer(struct bContext *C, int redraws, int sync, int enable);
-void   ED_screen_animation_timer_update(struct bScreen *screen, int redraws);
+void   ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
+void   ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
 int            ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
 void   ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
 void   ED_screen_full_restore(struct bContext *C, ScrArea *sa);
index 03ea9a8..c55dafa 100644 (file)
@@ -35,6 +35,7 @@
 typedef struct ScreenAnimData {
        ARegion *ar;            /* do not read from this, only for comparing if region exists */
        short redraws;
+       short refresh;
        short flag;                     /* flags for playback */
        int sfra;                       /* frame that playback was started from */
 } ScreenAnimData;
index d8ca65f..059805f 100644 (file)
@@ -69,7 +69,9 @@ static int particle_system_add_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
 
        object_add_particle_system(scene, ob, NULL);
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -107,7 +109,8 @@ static int particle_system_remove_exec(bContext *C, wmOperator *op)
                        if(scene->basact && scene->basact->object==ob)
                                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -166,7 +169,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *op)
        DAG_scene_sort(scene);
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -214,7 +217,7 @@ static int new_particle_target_exec(bContext *C, wmOperator *op)
        DAG_scene_sort(scene);
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -262,7 +265,7 @@ static int remove_particle_target_exec(bContext *C, wmOperator *op)
        DAG_scene_sort(scene);
        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
        
        return OPERATOR_FINISHED;
 }
@@ -300,7 +303,7 @@ static int target_move_up_exec(bContext *C, wmOperator *op)
                        BLI_insertlink(&psys->targets, pt->prev->prev, pt);
 
                        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
-                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
                        break;
                }
        }
@@ -338,7 +341,7 @@ static int target_move_down_exec(bContext *C, wmOperator *op)
                        BLI_insertlink(&psys->targets, pt->next, pt);
 
                        DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
-                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
                        break;
                }
        }
@@ -376,7 +379,7 @@ static int dupliob_move_up_exec(bContext *C, wmOperator *op)
                        BLI_remlink(&part->dupliweights, dw);
                        BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
 
-                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
                        break;
                }
        }
@@ -415,7 +418,7 @@ static int copy_particle_dupliob_exec(bContext *C, wmOperator *op)
                        dw->flag |= PART_DUPLIW_CURRENT;
                        BLI_addhead(&part->dupliweights, dw);
 
-                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
                        break;
                }
        }
@@ -461,7 +464,7 @@ static int remove_particle_dupliob_exec(bContext *C, wmOperator *op)
        if(dw)
                dw->flag |= PART_DUPLIW_CURRENT;
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
        
        return OPERATOR_FINISHED;
 }
@@ -498,7 +501,7 @@ static int dupliob_move_down_exec(bContext *C, wmOperator *op)
                        BLI_remlink(&part->dupliweights, dw);
                        BLI_insertlink(&part->dupliweights, dw->next, dw);
 
-                       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
+                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
                        break;
                }
        }
@@ -590,7 +593,7 @@ static int disconnect_hair_exec(bContext *C, wmOperator *op)
                disconnect_hair(scene, ob, psys);
        }
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
 
        return OPERATOR_FINISHED;
 }
@@ -729,7 +732,7 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
                connect_hair(scene, ob, psys);
        }
 
-       WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
 
        return OPERATOR_FINISHED;
 }
index 5ebbb00..8e53e3c 100644 (file)
@@ -115,6 +115,7 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
        BKE_ptcache_make_cache(&baker);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -133,6 +134,8 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
                }
                
                BLI_freelistN(&pidlist);
+               
+               WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
        }
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
@@ -211,6 +214,7 @@ static int ptcache_bake_exec(bContext *C, wmOperator *op)
        BLI_freelistN(&pidlist);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
 
        return OPERATOR_FINISHED;
 }
@@ -218,6 +222,7 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *op)
 {
        PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
        PointCache *cache= ptr.data;
+       Object *ob= ptr.id.data;
 
        if(cache->edit) {
                if(!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
@@ -228,6 +233,8 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *op)
        }
        else
                cache->flag &= ~PTCACHE_BAKED;
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
 
        return OPERATOR_FINISHED;
 }
@@ -235,8 +242,11 @@ static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *op)
 {
        PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
        PointCache *cache= ptr.data;
+       Object *ob= ptr.id.data;
        
        cache->flag |= PTCACHE_BAKED;
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
 
        return OPERATOR_FINISHED;
 }
@@ -303,6 +313,7 @@ static int ptcache_add_new_exec(bContext *C, wmOperator *op)
        BLI_freelistN(&pidlist);
 
        WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
 
        return OPERATOR_FINISHED;
 }
@@ -331,6 +342,8 @@ static int ptcache_remove_exec(bContext *C, wmOperator *op)
        }
 
        BLI_freelistN(&pidlist);
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
 
        return OPERATOR_FINISHED;
 }
index 4a0a79b..ced8f9a 100644 (file)
@@ -1651,7 +1651,7 @@ void ED_refresh_viewport_fps(bContext *C)
 /* redraws: uses defines from stime->redraws 
  * enable: 1 - forward on, -1 - backwards on, 0 - off
  */
-void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
+void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable)
 {
        bScreen *screen= CTX_wm_screen(C);
        wmWindowManager *wm= CTX_wm_manager(C);
@@ -1669,6 +1669,7 @@ void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable)
                sad->ar= CTX_wm_region(C);
                sad->sfra = scene->r.cfra;
                sad->redraws= redraws;
+               sad->refresh= refresh;
                sad->flag |= (enable < 0)? ANIMPLAY_FLAG_REVERSE: 0;
                sad->flag |= (sync == 0)? ANIMPLAY_FLAG_NO_SYNC: (sync == 1)? ANIMPLAY_FLAG_SYNC: 0;
                screen->animtimer->customdata= sad;
@@ -1702,13 +1703,14 @@ static ARegion *time_top_left_3dwindow(bScreen *screen)
        return aret;
 }
 
-void ED_screen_animation_timer_update(bScreen *screen, int redraws)
+void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh)
 {
        if(screen && screen->animtimer) {
                wmTimer *wt= screen->animtimer;
                ScreenAnimData *sad= wt->customdata;
                
                sad->redraws= redraws;
+               sad->refresh= refresh;
                sad->ar= NULL;
                if(redraws & TIME_REGION)
                        sad->ar= time_top_left_3dwindow(screen);
index 4d644ce..515b06f 100644 (file)
@@ -2359,6 +2359,18 @@ void SCREEN_OT_header_toolbox(wmOperatorType *ot)
 
 /* ****************** anim player, with timer ***************** */
 
+static int match_area_with_refresh(int spacetype, int refresh)
+{
+       switch (spacetype) {
+               case SPACE_TIME:
+                       if (refresh & SPACE_TIME)
+                               return 1;
+                       break;
+       }
+       
+       return 0;
+}
+
 static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
 {
        if(regiontype==RGN_TYPE_WINDOW) {
@@ -2505,6 +2517,9 @@ static int screen_animation_step(bContext *C, wmOperator *op, wmEvent *event)
                                        if(match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws))
                                                ED_region_tag_redraw(ar);
                        }
+                       
+                       if (match_area_with_refresh(sa->spacetype, sad->refresh))
+                               ED_area_tag_refresh(sa);
                }
                
                /* update frame rate info too 
@@ -2548,11 +2563,12 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
 
        if(screen->animtimer) {
                /* stop playback now */
-               ED_screen_animation_timer(C, 0, 0, 0);
+               ED_screen_animation_timer(C, 0, 0, 0, 0);
                sound_stop_scene(scene);
        }
        else {
                ScrArea *sa= CTX_wm_area(C);
+               int refresh= SPACE_TIME;
 
                if(mode == 1) // XXX only play audio forwards!?
                        sound_play_scene(scene);
@@ -2561,10 +2577,10 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
                if ((sa) && (sa->spacetype == SPACE_TIME)) {
                        SpaceTime *stime= (SpaceTime *)sa->spacedata.first;
 
-                       ED_screen_animation_timer(C, stime->redraws, sync, mode);
+                       ED_screen_animation_timer(C, stime->redraws, refresh, sync, mode);
 
                        /* update region if TIME_REGION was set, to leftmost 3d window */
-                       ED_screen_animation_timer_update(screen, stime->redraws);
+                       ED_screen_animation_timer_update(screen, stime->redraws, refresh);
                }
                else {
                        int redraws = TIME_REGION|TIME_ALL_3D_WIN;
@@ -2574,7 +2590,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
                                redraws |= TIME_SEQ;
                        }
 
-                       ED_screen_animation_timer(C, redraws, sync, mode);
+                       ED_screen_animation_timer(C, redraws, refresh, sync, mode);
 
                        if(screen->animtimer) {
                                wmTimer *wt= screen->animtimer;
index 1460d08..245a60d 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -40,6 +41,7 @@
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_screen.h"
+#include "BKE_pointcache.h"
 #include "BKE_utildefines.h"
 
 #include "ED_anim_api.h"
@@ -84,6 +86,169 @@ static void time_draw_sfra_efra(const bContext *C, SpaceTime *stime, ARegion *ar
        fdrawline((float)PEFRA, v2d->cur.ymin, (float)PEFRA, v2d->cur.ymax);
 }
 
+#define CACHE_DRAW_HEIGHT      3.0f
+
+static void time_draw_cache(const bContext *C, SpaceTime *stime, ARegion *ar)
+{
+       SpaceTimeCache *stc;
+       float yoffs=0.f;
+       
+       if (!(stime->cache_display & TIME_CACHE_DISPLAY))
+               return;
+       
+       for (stc= stime->caches.first; stc; stc=stc->next) {
+               float col[4];
+               
+               if (!stc->array || !stc->ok)
+                       continue;
+               
+               glPushMatrix();
+               glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT+yoffs, 0.0);
+               glScalef(1.0, CACHE_DRAW_HEIGHT, 0.0);
+               
+               switch(stc->type) {
+                       case PTCACHE_TYPE_SOFTBODY:
+                               col[0] = 1.0;   col[1] = 0.4;   col[2] = 0.02;
+                               col[3] = 0.1;
+                               break;
+                       case PTCACHE_TYPE_PARTICLES:
+                               col[0] = 1.0;   col[1] = 0.1;   col[2] = 0.02;
+                               col[3] = 0.1;
+                               break;
+                       case PTCACHE_TYPE_CLOTH:
+                               col[0] = 0.1;   col[1] = 0.1;   col[2] = 0.75;
+                               col[3] = 0.1;
+                               break;
+                       case PTCACHE_TYPE_SMOKE_DOMAIN:
+                       case PTCACHE_TYPE_SMOKE_HIGHRES:
+                               col[0] = 0.2;   col[1] = 0.2;   col[2] = 0.2;
+                               col[3] = 0.1;
+                               break;
+               }
+               glColor4fv(col);
+               
+               glEnable(GL_BLEND);
+               
+               glRectf((float)stc->startframe, 0.0, (float)stc->endframe, 1.0);
+               
+               col[3] = 0.4;
+               if (stc->flag & PTCACHE_BAKED) {
+                       col[0] -= 0.4;  col[1] -= 0.4;  col[2] -= 0.4;
+               }
+               glColor4fv(col);
+               
+               glEnableClientState(GL_VERTEX_ARRAY);
+               glVertexPointer(2, GL_FLOAT, 0, stc->array);
+               glDrawArrays(GL_QUADS, 0, stc->len);
+               glDisableClientState(GL_VERTEX_ARRAY);
+               
+               glDisable(GL_BLEND);
+               
+               glPopMatrix();
+               
+               yoffs += CACHE_DRAW_HEIGHT;
+       }
+}
+
+static void time_cache_free(SpaceTime *stime)
+{
+       SpaceTimeCache *stc;
+       
+       for (stc= stime->caches.first; stc; stc=stc->next) {
+               if (stc->array) {
+                       MEM_freeN(stc->array);
+                       stc->array = NULL;
+               }
+       }
+       
+       BLI_freelistN(&stime->caches);
+}
+
+static void time_cache_refresh(const bContext *C, SpaceTime *stime, ARegion *ar)
+{
+       Object *ob = CTX_data_active_object(C);
+       PTCacheID *pid;
+       ListBase pidlist;
+       float *fp;
+       int i;
+       
+       time_cache_free(stime);
+       
+       if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob))
+               return;
+       
+       BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+       
+       /* iterate over pointcaches on the active object, 
+        * add spacetimecache and vertex array for each */
+       for(pid=pidlist.first; pid; pid=pid->next) {
+               SpaceTimeCache *stc;
+               
+               switch(pid->type) {
+                       case PTCACHE_TYPE_SOFTBODY:
+                               if (!(stime->cache_display & TIME_CACHE_SOFTBODY)) continue;
+                               break;
+                       case PTCACHE_TYPE_PARTICLES:
+                               if (!(stime->cache_display & TIME_CACHE_PARTICLES))     continue;
+                               break;
+                       case PTCACHE_TYPE_CLOTH:
+                               if (!(stime->cache_display & TIME_CACHE_CLOTH)) continue;
+                               break;
+                       case PTCACHE_TYPE_SMOKE_DOMAIN:
+                       case PTCACHE_TYPE_SMOKE_HIGHRES:
+                               if (!(stime->cache_display & TIME_CACHE_SMOKE)) continue;
+                               break;
+               }
+               
+               stc= MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache");
+               
+               stc->type = pid->type;
+               
+               if (pid->cache->flag & PTCACHE_BAKED)
+                       stc->flag |= PTCACHE_BAKED;
+               if (pid->cache->flag & PTCACHE_DISK_CACHE)
+                       stc->flag |= PTCACHE_DISK_CACHE;
+               
+               /* first allocate with maximum number of frames needed */
+               BKE_ptcache_id_time(pid, CTX_data_scene(C), 0, &stc->startframe, &stc->endframe, NULL);
+               stc->len = (stc->endframe - stc->startframe + 1)*4;
+               fp = stc->array = MEM_callocN(stc->len*2*sizeof(float), "SpaceTimeCache array");
+
+               /* fill the vertex array with a quad for each cached frame */
+               for (i=stc->startframe; i<=stc->endframe; i++) {
+                       if (BKE_ptcache_id_exist(pid, i)) {
+                               fp[0] = (float)i;
+                               fp[1] = 0.0;
+                               fp+=2;
+                               
+                               fp[0] = (float)i;
+                               fp[1] = 1.0;
+                               fp+=2;
+                               
+                               fp[0] = (float)(i+1);
+                               fp[1] = 1.0;
+                               fp+=2;
+                               
+                               fp[0] = (float)(i+1);
+                               fp[1] = 0.0;
+                               fp+=2;
+                       }
+               }
+               /* update with final number of frames */
+               stc->len = i*4;
+               stc->array = MEM_reallocN(stc->array, stc->len*2*sizeof(float));
+               
+               stc->ok = 1;
+               
+               BLI_addtail(&stime->caches, stc);
+       }
+       
+       /* todo: sort time->caches list for consistent order */
+       // ...
+       
+       BLI_freelistN(&pidlist);
+}
+
 /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
 static ActKeyColumn *time_cfra_find_ak (ActKeyColumn *ak, float cframe)
 {
@@ -206,6 +371,52 @@ static void time_draw_keyframes(const bContext *C, SpaceTime *stime, ARegion *ar
 
 /* ---------------- */
 
+static void time_refresh(const bContext *C, ScrArea *sa)
+{
+       SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
+       ARegion *ar;
+       
+       /* find the main timeline region and refresh cache display*/
+       for (ar= sa->regionbase.first; ar; ar= ar->next) {
+               if (ar->regiontype==RGN_TYPE_WINDOW) {
+                       time_cache_refresh(C, stime, ar);
+                       break;
+               }
+       }
+}
+
+/* editor level listener */
+static void time_listener(ScrArea *sa, wmNotifier *wmn)
+{
+
+       /* mainly for updating cache display */
+       switch (wmn->category) {
+               case NC_OBJECT:
+                       switch (wmn->data) {
+                               case ND_POINTCACHE:
+                                       ED_area_tag_refresh(sa);
+                                       ED_area_tag_redraw(sa);
+                                       break;
+                       }
+                       break;
+               case NC_SCENE:
+                       switch (wmn->data) {    
+                               case ND_OB_ACTIVE:
+                               case ND_FRAME:
+                                       ED_area_tag_refresh(sa);
+                                       break;
+                       }
+               case NC_SPACE:
+                       switch (wmn->data) {    
+                               case ND_SPACE_CHANGED:
+                                       ED_area_tag_refresh(sa);
+                                       break;
+                       }
+       }
+}
+
+/* ---------------- */
+
 /* add handlers, stuff you only do once or on area/region changes */
 static void time_main_area_init(wmWindowManager *wm, ARegion *ar)
 {
@@ -235,7 +446,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar)
 
        /* start and end frame */
        time_draw_sfra_efra(C, stime, ar);
-
+       
        /* grid */
        unit= (stime->flag & TIME_DRAWFRAMES)? V2D_UNIT_FRAMES: V2D_UNIT_SECONDS;
        grid= UI_view2d_grid_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY, ar->winx, ar->winy);
@@ -254,6 +465,9 @@ static void time_main_area_draw(const bContext *C, ARegion *ar)
        UI_view2d_view_orthoSpecial(C, v2d, 1);
        draw_markers_time(C, 0);
        
+       /* caches */
+       time_draw_cache(C, stime, ar);
+       
        /* reset view matrix */
        UI_view2d_view_restore(C);
        
@@ -277,7 +491,6 @@ static void time_main_area_listener(ARegion *ar, wmNotifier *wmn)
                        break;
                
                case NC_SCENE:
-                       /* any scene change for now */
                        ED_region_tag_redraw(ar);
                        break;
                
@@ -377,13 +590,23 @@ static SpaceLink *time_new(const bContext *C)
 /* not spacelink itself */
 static void time_free(SpaceLink *sl)
 {
+       SpaceTime *stime= (SpaceTime *)sl;
+       
+       time_cache_free(stime);
 }
 /* spacetype; init callback in ED_area_initialize() */
 /* init is called to (re)initialize an existing editor (file read, screen changes) */
 /* validate spacedata, add own area level handlers */
 static void time_init(wmWindowManager *wm, ScrArea *sa)
 {
+       SpaceTime *stime= (SpaceTime *)sa->spacedata.first;
        
+       time_cache_free(stime);
+       
+       /* enable all cache display */
+       stime->cache_display |= TIME_CACHE_DISPLAY;
+       stime->cache_display |= (TIME_CACHE_SOFTBODY|TIME_CACHE_PARTICLES);
+       stime->cache_display |= (TIME_CACHE_CLOTH|TIME_CACHE_SMOKE);
 }
 
 static SpaceLink *time_duplicate(SpaceLink *sl)
@@ -391,6 +614,8 @@ static SpaceLink *time_duplicate(SpaceLink *sl)
        SpaceTime *stime= (SpaceTime *)sl;
        SpaceTime *stimen= MEM_dupallocN(stime);
        
+       time_cache_free(stimen);
+       
        return (SpaceLink *)stimen;
 }
 
@@ -410,6 +635,8 @@ void ED_spacetype_time(void)
        st->duplicate= time_duplicate;
        st->operatortypes= time_operatortypes;
        st->keymap= NULL;
+       st->listener= time_listener;
+       st->refresh= time_refresh;
        
        /* regions: main window */
        art= MEM_callocN(sizeof(ARegionType), "spacetype time region");
index e59cad0..ba9d038 100644 (file)
@@ -346,6 +346,17 @@ typedef struct SpaceScript {
        void *but_refs;
 } SpaceScript;
 
+typedef struct SpaceTimeCache {
+       struct SpaceTimeCache *next, *prev;
+       int type;
+       int flag;
+       
+       float *array;
+       int len;
+       int startframe, endframe;
+       int ok;
+} SpaceTimeCache;
+
 typedef struct SpaceTime {
        SpaceLink *next, *prev;
        ListBase regionbase;            /* storage of regions for inactive spaces */
@@ -354,6 +365,9 @@ typedef struct SpaceTime {
        
        View2D v2d; /* deprecated, copied to region */
        
+       ListBase caches;
+       int cache_display, pad;
+       
        int flag, redraws;
        
 } SpaceTime;
@@ -860,6 +874,13 @@ enum {
 #define TIME_CONTINUE_PHYSICS  128
 #define TIME_NODES                             256
 
+/* time->cache */
+#define TIME_CACHE_DISPLAY             1
+#define TIME_CACHE_SOFTBODY            2
+#define TIME_CACHE_PARTICLES   4
+#define TIME_CACHE_CLOTH               8
+#define TIME_CACHE_SMOKE               16
+
 /* sseq->mainb */
 #define SEQ_DRAW_SEQUENCE         0
 #define SEQ_DRAW_IMG_IMBUF        1
index 774ae94..d5b3db1 100644 (file)
@@ -603,7 +603,7 @@ static void rna_SpaceTime_redraw_update(Main *bmain, Scene *scene, PointerRNA *p
        SpaceTime *st= (SpaceTime*)ptr->data;
        bScreen *screen= (bScreen*)ptr->id.data;
 
-       ED_screen_animation_timer_update(screen, st->redraws);
+       ED_screen_animation_timer_update(screen, st->redraws, SPACE_TIME);
 }
 
 /* Space Dopesheet */
@@ -1878,6 +1878,32 @@ static void rna_def_space_time(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", TIME_CFRA_NUM);
        RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line");
        RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
+       
+       /* displaying cache status */
+       prop= RNA_def_property(srna, "show_cache", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DISPLAY);
+       RNA_def_property_ui_text(prop, "Show Cache", "Show the status of cached frames in the timeline");       
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
+       
+       prop= RNA_def_property(srna, "cache_softbody", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SOFTBODY);
+       RNA_def_property_ui_text(prop, "Softbody", "Show the active object's softbody point cache");    
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
+       
+       prop= RNA_def_property(srna, "cache_particles", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_PARTICLES);
+       RNA_def_property_ui_text(prop, "Particles", "Show the active object's particle point cache");   
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
+       
+       prop= RNA_def_property(srna, "cache_cloth", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_CLOTH);
+       RNA_def_property_ui_text(prop, "Cloth", "Show the active object's cloth point cache");  
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
+       
+       prop= RNA_def_property(srna, "cache_smoke", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SMOKE);
+       RNA_def_property_ui_text(prop, "Smoke", "Show the active object's smoke cache");        
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_TIME, NULL);
 }
 
 static void rna_def_console_line(BlenderRNA *brna)
index 199b17b..067df17 100644 (file)
@@ -195,6 +195,7 @@ typedef struct wmNotifier {
 #define ND_KEYS                                (23<<16)
 #define ND_CONSTRAINT          (24<<16)
 #define ND_PARTICLE                    (25<<16)
+#define ND_POINTCACHE          (26<<16)
 
        /* NC_MATERIAL Material */
 #define        ND_SHADING                      (30<<16)