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