svn merge -r36603:36628 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / editors / physics / physics_pointcache.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 by Janne Karhu.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/editors/physics/physics_pointcache.c
31  *  \ingroup edphys
32  */
33
34
35 #include <stdlib.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41
42 #include "DNA_scene_types.h"
43
44 #include "BKE_context.h"
45 #include "BKE_global.h"
46 #include "BKE_main.h"
47 #include "BKE_modifier.h"
48 #include "BKE_particle.h"
49 #include "BKE_pointcache.h"
50 #include "BKE_report.h"
51 #include "BKE_scene.h"
52  
53
54 #include "ED_particle.h"
55
56 #include "WM_api.h"
57 #include "WM_types.h"
58
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61
62 #include "physics_intern.h"
63
64 static int cache_break_test(void *UNUSED(cbd)) {
65         return G.afbreek==1;
66 }
67 static int ptcache_bake_all_poll(bContext *C)
68 {
69         Scene *scene= CTX_data_scene(C);
70
71         if(!scene)
72                 return 0;
73         
74         return 1;
75 }
76
77 static int ptcache_poll(bContext *C)
78 {
79         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
80         return (ptr.data && ptr.id.data);
81 }
82
83 static void bake_console_progress(void *UNUSED(arg), int nr)
84 {
85         printf("\rbake: %3i%%", nr);
86         fflush(stdout);
87 }
88
89 static void bake_console_progress_end(void *UNUSED(arg))
90 {
91         printf("\rbake: done!\n");
92 }
93
94 static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
95 {
96         Main *bmain = CTX_data_main(C);
97         Scene *scene= CTX_data_scene(C);
98         wmWindow *win = G.background ? NULL : CTX_wm_window(C);
99         PTCacheBaker baker;
100
101         baker.main = bmain;
102         baker.scene = scene;
103         baker.pid = NULL;
104         baker.bake = RNA_boolean_get(op->ptr, "bake");
105         baker.render = 0;
106         baker.anim_init = 0;
107         baker.quick_step = 1;
108         baker.break_test = cache_break_test;
109         baker.break_data = NULL;
110
111         /* Disabled for now as this doesn't work properly,
112          * and pointcache baking will be reimplemented with
113          * the job system soon anyways. */
114         if (win) {
115                 baker.progressbar = (void (*)(void *, int))WM_timecursor;
116                 baker.progressend = (void (*)(void *))WM_cursor_restore;
117                 baker.progresscontext = win;
118         } else {
119                 baker.progressbar = bake_console_progress;
120                 baker.progressend = bake_console_progress_end;
121                 baker.progresscontext = NULL;
122         }
123
124         BKE_ptcache_bake(&baker);
125
126         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
127         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, NULL);
128
129         return OPERATOR_FINISHED;
130 }
131 static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
132 {
133         Scene *scene= CTX_data_scene(C);
134         Base *base;
135         PTCacheID *pid;
136         ListBase pidlist;
137
138         for(base=scene->base.first; base; base= base->next) {
139                 BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
140
141                 for(pid=pidlist.first; pid; pid=pid->next) {
142                         pid->cache->flag &= ~PTCACHE_BAKED;
143                 }
144                 
145                 BLI_freelistN(&pidlist);
146                 
147                 WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
148         }
149
150         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
151
152         return OPERATOR_FINISHED;
153 }
154
155 void PTCACHE_OT_bake_all(wmOperatorType *ot)
156 {
157         /* identifiers */
158         ot->name= "Bake All Physics";
159         ot->idname= "PTCACHE_OT_bake_all";
160         
161         /* api callbacks */
162         ot->exec= ptcache_bake_all_exec;
163         ot->poll= ptcache_bake_all_poll;
164
165         /* flags */
166         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
167
168         RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
169 }
170 void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
171 {
172         /* identifiers */
173         ot->name= "Free All Physics Bakes";
174         ot->idname= "PTCACHE_OT_free_bake_all";
175         
176         /* api callbacks */
177         ot->exec= ptcache_free_bake_all_exec;
178         ot->poll= ptcache_bake_all_poll;
179
180         /* flags */
181         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
182 }
183 static int ptcache_bake_exec(bContext *C, wmOperator *op)
184 {
185         Main *bmain = CTX_data_main(C);
186         Scene *scene = CTX_data_scene(C);
187         wmWindow *win = G.background ? NULL : CTX_wm_window(C);
188         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
189         Object *ob= ptr.id.data;
190         PointCache *cache= ptr.data;
191         PTCacheBaker baker;
192         PTCacheID *pid;
193         ListBase pidlist;
194
195         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
196         
197         for(pid=pidlist.first; pid; pid=pid->next) {
198                 if(pid->cache == cache)
199                         break;
200         }
201
202         baker.main = bmain;
203         baker.scene = scene;
204         baker.pid = pid;
205         baker.bake = RNA_boolean_get(op->ptr, "bake");
206         baker.render = 0;
207         baker.anim_init = 0;
208         baker.quick_step = 1;
209         baker.break_test = cache_break_test;
210         baker.break_data = NULL;
211
212         /* Disabled for now as this doesn't work properly,
213          * and pointcache baking will be reimplemented with
214          * the job system soon anyways. */
215         if (win) {
216                 baker.progressbar = (void (*)(void *, int))WM_timecursor;
217                 baker.progressend = (void (*)(void *))WM_cursor_restore;
218                 baker.progresscontext = win;
219         } else {
220                 printf("\n"); /* empty first line before console reports */
221                 baker.progressbar = bake_console_progress;
222                 baker.progressend = bake_console_progress_end;
223                 baker.progresscontext = NULL;
224         }
225
226         BKE_ptcache_bake(&baker);
227
228         BLI_freelistN(&pidlist);
229
230         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
231         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
232
233         return OPERATOR_FINISHED;
234 }
235 static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
236 {
237         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
238         PointCache *cache= ptr.data;
239         Object *ob= ptr.id.data;
240
241         if(cache->edit) {
242                 if(!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) {
243                         PE_free_ptcache_edit(cache->edit);
244                         cache->edit = NULL;
245                         cache->flag &= ~PTCACHE_BAKED;
246                 }
247         }
248         else
249                 cache->flag &= ~PTCACHE_BAKED;
250         
251         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
252
253         return OPERATOR_FINISHED;
254 }
255 static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
256 {
257         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
258         PointCache *cache= ptr.data;
259         Object *ob= ptr.id.data;
260         
261         cache->flag |= PTCACHE_BAKED;
262         
263         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
264
265         return OPERATOR_FINISHED;
266 }
267 void PTCACHE_OT_bake(wmOperatorType *ot)
268 {
269         /* identifiers */
270         ot->name= "Bake Physics";
271         ot->idname= "PTCACHE_OT_bake";
272         
273         /* api callbacks */
274         ot->exec= ptcache_bake_exec;
275         ot->poll= ptcache_poll;
276
277         /* flags */
278         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
279
280         RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
281 }
282 void PTCACHE_OT_free_bake(wmOperatorType *ot)
283 {
284         /* identifiers */
285         ot->name= "Free Physics Bake";
286         ot->idname= "PTCACHE_OT_free_bake";
287         
288         /* api callbacks */
289         ot->exec= ptcache_free_bake_exec;
290         ot->poll= ptcache_poll;
291
292         /* flags */
293         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
294 }
295 void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
296 {
297         /* identifiers */
298         ot->name= "Bake From Cache";
299         ot->idname= "PTCACHE_OT_bake_from_cache";
300         
301         /* api callbacks */
302         ot->exec= ptcache_bake_from_cache_exec;
303         ot->poll= ptcache_poll;
304
305         /* flags */
306         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
307 }
308
309 static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
310 {
311         Scene *scene = CTX_data_scene(C);
312         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
313         Object *ob= ptr.id.data;
314         PointCache *cache= ptr.data;
315         PTCacheID *pid;
316         ListBase pidlist;
317
318         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
319         
320         for(pid=pidlist.first; pid; pid=pid->next) {
321                 if(pid->cache == cache) {
322                         *(pid->cache_ptr) = BKE_ptcache_add(pid->ptcaches);
323                         break;
324                 }
325         }
326
327         BLI_freelistN(&pidlist);
328
329         WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
330         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
331
332         return OPERATOR_FINISHED;
333 }
334 static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
335 {
336         PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
337         Scene *scene= CTX_data_scene(C);
338         Object *ob= ptr.id.data;
339         PointCache *cache= ptr.data;
340         PTCacheID *pid;
341         ListBase pidlist;
342
343         BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
344         
345         for(pid=pidlist.first; pid; pid=pid->next) {
346                 if(pid->cache == cache) {
347                         if(pid->ptcaches->first == pid->ptcaches->last)
348                                 continue; /* don't delete last cache */
349
350                         BLI_remlink(pid->ptcaches, pid->cache);
351                         BKE_ptcache_free(pid->cache);
352                         *(pid->cache_ptr) = pid->ptcaches->first;
353
354                         break;
355                 }
356         }
357
358         BLI_freelistN(&pidlist);
359         
360         WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
361
362         return OPERATOR_FINISHED;
363 }
364 void PTCACHE_OT_add(wmOperatorType *ot)
365 {
366         /* identifiers */
367         ot->name= "Add new cache";
368         ot->idname= "PTCACHE_OT_add";
369         
370         /* api callbacks */
371         ot->exec= ptcache_add_new_exec;
372         ot->poll= ptcache_poll; // ptcache_bake_all_poll;
373
374         /* flags */
375         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
376 }
377 void PTCACHE_OT_remove(wmOperatorType *ot)
378 {
379         /* identifiers */
380         ot->name= "Delete current cache";
381         ot->idname= "PTCACHE_OT_remove";
382         
383         /* api callbacks */
384         ot->exec= ptcache_remove_exec;
385         ot->poll= ptcache_poll;
386
387         /* flags */
388         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
389 }
390