Fluid: Fix that maps old smoke and fluid modifiers to new manta modifier
authorSebastián Barschkis <sebbas@sebbas.org>
Tue, 17 Dec 2019 17:00:27 +0000 (18:00 +0100)
committerSebastián Barschkis <sebbas@sebbas.org>
Tue, 17 Dec 2019 17:00:27 +0000 (18:00 +0100)
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenkernel/BKE_fluid.h
source/blender/blenkernel/intern/fluid.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_fluid.c

index dfccd0732eeb95685791f41e16c3f48112f11d2f..9855c2202cccc62e6f2a267fab899a95ced21e9c 100644 (file)
@@ -27,7 +27,7 @@
  * \note Use #STRINGIFY() rather than defining with quotes.
  */
 #define BLENDER_VERSION 282
-#define BLENDER_SUBVERSION 5
+#define BLENDER_SUBVERSION 6
 /** Several breakages with 280, e.g. collections vs layers. */
 #define BLENDER_MINVERSION 280
 #define BLENDER_MINSUBVERSION 0
index 3e389cfec58446230a13c83f3f81734e1db61794..af8e79275eb66436035a8f4a6289bf9055a75e96 100644 (file)
@@ -66,4 +66,23 @@ void BKE_fluid_particle_system_create(struct Main *bmain,
                                       const int psys_type);
 void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type);
 
+void BKE_fluid_cachetype_mesh_set(struct FluidDomainSettings *settings, int cache_mesh_format);
+void BKE_fluid_cachetype_data_set(struct FluidDomainSettings *settings, int cache_data_format);
+void BKE_fluid_cachetype_particle_set(struct FluidDomainSettings *settings,
+                                      int cache_particle_format);
+void BKE_fluid_cachetype_noise_set(struct FluidDomainSettings *settings, int cache_noise_format);
+void BKE_fluid_collisionextents_set(struct FluidDomainSettings *settings, int value, bool clear);
+void BKE_fluid_particles_set(struct FluidDomainSettings *settings, int value, bool clear);
+
+void BKE_fluid_domain_type_set(struct Object *object,
+                               struct FluidDomainSettings *settings,
+                               int type);
+void BKE_fluid_flow_type_set(struct Object *object, struct FluidFlowSettings *settings, int type);
+void BKE_fluid_effector_type_set(struct Object *object,
+                                 struct FluidEffectorSettings *settings,
+                                 int type);
+void BKE_fluid_flow_behavior_set(struct Object *object,
+                                 struct FluidFlowSettings *settings,
+                                 int behavior);
+
 #endif /* __BKE_FLUID_H__ */
index 81c7c700cc2c42d5ba412d2827f6e9bb4ba26a9a..e1eeb7f611d374018cb018e5a32b45610f2d4227 100644 (file)
@@ -4803,4 +4803,121 @@ void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_typ
   }
 }
 
