133
127
float longest_axis;
135
object_get_dimensions(domainob, dim);
136
longest_axis = MAX3(dim[0], dim[1], dim[2]);
129
BKE_object_dimensions_get(domainob, dim);
130
longest_axis = max_fff(dim[0], dim[1], dim[2]);
138
132
return longest_axis * scene->unit.scale_length;
150
144
/* helper function */
151
void fluidsimGetGeometryObjFilename(Object *ob, char *dst) { //, char *srcname)
145
void fluidsimGetGeometryObjFilename(Object *ob, char *dst) //, char *srcname)
153
//BLI_snprintf(dst,FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
154
BLI_snprintf(dst,FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
147
//BLI_snprintf(dst, FILE_MAXFILE, "%s_cfgdata_%s.bobj.gz", srcname, ob->id.name);
148
BLI_snprintf(dst, FILE_MAXFILE, "fluidcfgdata_%s.bobj.gz", ob->id.name);
200
194
static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char *str, int entries)
203
197
int channelSize = paramsize;
206
elbeemSimplifyChannelVec3( channel, &channelSize);
200
elbeemSimplifyChannelVec3(channel, &channelSize);
208
else if (entries==1) {
209
elbeemSimplifyChannelFloat( channel, &channelSize);
202
else if (entries == 1) {
203
elbeemSimplifyChannelFloat(channel, &channelSize);
212
// invalid, cant happen?
206
/* invalid, cant happen? */
215
209
fprintf(file, " CHANNEL %s =\n", str);
216
for (i=0; i<channelSize;i++) {
218
for (j=0;j<=entries;j++) { // also print time value
219
fprintf(file," %f ", channel[i*(entries+1)+j] );
220
if (j==entries-1) { fprintf(file," "); }
210
for (i=0; i < channelSize; i++) {
212
for (j=0;j <= entries;j++) { // also print time value
213
fprintf(file, " %f ", channel[i*(entries + 1) + j]);
214
if (j == entries-1) { fprintf(file, " "); }
225
fprintf(file, " ;\n" );
219
fprintf(file, " ;\n");
246
channels->timeAtFrame = MEM_callocN( (channels->length+1)*sizeof(float), "timeAtFrame channel");
240
channels->timeAtFrame = MEM_callocN((channels->length + 1) * sizeof(float), "timeAtFrame channel");
248
242
channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1
250
244
for (i=2; i <= channels->length; i++) {
251
channels->timeAtFrame[i] = channels->timeAtFrame[i-1] + channels->aniFrameTime;
245
channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime;
273
267
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
275
269
int *tris=NULL, numVerts=0, numTris=0;
276
int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
270
int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
277
271
int framesize = (3*fobj->numVerts) + 1;
361
355
init_time(domainSettings, channels);
363
357
/* allocate domain animation channels */
364
channels->DomainGravity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
365
channels->DomainViscosity = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
366
channels->DomainTime = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
358
channels->DomainGravity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "channel DomainGravity");
359
channels->DomainViscosity = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainViscosity");
360
channels->DomainTime = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "channel DomainTime");
368
362
/* allocate fluid objects */
369
363
for (base=scene->base.first; base; base= base->next) {
382
fobj->Translation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation");
383
fobj->Rotation = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation");
384
fobj->Scale = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale");
385
fobj->Active = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active");
386
fobj->InitialVelocity = MEM_callocN( length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity");
376
fobj->Translation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Translation");
377
fobj->Rotation = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Rotation");
378
fobj->Scale = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject Scale");
379
fobj->Active = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject Active");
380
fobj->InitialVelocity = MEM_callocN(length * (CHANNEL_VEC+1) * sizeof(float), "fluidobject InitialVelocity");
388
382
if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
389
fobj->AttractforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength");
390
fobj->AttractforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius");
391
fobj->VelocityforceStrength = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength");
392
fobj->VelocityforceRadius = MEM_callocN( length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius");
383
fobj->AttractforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceStrength");
384
fobj->AttractforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject AttractforceRadius");
385
fobj->VelocityforceStrength = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceStrength");
386
fobj->VelocityforceRadius = MEM_callocN(length * (CHANNEL_FLOAT+1) * sizeof(float), "fluidobject VelocityforceRadius");
395
389
if (fluid_is_animated_mesh(fluidmd->fss)) {
396
390
float *verts=NULL;
397
int *tris=NULL, modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
391
int *tris=NULL, modifierIndex = BLI_findindex(&ob->modifiers, (ModifierData *)fluidmd);
399
393
initElbeemMesh(scene, ob, &fobj->numVerts, &verts, &fobj->numTris, &tris, 0, modifierIndex);
400
fobj->VertexCache = MEM_callocN( length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
394
fobj->VertexCache = MEM_callocN(length *((fobj->numVerts*CHANNEL_VEC)+1) * sizeof(float), "fluidobject VertexCache");
402
396
MEM_freeN(verts);
425
419
/* Modifying the global scene isn't nice, but we can do it in
426
420
* this part of the process before a threaded job is created */
427
421
scene->r.cfra = (int)eval_time;
428
ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
422
ED_update_for_newframe(CTX_data_main(C), scene, 1);
430
424
/* now scene data should be current according to animation system, so we fill the channels */
432
426
/* Domain time */
433
427
// TODO: have option for not running sim, time mangling, in which case second case comes in handy
434
428
if (channels->DomainTime) {
435
time = get_fluid_rate(domainSettings) * channels->aniFrameTime;
429
time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime;
436
430
timeAtFrame = channels->timeAtFrame[i] + time;
438
432
channels->timeAtFrame[i+1] = timeAtFrame;
452
446
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
453
447
Object *ob = fobj->object;
454
448
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
455
float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE);
449
float active= (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) > 0 ? 1 : 0);
456
450
float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f};
458
452
if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
462
456
/* get the rotation from ob->obmat rather than ob->rot to account for parent animations */
464
458
copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1));
465
mul_v3_fl(old_rot, -M_PI/180.f);
459
mul_v3_fl(old_rot, (float)-M_PI / 180.f);
468
462
mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat);
469
mul_v3_fl(rot_d, -180.f/M_PI);
463
mul_v3_fl(rot_d, -180.0f / (float)M_PI);
471
465
set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC);
472
466
set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC);
473
467
set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC);
474
468
set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT);
475
469
set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC);
471
// printf("Active: %f, Frame: %f\n", active, timeAtFrame);
477
473
if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) {
478
474
set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT);
495
491
for (fobj=fobjects->first; fobj; fobj=fobj->next) {
496
492
Object *ob = fobj->object;
497
493
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
498
int modifierIndex = modifiers_indexInObject(ob, (ModifierData *)fluidmd);
494
int modifierIndex = BLI_findindex(&ob->modifiers, fluidmd);
500
496
float *verts=NULL;
507
503
if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE))
510
elbeemResetMesh( &fsmesh );
506
elbeemResetMesh(&fsmesh);
512
508
fsmesh.type = fluidmd->fss->type;
513
509
fsmesh.name = ob->id.name;
533
529
if ( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) {
534
530
fsmesh.channelInitialVel = fobj->InitialVelocity;
535
531
fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD)?1:0);
538
534
if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP)
539
535
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
546
542
fsmesh.volumeInitType = fluidmd->fss->volumeInitType;
547
543
fsmesh.obstacleImpactFactor = fluidmd->fss->surfaceSmoothing; // misused value
549
if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
545
if (fsmesh.type == OB_FLUIDSIM_CONTROL) {
550
546
fsmesh.cpsTimeStart = fluidmd->fss->cpsTimeStart;
551
547
fsmesh.cpsTimeEnd = fluidmd->fss->cpsTimeEnd;
552
548
fsmesh.cpsQuality = fluidmd->fss->cpsQuality;
574
570
fsmesh.channelSizeVertices = length;
575
571
fsmesh.channelVertices = fobj->VertexCache;
573
/* remove channels */
578
574
fsmesh.channelTranslation =
579
575
fsmesh.channelRotation =
580
fsmesh.channelScale = NULL;
576
fsmesh.channelScale = NULL;
578
/* Override user settings, only noslip is supported here! */
579
if (fsmesh.type != OB_FLUIDSIM_CONTROL)
580
fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP;
583
583
elbeemAddMesh(&fsmesh);
594
594
int channelObjCount = 0;
595
595
int fluidInputCount = 0;
597
for (base=scene->base.first; base; base= base->next)
597
for (base=scene->base.first; base; base= base->next) {
599
598
Object *ob = base->object;
600
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
599
FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
602
601
/* only find objects with fluid modifiers */
603
602
if (!fluidmdtmp || ob->type != OB_MESH) continue;
652
651
static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer)
654
653
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
655
FluidsimSettings *domainSettings= fluidmd->fss;
654
FluidsimSettings *domainSettings= fluidmd->fss;
657
656
int dirExist = 0;
658
char newSurfdataPath[FILE_MAX]; // modified output settings
657
char newSurfdataPath[FILE_MAX]; /* modified output settings */
659
658
const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP;
660
659
int outStringsChanged = 0;
661
/* prepare names... */
663
662
const char *relbase= modifier_path_relbase(fsDomain);
665
664
BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR);
666
665
BLI_strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); /* if 0'd out below, this value is never used! */
667
BLI_path_abs(targetDir, relbase); // fixed #frame-no
666
BLI_path_abs(targetDir, relbase); /* fixed #frame-no */
669
668
/* .tmp: don't overwrite/delete original file */
670
669
BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp);
677
676
// check selected directory
678
677
// simply try to open cfg file for writing to test validity of settings
679
678
fileCfg = BLI_fopen(targetFile, "w");
681
680
dirExist = 1; fclose(fileCfg);
682
681
// remove cfg dummy from directory test
683
BLI_delete(targetFile, 0,0);
682
BLI_delete(targetFile, 0, 0);
686
685
if (targetDir[0] == '\0' || (!dirExist)) {
692
691
BLI_splitdirstring(blendDir, blendFile);
693
692
BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */
695
BLI_snprintf(newSurfdataPath, FILE_MAX ,"//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
694
BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name);
697
696
BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath);
698
697
elbeemDebugOut(debugStrBuffer);
699
698
outStringsChanged=1;
702
// check if modified output dir is ok
701
/* check if modified output dir is ok */
704
703
if (outStringsChanged) {
705
704
char dispmsg[FILE_MAX+256];
707
BLI_strncpy(dispmsg,"Output settings set to: '", sizeof(dispmsg));
706
BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg));
708
707
strcat(dispmsg, newSurfdataPath);
709
strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0");
708
strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0");
711
// ask user if thats what he/she wants...
710
/* ask user if thats what he/she wants... */
712
711
selection = pupmenu(dispmsg);
713
if (selection<1) return 0; // 0 from menu, or -1 aborted
712
if (selection < 1) return 0; /* 0 from menu, or -1 aborted */
714
713
BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir));
715
714
strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR);
716
BLI_path_abs(targetDir, G.main->name); // fixed #frame-no
715
BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */
719
718
return outStringsChanged;
789
int runSimulationCallback(void *data, int status, int frame)
788
static int runSimulationCallback(void *data, int status, int frame)
791
790
FluidBakeJob *fb = (FluidBakeJob *)data;
792
791
elbeemSimulationSettings *settings = fb->settings;
794
793
if (status == FLUIDSIM_CBSTATUS_NEWFRAME) {
795
794
fluidbake_updatejob(fb, frame / (float)settings->noOfFrames);
796
//printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n", status,frame, settings->domainId, settings->noOfFrames ); // DEBUG
795
//printf("elbeem blender cb s%d, f%d, domainid:%d noOfFrames: %d\n", status, frame, settings->domainId, settings->noOfFrames ); // DEBUG
799
798
if (fluidbake_breakjob(fb)) {
899
898
if (getenv(strEnvName)) {
900
899
int dlevel = atoi(getenv(strEnvName));
901
900
elbeemSetDebugLevel(dlevel);
902
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer),"fluidsimBake::msg: Debug messages activated due to envvar '%s'\n",strEnvName);
901
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Debug messages activated due to envvar '%s'\n", strEnvName);
903
902
elbeemDebugOut(debugStrBuffer);
906
905
/* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */;
907
906
noFrames = scene->r.efra - 0;
908
907
if (noFrames<=0) {
909
BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings");
908
BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)");
910
909
fluidbake_free_data(channels, fobjects, fsset, fb);
920
/* these both have to be valid, otherwise we wouldnt be here */
919
/* these both have to be valid, otherwise we wouldn't be here */
921
920
fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim);
922
921
domainSettings = fluidmd->fss;
923
922
mesh = fsDomain->data;
937
936
/* rough check of settings... */
938
937
if (domainSettings->previewresxyz > domainSettings->resolutionxyz) {
939
BLI_snprintf(debugStrBuffer,sizeof(debugStrBuffer),"fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz , domainSettings->resolutionxyz);
938
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::warning - Preview (%d) >= Resolution (%d)... setting equal.\n", domainSettings->previewresxyz, domainSettings->resolutionxyz);
940
939
elbeemDebugOut(debugStrBuffer);
941
940
domainSettings->previewresxyz = domainSettings->resolutionxyz;
960
958
gridlevels = domainSettings->maxRefine;
962
BLI_snprintf(debugStrBuffer,sizeof(debugStrBuffer),"fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name , gridlevels );
960
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::msg: Baking %s, refine: %d\n", fsDomain->id.name, gridlevels);
963
961
elbeemDebugOut(debugStrBuffer);
967
965
/* ******** prepare output file paths ******** */
968
966
outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer);
969
channels->length = scene->r.efra;
970
channels->aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames;
967
channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra)
968
channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames;
972
970
/* ******** initialize and allocate animation channels ******** */
973
971
fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects);
975
973
/* reset to original current frame */
976
974
scene->r.cfra = origFrame;
977
ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
975
ED_update_for_newframe(CTX_data_main(C), scene, 1);
979
977
/* ******** init domain object's matrix ******** */
980
978
copy_m4_m4(domainMat, fsDomain->obmat);
981
979
if (!invert_m4_m4(invDomMat, domainMat)) {
982
BLI_snprintf(debugStrBuffer,sizeof(debugStrBuffer),"fluidsimBake::error - Invalid obj matrix?\n");
980
BLI_snprintf(debugStrBuffer, sizeof(debugStrBuffer), "fluidsimBake::error - Invalid obj matrix?\n");
983
981
elbeemDebugOut(debugStrBuffer);
984
982
BKE_report(reports, RPT_ERROR, "Invalid object matrix");
1072
1070
fb->settings = fsset;
1075
wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation", WM_JOB_PROGRESS);
1073
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Fluid Simulation",
1074
WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_FLUID);
1077
1076
/* setup job */
1078
WM_jobs_customdata(steve, fb, fluidbake_free);
1079
WM_jobs_timer(steve, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
1080
WM_jobs_callbacks(steve, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
1077
WM_jobs_customdata_set(wm_job, fb, fluidbake_free);
1078
WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME);
1079
WM_jobs_callbacks(wm_job, fluidbake_startjob, NULL, NULL, fluidbake_endjob);
1082
WM_jobs_start(CTX_wm_manager(C), steve);
1081
WM_jobs_start(CTX_wm_manager(C), wm_job);
1085
1084
short dummy_stop, dummy_do_update;
1134
1133
static int fluid_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1136
1135
/* only one bake job at a time */
1137
if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
1136
if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID))
1138
1137
return OPERATOR_CANCELLED;
1140
1139
if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), TRUE))