Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2010-07-19 08:44:37 +0400
committerJoseph Eagar <joeedh@gmail.com>2010-07-19 08:44:37 +0400
commitc11c196efadf5ef52293d782638497f86a209722 (patch)
tree43abcd60b2400d28db8686f4dbea68f17475ef58 /source/blender/editors/physics
parentf54aa7811029c90b6071ccc9e27e57a758e5884d (diff)
parent7f083c45bee15f7540e2a35a725efe28fc962239 (diff)
part 1 of merge from trunk at r30358; it compiles, but doesn't link quite yet :)
Diffstat (limited to 'source/blender/editors/physics')
-rw-r--r--source/blender/editors/physics/CMakeLists.txt47
-rw-r--r--source/blender/editors/physics/particle_boids.c4
-rw-r--r--source/blender/editors/physics/particle_edit.c150
-rw-r--r--source/blender/editors/physics/particle_object.c38
-rw-r--r--source/blender/editors/physics/physics_fluid.c1607
-rw-r--r--source/blender/editors/physics/physics_intern.h4
-rw-r--r--source/blender/editors/physics/physics_ops.c8
-rw-r--r--source/blender/editors/physics/physics_pointcache.c45
8 files changed, 932 insertions, 971 deletions
diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt
new file mode 100644
index 00000000000..ebe3f913508
--- /dev/null
+++ b/source/blender/editors/physics/CMakeLists.txt
@@ -0,0 +1,47 @@
+# $Id: CMakeLists.txt 12931 2007-12-17 18:20:48Z theeth $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB SRC *.c)
+
+SET(INC
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../makesdna
+ ../../makesrna
+ ../../windowmanager
+ ../../../../intern/elbeem/extern
+ ../../../../intern/guardedalloc
+)
+
+IF(NOT WITH_ELBEEM)
+ ADD_DEFINITIONS(-DDISABLE_ELBEEM)
+ENDIF(NOT WITH_ELBEEM)
+
+IF(WITH_OPENMP)
+ ADD_DEFINITIONS(-DPARALLEL=1)
+ENDIF(WITH_OPENMP)
+
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
+BLENDERLIB(bf_editor_physics "${SRC}" "${INC}")
diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c
index e738aa34d07..37de0d8f873 100644
--- a/source/blender/editors/physics/particle_boids.c
+++ b/source/blender/editors/physics/particle_boids.c
@@ -1,5 +1,5 @@
/**
- * $Id:
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -29,9 +29,7 @@
#include "MEM_guardedalloc.h"
-#include "DNA_boid_types.h"
#include "DNA_particle_types.h"
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_boids.h"
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 71c18b35365..da0034ac2f9 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -36,15 +36,9 @@
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
-#include "DNA_object_types.h"
-#include "DNA_vec_types.h"
-#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
-#include "DNA_windowmanager_types.h"
#include "BKE_DerivedMesh.h"
#include "BKE_depsgraph.h"
@@ -66,7 +60,6 @@
#include "BLI_kdtree.h"
#include "BLI_rand.h"
-#include "PIL_time.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -75,7 +68,6 @@
#include "ED_particle.h"
#include "ED_view3d.h"
-#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -132,7 +124,7 @@ int PE_hair_poll(bContext *C)
return (edit && edit->psys);
}
-int PE_poll_3dview(bContext *C)
+int PE_poll_view3d(bContext *C)
{
return PE_poll(C) && CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
@@ -168,7 +160,7 @@ void PE_free_ptcache_edit(PTCacheEdit *edit)
edit->emitter_field= 0;
}
- psys_free_path_cache(NULL, edit);
+ psys_free_path_cache(edit->psys, edit);
MEM_freeN(edit);
}
@@ -211,7 +203,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
pset->scene = scene;
pset->object = ob;
- BKE_ptcache_ids_from_object(&pidlist, ob);
+ BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
/* in the case of only one editable thing, set pset->edittype accordingly */
if(pidlist.first && pidlist.first == pidlist.last) {
@@ -831,9 +823,12 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit= psys->edit;
psmd= psys_get_modifier(ob, psys);
- if(!edit->mirror_cache || !psmd->dm)
+ if(!psmd->dm)
return;
+ if(!edit->mirror_cache)
+ PE_update_mirror_cache(ob, psys);
+
/* we delay settings the PARS_EDIT_RECALC for mirrored particles
* to avoid doing mirror twice */
LOOP_POINTS {
@@ -902,13 +897,13 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
if(dot<dist_1st) {
normalize_v3(dvec);
mul_v3_fl(dvec,dist_1st-dot);
- add_v3_v3v3(key->co,key->co,dvec);
+ add_v3_v3(key->co, dvec);
}
}
else {
normalize_v3(dvec);
mul_v3_fl(dvec,dist_1st-dot);
- add_v3_v3v3(key->co,key->co,dvec);
+ add_v3_v3(key->co, dvec);
}
if(k==1)
dist_1st*=1.3333f;
@@ -994,7 +989,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
}
if(k) {
- add_v3_v3v3((key-1)->co,(key-1)->co,dv1);
+ add_v3_v3((key-1)->co, dv1);
}
VECADD(dv1,dv0,dv2);
@@ -1326,7 +1321,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
}
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1376,7 +1371,7 @@ int PE_mouse_particles(bContext *C, short *mval, int extend)
for_mouse_hit_keys(&data, toggle_key_select, 1); /* nearest only */
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
@@ -1385,11 +1380,14 @@ int PE_mouse_particles(bContext *C, short *mval, int extend)
static void select_root(PEData *data, int point_index)
{
+ if (data->edit->points[point_index].flag & PEP_HIDE)
+ return;
+
data->edit->points[point_index].keys->flag |= PEK_SELECT;
data->edit->points[point_index].flag |= PEP_EDIT_RECALC; /* redraw selection only */
}
-static int select_first_exec(bContext *C, wmOperator *op)
+static int select_roots_exec(bContext *C, wmOperator *op)
{
PEData data;
@@ -1397,19 +1395,19 @@ static int select_first_exec(bContext *C, wmOperator *op)
foreach_point(&data, select_root);
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
-void PARTICLE_OT_select_first(wmOperatorType *ot)
+void PARTICLE_OT_select_roots(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Select First";
- ot->idname= "PARTICLE_OT_select_first";
+ ot->name= "Select Roots";
+ ot->idname= "PARTICLE_OT_select_roots";
/* api callbacks */
- ot->exec= select_first_exec;
+ ot->exec= select_roots_exec;
ot->poll= PE_poll;
/* flags */
@@ -1421,11 +1419,15 @@ void PARTICLE_OT_select_first(wmOperatorType *ot)
static void select_tip(PEData *data, int point_index)
{
PTCacheEditPoint *point = data->edit->points + point_index;
+
+ if (point->flag & PEP_HIDE)
+ return;
+
point->keys[point->totkey - 1].flag |= PEK_SELECT;
point->flag |= PEP_EDIT_RECALC; /* redraw selection only */
}
-static int select_last_exec(bContext *C, wmOperator *op)
+static int select_tips_exec(bContext *C, wmOperator *op)
{
PEData data;
@@ -1433,19 +1435,19 @@ static int select_last_exec(bContext *C, wmOperator *op)
foreach_point(&data, select_tip);
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
-void PARTICLE_OT_select_last(wmOperatorType *ot)
+void PARTICLE_OT_select_tips(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Select Last";
- ot->idname= "PARTICLE_OT_select_last";
+ ot->name= "Select Tips";
+ ot->idname= "PARTICLE_OT_select_tips";
/* api callbacks */
- ot->exec= select_last_exec;
+ ot->exec= select_tips_exec;
ot->poll= PE_poll;
/* flags */
@@ -1473,7 +1475,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
@@ -1499,7 +1501,7 @@ void PARTICLE_OT_select_linked(wmOperatorType *ot)
/* api callbacks */
ot->exec= select_linked_exec;
ot->invoke= select_linked_invoke;
- ot->poll= PE_poll_3dview;
+ ot->poll= PE_poll_view3d;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -1539,7 +1541,7 @@ int PE_border_select(bContext *C, rcti *rect, int select, int extend)
for_mouse_hit_keys(&data, select_key, 0);
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1564,7 +1566,7 @@ int PE_circle_select(bContext *C, int selecting, short *mval, float rad)
for_mouse_hit_keys(&data, select_key, 0);
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1630,7 +1632,7 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
}
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1664,7 +1666,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1706,7 +1708,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
PE_update_selection(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
}
@@ -1764,7 +1766,7 @@ static int select_less_exec(bContext *C, wmOperator *op)
foreach_point(&data, select_less_keys);
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
@@ -1825,7 +1827,7 @@ static int select_more_exec(bContext *C, wmOperator *op)
foreach_point(&data, select_more_keys);
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
@@ -1862,7 +1864,7 @@ static int select_inverse_exec(bContext *C, wmOperator *op)
}
PE_update_selection(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
}
@@ -1953,7 +1955,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
recalc_lengths(data.edit);
PE_update_object(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
}
@@ -2258,7 +2260,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
recalc_lengths(data.edit);
PE_update_object(data.scene, data.ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
}
@@ -2346,7 +2348,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
return OPERATOR_FINISHED;
}
@@ -2381,21 +2383,22 @@ static int weight_set_exec(bContext *C, wmOperator *op)
HairKey *hkey;
float weight;
ParticleBrushData *brush= &pset->brush[pset->brushtype];
- edit= psys->edit;
+ float factor= RNA_float_get(op->ptr, "factor");
- weight= (float)(brush->strength / 100.0f);
+ weight= brush->strength;
+ edit= psys->edit;
LOOP_SELECTED_POINTS {
ParticleData *pa= psys->particles + p;
LOOP_SELECTED_KEYS {
hkey= pa->hair + k;
- hkey->weight= weight;
+ hkey->weight= interpf(weight, hkey->weight, factor);
}
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
return OPERATOR_FINISHED;
}
@@ -2412,6 +2415,8 @@ void PARTICLE_OT_weight_set(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_float(ot->srna, "factor", 1, 0, 1, "Factor", "", 0, 1);
}
/************************ cursor drawing *******************************/
@@ -2451,7 +2456,7 @@ static void toggle_particle_cursor(bContext *C, int enable)
pset->paintcursor = NULL;
}
else if(enable)
- pset->paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), PE_poll_3dview, brush_drawcursor, NULL);
+ pset->paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), PE_poll_view3d, brush_drawcursor, NULL);
}
/********************* radial control operator *********************/
@@ -2507,6 +2512,8 @@ static int brush_radial_control_exec(bContext *C, wmOperator *op)
else if(mode == WM_RADIALCONTROL_STRENGTH)
brush->strength= new_value;
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
return OPERATOR_FINISHED;
}
@@ -2568,7 +2575,7 @@ static int delete_exec(bContext *C, wmOperator *op)
}
DAG_id_flush_update(&data.ob->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
}
@@ -2727,7 +2734,7 @@ static int mirror_exec(bContext *C, wmOperator *op)
PE_mirror_x(scene, ob, 0);
update_world_cos(ob, edit);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
return OPERATOR_FINISHED;
@@ -2941,7 +2948,7 @@ static void brush_puff(PEData *data, int point_index)
VECCOPY(co, key->co);
mul_m4_v3(mat, co);
length += len_v3v3(lastco, co);
- if((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE)) {
+ if((data->select==0 || (key->flag & PEK_SELECT)) && !(key->flag & PEK_HIDE)) {
VECADDFAC(kco, rootco, nor, length);
/* blend between the current and straight position */
@@ -3356,7 +3363,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.mval= mval;
data.rad= (float)brush->size;
- data.combfac= (float)(brush->strength - 50) / 50.0f;
+ data.combfac= (brush->strength - 0.5f) * 2.0f;
if(data.combfac < 0.0f)
data.combfac= 1.0f - 9.0f * data.combfac;
else
@@ -3378,7 +3385,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
PE_set_view3d_data(C, &data);
data.mval= mval;
data.rad= (float)brush->size;
- data.cutfac= (float)(brush->strength / 100.0f);
+ data.cutfac= brush->strength;
if(selected)
foreach_selected_point(&data, brush_cut);
@@ -3402,7 +3409,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.mval= mval;
data.rad= (float)brush->size;
- data.growfac= (float)brush->strength / 5000.0f;
+ data.growfac= brush->strength / 50.0f;
if(brush->invert ^ flip)
data.growfac= 1.0f - data.growfac;
@@ -3424,8 +3431,9 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.dm= psmd->dm;
data.mval= mval;
data.rad= (float)brush->size;
+ data.select= selected;
- data.pufffac= (float)(brush->strength - 50) / 50.0f;
+ data.pufffac= (brush->strength - 0.5f) * 2.0f;
if(data.pufffac < 0.0f)
data.pufffac= 1.0f - 9.0f * data.pufffac;
else
@@ -3446,7 +3454,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
PE_set_view3d_data(C, &data);
data.mval= mval;
- added= brush_add(&data, brush->strength);
+ added= brush_add(&data, brush->count);
if(pset->flag & PE_KEEP_LENGTHS)
recalc_lengths(edit);
@@ -3466,7 +3474,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.vec[0]= data.vec[1]= data.vec[2]= 0.0f;
data.tot= 0;
- data.smoothfac= (float)(brush->strength / 100.0f);
+ data.smoothfac= brush->strength;
invert_m4_m4(ob->imat, ob->obmat);
@@ -3489,7 +3497,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
data.mval= mval;
data.rad= (float)brush->size;
- data.weightfac = (float)(brush->strength / 100.0f); /* note that this will never be zero */
+ data.weightfac = brush->strength; /* note that this will never be zero */
foreach_mouse_hit_key(&data, brush_weight, selected);
}
@@ -3511,7 +3519,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
else
PE_update_object(scene, ob, 1);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
bedit->lastmouse[0]= mouse[0];
bedit->lastmouse[1]= mouse[1];
@@ -3608,7 +3616,7 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot)
ot->invoke= brush_edit_invoke;
ot->modal= brush_edit_modal;
ot->cancel= brush_edit_cancel;
- ot->poll= PE_poll_3dview;
+ ot->poll= PE_poll_view3d;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
@@ -3665,6 +3673,8 @@ static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
for(; pm; pm=pm->next) {
for(i=0; i<BPHYS_TOT_DATA; i++)
pm->data[i] = MEM_dupallocN(pm->data[i]);
+
+ pm->index_array = MEM_dupallocN(pm->index_array);
}
}
@@ -3739,6 +3749,8 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
for(i=0; i<BPHYS_TOT_DATA; i++)
pm->data[i] = MEM_dupallocN(pm->data[i]);
+ pm->index_array = MEM_dupallocN(pm->index_array);
+
BKE_ptcache_mem_init_pointers(pm);
LOOP_POINTS {
@@ -4003,12 +4015,20 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache,
LOOP_POINTS {
if(psys) {
- pa = psys->particles + p;
- if((pm->next && pm->next->frame < pa->time)
- || (pm->prev && pm->prev->frame >= pa->dietime)) {
- BKE_ptcache_mem_incr_pointers(pm);
+ if(pm->index_array) {
+ if(pm->index_array[p])
+ BKE_ptcache_mem_seek_pointers(p, pm);
+ else
continue;
- }
+ }
+ else {
+ pa = psys->particles + p;
+ if((pm->next && pm->next->frame < pa->time)
+ || (pm->prev && pm->prev->frame >= pa->dietime)) {
+ BKE_ptcache_mem_incr_pointers(pm);
+ continue;
+ }
+ }
}
if(!point->totkey) {
@@ -4118,7 +4138,7 @@ static int clear_edited_exec(bContext *C, wmOperator *op)
psys->flag &= ~PSYS_EDITED;
psys_reset(psys, PSYS_RESET_DEPSGRAPH);
- WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob);
+ WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
}
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index f590339b91d..bb30d30fd0e 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -1,5 +1,5 @@
/**
- * $Id:
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -32,10 +32,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
-#include "DNA_windowmanager_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -72,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;
}
@@ -110,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;
}
@@ -169,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;
}
@@ -217,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;
}
@@ -265,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;
}
@@ -303,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;
}
}
@@ -341,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;
}
}
@@ -379,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;
}
}
@@ -418,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;
}
}
@@ -464,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;
}
@@ -501,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;
}
}
@@ -526,6 +526,7 @@ void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
+ ParticleEditSettings *pset= PE_settings(scene);
ParticleData *pa;
PTCacheEdit *edit;
PTCacheEditPoint *point;
@@ -565,6 +566,9 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_GLOBAL_HAIR;
+ if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
+ pset->brushtype = PE_BRUSH_NONE;
+
PE_update_object(scene, ob, 0);
}
@@ -589,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;
}
@@ -728,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;
}
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 65701f89c4e..23f604d8c12 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -45,25 +45,17 @@
#include "MEM_guardedalloc.h"
/* types */
-#include "DNA_curve_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
-#include "DNA_key_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_key_types.h"
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_math.h"
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
@@ -80,17 +72,15 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_softbody.h"
+#include "BKE_unit.h"
-#include "PIL_time.h"
#include "LBM_fluidsim.h"
#include "BIF_gl.h"
-#include "ED_fluidsim.h"
#include "ED_screen.h"
-#include "WM_api.h"
#include "WM_types.h"
#include "physics_intern.h" // own include
@@ -98,85 +88,110 @@
/* enable/disable overall compilation */
#ifndef DISABLE_ELBEEM
-#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
-/* ************** libgomp (Apple gcc 4.2.1) TLS bug workaround *************** */
-#include <pthread.h>
-extern pthread_key_t gomp_tls_key;
-static void *thread_tls_data;
-#endif
+#include "WM_api.h"
+#include "DNA_scene_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_mesh_types.h"
-/* XXX */
-/* from header info.c */
-static int start_progress_bar(void) {return 0;};
-static void end_progress_bar(wmWindow *win) {WM_cursor_restore(win);};
-static void waitcursor(int val) {};
-static int progress_bar(wmWindow *win, float done, char *busy_info) { WM_timecursor(win,done*100); return 0;}
-static int pupmenu() {return 0;}
-/* XXX */
-
-
-double fluidsimViscosityPreset[6] = {
- -1.0, /* unused */
- -1.0, /* manual */
- 1.0e-6, /* water */
- 5.0e-5, /* some (thick) oil */
- 2.0e-3, /* ca. honey */
- -1.0 /* end */
-};
-
-char* fluidsimViscosityPresetString[6] = {
- "UNUSED", /* unused */
- "UNUSED", /* manual */
- " = 1.0 * 10^-6", /* water */
- " = 5.0 * 10^-5", /* some (thick) oil */
- " = 2.0 * 10^-3", /* ca. honey */
- "INVALID" /* end */
-};
+#include "PIL_time.h"
+
+
+static float get_fluid_viscosity(FluidsimSettings *settings)
+{
+ switch (settings->viscosityMode) {
+ case 0: /* unused */
+ return -1.0;
+ case 2: /* water */
+ return 1.0e-6;
+ case 3: /* some (thick) oil */
+ return 5.0e-5;
+ case 4: /* ca. honey */
+ return 2.0e-3;
+ case 1: /* manual */
+ default:
+ return (1.0/pow(10.0, settings->viscosityExponent)) * settings->viscosityValue;
+ }
+}
+
+static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fss)
+{
+ if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+ copy_v3_v3(gravity, scene->physics_settings.gravity);
+ } else {
+ copy_v3_v3(gravity, &fss->gravx);
+ }
+}
+
+static float get_fluid_size_m(Scene *scene, Object *domainob, FluidsimSettings *fss)
+{
+ if (!scene->unit.system) {
+ return fss->realsize;
+ } else {
+ float dim[3];
+ float longest_axis;
+
+ object_get_dimensions(domainob, dim);
+ longest_axis = MAX3(dim[0], dim[1], dim[2]);
+
+ return longest_axis * scene->unit.scale_length;
+ }
+}
+
+static int fluid_is_animated_mesh(FluidsimSettings *fss)
+{
+ return ((fss->type == OB_FLUIDSIM_CONTROL) || fss->domainNovecgen);
+}
/* ********************** fluid sim settings struct functions ********************** */
+#if 0
/* helper function */
void fluidsimGetGeometryObjFilename(Object *ob, char *dst) { //, char *srcname) {
//snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
snprintf(dst,FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
}
+#endif
-
-
-/* ******************************************************************************** */
/* ********************** fluid sim channel helper functions ********************** */
-/* ******************************************************************************** */
+
+typedef struct FluidAnimChannels {
+ int length;
+
+ double aniFrameTime;
+
+ float *timeAtFrame;
+ float *DomainTime;
+ float *DomainGravity;
+ float *DomainViscosity;
+} FluidAnimChannels;
+
+typedef struct FluidObject {
+ struct FluidObject *next, *prev;
+
+ struct Object *object;
+
+ float *Translation;
+ float *Rotation;
+ float *Scale;
+ float *Active;
+
+ float *InitialVelocity;
+
+ float *AttractforceStrength;
+ float *AttractforceRadius;
+ float *VelocityforceStrength;
+ float *VelocityforceRadius;
+
+ float *VertexCache;
+ int numVerts, numTris;
+} FluidObject;
// no. of entries for the two channel sizes
#define CHANNEL_FLOAT 1
#define CHANNEL_VEC 3
-#define FS_FREE_ONECHANNEL(c,str) { \
- if(c){ MEM_freeN(c); c=NULL; } \
-} // end ONE CHANN, debug: fprintf(stderr,"freeing " str " \n");
-
-#define FS_FREE_CHANNELS { \
- FS_FREE_ONECHANNEL(timeAtIndex,"timeAtIndex");\
- FS_FREE_ONECHANNEL(timeAtFrame,"timeAtFrame");\
- FS_FREE_ONECHANNEL(channelDomainTime,"channelDomainTime"); \
- FS_FREE_ONECHANNEL(channelDomainGravity,"channelDomainGravity");\
- FS_FREE_ONECHANNEL(channelDomainViscosity,"channelDomainViscosity");\
- for(i=0;i<256;i++) { \
- FS_FREE_ONECHANNEL(channelObjMove[i][0],"channelObjMove0"); \
- FS_FREE_ONECHANNEL(channelObjMove[i][1],"channelObjMove1"); \
- FS_FREE_ONECHANNEL(channelObjMove[i][2],"channelObjMove2"); \
- FS_FREE_ONECHANNEL(channelObjInivel[i],"channelObjInivel"); \
- FS_FREE_ONECHANNEL(channelObjActive[i],"channelObjActive"); \
- FS_FREE_ONECHANNEL(channelAttractforceStrength[i],"channelAttractforceStrength"); \
- FS_FREE_ONECHANNEL(channelAttractforceRadius[i],"channelAttractforceRadius"); \
- FS_FREE_ONECHANNEL(channelVelocityforceStrength[i],"channelVelocityforceStrength"); \
- FS_FREE_ONECHANNEL(channelVelocityforceRadius[i],"channelVelocityforceRadius"); \
- } \
-} // end FS FREE CHANNELS
-
-
// simplify channels before printing
// for API this is done anyway upon init
#if 0
@@ -207,341 +222,653 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char
}
#endif
-static void fluidsimInitChannel(Scene *scene, float **setchannel, int size, float *time,
- int *icuIds, float *defaults, Ipo* ipo, int entries)
+
+/* Note: fluid anim channel data layout
+ * ------------------------------------
+ * CHANNEL_FLOAT:
+ * frame 1 |frame 2
+ * [dataF][time][dataF][time]
+ *
+ * CHANNEL_VEC:
+ * frame 1 |frame 2
+ * [dataX][dataY][dataZ][time][dataX][dataY][dataZ][time]
+ *
+ */
+
+static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *channels)
{
+ int i;
+
+ channels->timeAtFrame = MEM_callocN( (channels->length+1)*sizeof(float), "timeAtFrame channel");
+
+ channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1
+
+ for(i=2; i<=channels->length; i++) {
+ channels->timeAtFrame[i] = channels->timeAtFrame[i-1] + channels->aniFrameTime;
+ }
+}
+
+/* if this is slow, can replace with faster, less readable code */
+static void set_channel(float *channel, float time, float *value, int i, int size)
+{
+ if (size == CHANNEL_FLOAT) {
+ channel[(i * 2) + 0] = value[0];
+ channel[(i * 2) + 1] = time;
+ }
+ else if (size == CHANNEL_VEC) {
+ channel[(i * 4) + 0] = value[0];
+ channel[(i * 4) + 1] = value[1];
+ channel[(i * 4) + 2] = value[2];
+ channel[(i * 4) + 3] = time;
+ }
+}
- int i, j;
- char *cstr = NULL;
- float *channel = NULL;
+static void set_vertex_channel(float *channel, float time, struct Scene *scene, struct FluidObject *fobj, int i)
+{
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+ float *verts;
+ int *tris=NULL, numVerts=0, numTris=0;
+ int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+ int framesize = (3*fobj->numVerts) + 1;
+ int j;
+
+ if (channel == NULL)
+ return;
- cstr = "fluidsiminit_channelfloat";
- if(entries>1) cstr = "fluidsiminit_channelvec";
- channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr );
+ initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
- /* defaults for now */
- for(j=0; j<entries; j++) {
- for(i=1; i<=size; i++) {
- channel[(i-1)*(entries+1) + j] = defaults[j];
- }
+ /* don't allow mesh to change number of verts in anim sequence */
+ if (numVerts != fobj->numVerts) {
+ MEM_freeN(channel);
+ channel = NULL;
+ return;
}
- for(i=1; i<=size; i++) {
- channel[(i-1)*(entries+1) + entries] = time[i];
+ /* fill frame of channel with vertex locations */
+ for(j=0; j < (3*numVerts); j++) {
+ channel[i*framesize + j] = verts[j];
}
+ channel[i*framesize + framesize-1] = time;
+
+ MEM_freeN(verts);
+ MEM_freeN(tris);
+}
- *setchannel = channel;
+static void free_domain_channels(FluidAnimChannels *channels)
+{
+ if (!channels->timeAtFrame)
+ return;
+ MEM_freeN(channels->timeAtFrame);
+ channels->timeAtFrame = NULL;
+ MEM_freeN(channels->DomainGravity);
+ channels->DomainGravity = NULL;
+ MEM_freeN(channels->DomainViscosity);
+ channels->DomainViscosity = NULL;
+}
-#if 0
- /* goes away completely */
- int i,j;
- IpoCurve* icus[3];
- char *cstr = NULL;
- float *channel = NULL;
- float aniFrlen = scene->r.framelen;
- int current_frame = scene->r.cfra;
- if((entries<1) || (entries>3)) {
- printf("fluidsimInitChannel::Error - invalid no. of entries: %d\n",entries);
- entries = 1;
+static void free_all_fluidobject_channels(ListBase *fobjects)
+{
+ FluidObject *fobj;
+
+ for (fobj=fobjects->first; fobj; fobj=fobj->next) {
+ if (fobj->Translation) {
+ MEM_freeN(fobj->Translation);
+ fobj->Translation = NULL;
+ MEM_freeN(fobj->Rotation);
+ fobj->Rotation = NULL;
+ MEM_freeN(fobj->Scale);
+ fobj->Scale = NULL;
+ MEM_freeN(fobj->Active);
+ fobj->Active = NULL;
+ MEM_freeN(fobj->InitialVelocity);
+ fobj->InitialVelocity = NULL;
+ }
+
+ if (fobj->AttractforceStrength) {
+ MEM_freeN(fobj->AttractforceStrength);
+ fobj->AttractforceStrength = NULL;
+ MEM_freeN(fobj->AttractforceRadius);
+ fobj->AttractforceRadius = NULL;
+ MEM_freeN(fobj->VelocityforceStrength);
+ fobj->VelocityforceStrength = NULL;
+ MEM_freeN(fobj->VelocityforceRadius);
+ fobj->VelocityforceRadius = NULL;
+ }
+
+ if (fobj->VertexCache) {
+ MEM_freeN(fobj->VertexCache);
+ fobj->VertexCache = NULL;
+ }
}
+}
- cstr = "fluidsiminit_channelfloat";
- if(entries>1) cstr = "fluidsiminit_channelvec";
- channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr );
+static void fluid_init_all_channels(bContext *C, Object *fsDomain, FluidsimSettings *domainSettings, FluidAnimChannels *channels, ListBase *fobjects)
+{
+ Scene *scene = CTX_data_scene(C);
+ Base *base;
+ int i;
+ int length = channels->length;
+ float eval_time;
- if(ipo) {
- for(j=0; j<entries; j++) icus[j] = find_ipocurve(ipo, icuIds[j] );
- } else {
- for(j=0; j<entries; j++) icus[j] = NULL;
- }
+ /* XXX: first init time channel - temporary for now */
+ /* init time values (should be done after evaluating animated time curve) */
+ init_time(domainSettings, channels);
- for(j=0; j<entries; j++) {
- if(icus[j]) {
- for(i=1; i<=size; i++) {
- /* Bugfix to make python drivers working
- // which uses Blender.get("curframe")
- */
- scene->r.cfra = floor(aniFrlen*((float)i));
+ /* allocate domain animation channels */
+ channels->DomainGravity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
+ channels->DomainViscosity = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
+ //channels->DomainTime = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
+
+ /* allocate fluid objects */
+ for (base=scene->base.first; base; base= base->next) {
+ Object *ob = base->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+
+ if (fluidmd) {
+ FluidObject *fobj = MEM_callocN(sizeof(FluidObject), "Fluid Object");
+ fobj->object = ob;
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) {
+ BLI_addtail(fobjects, fobj);
+ continue;
+ }
+
+ fobj->Translation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation");
+ fobj->Rotation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation");
+ fobj->Scale = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale");
+ fobj->Active = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active");
+ fobj->InitialVelocity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity");
+
+ if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
+ fobj->AttractforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength");
+ fobj->AttractforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius");
+ fobj->VelocityforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength");
+ fobj->VelocityforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius");
+ }
+
+ if (fluid_is_animated_mesh(fluidmd->fss)) {
+ float *verts=NULL;
+ int *tris=NULL, modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+
+ initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
+ fobj->VertexCache = MEM_callocN( length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
- // XXX calc_icu(icus[j], aniFrlen*((float)i) );
- channel[(i-1)*(entries+1) + j] = icus[j]->curval;
+ MEM_freeN(verts);
+ MEM_freeN(tris);
}
- } else {
- for(i=1; i<=size; i++) { channel[(i-1)*(entries+1) + j] = defaults[j]; }
+
+ BLI_addtail(fobjects, fobj);
}
- //printf("fluidsimInitChannel entry:%d , ",j); for(i=1; i<=size; i++) { printf(" val%d:%f ",i, channel[(i-1)*(entries+1) + j] ); } printf(" \n"); // DEBUG
}
- // set time values
- for(i=1; i<=size; i++) {
- channel[(i-1)*(entries+1) + entries] = time[i];
+
+ /* now we loop over the frames and fill the allocated channels with data */
+ for (i=0; i<channels->length; i++) {
+ FluidObject *fobj;
+ float viscosity, gravity[3];
+ float timeAtFrame;
+
+ eval_time = domainSettings->bakeStart + i;
+ timeAtFrame = channels->timeAtFrame[i+1];
+
+ /* XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
+ * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
+ * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
+ * This doesn't work with drivers:
+ * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
+ */
+
+ /* Modifying the global scene isn't nice, but we can do it in
+ * this part of the process before a threaded job is created */
+ scene->r.cfra = (int)eval_time;
+ ED_update_for_newframe(C, 1);
+
+ /* now scene data should be current according to animation system, so we fill the channels */
+
+ /* Domain properties - gravity/viscosity/time */
+ get_fluid_gravity(gravity, scene, domainSettings);
+ set_channel(channels->DomainGravity, timeAtFrame, gravity, i, CHANNEL_VEC);
+ viscosity = get_fluid_viscosity(domainSettings);
+ set_channel(channels->DomainViscosity, timeAtFrame, &viscosity, i, CHANNEL_FLOAT);
+ // XXX : set_channel(channels->DomainTime, timeAtFrame, &time, i, CHANNEL_VEC);
+
+ /* object movement */
+ for (fobj=fobjects->first; fobj; fobj=fobj->next) {
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+ float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE);
+ float rot_d[3], rot_360[3] = {360.f, 360.f, 360.f};
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
+ continue;
+
+ /* init euler rotation values and convert to elbeem format */
+ BKE_rotMode_change_values(ob->quat, ob->rot, ob->rotAxis, &ob->rotAngle, ob->rotmode, ROT_MODE_EUL);
+ mul_v3_v3fl(rot_d, ob->rot, 180.f/M_PI);
+ sub_v3_v3v3(rot_d, rot_360, rot_d);
+
+ set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
+ set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
+ set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC);
+ set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
+ set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
+
+ if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
+ set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT);
+ set_channel(fobj->AttractforceRadius, timeAtFrame, &fluidmd->fss->attractforceRadius, i, CHANNEL_FLOAT);
+ set_channel(fobj->VelocityforceStrength, timeAtFrame, &fluidmd->fss->velocityforceStrength, i, CHANNEL_FLOAT);
+ set_channel(fobj->VelocityforceRadius, timeAtFrame, &fluidmd->fss->velocityforceRadius, i, CHANNEL_FLOAT);
+ }
+
+ if (fluid_is_animated_mesh(fluidmd->fss)) {
+ set_vertex_channel(fobj->VertexCache, timeAtFrame, scene, fobj, i);
+ }
+ }
}
- scene->r.cfra = current_frame;
- *setchannel = channel;
-#endif
}
-static void fluidsimInitMeshChannel(bContext *C, float **setchannel, int size, Object *obm, int vertices,
- float *time, int modifierIndex)
+static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length)
{
- Scene *scene= CTX_data_scene(C);
- float *channel = NULL;
- int mallsize = size* (3*vertices+1);
- int frame,i;
- int numVerts=0, numTris=0;
- int setsize = 3*vertices+1;
-
- channel = MEM_callocN( mallsize* sizeof(float), "fluidsim_meshchannel" );
-
- //fprintf(stderr,"\n\nfluidsimInitMeshChannel size%d verts%d mallsize%d \n\n\n",size,vertices,mallsize);
- for(frame=1; frame<=size; frame++) {
+ FluidObject *fobj;
+
+ for (fobj=fobjects->first; fobj; fobj=fobj->next) {
+ Object *ob = fobj->object;
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+ int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
+
float *verts=NULL;
int *tris=NULL;
- scene->r.cfra = frame;
- ED_update_for_newframe(C, 1);
+ int numVerts=0, numTris=0;
+ int deform = fluid_is_animated_mesh(fluidmd->fss);
+
+ elbeemMesh fsmesh;
+
+ if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
+ continue;
+
+ elbeemResetMesh( &fsmesh );
+
+ fsmesh.type = fluidmd->fss->type;
+ fsmesh.name = ob->id.name;
+
+ initElbeemMesh(scene, ob, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
+
+ fsmesh.numVertices = numVerts;
+ fsmesh.numTriangles = numTris;
+ fsmesh.vertices = verts;
+ fsmesh.triangles = tris;
+
+ fsmesh.channelSizeTranslation =
+ fsmesh.channelSizeRotation =
+ fsmesh.channelSizeScale =
+ fsmesh.channelSizeInitialVel =
+ fsmesh.channelSizeActive = length;
+
+ fsmesh.channelTranslation = fobj->Translation;
+ fsmesh.channelRotation = fobj->Rotation;
+ fsmesh.channelScale = fobj->Scale;
+ fsmesh.channelActive = fobj->Active;
+
+ if( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
+ fsmesh.channelInitialVel = fobj->InitialVelocity;
+ fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD)?1:0);
+ }
+
+ if(fluidmd->fss->typeFlags & OB_FSBND_NOSLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if(fluidmd->fss->typeFlags & OB_FSBND_PARTSLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if(fluidmd->fss->typeFlags & OB_FSBND_FREESLIP)
+ fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
+
+ fsmesh.obstaclePartslip = fluidmd->fss->partSlipValue;
+ fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
+ fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
+
+ if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
+ fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
+ fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
+ fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
+ fsmesh.obstacleType = (fluidmd->fss->flag & OB_FLUIDSIM_REVERSE);
+
+ fsmesh.channelSizeAttractforceRadius =
+ fsmesh.channelSizeVelocityforceStrength =
+ fsmesh.channelSizeVelocityforceRadius =
+ fsmesh.channelSizeAttractforceStrength = length;
+
+ fsmesh.channelAttractforceStrength = fobj->AttractforceStrength;
+ fsmesh.channelAttractforceRadius = fobj->AttractforceRadius;
+ fsmesh.channelVelocityforceStrength = fobj->VelocityforceStrength;
+ fsmesh.channelVelocityforceRadius = fobj->VelocityforceRadius;
+ }
+ else {
+ fsmesh.channelAttractforceStrength =
+ fsmesh.channelAttractforceRadius =
+ fsmesh.channelVelocityforceStrength =
+ fsmesh.channelVelocityforceRadius = NULL;
+ }
+
+ /* animated meshes */
+ if(deform) {
+ fsmesh.channelSizeVertices = length;
+ fsmesh.channelVertices = fobj->VertexCache;
+
+ // remove channels
+ fsmesh.channelTranslation =
+ fsmesh.channelRotation =
+ fsmesh.channelScale = NULL;
+ }
+
+ elbeemAddMesh(&fsmesh);
+
+ if(verts) MEM_freeN(verts);
+ if(tris) MEM_freeN(tris);
+ if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices);
+ }
+}
+
+static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDomain)
+{
+ Base *base;
+ Object *newdomain = NULL;
+ int channelObjCount = 0;
+ int fluidInputCount = 0;
+
+ for(base=scene->base.first; base; base= base->next)
+ {
+ Object *ob = base->object;
+ FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- initElbeemMesh(scene, obm, &numVerts, &verts, &numTris, &tris, 1, modifierIndex);
- //fprintf(stderr,"\nfluidsimInitMeshChannel frame%d verts%d/%d \n\n",frame,vertices,numVerts);
- for(i=0; i<3*vertices;i++) {
- channel[(frame-1)*setsize + i] = verts[i];
- //fprintf(stdout," frame%d vert%d=%f \n",frame,i,verts[i]);
- //if(i%3==2) fprintf(stdout,"\n");
+ /* only find objects with fluid modifiers */
+ if (!fluidmdtmp || ob->type != OB_MESH) continue;
+
+ if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN) {
+ /* if no initial domain object given, find another potential domain */
+ if (!fsDomain) {
+ newdomain = ob;
+ }
+ /* if there's more than one domain, cancel */
+ else if (fsDomain && ob != fsDomain) {
+ BKE_report(reports, RPT_ERROR, "There should be only one domain object.");
+ return 0;
+ }
}
- channel[(frame-1)*setsize + setsize-1] = time[frame];
+
+ /* count number of objects needed for animation channels */
+ if ( !ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE) )
+ channelObjCount++;
+
+ /* count number of fluid input objects */
+ if (ELEM(fluidmdtmp->fss->type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW))
+ fluidInputCount++;
+ }
- MEM_freeN(verts);
- MEM_freeN(tris);
+ if (newdomain)
+ fsDomain = newdomain;
+
+ if (!fsDomain) {
+ BKE_report(reports, RPT_ERROR, "No domain object found.");
+ return 0;
+ }
+
+ if (channelObjCount>=255) {
+ BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects.");
+ return 0;
}
- *setchannel = channel;
+
+ if (fluidInputCount == 0) {
+ BKE_report(reports, RPT_ERROR, "No fluid input objects in the scene.");
+ return 0;
+ }
+
+ return 1;
}
+#define FLUID_SUFFIX_CONFIG "fluidsim.cfg"
+#define FLUID_SUFFIX_SURFACE "fluidsurface"
+
+static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer)
+{
+ FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
+ FluidsimSettings *domainSettings= fluidmd->fss;
+ FILE *fileCfg;
+ int dirExist = 0;
+ char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
+ char *suffixConfig = FLUID_SUFFIX_CONFIG;
+ int outStringsChanged = 0;
+
+ // prepare names...
+ strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
+ strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
+ BLI_path_abs(targetDir, G.sce); // fixed #frame-no
+
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixConfig);
+ strcat(targetFile,".tmp"); // dont overwrite/delete original file
+ // make sure all directories exist
+ // as the bobjs use the same dir, this only needs to be checked
+ // for the cfg output
+ BLI_make_existing_file(targetFile);
+
+ // check selected directory
+ // simply try to open cfg file for writing to test validity of settings
+ fileCfg = fopen(targetFile, "w");
+ if(fileCfg) {
+ dirExist = 1; fclose(fileCfg);
+ // remove cfg dummy from directory test
+ BLI_delete(targetFile, 0,0);
+ }
+
+ if((strlen(targetDir)<1) || (!dirExist)) {
+ char blendDir[FILE_MAXDIR+FILE_MAXFILE];
+ char blendFile[FILE_MAXDIR+FILE_MAXFILE];
+
+ // invalid dir, reset to current/previous
+ strcpy(blendDir, G.sce);
+ BLI_splitdirstring(blendDir, blendFile);
+ if(strlen(blendFile)>6){
+ int len = strlen(blendFile);
+ if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&&
+ (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){
+ blendFile[len-6] = '\0';
+ }
+ }
+ // todo... strip .blend ?
+ snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
+
+ snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
+ elbeemDebugOut(debugStrBuffer);
+ outStringsChanged=1;
+ }
+
+ // check if modified output dir is ok
+#if 0
+ if(outStringsChanged) {
+ char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
+ int selection=0;
+ strcpy(dispmsg,"Output settings set to: '");
+ strcat(dispmsg, newSurfdataPath);
+ strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");
+
+ // ask user if thats what he/she wants...
+ selection = pupmenu(dispmsg);
+ if(selection<1) return 0; // 0 from menu, or -1 aborted
+ strcpy(targetDir, newSurfdataPath);
+ strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
+ BLI_path_abs(targetDir, G.sce); // fixed #frame-no
+ }
+#endif
+ return outStringsChanged;
+}
+
/* ******************************************************************************** */
-/* ********************** simulation thread ************************* */
+/* ********************** write fluidsim config to file ************************* */
/* ******************************************************************************** */
-static volatile int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done
-static volatile int globalBakeFrame = 0;
-static volatile int g_break= 0;
+typedef struct FluidBakeJob {
+ /* from wmJob */
+ void *owner;
+ short *stop, *do_update;
+ float *progress;
+ int current_frame;
+ elbeemSimulationSettings *settings;
+} FluidBakeJob;
-// run simulation in seperate thread
-static void *fluidsimSimulateThread(void *unused) { // *ptr) {
- //char* fnameCfgPath = (char*)(ptr);
- int ret=0;
+static void fluidbake_free(void *customdata)
+{
+ FluidBakeJob *fb= customdata;
+ MEM_freeN(fb);
+}
+
+/* called by fluidbake, only to check job 'stop' value */
+static int fluidbake_breakjob(void *customdata)
+{
+ //FluidBakeJob *fb= (FluidBakeJob *)customdata;
+ //return *(fb->stop);
-#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
- // Workaround for Apple gcc 4.2.1 omp vs background thread bug
- pthread_setspecific (gomp_tls_key, thread_tls_data);
-#endif
+ /* this is not nice yet, need to make the jobs list template better
+ * for identifying/acting upon various different jobs */
+ /* but for now we'll reuse the render break... */
+ return (G.afbreek);
+}
- ret = elbeemSimulate();
- BLI_lock_thread(LOCK_CUSTOM1);
- if(globalBakeState==0) {
- if(ret==0) {
- // if no error, set to normal exit
- globalBakeState = 1;
- } else {
- // simulation failed, display error
- globalBakeState = -2;
- }
- }
- BLI_unlock_thread(LOCK_CUSTOM1);
- return NULL;
+/* called by fluidbake, wmJob sends notifier */
+static void fluidbake_updatejob(void *customdata, float progress)
+{
+ FluidBakeJob *fb= customdata;
+
+ *(fb->do_update)= 1;
+ *(fb->progress)= progress;
}
+static void fluidbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+ FluidBakeJob *fb= customdata;
+
+ fb->stop= stop;
+ fb->do_update = do_update;
+ fb->progress = progress;
+
+ G.afbreek= 0; /* XXX shared with render - replace with job 'stop' switch */
+
+ elbeemSimulate();
+ *do_update= 1;
+ *stop = 0;
+}
-int runSimulationCallback(void *data, int status, int frame) {
- //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data;
- //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG
- int state = 0;
- if(status==FLUIDSIM_CBSTATUS_NEWFRAME) {
- BLI_lock_thread(LOCK_CUSTOM1);
- globalBakeFrame = frame-1;
- BLI_unlock_thread(LOCK_CUSTOM1);
+static void fluidbake_endjob(void *customdata)
+{
+ FluidBakeJob *fb= customdata;
+
+ if (fb->settings) {
+ MEM_freeN(fb->settings);
+ fb->settings = NULL;
}
+}
+
+int runSimulationCallback(void *data, int status, int frame) {
+ FluidBakeJob *fb = (FluidBakeJob *)data;
+ elbeemSimulationSettings *settings = fb->settings;
- //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; }
-
- BLI_lock_thread(LOCK_CUSTOM1);
- state = globalBakeState;
- BLI_unlock_thread(LOCK_CUSTOM1);
+ if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
+ fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
+ //printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d \n", status,frame, settings->domainId, settings->noOfFrames ); // DEBUG
+ }
- if(state!=0) {
+ if (fluidbake_breakjob(fb)) {
return FLUIDSIM_CBRET_ABORT;
}
return FLUIDSIM_CBRET_CONTINUE;
}
+static void fluidbake_free_data(FluidAnimChannels *channels, ListBase *fobjects, elbeemSimulationSettings *fsset, FluidBakeJob *fb)
+{
+ free_domain_channels(channels);
+ MEM_freeN(channels);
+ channels = NULL;
+
+ free_all_fluidobject_channels(fobjects);
+ BLI_freelistN(fobjects);
+ MEM_freeN(fobjects);
+ fobjects = NULL;
+
+ if (fsset) {
+ MEM_freeN(fsset);
+ fsset = NULL;
+ }
+
+ if (fb) {
+ MEM_freeN(fb);
+ fb = NULL;
+ }
+}
-/* ******************************************************************************** */
-/* ********************** write fluidsim config to file ************************* */
-/* ******************************************************************************** */
-
-int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
+int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain)
{
Scene *scene= CTX_data_scene(C);
- FILE *fileCfg;
int i;
- Object *fsDomain = NULL;
FluidsimSettings *domainSettings;
- Object *obit = NULL; /* object iterator */
- Base *base;
- int origFrame = scene->r.cfra;
+
char debugStrBuffer[256];
- int dirExist = 0;
+
int gridlevels = 0;
- int simAborted = 0; // was the simulation aborted by user?
- int doExportOnly = 0;
- char *exportEnvStr = "BLENDER_ELBEEMEXPORTONLY";
const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
- //char *channelNames[3] = { "translation","rotation","scale" };
+ char *suffixConfig = FLUID_SUFFIX_CONFIG;
+ char *suffixSurface = FLUID_SUFFIX_SURFACE;
- char *suffixConfig = "fluidsim.cfg";
- char *suffixSurface = "fluidsurface";
- char newSurfdataPath[FILE_MAXDIR+FILE_MAXFILE]; // modified output settings
char targetDir[FILE_MAXDIR+FILE_MAXFILE]; // store & modify output settings
char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
int outStringsChanged = 0; // modified? copy back before baking
- int haveSomeFluid = 0; // check if any fluid objects are set
- // config vars, inited before either export or run...
- double calcViscosity = 0.0;
- int noFrames;
- double aniFrameTime;
- float aniFrlen;
- int channelObjCount;
- float *bbStart = NULL;
- float *bbSize = NULL;
float domainMat[4][4];
float invDomMat[4][4];
- // channel data
- int allchannelSize; // fixed by no. of frames
- int startFrame = 1; // dont use scene->r.sfra here, always start with frame 1
- // easy frame -> sim time calc
- float *timeAtFrame=NULL, *timeAtIndex=NULL;
- // domain
- float *channelDomainTime = NULL;
- float *channelDomainViscosity = NULL;
- float *channelDomainGravity = NULL;
- // objects (currently max. 256 objs)
- float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale
- float *channelObjInivel[256]; // initial velocities
- float *channelObjActive[256]; // obj active channel
-
- /* fluid control channels */
- float *channelAttractforceStrength[256];
- float *channelAttractforceRadius[256];
- float *channelVelocityforceStrength[256];
- float *channelVelocityforceRadius[256];
+
+ int noFrames;
+ int origFrame = scene->r.cfra;
+
+ FluidAnimChannels *channels = MEM_callocN(sizeof(FluidAnimChannels), "fluid domain animation channels");
+ ListBase *fobjects = MEM_callocN(sizeof(ListBase), "fluid objects");
FluidsimModifierData *fluidmd = NULL;
Mesh *mesh = NULL;
+ wmJob *steve;
+ FluidBakeJob *fb;
+ elbeemSimulationSettings *fsset= MEM_callocN(sizeof(elbeemSimulationSettings), "Fluid sim settings");
+
+ steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", WM_JOB_PROGRESS);
+ fb= MEM_callocN(sizeof(FluidBakeJob), "fluid bake job");
+
if(getenv(strEnvName)) {
int dlevel = atoi(getenv(strEnvName));
elbeemSetDebugLevel(dlevel);
snprintf(debugStrBuffer,256,"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName);
elbeemDebugOut(debugStrBuffer);
}
- if(getenv(exportEnvStr)) {
- doExportOnly = atoi(getenv(exportEnvStr));
- snprintf(debugStrBuffer,256,"fluidsimBake::msg: Exporting mode set to '%d' due to envvar '%s'\n",doExportOnly, exportEnvStr);
- elbeemDebugOut(debugStrBuffer);
- }
-
- // make sure it corresponds to startFrame setting
- // old: noFrames = scene->r.efra - scene->r.sfra +1;
+
+ /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
noFrames = scene->r.efra - 0;
if(noFrames<=0) {
BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings.");
+ fluidbake_free_data(channels, fobjects, fsset, fb);
return 0;
}
-
- /* no object pointer, find in selected ones.. */
- if(!ob) {
- for(base=scene->base.first; base; base= base->next) {
- if ((base)->flag & SELECT)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
-
- if(fluidmdtmp && (base->object->type==OB_MESH))
- {
- if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
- {
- ob = base->object;
- break;
- }
- }
- }
- }
- // no domains found?
- if(!ob) return 0;
- }
- channelObjCount = 0;
- for(base=scene->base.first; base; base= base->next)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
- obit = base->object;
- if( fluidmdtmp &&
- (obit->type==OB_MESH) &&
- (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
- (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) )
- {
- channelObjCount++;
- }
- }
-
- if (channelObjCount>=255) {
- BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects.");
- return 0;
- }
-
- /* check if there's another domain... */
- for(base=scene->base.first; base; base= base->next)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
- obit = base->object;
- if( fluidmdtmp &&(obit->type==OB_MESH))
- {
- if(fluidmdtmp->fss->type == OB_FLUIDSIM_DOMAIN)
- {
- if(obit != ob)
- {
- BKE_report(reports, RPT_ERROR, "There should be only one domain object.");
- return 0;
- }
- }
- }
- }
-
- // check if theres any fluid
- // abort baking if not...
- for(base=scene->base.first; base; base= base->next)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
- obit = base->object;
- if( fluidmdtmp &&
- (obit->type==OB_MESH) &&
- ((fluidmdtmp->fss->type == OB_FLUIDSIM_FLUID) ||
- (fluidmdtmp->fss->type == OB_FLUIDSIM_INFLOW) ))
- {
- haveSomeFluid = 1;
- break;
- }
- }
- if(!haveSomeFluid) {
- BKE_report(reports, RPT_ERROR, "No fluid objects in scene.");
+ /* check scene for sane object/modifier settings */
+ if (!fluid_validate_scene(reports, scene, fsDomain)) {
+ fluidbake_free_data(channels, fobjects, fsset, fb);
return 0;
}
/* these both have to be valid, otherwise we wouldnt be here */
- /* dont use ob here after...*/
- fsDomain = ob;
- fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
+ fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
domainSettings = fluidmd->fss;
- ob = NULL;
mesh = fsDomain->data;
+ domainSettings->bakeStart = 1;
+ domainSettings->bakeEnd = scene->r.efra;
+
// calculate bounding box
fluid_get_bb(mesh->mvert, mesh->totvert, fsDomain->obmat, domainSettings->bbStart, domainSettings->bbSize);
@@ -572,107 +899,26 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
}
snprintf(debugStrBuffer,256,"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels );
elbeemDebugOut(debugStrBuffer);
-
- // prepare names...
- strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
- strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR);
- BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no
-
- strcpy(targetFile, targetDir);
- strcat(targetFile, suffixConfig);
- if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
- // make sure all directories exist
- // as the bobjs use the same dir, this only needs to be checked
- // for the cfg output
- BLI_make_existing_file(targetFile);
-
- // check selected directory
- // simply try to open cfg file for writing to test validity of settings
- fileCfg = fopen(targetFile, "w");
- if(fileCfg) {
- dirExist = 1; fclose(fileCfg);
- // remove cfg dummy from directory test
- if(!doExportOnly) { BLI_delete(targetFile, 0,0); }
- }
-
- if((strlen(targetDir)<1) || (!dirExist)) {
- char blendDir[FILE_MAXDIR+FILE_MAXFILE], blendFile[FILE_MAXDIR+FILE_MAXFILE];
- // invalid dir, reset to current/previous
- strcpy(blendDir, G.sce);
- BLI_splitdirstring(blendDir, blendFile);
- if(strlen(blendFile)>6){
- int len = strlen(blendFile);
- if( (blendFile[len-6]=='.')&& (blendFile[len-5]=='b')&& (blendFile[len-4]=='l')&&
- (blendFile[len-3]=='e')&& (blendFile[len-2]=='n')&& (blendFile[len-1]=='d') ){
- blendFile[len-6] = '\0';
- }
- }
- // todo... strip .blend ?
- snprintf(newSurfdataPath,FILE_MAXFILE+FILE_MAXDIR,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
-
- snprintf(debugStrBuffer,256,"fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
- elbeemDebugOut(debugStrBuffer);
- outStringsChanged=1;
- }
-
- // check if modified output dir is ok
- if(outStringsChanged) {
- char dispmsg[FILE_MAXDIR+FILE_MAXFILE+256];
- int selection=0;
- strcpy(dispmsg,"Output settings set to: '");
- strcat(dispmsg, newSurfdataPath);
- strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");
-
- // ask user if thats what he/she wants...
- selection = pupmenu(dispmsg);
- if(selection<1) return 0; // 0 from menu, or -1 aborted
- strcpy(targetDir, newSurfdataPath);
- strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
- BLI_convertstringcode(targetDir, G.sce); // fixed #frame-no
- }
- // --------------------------------------------------------------------------------------------
- // dump data for start frame
- // CHECK more reasonable to number frames according to blender?
- // dump data for frame 0
- scene->r.cfra = startFrame;
- ED_update_for_newframe(C, 1);
- // init common export vars for both file export and run
- for(i=0; i<256; i++) {
- channelObjMove[i][0] = channelObjMove[i][1] = channelObjMove[i][2] = NULL;
- channelObjInivel[i] = NULL;
- channelObjActive[i] = NULL;
- channelAttractforceStrength[i] = NULL;
- channelAttractforceRadius[i] = NULL;
- channelVelocityforceStrength[i] = NULL;
- channelVelocityforceRadius[i] = NULL;
- }
- allchannelSize = scene->r.efra; // always use till last frame
- aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
- // blender specific - scale according to map old/new settings in anim panel:
- aniFrlen = scene->r.framelen;
- if(domainSettings->viscosityMode==1) {
- /* manual mode, visc=value/(10^-vexp) */
- calcViscosity = (1.0/pow(10.0,domainSettings->viscosityExponent)) * domainSettings->viscosityValue;
- } else {
- calcViscosity = fluidsimViscosityPreset[ domainSettings->viscosityMode ];
- }
-
- bbStart = domainSettings->bbStart;
- bbSize = domainSettings->bbSize;
+
+ /* ******** prepare output file paths ******** */
+ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
+ channels->length = scene->r.efra;
+ channels->aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
+
+ /* ******** initialise and allocate animation channels ******** */
+ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);
- // always init
+ /* reset to original current frame */
+ scene->r.cfra = origFrame;
+ ED_update_for_newframe(C, 1);
+
+
+ /* ---- XXX: No Time animation curve for now, leaving this code here for reference
+
{ int timeIcu[1] = { FLUIDSIM_TIME };
float timeDef[1] = { 1. };
- int gravIcu[3] = { FLUIDSIM_GRAV_X, FLUIDSIM_GRAV_Y, FLUIDSIM_GRAV_Z };
- float gravDef[3];
- int viscIcu[1] = { FLUIDSIM_VISC };
- float viscDef[1] = { 1. };
-
- gravDef[0] = domainSettings->gravx;
- gravDef[1] = domainSettings->gravy;
- gravDef[2] = domainSettings->gravz;
// time channel is a bit special, init by hand...
timeAtIndex = MEM_callocN( (allchannelSize+1)*1*sizeof(float), "fluidsiminit_timeatindex");
@@ -680,7 +926,7 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
timeAtIndex[i] = (float)(i-startFrame);
}
fluidsimInitChannel(scene, &channelDomainTime, allchannelSize, timeAtIndex, timeIcu,timeDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
- // time channel is a multiplicator for aniFrameTime
+ // time channel is a multiplicator for
if(channelDomainTime) {
for(i=0; i<allchannelSize; i++) {
channelDomainTime[i*2+0] = aniFrameTime * channelDomainTime[i*2+0];
@@ -693,474 +939,112 @@ int fluidsimBake(bContext *C, ReportList *reports, Object *ob)
for(i=2; i<=allchannelSize; i++) {
timeAtFrame[i] = timeAtFrame[i-1]+channelDomainTime[(i-1)*2+0];
}
- } else {
+ fsset->} else {
for(i=2; i<=allchannelSize; i++) { timeAtFrame[i] = timeAtFrame[i-1]+aniFrameTime; }
}
- fluidsimInitChannel(scene, &channelDomainViscosity, allchannelSize, timeAtFrame, viscIcu,viscDef, domainSettings->ipo, CHANNEL_FLOAT ); // NDEB
- if(channelDomainViscosity) {
- for(i=0; i<allchannelSize; i++) { channelDomainViscosity[i*2+0] = calcViscosity * channelDomainViscosity[i*2+0]; }
- }
- fluidsimInitChannel(scene, &channelDomainGravity, allchannelSize, timeAtFrame, gravIcu,gravDef, domainSettings->ipo, CHANNEL_VEC );
} // domain channel init
-
- // init obj movement channels
- channelObjCount=0;
- for(base=scene->base.first; base; base= base->next)
- {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
- obit = base->object;
+ */
- if( fluidmdtmp &&
- (obit->type==OB_MESH) &&
- (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH
- (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE) ) {
-
- // cant use fluidsimInitChannel for obj channels right now, due
- // to the special DXXX channels, and the rotation specialities
- IpoCurve *icuex[3][3];
- //IpoCurve *par_icuex[3][3];
-#if 0
- int icuIds[3][3] = {
- {OB_LOC_X, OB_LOC_Y, OB_LOC_Z},
- {OB_ROT_X, OB_ROT_Y, OB_ROT_Z},
- {OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z}
- };
- int icudIds[3][3] = {
- {OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z},
- {OB_DROT_X, OB_DROT_Y, OB_DROT_Z},
- {OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z}
- };
-#endif
- // relative ipos
- IpoCurve *icudex[3][3];
- //IpoCurve *par_icudex[3][3];
- int j,k;
- float vals[3] = {0.0,0.0,0.0};
- int o = channelObjCount;
- int inivelIcu[3] = { FLUIDSIM_VEL_X, FLUIDSIM_VEL_Y, FLUIDSIM_VEL_Z };
- float inivelDefs[3];
- int activeIcu[1] = { FLUIDSIM_ACTIVE };
- float activeDefs[1] = { 1 }; // default to on
-
- inivelDefs[0] = fluidmdtmp->fss->iniVelx;
- inivelDefs[1] = fluidmdtmp->fss->iniVely;
- inivelDefs[2] = fluidmdtmp->fss->iniVelz;
-
- // check & init loc,rot,size
- for(j=0; j<3; j++) {
- for(k=0; k<3; k++) {
- // XXX prevent invalid memory access until this works
- icuex[j][k]= NULL;
- icudex[j][k]= NULL;
-
- // XXX icuex[j][k] = find_ipocurve(obit->ipo, icuIds[j][k] );
- // XXX icudex[j][k] = find_ipocurve(obit->ipo, icudIds[j][k] );
- // XXX lines below were already disabled!
- //if(obit->parent) {
- //par_icuex[j][k] = find_ipocurve(obit->parent->ipo, icuIds[j][k] );
- //par_icudex[j][k] = find_ipocurve(obit->parent->ipo, icudIds[j][k] );
- //}
- }
- }
-
- for(j=0; j<3; j++) {
- channelObjMove[o][j] = MEM_callocN( allchannelSize*4*sizeof(float), "fluidsiminit_objmovchannel");
- for(i=1; i<=allchannelSize; i++) {
-
- for(k=0; k<3; k++) {
- if(icuex[j][k]) {
- // IPO exists, use it ...
- // XXX calc_icu(icuex[j][k], aniFrlen*((float)i) );
- vals[k] = icuex[j][k]->curval;
- if(obit->parent) {
- // add parent transform, multiply scaling, add trafo&rot
- //calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
- //if(j==2) { vals[k] *= par_icuex[j][k]->curval; }
- //else { vals[k] += par_icuex[j][k]->curval; }
- }
- } else {
- // use defaults from static values
- float setval=0.0;
- if(j==0) {
- setval = obit->loc[k];
- if(obit->parent){ setval += obit->parent->loc[k]; }
- } else if(j==1) {
- setval = ( 180.0*obit->rot[k] )/( 10.0*M_PI );
- if(obit->parent){ setval = ( 180.0*(obit->rot[k]+obit->parent->rot[k]) )/( 10.0*M_PI ); }
- } else {
- setval = obit->size[k];
- if(obit->parent){ setval *= obit->parent->size[k]; }
- }
- vals[k] = setval;
- }
- if(icudex[j][k]) {
- // XXX calc_icu(icudex[j][k], aniFrlen*((float)i) );
- //vals[k] += icudex[j][k]->curval;
- // add transform, multiply scaling, add trafo&rot
- if(j==2) { vals[k] *= icudex[j][k]->curval; }
- else { vals[k] += icudex[j][k]->curval; }
- if(obit->parent) {
- // add parent transform, multiply scaling, add trafo&rot
- //calc_icu(par_icuex[j][k], aniFrlen*((float)i) );
- //if(j==2) { vals[k] *= par_icudex[j][k]->curval; }
- //else { vals[k] += par_icudex[j][k]->curval; }
- }
- }
- } // k
-
- for(k=0; k<3; k++) {
- float set = vals[k];
- if(j==1) { // rot is downscaled by 10 for ipo !?
- set = 360.0 - (10.0*set);
- }
- channelObjMove[o][j][(i-1)*4 + k] = set;
- } // k
- channelObjMove[o][j][(i-1)*4 + 3] = timeAtFrame[i];
- }
- }
-
- {
- int attrFSIcu[1] = { FLUIDSIM_ATTR_FORCE_STR };
- int attrFRIcu[1] = { FLUIDSIM_ATTR_FORCE_RADIUS };
- int velFSIcu[1] = { FLUIDSIM_VEL_FORCE_STR };
- int velFRIcu[1] = { FLUIDSIM_VEL_FORCE_RADIUS };
-
- float attrFSDefs[1];
- float attrFRDefs[1];
- float velFSDefs[1];
- float velFRDefs[1];
-
- attrFSDefs[0] = fluidmdtmp->fss->attractforceStrength;
- attrFRDefs[0] = fluidmdtmp->fss->attractforceRadius;
- velFSDefs[0] = fluidmdtmp->fss->velocityforceStrength;
- velFRDefs[0] = fluidmdtmp->fss->velocityforceRadius;
-
- fluidsimInitChannel(scene, &channelAttractforceStrength[o], allchannelSize, timeAtFrame, attrFSIcu,attrFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
- fluidsimInitChannel(scene, &channelAttractforceRadius[o], allchannelSize, timeAtFrame, attrFRIcu,attrFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
- fluidsimInitChannel(scene, &channelVelocityforceStrength[o], allchannelSize, timeAtFrame, velFSIcu,velFSDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
- fluidsimInitChannel(scene, &channelVelocityforceRadius[o], allchannelSize, timeAtFrame, velFRIcu,velFRDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
- }
-
- fluidsimInitChannel(scene, &channelObjInivel[o], allchannelSize, timeAtFrame, inivelIcu,inivelDefs, fluidmdtmp->fss->ipo, CHANNEL_VEC );
- fluidsimInitChannel(scene, &channelObjActive[o], allchannelSize, timeAtFrame, activeIcu,activeDefs, fluidmdtmp->fss->ipo, CHANNEL_FLOAT );
-
-
- channelObjCount++;
-
- }
- }
-
- // init trafo matrix
+ /* ******** init domain object's matrix ******** */
copy_m4_m4(domainMat, fsDomain->obmat);
if(!invert_m4_m4(invDomMat, domainMat)) {
snprintf(debugStrBuffer,256,"fluidsimBake::error - Invalid obj matrix?\n");
elbeemDebugOut(debugStrBuffer);
BKE_report(reports, RPT_ERROR, "Invalid object matrix.");
- // FIXME add fatal msg
- FS_FREE_CHANNELS;
+
+ fluidbake_free_data(channels, fobjects, fsset, fb);
return 0;
}
- // --------------------------------------------------------------------------------------------
- // start writing / exporting
+ /* ******** start writing / exporting ******** */
strcpy(targetFile, targetDir);
strcat(targetFile, suffixConfig);
- if(!doExportOnly) { strcat(targetFile,".tmp"); } // dont overwrite/delete original file
+ strcat(targetFile,".tmp"); // dont overwrite/delete original file
+
// make sure these directories exist as well
if(outStringsChanged) {
BLI_make_existing_file(targetFile);
}
- if(!doExportOnly) {
- ListBase threads;
+ /* ******** export domain to elbeem ******** */
+ elbeemResetSettings(fsset);
+ fsset->version = 1;
- // perform simulation with El'Beem api and threads
- elbeemSimulationSettings fsset;
- elbeemResetSettings(&fsset);
- fsset.version = 1;
+ // setup global settings
+ copy_v3_v3(fsset->geoStart, domainSettings->bbStart);
+ copy_v3_v3(fsset->geoSize, domainSettings->bbSize);
+
+ // simulate with 50^3
+ fsset->resolutionxyz = (int)domainSettings->resolutionxyz;
+ fsset->previewresxyz = (int)domainSettings->previewresxyz;
- // setup global settings
- for(i=0 ; i<3; i++) fsset.geoStart[i] = bbStart[i];
- for(i=0 ; i<3; i++) fsset.geoSize[i] = bbSize[i];
-
- // simulate with 50^3
- fsset.resolutionxyz = (int)domainSettings->resolutionxyz;
- fsset.previewresxyz = (int)domainSettings->previewresxyz;
- // 10cm water domain
- fsset.realsize = domainSettings->realsize;
- fsset.viscosity = calcViscosity;
- // earth gravity
- fsset.gravity[0] = domainSettings->gravx;
- fsset.gravity[1] = domainSettings->gravy;
- fsset.gravity[2] = domainSettings->gravz;
- // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
- fsset.animStart = domainSettings->animStart;
- fsset.aniFrameTime = aniFrameTime;
- fsset.noOfFrames = noFrames; // is otherwise subtracted in parser
- strcpy(targetFile, targetDir);
- strcat(targetFile, suffixSurface);
- // defaults for compressibility and adaptive grids
- fsset.gstar = domainSettings->gstar;
- fsset.maxRefine = domainSettings->maxRefine; // check <-> gridlevels
- fsset.generateParticles = domainSettings->generateParticles;
- fsset.numTracerParticles = domainSettings->generateTracers;
- fsset.surfaceSmoothing = domainSettings->surfaceSmoothing;
- fsset.surfaceSubdivs = domainSettings->surfaceSubdivs;
- fsset.farFieldSize = domainSettings->farFieldSize;
- strcpy( fsset.outputPath, targetFile);
-
- // domain channels
- fsset.channelSizeFrameTime =
- fsset.channelSizeViscosity =
- fsset.channelSizeGravity = allchannelSize;
- fsset.channelFrameTime = channelDomainTime;
- fsset.channelViscosity = channelDomainViscosity;
- fsset.channelGravity = channelDomainGravity;
-
- fsset.runsimCallback = &runSimulationCallback;
- fsset.runsimUserData = &fsset;
-
- if( (domainSettings->typeFlags&OB_FSBND_NOSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
- else if((domainSettings->typeFlags&OB_FSBND_PARTSLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
- else if((domainSettings->typeFlags&OB_FSBND_FREESLIP)) fsset.domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
- fsset.domainobsPartslip = domainSettings->partSlipValue;
- fsset.generateVertexVectors = (domainSettings->domainNovecgen==0);
-
- // init blender trafo matrix
- // fprintf(stderr,"elbeemInit - mpTrafo:\n");
- { int j;
- for(i=0; i<4; i++) {
- for(j=0; j<4; j++) {
- fsset.surfaceTrafo[i*4+j] = invDomMat[j][i];
- // fprintf(stderr,"elbeemInit - mpTrafo %d %d = %f (%d) \n", i,j, fsset.surfaceTrafo[i*4+j] , (i*4+j) );
- }
- } }
+ fsset->realsize = get_fluid_size_m(scene, fsDomain, domainSettings);
+ fsset->viscosity = get_fluid_viscosity(domainSettings);
+ get_fluid_gravity(fsset->gravity, scene, domainSettings);
- // init solver with settings
- elbeemInit();
- elbeemAddDomain(&fsset);
-
- // init objects
- channelObjCount = 0;
- for(base=scene->base.first; base; base= base->next) {
- FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(base->object, eModifierType_Fluidsim);
- obit = base->object;
- //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG
- if( fluidmdtmp && // if has to match 3 places! // CHECKMATCH
- (obit->type==OB_MESH) &&
- (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN) &&
- (fluidmdtmp->fss->type != OB_FLUIDSIM_PARTICLE))
- {
- float *verts=NULL;
- int *tris=NULL;
- int numVerts=0, numTris=0;
- int o = channelObjCount;
- int deform = (fluidmdtmp->fss->domainNovecgen); // misused value
- // todo - use blenderInitElbeemMesh
- int modifierIndex = modifiers_indexInObject(obit, (ModifierData *)fluidmdtmp);
-
- elbeemMesh fsmesh;
- elbeemResetMesh( &fsmesh );
- fsmesh.type = fluidmdtmp->fss->type;
- // get name of object for debugging solver
- fsmesh.name = obit->id.name;
-
- initElbeemMesh(scene, obit, &numVerts, &verts, &numTris, &tris, 0, modifierIndex);
- fsmesh.numVertices = numVerts;
- fsmesh.numTriangles = numTris;
- fsmesh.vertices = verts;
- fsmesh.triangles = tris;
-
- fsmesh.channelSizeTranslation =
- fsmesh.channelSizeRotation =
- fsmesh.channelSizeScale =
- fsmesh.channelSizeInitialVel =
- fsmesh.channelSizeActive = allchannelSize;
-
- fsmesh.channelTranslation = channelObjMove[o][0];
- fsmesh.channelRotation = channelObjMove[o][1];
- fsmesh.channelScale = channelObjMove[o][2];
- fsmesh.channelActive = channelObjActive[o];
- if( (fsmesh.type == OB_FLUIDSIM_FLUID) ||
- (fsmesh.type == OB_FLUIDSIM_INFLOW)) {
- fsmesh.channelInitialVel = channelObjInivel[o];
- fsmesh.localInivelCoords = ((fluidmdtmp->fss->typeFlags&OB_FSINFLOW_LOCALCOORD)?1:0);
- }
-
- if( (fluidmdtmp->fss->typeFlags&OB_FSBND_NOSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
- else if((fluidmdtmp->fss->typeFlags&OB_FSBND_PARTSLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_PARTSLIP;
- else if((fluidmdtmp->fss->typeFlags&OB_FSBND_FREESLIP)) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_FREESLIP;
- fsmesh.obstaclePartslip = fluidmdtmp->fss->partSlipValue;
- fsmesh.volumeInitType = fluidmdtmp->fss->volumeInitType;
- fsmesh.obstacleImpactFactor = fluidmdtmp->fss->surfaceSmoothing; // misused value
-
- if(fsmesh.type == OB_FLUIDSIM_CONTROL)
- {
- // control fluids will get exported as whole
- deform = 1;
-
- fsmesh.cpsTimeStart = fluidmdtmp->fss->cpsTimeStart;
- fsmesh.cpsTimeEnd = fluidmdtmp->fss->cpsTimeEnd;
- fsmesh.cpsQuality = fluidmdtmp->fss->cpsQuality;
- fsmesh.obstacleType = (fluidmdtmp->fss->flag & OB_FLUIDSIM_REVERSE);
-
- fsmesh.channelSizeAttractforceRadius =
- fsmesh.channelSizeVelocityforceStrength =
- fsmesh.channelSizeVelocityforceRadius =
- fsmesh.channelSizeAttractforceStrength = allchannelSize;
-
- fsmesh.channelAttractforceStrength = channelAttractforceStrength[o];
- fsmesh.channelAttractforceRadius = channelAttractforceRadius[o];
- fsmesh.channelVelocityforceStrength = channelVelocityforceStrength[o];
- fsmesh.channelVelocityforceRadius = channelVelocityforceRadius[o];
- }
- else
- {
- // set channels to 0
- fsmesh.channelAttractforceStrength =
- fsmesh.channelAttractforceRadius =
- fsmesh.channelVelocityforceStrength =
- fsmesh.channelVelocityforceRadius = NULL;
- }
-
- // animated meshes
- if(deform) {
- fsmesh.channelSizeVertices = allchannelSize;
- fluidsimInitMeshChannel(C, &fsmesh.channelVertices, allchannelSize, obit, numVerts, timeAtFrame, modifierIndex);
- scene->r.cfra = startFrame;
- ED_update_for_newframe(C, 1);
- // remove channels
- fsmesh.channelTranslation =
- fsmesh.channelRotation =
- fsmesh.channelScale = NULL;
- }
-
- elbeemAddMesh(&fsmesh);
-
- if(verts) MEM_freeN(verts);
- if(tris) MEM_freeN(tris);
- if(fsmesh.channelVertices) MEM_freeN(fsmesh.channelVertices);
- channelObjCount++;
- } // valid mesh
- } // objects
- //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again
-
- // set to neutral, -1 means user abort, -2 means init error
- globalBakeState = 0;
- globalBakeFrame = 0;
-
-#if defined(__APPLE__) && (PARALLEL == 1) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2)
- // Workaround for Apple gcc 4.2.1 omp vs background thread bug
- thread_tls_data = pthread_getspecific(gomp_tls_key);
-#endif
- BLI_init_threads(&threads, fluidsimSimulateThread, 1);
- BLI_insert_thread(&threads, targetFile);
-
- {
- int done = 0;
- float noFramesf = (float)noFrames;
- float percentdone = 0.0, oldpercentdone = -1.0;
- int lastRedraw = -1;
-
- g_break= 0;
- G.afbreek= 0; /* blender_test_break uses this global */
-
- start_progress_bar();
+ // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz
+ fsset->animStart = domainSettings->animStart;
+ fsset->aniFrameTime = channels->aniFrameTime;
+ fsset->noOfFrames = noFrames; // is otherwise subtracted in parser
- while(done==0) {
- char busy_mess[80];
-
- waitcursor(1);
-
- // lukep we add progress bar as an interim mesure
- percentdone = globalBakeFrame / noFramesf;
- if (percentdone != oldpercentdone) {
- sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf);
- percentdone = percentdone < 0.0 ? 0.0:percentdone;
- progress_bar(CTX_wm_window(C), percentdone, busy_mess );
- oldpercentdone = percentdone;
- }
-
- //XXX no more need for longer delay to prevent frequent redrawing
- PIL_sleep_ms(200);
-
- BLI_lock_thread(LOCK_CUSTOM1);
- if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort
- BLI_unlock_thread(LOCK_CUSTOM1);
-
- if (!G.background) {
- g_break= blender_test_break();
-
- if(g_break)
- {
- // abort...
- BLI_lock_thread(LOCK_CUSTOM1);
-
- if(domainSettings)
- domainSettings->lastgoodframe = startFrame+globalBakeFrame;
-
- done = -1;
- globalBakeFrame = 0;
- globalBakeState = -1;
- simAborted = 1;
- BLI_unlock_thread(LOCK_CUSTOM1);
- break;
- }
- }
-
- // redraw the 3D for showing progress once in a while...
- if(lastRedraw!=globalBakeFrame) {
-#if 0
- ScrArea *sa;
- scene->r.cfra = startFrame+globalBakeFrame;
- lastRedraw = globalBakeFrame;
- ED_update_for_newframe(C, 1);
- sa= G.curscreen->areabase.first;
- while(sa) {
- if(sa->spacetype == SPACE_VIEW3D) { scrarea_do_windraw(sa); }
- sa= sa->next;
- }
- screen_swapbuffers();
-#endif
- } // redraw
- }
- end_progress_bar(CTX_wm_window(C));
+ strcpy(targetFile, targetDir);
+ strcat(targetFile, suffixSurface);
+ // defaults for compressibility and adaptive grids
+ fsset->gstar = domainSettings->gstar;
+ fsset->maxRefine = domainSettings->maxRefine; // check <-> gridlevels
+ fsset->generateParticles = domainSettings->generateParticles;
+ fsset->numTracerParticles = domainSettings->generateTracers;
+ fsset->surfaceSmoothing = domainSettings->surfaceSmoothing;
+ fsset->surfaceSubdivs = domainSettings->surfaceSubdivs;
+ fsset->farFieldSize = domainSettings->farFieldSize;
+ strcpy( fsset->outputPath, targetFile);
+
+ // domain channels
+ fsset->channelSizeFrameTime =
+ fsset->channelSizeViscosity =
+ fsset->channelSizeGravity = channels->length;
+ fsset->channelFrameTime = channels->DomainTime;
+ fsset->channelViscosity = channels->DomainViscosity;
+ fsset->channelGravity = channels->DomainGravity;
+
+ fsset->runsimCallback = &runSimulationCallback;
+ fsset->runsimUserData = fb;
+
+ if (domainSettings->typeFlags & OB_FSBND_NOSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_NOSLIP;
+ else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP;
+ else if (domainSettings->typeFlags&OB_FSBND_FREESLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP;
+ fsset->domainobsPartslip = domainSettings->partSlipValue;
+ fsset->generateVertexVectors = (domainSettings->domainNovecgen==0);
+
+ // init blender domain transform matrix
+ { int j;
+ for(i=0; i<4; i++) {
+ for(j=0; j<4; j++) {
+ fsset->surfaceTrafo[i*4+j] = invDomMat[j][i];
}
- BLI_end_threads(&threads);
- } // El'Beem API init, thread creation
- // --------------------------------------------------------------------------------------------
- else
- { // write config file to be run with command line simulator
- BKE_report(reports, RPT_WARNING, "Config file export not supported.");
- } // config file export done!
+ } }
- // --------------------------------------------------------------------------------------------
- FS_FREE_CHANNELS;
-
- // go back to "current" blender time
- waitcursor(0);
+ /* ******** init solver with settings ******** */
+ elbeemInit();
+ elbeemAddDomain(fsset);
- if(globalBakeState >= 0)
- {
- if(domainSettings)
- domainSettings->lastgoodframe = startFrame+globalBakeFrame;
- }
+ /* ******** export all fluid objects to elbeem ******** */
+ export_fluid_objects(fobjects, scene, channels->length);
- scene->r.cfra = origFrame;
- ED_update_for_newframe(C, 1);
+ /* custom data for fluid bake job */
+ fb->settings = fsset;
+
+ /* setup job */
+ WM_jobs_customdata(steve, fb, fluidbake_free);
+ WM_jobs_timer(steve, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
+ WM_jobs_callbacks(steve, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), steve);
- if(!simAborted) {
- char elbeemerr[256];
+ /* ******** free stored animation data ******** */
+ fluidbake_free_data(channels, fobjects, NULL, NULL);
- // check if some error occurred
- if(globalBakeState==-2) {
- elbeemGetErrorString(elbeemerr);
- BKE_reportf(reports, RPT_ERROR, "Failed to initialize [Msg: %s]", elbeemerr);
- return 0;
- } // init error
- }
-
// elbeemFree();
return 1;
}
@@ -1206,7 +1090,6 @@ static int fluid_bake_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
- // XXX TODO redraw, escape, non-blocking, ..
if(!fluidsimBake(C, op->reports, ob))
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index aa3a2e22e31..b3d11810c43 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -37,8 +37,8 @@ struct wmOperatorType;
/* particle_edit.c */
void PARTICLE_OT_select_all(struct wmOperatorType *ot);
-void PARTICLE_OT_select_first(struct wmOperatorType *ot);
-void PARTICLE_OT_select_last(struct wmOperatorType *ot);
+void PARTICLE_OT_select_roots(struct wmOperatorType *ot);
+void PARTICLE_OT_select_tips(struct wmOperatorType *ot);
void PARTICLE_OT_select_linked(struct wmOperatorType *ot);
void PARTICLE_OT_select_less(struct wmOperatorType *ot);
void PARTICLE_OT_select_more(struct wmOperatorType *ot);
diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c
index 55568c89e75..28839693e2c 100644
--- a/source/blender/editors/physics/physics_ops.c
+++ b/source/blender/editors/physics/physics_ops.c
@@ -1,5 +1,5 @@
/**
- * $Id:
+ * $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -27,7 +27,6 @@
#include <stdlib.h>
-#include "DNA_windowmanager_types.h"
#include "RNA_access.h"
@@ -44,8 +43,8 @@
static void operatortypes_particle(void)
{
WM_operatortype_append(PARTICLE_OT_select_all);
- WM_operatortype_append(PARTICLE_OT_select_first);
- WM_operatortype_append(PARTICLE_OT_select_last);
+ WM_operatortype_append(PARTICLE_OT_select_roots);
+ WM_operatortype_append(PARTICLE_OT_select_tips);
WM_operatortype_append(PARTICLE_OT_select_linked);
WM_operatortype_append(PARTICLE_OT_select_less);
WM_operatortype_append(PARTICLE_OT_select_more);
@@ -101,6 +100,7 @@ static void keymap_particle(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "PARTICLE_OT_delete", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PARTICLE_OT_delete", DELKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "PARTICLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PARTICLE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index 1359af5377f..8e53e3c6f50 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -32,9 +32,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
-#include "DNA_modifier_types.h"
+#include "BKE_anim.h"
#include "BKE_context.h"
#include "BKE_particle.h"
#include "BKE_report.h"
@@ -46,12 +45,8 @@
#include "BLI_blenlib.h"
-#include "ED_screen.h"
-#include "ED_physics.h"
#include "ED_particle.h"
-#include "UI_interface.h"
-#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -76,7 +71,7 @@ static int ptcache_bake_all_poll(bContext *C)
static int ptcache_poll(bContext *C)
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
return (ptr.data && ptr.id.data);
}
@@ -94,7 +89,7 @@ void bake_console_progress_end(void *arg)
static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = G.background ? NULL : CTX_wm_window(C);
PTCacheBaker baker;
@@ -120,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;
}
@@ -131,13 +127,15 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
ListBase pidlist;
for(base=scene->base.first; base; base= base->next) {
- BKE_ptcache_ids_from_object(&pidlist, base->object);
+ BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for(pid=pidlist.first; pid; pid=pid->next) {
pid->cache->flag &= ~PTCACHE_BAKED;
}
BLI_freelistN(&pidlist);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
}
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
@@ -176,15 +174,15 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
static int ptcache_bake_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- wmWindow *win = CTX_wm_window(C);
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ wmWindow *win = G.background ? NULL : CTX_wm_window(C);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
Object *ob= ptr.id.data;
PointCache *cache= ptr.data;
PTCacheBaker baker;
PTCacheID *pid;
ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob);
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
for(pid=pidlist.first; pid; pid=pid->next) {
if(pid->cache == cache)
@@ -216,13 +214,15 @@ 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;
}
static int ptcache_free_bake_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ 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?")) {
@@ -233,15 +233,20 @@ 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;
}
static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ 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;
}
@@ -290,13 +295,13 @@ void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
static int ptcache_add_new_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
Object *ob= ptr.id.data;
PointCache *cache= ptr.data;
PTCacheID *pid;
ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob);
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
for(pid=pidlist.first; pid; pid=pid->next) {
if(pid->cache == cache) {
@@ -308,18 +313,20 @@ 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;
}
static int ptcache_remove_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
+ Scene *scene= CTX_data_scene(C);
Object *ob= ptr.id.data;
PointCache *cache= ptr.data;
PTCacheID *pid;
ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob);
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
for(pid=pidlist.first; pid; pid=pid->next) {
if(pid->cache == cache) {
@@ -335,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;
}