+void BKE_fluid_cachetype_mesh_set(FluidDomainSettings *settings, int cache_mesh_format)
+{
+  if (cache_mesh_format == settings->cache_mesh_format) {
+    return;
+  }
+  /* TODO(sebbas): Clear old caches. */
+  settings->cache_mesh_format = cache_mesh_format;
+}
+
+void BKE_fluid_cachetype_data_set(FluidDomainSettings *settings, int cache_data_format)
+{
+  if (cache_data_format == settings->cache_data_format) {
+    return;
+  }
+  /* TODO(sebbas): Clear old caches. */
+  settings->cache_data_format = cache_data_format;
+}
+
+void BKE_fluid_cachetype_particle_set(FluidDomainSettings *settings, int cache_particle_format)
+{
+  if (cache_particle_format == settings->cache_particle_format) {
+    return;
+  }
+  /* TODO(sebbas): Clear old caches. */
+  settings->cache_particle_format = cache_particle_format;
+}
+
+void BKE_fluid_cachetype_noise_set(FluidDomainSettings *settings, int cache_noise_format)
+{
+  if (cache_noise_format == settings->cache_noise_format) {
+    return;
+  }
+  /* TODO(sebbas): Clear old caches. */
+  settings->cache_noise_format = cache_noise_format;
+}
+
+void BKE_fluid_collisionextents_set(FluidDomainSettings *settings, int value, bool clear)
+{
+  if (clear) {
+    settings->border_collisions &= value;
+  }
+  else {
+    settings->border_collisions |= value;
+  }
+}
+
+void BKE_fluid_particles_set(FluidDomainSettings *settings, int value, bool clear)
+{
+  if (clear) {
+    settings->particle_type &= ~value;
+  }
+  else {
+    settings->border_collisions |= value;
+  }
+}
+
+void BKE_fluid_domain_type_set(Object *object, FluidDomainSettings *settings, int type)
+{
+  /* Set common values for liquid/smoke domain: cache type,
+   * border collision and viewport draw-type. */
+  if (type == FLUID_DOMAIN_TYPE_GAS) {
+    BKE_fluid_cachetype_mesh_set(settings, FLUID_DOMAIN_FILE_BIN_OBJECT);
+    BKE_fluid_cachetype_data_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_cachetype_particle_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_cachetype_noise_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_FRONT, 1);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BACK, 1);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_RIGHT, 1);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_LEFT, 1);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_TOP, 1);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BOTTOM, 1);
+    object->dt = OB_WIRE;
+  }
+  else if (type == FLUID_DOMAIN_TYPE_LIQUID) {
+    BKE_fluid_cachetype_mesh_set(settings, FLUID_DOMAIN_FILE_BIN_OBJECT);
+    BKE_fluid_cachetype_data_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_cachetype_particle_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_cachetype_noise_set(settings, FLUID_DOMAIN_FILE_UNI);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_FRONT, 0);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BACK, 0);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_RIGHT, 0);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_LEFT, 0);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_TOP, 0);
+    BKE_fluid_collisionextents_set(settings, FLUID_DOMAIN_BORDER_BOTTOM, 0);
+    BKE_fluid_particles_set(settings, FLUID_DOMAIN_PARTICLE_FLIP, 0);
+    object->dt = OB_SOLID;
+  }
+
+  /* Set actual domain type. */
+  settings->type = type;
+}
+
+void BKE_fluid_flow_behavior_set(Object *UNUSED(object), FluidFlowSettings *settings, int behavior)
+{
+  settings->behavior = behavior;
+}
+
+void BKE_fluid_flow_type_set(Object *object, FluidFlowSettings *settings, int type)
+{
+  /* By default, liquid flow objects should behave like their geometry (geomtery behavior),
+   * gas flow objects should continously produce smoke (inflow behavior). */
+  if (type == FLUID_FLOW_TYPE_LIQUID) {
+    BKE_fluid_flow_behavior_set(object, settings, FLUID_FLOW_BEHAVIOR_GEOMETRY);
+  }
+  else {
+    BKE_fluid_flow_behavior_set(object, settings, FLUID_FLOW_BEHAVIOR_INFLOW);
+  }
+
+  /* Set actual flow type. */
+  settings->type = type;
+}
+
+void BKE_fluid_effector_type_set(Object *UNUSED(object), FluidEffectorSettings *settings, int type)
+{
+  settings->type = type;
+}
+
 #endif /* WITH_FLUID */
index cfd3c87327afa372646f4ea8eacdb9ea6f21fb6f..bdebe2b9f4d29fff876972e3badfb7a57240d9d0 100644 (file)
 #include "BKE_curve.h"
 #include "BKE_effect.h"
 #include "BKE_fcurve.h"
+#include "BKE_fluid.h"
 #include "BKE_global.h"  // for G
 #include "BKE_gpencil_modifier.h"
 #include "BKE_idcode.h"
 /* local prototypes */
 static void read_libraries(FileData *basefd, ListBase *mainlist);
 static void *read_struct(FileData *fd, BHead *bh, const char *blockname);
-static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob);
+static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob);
 static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const char *name);
 static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
 
@@ -5485,7 +5486,118 @@ static void direct_link_pose(FileData *fd, bPose *pose)
   }
 }
 
