Blender  V2.59
physics_pointcache.c
Go to the documentation of this file.
00001 /*
00002  * $Id: physics_pointcache.c 36704 2011-05-15 17:59:48Z dingto $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2007 by Janne Karhu.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include <stdlib.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "BLI_blenlib.h"
00040 #include "BLI_utildefines.h"
00041 
00042 #include "DNA_scene_types.h"
00043 
00044 #include "BKE_context.h"
00045 #include "BKE_global.h"
00046 #include "BKE_main.h"
00047 #include "BKE_modifier.h"
00048 #include "BKE_particle.h"
00049 #include "BKE_pointcache.h"
00050 #include "BKE_report.h"
00051 #include "BKE_scene.h"
00052  
00053 
00054 #include "ED_particle.h"
00055 
00056 #include "WM_api.h"
00057 #include "WM_types.h"
00058 
00059 #include "RNA_access.h"
00060 #include "RNA_define.h"
00061 
00062 #include "physics_intern.h"
00063 
00064 static int cache_break_test(void *UNUSED(cbd)) {
00065         return G.afbreek==1;
00066 }
00067 static int ptcache_bake_all_poll(bContext *C)
00068 {
00069         Scene *scene= CTX_data_scene(C);
00070 
00071         if(!scene)
00072                 return 0;
00073         
00074         return 1;
00075 }
00076 
00077 static int ptcache_poll(bContext *C)
00078 {
00079         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00080         return (ptr.data && ptr.id.data);
00081 }
00082 
00083 static void bake_console_progress(void *UNUSED(arg), int nr)
00084 {
00085         printf("\rbake: %3i%%", nr);
00086         fflush(stdout);
00087 }
00088 
00089 static void bake_console_progress_end(void *UNUSED(arg))
00090 {
00091         printf("\rbake: done!\n");
00092 }
00093 
00094 static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
00095 {
00096         Main *bmain = CTX_data_main(C);
00097         Scene *scene= CTX_data_scene(C);
00098         wmWindow *win = G.background ? NULL : CTX_wm_window(C);
00099         PTCacheBaker baker;
00100 
00101         baker.main = bmain;
00102         baker.scene = scene;
00103         baker.pid = NULL;
00104         baker.bake = RNA_boolean_get(op->ptr, "bake");
00105         baker.render = 0;
00106         baker.anim_init = 0;
00107         baker.quick_step = 1;
00108         baker.break_test = cache_break_test;
00109         baker.break_data = NULL;
00110 
00111         /* Disabled for now as this doesn't work properly,
00112          * and pointcache baking will be reimplemented with
00113          * the job system soon anyways. */
00114         if (win) {
00115                 baker.progressbar = (void (*)(void *, int))WM_timecursor;
00116                 baker.progressend = (void (*)(void *))WM_cursor_restore;
00117                 baker.progresscontext = win;
00118         } else {
00119                 baker.progressbar = bake_console_progress;
00120                 baker.progressend = bake_console_progress_end;
00121                 baker.progresscontext = NULL;
00122         }
00123 
00124         BKE_ptcache_bake(&baker);
00125 
00126         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
00127         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, NULL);
00128 
00129         return OPERATOR_FINISHED;
00130 }
00131 static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
00132 {
00133         Scene *scene= CTX_data_scene(C);
00134         Base *base;
00135         PTCacheID *pid;
00136         ListBase pidlist;
00137 
00138         for(base=scene->base.first; base; base= base->next) {
00139                 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
00140 
00141                 for(pid=pidlist.first; pid; pid=pid->next) {
00142                         pid->cache->flag &= ~PTCACHE_BAKED;
00143                 }
00144                 
00145                 BLI_freelistN(&pidlist);
00146                 
00147                 WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
00148         }
00149 
00150         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
00151 
00152         return OPERATOR_FINISHED;
00153 }
00154 
00155 void PTCACHE_OT_bake_all(wmOperatorType *ot)
00156 {
00157         /* identifiers */
00158         ot->name= "Bake All Physics";
00159         ot->description= "Bake all physics";
00160         ot->idname= "PTCACHE_OT_bake_all";
00161         
00162         /* api callbacks */
00163         ot->exec= ptcache_bake_all_exec;
00164         ot->poll= ptcache_bake_all_poll;
00165 
00166         /* flags */
00167         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00168 
00169         RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
00170 }
00171 void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
00172 {
00173         /* identifiers */
00174         ot->name= "Free All Physics Bakes";
00175         ot->name= "Free all physics bakes";
00176         ot->idname= "PTCACHE_OT_free_bake_all";
00177         
00178         /* api callbacks */
00179         ot->exec= ptcache_free_bake_all_exec;
00180         ot->poll= ptcache_bake_all_poll;
00181 
00182         /* flags */
00183         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00184 }
00185 static int ptcache_bake_exec(bContext *C, wmOperator *op)
00186 {
00187         Main *bmain = CTX_data_main(C);
00188         Scene *scene = CTX_data_scene(C);
00189         wmWindow *win = G.background ? NULL : CTX_wm_window(C);
00190         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00191         Object *ob= ptr.id.data;
00192         PointCache *cache= ptr.data;
00193         PTCacheBaker baker;
00194         PTCacheID *pid;
00195         ListBase pidlist;
00196 
00197         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
00198         
00199         for(pid=pidlist.first; pid; pid=pid->next) {
00200                 if(pid->cache == cache)
00201                         break;
00202         }
00203 
00204         baker.main = bmain;
00205         baker.scene = scene;
00206         baker.pid = pid;
00207         baker.bake = RNA_boolean_get(op->ptr, "bake");
00208         baker.render = 0;
00209         baker.anim_init = 0;
00210         baker.quick_step = 1;
00211         baker.break_test = cache_break_test;
00212         baker.break_data = NULL;
00213 
00214         /* Disabled for now as this doesn't work properly,
00215          * and pointcache baking will be reimplemented with
00216          * the job system soon anyways. */
00217         if (win) {
00218                 baker.progressbar = (void (*)(void *, int))WM_timecursor;
00219                 baker.progressend = (void (*)(void *))WM_cursor_restore;
00220                 baker.progresscontext = win;
00221         } else {
00222                 printf("\n"); /* empty first line before console reports */
00223                 baker.progressbar = bake_console_progress;
00224                 baker.progressend = bake_console_progress_end;
00225                 baker.progresscontext = NULL;
00226         }
00227 
00228         BKE_ptcache_bake(&baker);
00229 
00230         BLI_freelistN(&pidlist);
00231 
00232         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
00233         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00234 
00235         return OPERATOR_FINISHED;
00236 }
00237 static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
00238 {
00239         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00240         PointCache *cache= ptr.data;
00241         Object *ob= ptr.id.data;
00242 
00243         if(cache->edit) {
00244                 if(!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
00245                         PE_free_ptcache_edit(cache->edit);
00246                         cache->edit = NULL;
00247                         cache->flag &= ~PTCACHE_BAKED;
00248                 }
00249         }
00250         else
00251                 cache->flag &= ~PTCACHE_BAKED;
00252         
00253         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00254 
00255         return OPERATOR_FINISHED;
00256 }
00257 static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
00258 {
00259         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00260         PointCache *cache= ptr.data;
00261         Object *ob= ptr.id.data;
00262         
00263         cache->flag |= PTCACHE_BAKED;
00264         
00265         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00266 
00267         return OPERATOR_FINISHED;
00268 }
00269 void PTCACHE_OT_bake(wmOperatorType *ot)
00270 {
00271         /* identifiers */
00272         ot->name= "Bake Physics";
00273         ot->description= "Bake physics";
00274         ot->idname= "PTCACHE_OT_bake";
00275         
00276         /* api callbacks */
00277         ot->exec= ptcache_bake_exec;
00278         ot->poll= ptcache_poll;
00279 
00280         /* flags */
00281         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00282 
00283         RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
00284 }
00285 void PTCACHE_OT_free_bake(wmOperatorType *ot)
00286 {
00287         /* identifiers */
00288         ot->name= "Free Physics Bake";
00289         ot->description= "Free physics bake";
00290         ot->idname= "PTCACHE_OT_free_bake";
00291         
00292         /* api callbacks */
00293         ot->exec= ptcache_free_bake_exec;
00294         ot->poll= ptcache_poll;
00295 
00296         /* flags */
00297         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00298 }
00299 void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
00300 {
00301         /* identifiers */
00302         ot->name= "Bake From Cache";
00303         ot->description= "Bake from cache";
00304         ot->idname= "PTCACHE_OT_bake_from_cache";
00305         
00306         /* api callbacks */
00307         ot->exec= ptcache_bake_from_cache_exec;
00308         ot->poll= ptcache_poll;
00309 
00310         /* flags */
00311         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00312 }
00313 
00314 static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
00315 {
00316         Scene *scene = CTX_data_scene(C);
00317         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00318         Object *ob= ptr.id.data;
00319         PointCache *cache= ptr.data;
00320         PTCacheID *pid;
00321         ListBase pidlist;
00322 
00323         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
00324         
00325         for(pid=pidlist.first; pid; pid=pid->next) {
00326                 if(pid->cache == cache) {
00327                         *(pid->cache_ptr) = BKE_ptcache_add(pid->ptcaches);
00328                         break;
00329                 }
00330         }
00331 
00332         BLI_freelistN(&pidlist);
00333 
00334         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
00335         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00336 
00337         return OPERATOR_FINISHED;
00338 }
00339 static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
00340 {
00341         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
00342         Scene *scene= CTX_data_scene(C);
00343         Object *ob= ptr.id.data;
00344         PointCache *cache= ptr.data;
00345         PTCacheID *pid;
00346         ListBase pidlist;
00347 
00348         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
00349         
00350         for(pid=pidlist.first; pid; pid=pid->next) {
00351                 if(pid->cache == cache) {
00352                         if(pid->ptcaches->first == pid->ptcaches->last)
00353                                 continue; /* don't delete last cache */
00354 
00355                         BLI_remlink(pid->ptcaches, pid->cache);
00356                         BKE_ptcache_free(pid->cache);
00357                         *(pid->cache_ptr) = pid->ptcaches->first;
00358 
00359                         break;
00360                 }
00361         }
00362 
00363         BLI_freelistN(&pidlist);
00364         
00365         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
00366 
00367         return OPERATOR_FINISHED;
00368 }
00369 void PTCACHE_OT_add(wmOperatorType *ot)
00370 {
00371         /* identifiers */
00372         ot->name= "Add New Cache";
00373         ot->description= "Add new cache";
00374         ot->idname= "PTCACHE_OT_add";
00375         
00376         /* api callbacks */
00377         ot->exec= ptcache_add_new_exec;
00378         ot->poll= ptcache_poll; // ptcache_bake_all_poll;
00379 
00380         /* flags */
00381         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00382 }
00383 void PTCACHE_OT_remove(wmOperatorType *ot)
00384 {
00385         /* identifiers */
00386         ot->name= "Delete Current Cache";
00387         ot->description= "Delete current cache";
00388         ot->idname= "PTCACHE_OT_remove";
00389         
00390         /* api callbacks */
00391         ot->exec= ptcache_remove_exec;
00392         ot->poll= ptcache_poll;
00393 
00394         /* flags */
00395         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00396 }
00397