Refactor: move modifier .blend I/O to blenkernel
Ref T76372.
This commit is contained in:
parent
f6ad56b1bc
commit
019407810b
Notes:
blender-bot
2023-02-14 10:14:07 +01:00
Referenced by issue #76372, Blenloader Decentralization
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
struct ARegionType;
|
||||
struct BMEditMesh;
|
||||
struct BlendDataReader;
|
||||
struct BlendLibReader;
|
||||
struct BlendWriter;
|
||||
struct CustomData_MeshMasks;
|
||||
struct DepsNodeHandle;
|
||||
|
@ -535,6 +536,12 @@ struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object
|
|||
|
||||
void BKE_modifier_check_uuids_unique_and_report(const struct Object *object);
|
||||
|
||||
void BKE_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase);
|
||||
void BKE_modifier_blend_read_data(struct BlendDataReader *reader,
|
||||
struct ListBase *lb,
|
||||
struct Object *ob);
|
||||
void BKE_modifier_blend_read_lib(struct BlendLibReader *reader, struct Object *ob);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
/* Allow using deprecated functionality for .blend file I/O. */
|
||||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -34,8 +37,12 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_cloth_types.h"
|
||||
#include "DNA_fluid_types.h"
|
||||
#include "DNA_gpencil_modifier_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_object_fluidsim_types.h"
|
||||
#include "DNA_object_force_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
@ -54,6 +61,8 @@
|
|||
#include "BKE_appdir.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_editmesh_cache.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_fluid.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_gpencil_modifier.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -64,6 +73,7 @@
|
|||
#include "BKE_mesh_wrapper.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
/* may move these, only for BKE_modifier_path_relbase */
|
||||
#include "BKE_main.h"
|
||||
|
@ -74,6 +84,8 @@
|
|||
|
||||
#include "MOD_modifiertypes.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
static CLG_LogRef LOG = {"bke.modifier"};
|
||||
|
@ -1116,3 +1128,423 @@ void BKE_modifier_check_uuids_unique_and_report(const Object *object)
|
|||
|
||||
BLI_gset_free(used_uuids, NULL);
|
||||
}
|
||||
|
||||
void BKE_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
|
||||
{
|
||||
if (modbase == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, modbase) {
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
if (mti == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLO_write_struct_by_name(writer, mti->structName, md);
|
||||
|
||||
if (md->type == eModifierType_Cloth) {
|
||||
ClothModifierData *clmd = (ClothModifierData *)md;
|
||||
|
||||
BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
|
||||
BLO_write_struct(writer, ClothCollSettings, clmd->coll_parms);
|
||||
BLO_write_struct(writer, EffectorWeights, clmd->sim_parms->effector_weights);
|
||||
BKE_ptcache_blend_write(writer, &clmd->ptcaches);
|
||||
}
|
||||
else if (md->type == eModifierType_Fluid) {
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
|
||||
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
||||
BLO_write_struct(writer, FluidDomainSettings, fmd->domain);
|
||||
|
||||
if (fmd->domain) {
|
||||
BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[0]));
|
||||
|
||||
/* create fake pointcache so that old blender versions can read it */
|
||||
fmd->domain->point_cache[1] = BKE_ptcache_add(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
|
||||
fmd->domain->point_cache[1]->step = 1;
|
||||
|
||||
BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[1]));
|
||||
|
||||
if (fmd->domain->coba) {
|
||||
BLO_write_struct(writer, ColorBand, fmd->domain->coba);
|
||||
}
|
||||
|
||||
/* cleanup the fake pointcache */
|
||||
BKE_ptcache_free_list(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1] = NULL;
|
||||
|
||||
BLO_write_struct(writer, EffectorWeights, fmd->domain->effector_weights);
|
||||
}
|
||||
}
|
||||
else if (fmd->type & MOD_FLUID_TYPE_FLOW) {
|
||||
BLO_write_struct(writer, FluidFlowSettings, fmd->flow);
|
||||
}
|
||||
else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
|
||||
BLO_write_struct(writer, FluidEffectorSettings, fmd->effector);
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Fluidsim) {
|
||||
FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
|
||||
|
||||
BLO_write_struct(writer, FluidsimSettings, fluidmd->fss);
|
||||
}
|
||||
else if (md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
||||
|
||||
if (pmd->canvas) {
|
||||
BLO_write_struct(writer, DynamicPaintCanvasSettings, pmd->canvas);
|
||||
|
||||
/* write surfaces */
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
BLO_write_struct(writer, DynamicPaintSurface, surface);
|
||||
}
|
||||
/* write caches and effector weights */
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
BKE_ptcache_blend_write(writer, &(surface->ptcaches));
|
||||
|
||||
BLO_write_struct(writer, EffectorWeights, surface->effector_weights);
|
||||
}
|
||||
}
|
||||
if (pmd->brush) {
|
||||
BLO_write_struct(writer, DynamicPaintBrushSettings, pmd->brush);
|
||||
BLO_write_struct(writer, ColorBand, pmd->brush->paint_ramp);
|
||||
BLO_write_struct(writer, ColorBand, pmd->brush->vel_ramp);
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Collision) {
|
||||
|
||||
#if 0
|
||||
CollisionModifierData *collmd = (CollisionModifierData *)md;
|
||||
// TODO: CollisionModifier should use pointcache
|
||||
// + have proper reset events before enabling this
|
||||
writestruct(wd, DATA, MVert, collmd->numverts, collmd->x);
|
||||
writestruct(wd, DATA, MVert, collmd->numverts, collmd->xnew);
|
||||
writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mti->blendWrite != NULL) {
|
||||
mti->blendWrite(writer, md);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(sergey): Find a 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.
|
||||
*
|
||||
* The best approach seems to have the functionality in versioning_280.c but still call the
|
||||
* function from #BKE_modifier_blend_read_data().
|
||||
*/
|
||||
|
||||
/* 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 order to access sub-data pointers #BLO_read_get_new_data_address is to be
|
||||
* used.
|
||||
*/
|
||||
static ModifierData *modifier_replace_with_fluid(BlendDataReader *reader,
|
||||
Object *object,
|
||||
ListBase *modifiers,
|
||||
ModifierData *old_modifier_data)
|
||||
{
|
||||
ModifierData *new_modifier_data = BKE_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 = BLO_read_get_new_data_address(
|
||||
reader, 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;
|
||||
}
|
||||
|
||||
void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object *ob)
|
||||
{
|
||||
BLO_read_list(reader, lb);
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, lb) {
|
||||
BKE_modifier_session_uuid_generate(md);
|
||||
|
||||
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(
|
||||
BLO_read_data_reports(reader),
|
||||
RPT_WARNING,
|
||||
TIP_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
|
||||
md->name,
|
||||
ob->id.name + 2);
|
||||
md = modifier_replace_with_fluid(reader, ob, lb, md);
|
||||
is_allocated = true;
|
||||
}
|
||||
else if (md->type == eModifierType_Smoke) {
|
||||
BLO_reportf_wrap(
|
||||
BLO_read_data_reports(reader),
|
||||
RPT_WARNING,
|
||||
TIP_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
|
||||
md->name,
|
||||
ob->id.name + 2);
|
||||
md = modifier_replace_with_fluid(reader, ob, lb, md);
|
||||
is_allocated = true;
|
||||
}
|
||||
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
|
||||
/* if modifiers disappear, or for upward compatibility */
|
||||
if (mti == NULL) {
|
||||
md->type = eModifierType_None;
|
||||
}
|
||||
|
||||
if (is_allocated) {
|
||||
/* All the fields has been properly allocated. */
|
||||
}
|
||||
else if (md->type == eModifierType_Cloth) {
|
||||
ClothModifierData *clmd = (ClothModifierData *)md;
|
||||
|
||||
clmd->clothObject = NULL;
|
||||
clmd->hairdata = NULL;
|
||||
|
||||
BLO_read_data_address(reader, &clmd->sim_parms);
|
||||
BLO_read_data_address(reader, &clmd->coll_parms);
|
||||
|
||||
BKE_ptcache_blend_read_data(reader, &clmd->ptcaches, &clmd->point_cache, 0);
|
||||
|
||||
if (clmd->sim_parms) {
|
||||
if (clmd->sim_parms->presets > 10) {
|
||||
clmd->sim_parms->presets = 0;
|
||||
}
|
||||
|
||||
clmd->sim_parms->reset = 0;
|
||||
|
||||
BLO_read_data_address(reader, &clmd->sim_parms->effector_weights);
|
||||
|
||||
if (!clmd->sim_parms->effector_weights) {
|
||||
clmd->sim_parms->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
clmd->solver_result = NULL;
|
||||
}
|
||||
else if (md->type == eModifierType_Fluid) {
|
||||
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
|
||||
if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
|
||||
fmd->flow = NULL;
|
||||
fmd->effector = NULL;
|
||||
BLO_read_data_address(reader, &fmd->domain);
|
||||
fmd->domain->fmd = fmd;
|
||||
|
||||
fmd->domain->fluid = NULL;
|
||||
fmd->domain->fluid_mutex = BLI_rw_mutex_alloc();
|
||||
fmd->domain->tex_density = NULL;
|
||||
fmd->domain->tex_color = NULL;
|
||||
fmd->domain->tex_shadow = NULL;
|
||||
fmd->domain->tex_flame = NULL;
|
||||
fmd->domain->tex_flame_coba = NULL;
|
||||
fmd->domain->tex_coba = NULL;
|
||||
fmd->domain->tex_field = NULL;
|
||||
fmd->domain->tex_velocity_x = NULL;
|
||||
fmd->domain->tex_velocity_y = NULL;
|
||||
fmd->domain->tex_velocity_z = NULL;
|
||||
fmd->domain->tex_wt = NULL;
|
||||
fmd->domain->mesh_velocities = NULL;
|
||||
BLO_read_data_address(reader, &fmd->domain->coba);
|
||||
|
||||
BLO_read_data_address(reader, &fmd->domain->effector_weights);
|
||||
if (!fmd->domain->effector_weights) {
|
||||
fmd->domain->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
|
||||
BKE_ptcache_blend_read_data(
|
||||
reader, &(fmd->domain->ptcaches[0]), &(fmd->domain->point_cache[0]), 1);
|
||||
|
||||
/* Manta sim uses only one cache from now on, so store pointer convert */
|
||||
if (fmd->domain->ptcaches[1].first || fmd->domain->point_cache[1]) {
|
||||
if (fmd->domain->point_cache[1]) {
|
||||
PointCache *cache = BLO_read_get_new_data_address(reader, fmd->domain->point_cache[1]);
|
||||
if (cache->flag & PTCACHE_FAKE_SMOKE) {
|
||||
/* Manta-sim/smoke was already saved in "new format" and this cache is a fake one. */
|
||||
}
|
||||
else {
|
||||
printf(
|
||||
"High resolution manta cache not available due to pointcache update. Please "
|
||||
"reset the simulation.\n");
|
||||
}
|
||||
BKE_ptcache_free(cache);
|
||||
}
|
||||
BLI_listbase_clear(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1] = NULL;
|
||||
}
|
||||
}
|
||||
else if (fmd->type == MOD_FLUID_TYPE_FLOW) {
|
||||
fmd->domain = NULL;
|
||||
fmd->effector = NULL;
|
||||
BLO_read_data_address(reader, &fmd->flow);
|
||||
fmd->flow->fmd = fmd;
|
||||
fmd->flow->mesh = NULL;
|
||||
fmd->flow->verts_old = NULL;
|
||||
fmd->flow->numverts = 0;
|
||||
BLO_read_data_address(reader, &fmd->flow->psys);
|
||||
}
|
||||
else if (fmd->type == MOD_FLUID_TYPE_EFFEC) {
|
||||
fmd->flow = NULL;
|
||||
fmd->domain = NULL;
|
||||
BLO_read_data_address(reader, &fmd->effector);
|
||||
if (fmd->effector) {
|
||||
fmd->effector->fmd = fmd;
|
||||
fmd->effector->verts_old = NULL;
|
||||
fmd->effector->numverts = 0;
|
||||
fmd->effector->mesh = NULL;
|
||||
}
|
||||
else {
|
||||
fmd->type = 0;
|
||||
fmd->flow = NULL;
|
||||
fmd->domain = NULL;
|
||||
fmd->effector = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
||||
|
||||
if (pmd->canvas) {
|
||||
BLO_read_data_address(reader, &pmd->canvas);
|
||||
pmd->canvas->pmd = pmd;
|
||||
pmd->canvas->flags &= ~MOD_DPAINT_BAKING; /* just in case */
|
||||
|
||||
if (pmd->canvas->surfaces.first) {
|
||||
BLO_read_list(reader, &pmd->canvas->surfaces);
|
||||
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
surface->canvas = pmd->canvas;
|
||||
surface->data = NULL;
|
||||
BKE_ptcache_blend_read_data(reader, &(surface->ptcaches), &(surface->pointcache), 1);
|
||||
|
||||
BLO_read_data_address(reader, &surface->effector_weights);
|
||||
if (surface->effector_weights == NULL) {
|
||||
surface->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pmd->brush) {
|
||||
BLO_read_data_address(reader, &pmd->brush);
|
||||
pmd->brush->pmd = pmd;
|
||||
BLO_read_data_address(reader, &pmd->brush->psys);
|
||||
BLO_read_data_address(reader, &pmd->brush->paint_ramp);
|
||||
BLO_read_data_address(reader, &pmd->brush->vel_ramp);
|
||||
}
|
||||
}
|
||||
|
||||
if (mti->blendRead != NULL) {
|
||||
mti->blendRead(reader, md);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_modifier_blend_read_lib(BlendLibReader *reader, Object *ob)
|
||||
{
|
||||
BKE_modifiers_foreach_ID_link(ob, BKE_object_modifiers_lib_link_common, reader);
|
||||
|
||||
/* If linking from a library, clear 'local' library override flag. */
|
||||
if (ob->id.lib != NULL) {
|
||||
LISTBASE_FOREACH (ModifierData *, mod, &ob->modifiers) {
|
||||
mod->flag &= ~eModifierFlag_OverrideLibrary_Local;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,7 +264,6 @@
|
|||
/* 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(BlendDataReader *reader, 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);
|
||||
static bool library_link_idcode_needs_tag_check(const short idcode, const int flag);
|
||||
|
@ -2746,18 +2745,6 @@ void blo_do_versions_key_uidgen(Key *key)
|
|||
/** \name Read ID: Object
|
||||
* \{ */
|
||||
|
||||
static void lib_link_modifiers(BlendLibReader *reader, Object *ob)
|
||||
{
|
||||
BKE_modifiers_foreach_ID_link(ob, BKE_object_modifiers_lib_link_common, reader);
|
||||
|
||||
/* If linking from a library, clear 'local' library override flag. */
|
||||
if (ob->id.lib != NULL) {
|
||||
LISTBASE_FOREACH (ModifierData *, mod, &ob->modifiers) {
|
||||
mod->flag &= ~eModifierFlag_OverrideLibrary_Local;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_link_gpencil_modifiers(BlendLibReader *reader, Object *ob)
|
||||
{
|
||||
BKE_gpencil_modifiers_foreach_ID_link(ob, BKE_object_modifiers_lib_link_common, reader);
|
||||
|
@ -2923,7 +2910,7 @@ static void lib_link_object(BlendLibReader *reader, Object *ob)
|
|||
}
|
||||
|
||||
BKE_particle_system_blend_read_lib(reader, ob, &ob->id, &ob->particlesystem);
|
||||
lib_link_modifiers(reader, ob);
|
||||
BKE_modifier_blend_read_lib(reader, ob);
|
||||
lib_link_gpencil_modifiers(reader, ob);
|
||||
BKE_shaderfx_blend_read_lib(reader, ob);
|
||||
|
||||
|
@ -3001,310 +2988,6 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose)
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO(sergey): Find a 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.
|
||||
*
|
||||
* The best approach seems to have the functionality in versioning_280.c 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 order to access sub-data 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 = BKE_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(BlendDataReader *reader, ListBase *lb, Object *ob)
|
||||
{
|
||||
BLO_read_list(reader, lb);
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, lb) {
|
||||
BKE_modifier_session_uuid_generate(md);
|
||||
|
||||
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(
|
||||
BLO_read_data_reports(reader),
|
||||
RPT_WARNING,
|
||||
TIP_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
|
||||
md->name,
|
||||
ob->id.name + 2);
|
||||
md = modifier_replace_with_fluid(reader->fd, ob, lb, md);
|
||||
is_allocated = true;
|
||||
}
|
||||
else if (md->type == eModifierType_Smoke) {
|
||||
BLO_reportf_wrap(
|
||||
BLO_read_data_reports(reader),
|
||||
RPT_WARNING,
|
||||
TIP_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
|
||||
md->name,
|
||||
ob->id.name + 2);
|
||||
md = modifier_replace_with_fluid(reader->fd, ob, lb, md);
|
||||
is_allocated = true;
|
||||
}
|
||||
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
|
||||
/* if modifiers disappear, or for upward compatibility */
|
||||
if (mti == NULL) {
|
||||
md->type = eModifierType_None;
|
||||
}
|
||||
|
||||
if (is_allocated) {
|
||||
/* All the fields has been properly allocated. */
|
||||
}
|
||||
else if (md->type == eModifierType_Cloth) {
|
||||
ClothModifierData *clmd = (ClothModifierData *)md;
|
||||
|
||||
clmd->clothObject = NULL;
|
||||
clmd->hairdata = NULL;
|
||||
|
||||
BLO_read_data_address(reader, &clmd->sim_parms);
|
||||
BLO_read_data_address(reader, &clmd->coll_parms);
|
||||
|
||||
BKE_ptcache_blend_read_data(reader, &clmd->ptcaches, &clmd->point_cache, 0);
|
||||
|
||||
if (clmd->sim_parms) {
|
||||
if (clmd->sim_parms->presets > 10) {
|
||||
clmd->sim_parms->presets = 0;
|
||||
}
|
||||
|
||||
clmd->sim_parms->reset = 0;
|
||||
|
||||
BLO_read_data_address(reader, &clmd->sim_parms->effector_weights);
|
||||
|
||||
if (!clmd->sim_parms->effector_weights) {
|
||||
clmd->sim_parms->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
clmd->solver_result = NULL;
|
||||
}
|
||||
else if (md->type == eModifierType_Fluid) {
|
||||
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
|
||||
if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
|
||||
fmd->flow = NULL;
|
||||
fmd->effector = NULL;
|
||||
BLO_read_data_address(reader, &fmd->domain);
|
||||
fmd->domain->fmd = fmd;
|
||||
|
||||
fmd->domain->fluid = NULL;
|
||||
fmd->domain->fluid_mutex = BLI_rw_mutex_alloc();
|
||||
fmd->domain->tex_density = NULL;
|
||||
fmd->domain->tex_color = NULL;
|
||||
fmd->domain->tex_shadow = NULL;
|
||||
fmd->domain->tex_flame = NULL;
|
||||
fmd->domain->tex_flame_coba = NULL;
|
||||
fmd->domain->tex_coba = NULL;
|
||||
fmd->domain->tex_field = NULL;
|
||||
fmd->domain->tex_velocity_x = NULL;
|
||||
fmd->domain->tex_velocity_y = NULL;
|
||||
fmd->domain->tex_velocity_z = NULL;
|
||||
fmd->domain->tex_wt = NULL;
|
||||
fmd->domain->mesh_velocities = NULL;
|
||||
BLO_read_data_address(reader, &fmd->domain->coba);
|
||||
|
||||
BLO_read_data_address(reader, &fmd->domain->effector_weights);
|
||||
if (!fmd->domain->effector_weights) {
|
||||
fmd->domain->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
|
||||
BKE_ptcache_blend_read_data(
|
||||
reader, &(fmd->domain->ptcaches[0]), &(fmd->domain->point_cache[0]), 1);
|
||||
|
||||
/* Manta sim uses only one cache from now on, so store pointer convert */
|
||||
if (fmd->domain->ptcaches[1].first || fmd->domain->point_cache[1]) {
|
||||
if (fmd->domain->point_cache[1]) {
|
||||
PointCache *cache = BLO_read_get_new_data_address(reader, fmd->domain->point_cache[1]);
|
||||
if (cache->flag & PTCACHE_FAKE_SMOKE) {
|
||||
/* Manta-sim/smoke was already saved in "new format" and this cache is a fake one. */
|
||||
}
|
||||
else {
|
||||
printf(
|
||||
"High resolution manta cache not available due to pointcache update. Please "
|
||||
"reset the simulation.\n");
|
||||
}
|
||||
BKE_ptcache_free(cache);
|
||||
}
|
||||
BLI_listbase_clear(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1] = NULL;
|
||||
}
|
||||
}
|
||||
else if (fmd->type == MOD_FLUID_TYPE_FLOW) {
|
||||
fmd->domain = NULL;
|
||||
fmd->effector = NULL;
|
||||
BLO_read_data_address(reader, &fmd->flow);
|
||||
fmd->flow->fmd = fmd;
|
||||
fmd->flow->mesh = NULL;
|
||||
fmd->flow->verts_old = NULL;
|
||||
fmd->flow->numverts = 0;
|
||||
BLO_read_data_address(reader, &fmd->flow->psys);
|
||||
}
|
||||
else if (fmd->type == MOD_FLUID_TYPE_EFFEC) {
|
||||
fmd->flow = NULL;
|
||||
fmd->domain = NULL;
|
||||
BLO_read_data_address(reader, &fmd->effector);
|
||||
if (fmd->effector) {
|
||||
fmd->effector->fmd = fmd;
|
||||
fmd->effector->verts_old = NULL;
|
||||
fmd->effector->numverts = 0;
|
||||
fmd->effector->mesh = NULL;
|
||||
}
|
||||
else {
|
||||
fmd->type = 0;
|
||||
fmd->flow = NULL;
|
||||
fmd->domain = NULL;
|
||||
fmd->effector = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
||||
|
||||
if (pmd->canvas) {
|
||||
BLO_read_data_address(reader, &pmd->canvas);
|
||||
pmd->canvas->pmd = pmd;
|
||||
pmd->canvas->flags &= ~MOD_DPAINT_BAKING; /* just in case */
|
||||
|
||||
if (pmd->canvas->surfaces.first) {
|
||||
BLO_read_list(reader, &pmd->canvas->surfaces);
|
||||
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
surface->canvas = pmd->canvas;
|
||||
surface->data = NULL;
|
||||
BKE_ptcache_blend_read_data(reader, &(surface->ptcaches), &(surface->pointcache), 1);
|
||||
|
||||
BLO_read_data_address(reader, &surface->effector_weights);
|
||||
if (surface->effector_weights == NULL) {
|
||||
surface->effector_weights = BKE_effector_add_weights(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pmd->brush) {
|
||||
BLO_read_data_address(reader, &pmd->brush);
|
||||
pmd->brush->pmd = pmd;
|
||||
BLO_read_data_address(reader, &pmd->brush->psys);
|
||||
BLO_read_data_address(reader, &pmd->brush->paint_ramp);
|
||||
BLO_read_data_address(reader, &pmd->brush->vel_ramp);
|
||||
}
|
||||
}
|
||||
|
||||
if (mti->blendRead != NULL) {
|
||||
mti->blendRead(reader, md);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_gpencil_modifiers(BlendDataReader *reader, ListBase *lb)
|
||||
{
|
||||
BLO_read_list(reader, lb);
|
||||
|
@ -3427,7 +3110,7 @@ static void direct_link_object(BlendDataReader *reader, Object *ob)
|
|||
BLO_read_data_address(reader, &ob->matbits);
|
||||
|
||||
/* do it here, below old data gets converted */
|
||||
direct_link_modifiers(reader, &ob->modifiers, ob);
|
||||
BKE_modifier_blend_read_data(reader, &ob->modifiers, ob);
|
||||
direct_link_gpencil_modifiers(reader, &ob->greasepencil_modifiers);
|
||||
BKE_shaderfx_blend_read_data(reader, &ob->shader_fx);
|
||||
|
||||
|
|
|
@ -942,108 +942,6 @@ static void write_fmaps(BlendWriter *writer, ListBase *fbase)
|
|||
}
|
||||
}
|
||||
|
||||
static void write_modifiers(BlendWriter *writer, ListBase *modbase)
|
||||
{
|
||||
if (modbase == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, modbase) {
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
if (mti == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLO_write_struct_by_name(writer, mti->structName, md);
|
||||
|
||||
if (md->type == eModifierType_Cloth) {
|
||||
ClothModifierData *clmd = (ClothModifierData *)md;
|
||||
|
||||
BLO_write_struct(writer, ClothSimSettings, clmd->sim_parms);
|
||||
BLO_write_struct(writer, ClothCollSettings, clmd->coll_parms);
|
||||
BLO_write_struct(writer, EffectorWeights, clmd->sim_parms->effector_weights);
|
||||
BKE_ptcache_blend_write(writer, &clmd->ptcaches);
|
||||
}
|
||||
else if (md->type == eModifierType_Fluid) {
|
||||
FluidModifierData *fmd = (FluidModifierData *)md;
|
||||
|
||||
if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
|
||||
BLO_write_struct(writer, FluidDomainSettings, fmd->domain);
|
||||
|
||||
if (fmd->domain) {
|
||||
BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[0]));
|
||||
|
||||
/* create fake pointcache so that old blender versions can read it */
|
||||
fmd->domain->point_cache[1] = BKE_ptcache_add(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE | PTCACHE_FAKE_SMOKE;
|
||||
fmd->domain->point_cache[1]->step = 1;
|
||||
|
||||
BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[1]));
|
||||
|
||||
if (fmd->domain->coba) {
|
||||
BLO_write_struct(writer, ColorBand, fmd->domain->coba);
|
||||
}
|
||||
|
||||
/* cleanup the fake pointcache */
|
||||
BKE_ptcache_free_list(&fmd->domain->ptcaches[1]);
|
||||
fmd->domain->point_cache[1] = NULL;
|
||||
|
||||
BLO_write_struct(writer, EffectorWeights, fmd->domain->effector_weights);
|
||||
}
|
||||
}
|
||||
else if (fmd->type & MOD_FLUID_TYPE_FLOW) {
|
||||
BLO_write_struct(writer, FluidFlowSettings, fmd->flow);
|
||||
}
|
||||
else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
|
||||
BLO_write_struct(writer, FluidEffectorSettings, fmd->effector);
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Fluidsim) {
|
||||
FluidsimModifierData *fluidmd = (FluidsimModifierData *)md;
|
||||
|
||||
BLO_write_struct(writer, FluidsimSettings, fluidmd->fss);
|
||||
}
|
||||
else if (md->type == eModifierType_DynamicPaint) {
|
||||
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
|
||||
|
||||
if (pmd->canvas) {
|
||||
BLO_write_struct(writer, DynamicPaintCanvasSettings, pmd->canvas);
|
||||
|
||||
/* write surfaces */
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
BLO_write_struct(writer, DynamicPaintSurface, surface);
|
||||
}
|
||||
/* write caches and effector weights */
|
||||
LISTBASE_FOREACH (DynamicPaintSurface *, surface, &pmd->canvas->surfaces) {
|
||||
BKE_ptcache_blend_write(writer, &(surface->ptcaches));
|
||||
|
||||
BLO_write_struct(writer, EffectorWeights, surface->effector_weights);
|
||||
}
|
||||
}
|
||||
if (pmd->brush) {
|
||||
BLO_write_struct(writer, DynamicPaintBrushSettings, pmd->brush);
|
||||
BLO_write_struct(writer, ColorBand, pmd->brush->paint_ramp);
|
||||
BLO_write_struct(writer, ColorBand, pmd->brush->vel_ramp);
|
||||
}
|
||||
}
|
||||
else if (md->type == eModifierType_Collision) {
|
||||
|
||||
#if 0
|
||||
CollisionModifierData *collmd = (CollisionModifierData *)md;
|
||||
// TODO: CollisionModifier should use pointcache
|
||||
// + have proper reset events before enabling this
|
||||
writestruct(wd, DATA, MVert, collmd->numverts, collmd->x);
|
||||
writestruct(wd, DATA, MVert, collmd->numverts, collmd->xnew);
|
||||
writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mti->blendWrite != NULL) {
|
||||
mti->blendWrite(writer, md);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_gpencil_modifiers(BlendWriter *writer, ListBase *modbase)
|
||||
{
|
||||
if (modbase == NULL) {
|
||||
|
@ -1173,7 +1071,7 @@ static void write_object(BlendWriter *writer, Object *ob, const void *id_address
|
|||
}
|
||||
|
||||
BKE_particle_system_blend_write(writer, &ob->particlesystem);
|
||||
write_modifiers(writer, &ob->modifiers);
|
||||
BKE_modifier_blend_write(writer, &ob->modifiers);
|
||||
write_gpencil_modifiers(writer, &ob->greasepencil_modifiers);
|
||||
BKE_shaderfx_blend_write(writer, &ob->shader_fx);
|
||||
|
||||
|
|
Loading…
Reference in New Issue