-static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob)
+/* TODO(sergey): Find a more better place for this.
+ *
+ * Unfortunately, this can not be done as a regular do_versions() since the modifier type is
+ * set to NONE, so the do_versions code wouldn't know where the modifier came from.
+ *
+ * Most bestest approach seems to have the functionality in versioning_280 but still call the
+ * function from direct_link_modifiers(). */
+
+/* Domain, inflow, ... */
+static void modifier_ensure_type(FluidModifierData *fluid_modifier_data, int type)
+{
+  fluid_modifier_data->type = type;
+  BKE_fluid_modifier_free(fluid_modifier_data);
+  BKE_fluid_modifier_create_type_data(fluid_modifier_data);
+}
+
+/* NOTE: The old_modifier_data is NOT linked. This means that in ordet to access subdata
+ * pointers newdataadr is to be used. */
+static ModifierData *modifier_replace_with_fluid(FileData *fd,
+                                                 Object *object,
+                                                 ListBase *modifiers,
+                                                 ModifierData *old_modifier_data)
+{
+  ModifierData *new_modifier_data = modifier_new(eModifierType_Fluid);
+  FluidModifierData *fluid_modifier_data = (FluidModifierData *)new_modifier_data;
+
+  if (old_modifier_data->type == eModifierType_Fluidsim) {
+    FluidsimModifierData *old_fluidsim_modifier_data = (FluidsimModifierData *)old_modifier_data;
+    FluidsimSettings *old_fluidsim_settings = newdataadr(fd, old_fluidsim_modifier_data->fss);
+    switch (old_fluidsim_settings->type) {
+      case OB_FLUIDSIM_ENABLE:
+        modifier_ensure_type(fluid_modifier_data, 0);
+        break;
+      case OB_FLUIDSIM_DOMAIN:
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_DOMAIN);
+        BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_LIQUID);
+        break;
+      case OB_FLUIDSIM_FLUID:
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
+        BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
+        /* No need to emit liquid far away from surface. */
+        fluid_modifier_data->flow->surface_distance = 0.0f;
+        break;
+      case OB_FLUIDSIM_OBSTACLE:
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
+        BKE_fluid_effector_type_set(
+            object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
+        break;
+      case OB_FLUIDSIM_INFLOW:
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
+        BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
+        BKE_fluid_flow_behavior_set(object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_INFLOW);
+        /* No need to emit liquid far away from surface. */
+        fluid_modifier_data->flow->surface_distance = 0.0f;
+        break;
+      case OB_FLUIDSIM_OUTFLOW:
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
+        BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
+        BKE_fluid_flow_behavior_set(
+            object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_OUTFLOW);
+        break;
+      case OB_FLUIDSIM_PARTICLE:
+        /* "Particle" type objects not being used by Mantaflow fluid simulations.
+         * Skip this object, secondary particles can only be enabled through the domain object. */
+        break;
+      case OB_FLUIDSIM_CONTROL:
+        /* "Control" type objects not being used by Mantaflow fluid simulations.
+         * Use guiding type instead which is similar. */
+        modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
+        BKE_fluid_effector_type_set(
+            object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_GUIDE);
+        break;
+    }
+  }
+  else if (old_modifier_data->type == eModifierType_Smoke) {
+    SmokeModifierData *old_smoke_modifier_data = (SmokeModifierData *)old_modifier_data;
+    modifier_ensure_type(fluid_modifier_data, old_smoke_modifier_data->type);
+    if (fluid_modifier_data->type == MOD_FLUID_TYPE_DOMAIN) {
+      BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_GAS);
+    }
+    else if (fluid_modifier_data->type == MOD_FLUID_TYPE_FLOW) {
+      BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_SMOKE);
+    }
+    else if (fluid_modifier_data->type == MOD_FLUID_TYPE_EFFEC) {
+      BKE_fluid_effector_type_set(
+          object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
+    }
+  }
+
+  /* Replace modifier data in the stack. */
+  new_modifier_data->next = old_modifier_data->next;
+  new_modifier_data->prev = old_modifier_data->prev;
+  if (new_modifier_data->prev != NULL) {
+    new_modifier_data->prev->next = new_modifier_data;
+  }
+  if (new_modifier_data->next != NULL) {
+    new_modifier_data->next->prev = new_modifier_data;
+  }
+  if (modifiers->first == old_modifier_data) {
+    modifiers->first = new_modifier_data;
+  }
+  if (modifiers->last == old_modifier_data) {
+    modifiers->last = new_modifier_data;
+  }
+
+  /* Free old modifier data. */
+  MEM_freeN(old_modifier_data);
+
+  return new_modifier_data;
+}
+
+static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob)
 {
   ModifierData *md;
 
@@ -5495,6 +5607,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob)
     md->error = NULL;
     md->runtime = NULL;
 
+    /* Modifier data has been allocated as a part of data migration process and
+     * no reading of nested fields from file is needed. */
+    bool is_allocated = false;
+
     if (md->type == eModifierType_Fluidsim) {
       blo_reportf_wrap(
           fd->reports,
@@ -5503,6 +5619,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob)
               "Possible data loss when saving this file! %s modifier is deprecated (Object: %s)."),
           md->name,
           ob->id.name + 2);
+      md = modifier_replace_with_fluid(fd, ob, lb, md);
+      is_allocated = true;
     }
     else if (md->type == eModifierType_Smoke) {
       blo_reportf_wrap(
@@ -5512,13 +5630,18 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, const Object *ob)
               "Possible data loss when saving this file! %s modifier is deprecated (Object: %s)."),
           md->name,
           ob->id.name + 2);
+      md = modifier_replace_with_fluid(fd, ob, lb, md);
+      is_allocated = true;
     }
     /* if modifiers disappear, or for upward compatibility */
     if (NULL == modifierType_getInfo(md->type)) {
       md->type = eModifierType_None;
     }
 
-    if (md->type == eModifierType_Subsurf) {
+    if (is_allocated) {
+      /* All the fields has been properly allocated. */
+    }
+    else if (md->type == eModifierType_Subsurf) {
       SubsurfModifierData *smd = (SubsurfModifierData *)md;
 
       smd->emCache = smd->mCache = NULL;
index 0cc80a0112d4144cd5636be5c8ee5337c97afb36..9db993cca59bbf95f2dd9d38a68650f287e9aa70 100644 (file)
@@ -991,6 +991,10 @@ typedef struct FluidsimModifierData {
 /* DEPRECATED, only used for versioning. */
 typedef struct SmokeModifierData {
   ModifierData modifier;
+
+  /** Domain, inflow, outflow, .... */
+  int type;
+  int _pad;
 } SmokeModifierData;
 
 typedef struct ShrinkwrapModifierData {
index 44bcab7d41a26f8b7ebcf965924163c8110b1701..53fa863f6da71e75af076268f64a93462f683f4c 100644 (file)
@@ -407,41 +407,25 @@ static void rna_Fluid_combined_export_update(Main *bmain, Scene *scene, PointerR
 static void rna_Fluid_cachetype_mesh_set(struct PointerRNA *ptr, int value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
-
-  if (value != settings->cache_mesh_format) {
-    /* TODO (sebbas): Clear old caches. */
-    settings->cache_mesh_format = value;
-  }
+  BKE_fluid_cachetype_mesh_set(settings, value);
 }
 
 static void rna_Fluid_cachetype_data_set(struct PointerRNA *ptr, int value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
-
-  if (value != settings->cache_data_format) {
-    /* TODO (sebbas): Clear old caches. */
-    settings->cache_data_format = value;
-  }
+  BKE_fluid_cachetype_data_set(settings, value);
 }
 
 static void rna_Fluid_cachetype_particle_set(struct PointerRNA *ptr, int value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
-
-  if (value != settings->cache_particle_format) {
-    /* TODO (sebbas): Clear old caches. */
-    settings->cache_particle_format = value;
-  }
+  BKE_fluid_cachetype_particle_set(settings, value);
 }
 
 static void rna_Fluid_cachetype_noise_set(struct PointerRNA *ptr, int value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
-
-  if (value != settings->cache_noise_format) {
-    /* TODO (sebbas): Clear old caches. */
-    settings->cache_noise_format = value;
-  }
+  BKE_fluid_cachetype_noise_set(settings, value);
 }
 
 static void rna_Fluid_cachetype_set(struct PointerRNA *ptr, int value)
@@ -558,17 +542,6 @@ static const EnumPropertyItem *rna_Fluid_cachetype_particle_itemf(bContext *UNUS
   return item;
 }
 
-static void rna_Fluid_collisionextents_set(struct PointerRNA *ptr, int value, bool clear)
-{
-  FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
-  if (clear) {
-    settings->border_collisions &= value;
-  }
-  else {
-    settings->border_collisions |= value;
-  }
-}
-
 static void rna_Fluid_cache_directory_set(struct PointerRNA *ptr, const char *value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
@@ -588,40 +561,7 @@ static void rna_Fluid_domaintype_set(struct PointerRNA *ptr, int value)
 {
   FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data;
   Object *ob = (Object *)ptr->owner_id;
-
-  if (value != settings->type) {
-    /* Set common values for liquid/smoke domain: cache type,
-     * border collision and viewport draw-type. */
-    if (value == FLUID_DOMAIN_TYPE_GAS) {
-      rna_Fluid_cachetype_mesh_set(ptr, FLUID_DOMAIN_FILE_BIN_OBJECT);
-      rna_Fluid_cachetype_data_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_cachetype_particle_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_cachetype_noise_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_FRONT, 1);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BACK, 1);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_RIGHT, 1);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_LEFT, 1);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_TOP, 1);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BOTTOM, 1);
-      ob->dt = OB_WIRE;
-    }
-    else if (value == FLUID_DOMAIN_TYPE_LIQUID) {
-      rna_Fluid_cachetype_mesh_set(ptr, FLUID_DOMAIN_FILE_BIN_OBJECT);
-      rna_Fluid_cachetype_data_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_cachetype_particle_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_cachetype_noise_set(ptr, FLUID_DOMAIN_FILE_UNI);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_FRONT, 0);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BACK, 0);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_RIGHT, 0);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_LEFT, 0);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_TOP, 0);
-      rna_Fluid_collisionextents_set(ptr, FLUID_DOMAIN_BORDER_BOTTOM, 0);
-      ob->dt = OB_SOLID;
-    }
-
-    /* Set actual domain type */
-    settings->type = value;
-  }
+  BKE_fluid_domain_type_set(ob, settings, value);
 }
 
 static char *rna_FluidDomainSettings_path(PointerRNA *ptr)