diff options
Diffstat (limited to 'source/blender/blenkernel')
126 files changed, 6413 insertions, 2183 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index b517ecfa599..092eec578c9 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -364,6 +364,7 @@ struct Mesh *editbmesh_get_eval_cage_and_final(struct Depsgraph *depsgraph, float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3]; bool editbmesh_modifier_is_enabled(struct Scene *scene, + const struct Object *ob, struct ModifierData *md, bool has_prev_mesh); void makeDerivedMesh(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 699387a18c7..d8605941974 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -30,6 +30,12 @@ extern "C" { #endif +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; +struct BlendExpander; +struct bArmature; + /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ struct AnimationEvalContext; struct FCurve; @@ -216,6 +222,11 @@ void BKE_pose_rest(struct bPose *pose, bool selected_bones_only); /* Tag pose for recalc. Also tag all related data to be recalc. */ void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose); +void BKE_pose_blend_write(struct BlendWriter *writer, struct bPose *pose, struct bArmature *arm); +void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose); +void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose); +void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose); + #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_anim_visualization.h b/source/blender/blenkernel/BKE_anim_visualization.h index fb7875a112e..decb2e0b210 100644 --- a/source/blender/blenkernel/BKE_anim_visualization.h +++ b/source/blender/blenkernel/BKE_anim_visualization.h @@ -32,6 +32,8 @@ struct Scene; struct bAnimVizSettings; struct bMotionPath; struct bPoseChannel; +struct BlendWriter; +struct BlendDataReader; /* ---------------------------------------------------- */ /* Animation Visualization */ @@ -48,6 +50,9 @@ struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, struct Object *ob, struct bPoseChannel *pchan); +void animviz_motionpath_blend_write(struct BlendWriter *writer, struct bMotionPath *mpath); +void animviz_motionpath_blend_read_data(struct BlendDataReader *reader, struct bMotionPath *mpath); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 741abb50453..9fa32013ba6 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,15 +31,15 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 291 +#define BLENDER_VERSION 292 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 9 +#define BLENDER_FILE_SUBVERSION 4 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index f4393742dff..f35dafa15a8 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -35,10 +35,16 @@ extern "C" { struct BLI_Iterator; struct Base; +struct BlendDataReader; +struct BlendExpander; +struct BlendLibReader; +struct BlendWriter; struct Collection; +struct Library; struct Main; struct Object; struct Scene; +struct SceneCollection; struct ViewLayer; typedef struct CollectionParent { @@ -160,6 +166,22 @@ bool BKE_collection_has_collection(struct Collection *parent, struct Collection void BKE_collection_parent_relations_rebuild(struct Collection *collection); void BKE_main_collections_parent_relations_rebuild(struct Main *bmain); +/* .blend file I/O */ + +void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection); +void BKE_collection_blend_read_data(struct BlendDataReader *reader, struct Collection *collection); +void BKE_collection_blend_read_lib(struct BlendLibReader *reader, struct Collection *collection); +void BKE_collection_blend_read_expand(struct BlendExpander *expander, + struct Collection *collection); + +void BKE_collection_compat_blend_read_data(struct BlendDataReader *reader, + struct SceneCollection *sc); +void BKE_collection_compat_blend_read_lib(struct BlendLibReader *reader, + struct Library *lib, + struct SceneCollection *sc); +void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander, + struct SceneCollection *sc); + /* Iteration callbacks. */ typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index e56a1ac9ce3..3631feb5071 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -139,6 +139,11 @@ void BKE_color_managed_view_settings_copy(struct ColorManagedViewSettings *new_s const struct ColorManagedViewSettings *settings); void BKE_color_managed_view_settings_free(struct ColorManagedViewSettings *settings); +void BKE_color_managed_view_settings_blend_write(struct BlendWriter *writer, + struct ColorManagedViewSettings *settings); +void BKE_color_managed_view_settings_blend_read_data(struct BlendDataReader *reader, + struct ColorManagedViewSettings *settings); + void BKE_color_managed_colorspace_settings_init( struct ColorManagedColorspaceSettings *colorspace_settings); void BKE_color_managed_colorspace_settings_copy( diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index ecb891760b7..e5c4535560d 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -31,6 +31,10 @@ struct Scene; struct bConstraint; struct bConstraintTarget; struct bPoseChannel; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; +struct BlendExpander; /* ---------------------------------------------------------------------------- */ #ifdef __cplusplus @@ -183,6 +187,8 @@ bool BKE_constraint_remove_ex(ListBase *list, bool clear_dep); bool BKE_constraint_remove(ListBase *list, struct bConstraint *con); +void BKE_constraint_panel_expand(struct bConstraint *con); + /* Constraints + Proxies function prototypes */ void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *src); bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan); @@ -220,6 +226,13 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, struct bConstraintOb *cob, float ctime); +void BKE_constraint_blend_write(struct BlendWriter *writer, struct ListBase *conlist); +void BKE_constraint_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); +void BKE_constraint_blend_read_lib(struct BlendLibReader *reader, + struct ID *id, + struct ListBase *conlist); +void BKE_constraint_blend_read_expand(struct BlendExpander *expander, struct ListBase *lb); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index c9bc5e83a1f..f527f40d0d7 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -325,6 +325,9 @@ float fcurve_samplingcb_evalcurve(struct FCurve *fcu, void *data, float evaltime void fcurve_store_samples( struct FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb); +/* Convert baked/sampled fcurves into bezt/regular fcurves. */ +void fcurve_samples_to_keyframes(struct FCurve *fcu, const int start, const int end); + /* ************* F-Curve .blend file API ******************** */ void BKE_fmodifiers_blend_write(struct BlendWriter *writer, struct ListBase *fmodifiers); diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index e003144047b..7729d2c53ab 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -35,6 +35,9 @@ struct Main; struct ModifierUpdateDepsgraphContext; struct Object; struct Scene; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; /* NOTE: bakeModifier() called from UI: * needs to create new data-blocks, hence the need for this. */ struct bGPDframe; @@ -249,6 +252,7 @@ typedef struct GpencilModifierTypeInfo { void BKE_gpencil_modifier_init(void); void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname); +void BKE_gpencil_modifier_panel_expand(struct GpencilModifierData *md); const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type); struct GpencilModifierData *BKE_gpencil_modifier_new(int type); void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag); @@ -302,6 +306,10 @@ struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph, struct Object *ob, struct bGPDlayer *gpl); +void BKE_gpencil_modifier_blend_write(struct BlendWriter *writer, struct ListBase *modbase); +void BKE_gpencil_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); +void BKE_gpencil_modifier_blend_read_lib(struct BlendLibReader *reader, struct Object *ob); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 37a83a94079..9c250240e5e 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -147,8 +147,6 @@ void IDP_FreeProperty(struct IDProperty *prop); void IDP_ClearProperty(IDProperty *prop); -void IDP_RelinkProperty(struct IDProperty *prop); - void IDP_Reset(IDProperty *prop, const IDProperty *reference); #define IDP_Int(prop) ((prop)->data.val) diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index 3caf15d1b50..1298e3c2bbf 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -102,6 +102,10 @@ typedef void (*IDTypeBlendReadDataFunction)(struct BlendDataReader *reader, stru typedef void (*IDTypeBlendReadLibFunction)(struct BlendLibReader *reader, struct ID *id); typedef void (*IDTypeBlendReadExpandFunction)(struct BlendExpander *expander, struct ID *id); +typedef void (*IDTypeBlendReadUndoPreserve)(struct BlendLibReader *reader, + struct ID *id_new, + struct ID *id_old); + typedef struct IDTypeInfo { /* ********** General IDType data. ********** */ @@ -196,6 +200,13 @@ typedef struct IDTypeInfo { * Specify which other id data blocks should be loaded when the current one is loaded. */ IDTypeBlendReadExpandFunction blend_read_expand; + + /** + * Allow an ID type to preserve some of its data across (memfile) undo steps. + * + * \note Called from #setup_app_data when undoing or redoing a memfile step. + */ + IDTypeBlendReadUndoPreserve blend_read_undo_preserve; } IDTypeInfo; /* ********** Declaration of each IDTypeInfo. ********** */ diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 024d58174e8..1fb3e746b37 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -34,6 +34,9 @@ extern "C" { #define TODO_LAYER /* generic todo */ struct Base; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct Collection; struct Depsgraph; struct LayerCollection; @@ -147,6 +150,14 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph, struct Scene *scene, int view_layer_index); +/* .blend file I/O */ + +void BKE_view_layer_blend_write(struct BlendWriter *writer, struct ViewLayer *view_layer); +void BKE_view_layer_blend_read_data(struct BlendDataReader *reader, struct ViewLayer *view_layer); +void BKE_view_layer_blend_read_lib(struct BlendLibReader *reader, + struct Library *lib, + struct ViewLayer *view_layer); + /* iterators */ typedef struct ObjectsVisibleIteratorData { diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 789f78826e0..807f13efe14 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -177,7 +177,7 @@ void BKE_mesh_to_pointcloud(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); -void BKE_mesh_from_pointcloud(struct PointCloud *pointcloud, struct Mesh *me); +void BKE_mesh_from_pointcloud(const struct PointCloud *pointcloud, struct Mesh *me); void BKE_pointcloud_to_mesh(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index b2015c4e6d7..a2c3787bcd2 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -30,6 +30,7 @@ extern "C" { struct ARegionType; struct BMEditMesh; struct BlendDataReader; +struct BlendLibReader; struct BlendWriter; struct CustomData_MeshMasks; struct DepsNodeHandle; @@ -396,6 +397,7 @@ const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type); /* For modifier UI panels. */ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname); +void BKE_modifier_panel_expand(struct ModifierData *md); /* Modifier utility calls, do call through type pointer and return * default values if pointer is optional. @@ -427,8 +429,10 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md); bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode); -void BKE_modifier_set_error(struct ModifierData *md, const char *format, ...) - ATTR_PRINTF_FORMAT(2, 3); +void BKE_modifier_set_error(const struct Object *ob, + struct ModifierData *md, + const char *format, + ...) ATTR_PRINTF_FORMAT(3, 4); bool BKE_modifier_is_preview(struct ModifierData *md); void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData); @@ -532,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 diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index fbdfc5b76a7..5a668532033 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -36,7 +36,6 @@ struct DerivedMesh; struct MDisps; struct Mesh; struct ModifierData; -struct Multires; struct MultiresModifierData; struct Object; struct Scene; @@ -114,22 +113,12 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, struct MultiresModifierData *mmd, int rebuild_limit, bool switch_view_to_lower_level); -void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd, - struct Scene *scene, - struct Object *ob, - int updateblock, - int simple); void multiresModifier_sync_levels_ex(struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst); void multires_stitch_grids(struct Object *); -/* Related to the old multires */ -void multires_free(struct Multires *mr); -void multires_load_old(struct Object *ob, struct Mesh *me); -void multires_load_old_250(struct Mesh *); - void multiresModifier_scale_disp(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); @@ -229,6 +218,13 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] const float dPdv[3], const int corner); +/* Versioning. */ + +/* Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark + * subdivided mesh. */ +void multires_do_versions_simple_to_catmull_clark(struct Object *object, + struct MultiresModifierData *mmd); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 38045e22def..e3591b8fcd1 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -880,8 +880,7 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree); * } FOREACH_NODETREE_END; * \endcode * - * \{ - */ + * \{ */ /* should be an opaque type, only for internal use by BKE_node_tree_iter_*** */ struct NodeTreeIterStore { @@ -1337,8 +1336,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, /** \} */ -void init_nodesystem(void); -void free_nodesystem(void); +void BKE_node_system_init(void); +void BKE_node_system_exit(void); /* -------------------------------------------------------------------- */ /* evaluation support, */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0a992f2cb58..28c912a4c9a 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -191,6 +191,8 @@ struct Base **BKE_object_pose_base_array_get(struct ViewLayer *view_layer, unsigned int *r_bases_len); void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4]); + +/* Compute object world transform and store it in ob->obmat. */ void BKE_object_where_is_calc(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_object_where_is_calc_ex(struct Depsgraph *depsgraph, struct Scene *scene, @@ -414,6 +416,14 @@ void BKE_object_to_mesh_clear(struct Object *object); void BKE_object_check_uuids_unique_and_report(const struct Object *object); +void BKE_object_modifiers_lib_link_common(void *userData, + struct Object *ob, + struct ID **idpoin, + int cb_flag); + +struct PartEff; +struct PartEff *BKE_object_do_version_give_parteff_245(struct Object *ob); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 150d0d9b011..a58bf760ad5 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -66,6 +66,9 @@ struct ViewLayer; struct bContext; struct bToolRef; struct tPaletteColorHSV; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; enum eOverlayFlags; @@ -217,6 +220,15 @@ void BKE_paint_toolslots_brush_update(struct Paint *paint); void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint); struct Brush *BKE_paint_toolslots_brush_get(struct Paint *paint, int slot_index); +/* .blend I/O */ +void BKE_paint_blend_write(struct BlendWriter *writer, struct Paint *paint); +void BKE_paint_blend_read_data(struct BlendDataReader *reader, + const struct Scene *scene, + struct Paint *paint); +void BKE_paint_blend_read_lib(struct BlendLibReader *reader, + struct Scene *scene, + struct Paint *paint); + #define SCULPT_FACE_SET_NONE 0 /* Used for both vertex color and weight paint */ @@ -505,6 +517,9 @@ typedef struct SculptSession { int active_face_index; int active_grid_index; + /* When active, the cursor draws with faded colors, indicating that there is an action enabled. + */ + bool draw_faded_cursor; float cursor_radius; float cursor_location[3]; float cursor_normal[3]; @@ -514,6 +529,7 @@ typedef struct SculptSession { /* For Sculpt trimming gesture tools, initial raycast data from the position of the mouse when * the gesture starts (intersection with the surface and if they ray hit the surface or not). */ float gesture_initial_location[3]; + float gesture_initial_normal[3]; bool gesture_initial_hit; /* TODO(jbakker): Replace rv3d adn v3d with ViewContext */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 6ed3b94b8e5..73815325594 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -45,6 +45,9 @@ struct ParticleSystemModifierData; struct BVHTreeRay; struct BVHTreeRayHit; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; struct CustomData_MeshMasks; struct Depsgraph; struct EdgeHash; @@ -261,7 +264,7 @@ extern unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; extern unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]; extern float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; -void psys_init_rng(void); +void BKE_particle_init_rng(void); BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed) { @@ -625,6 +628,20 @@ void BKE_particle_batch_cache_free(struct ParticleSystem *psys); extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys, int mode); extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys); +/* .blend file I/O */ +void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader, + struct PartDeflect *pd); +void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader, + struct ID *id, + struct PartDeflect *pd); +void BKE_particle_system_blend_write(struct BlendWriter *writer, struct ListBase *particles); +void BKE_particle_system_blend_read_data(struct BlendDataReader *reader, + struct ListBase *particles); +void BKE_particle_system_blend_read_lib(struct BlendLibReader *reader, + struct Object *ob, + struct ID *id, + struct ListBase *particles); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index f8e04b75b3d..470d53f6655 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -91,6 +91,8 @@ struct RigidBodyWorld; struct Scene; struct SoftBody; struct ViewLayer; +struct BlendWriter; +struct BlendDataReader; /* temp structure for read/write */ typedef struct PTCacheData { @@ -167,7 +169,7 @@ typedef struct PTCacheID { * (the cfra parameter is just for using same function pointer with totwrite). */ int (*totpoint)(void *calldata, int cfra); /* report error if number of points does not match */ - void (*error)(void *calldata, const char *message); + void (*error)(const struct ID *owner_id, void *calldata, const char *message); /* number of points written for current cache frame */ int (*totwrite)(void *calldata, int cfra); @@ -374,6 +376,14 @@ void BKE_ptcache_validate(struct PointCache *cache, int framenr); /* Set correct flags after unsuccessful simulation step */ void BKE_ptcache_invalidate(struct PointCache *cache); +/********************** .blend File I/O *********************/ + +void BKE_ptcache_blend_write(struct BlendWriter *writer, struct ListBase *ptcaches); +void BKE_ptcache_blend_read_data(struct BlendDataReader *reader, + struct ListBase *ptcaches, + struct PointCache **ocache, + int force_disk); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 35a3d0415a8..fd5339940dd 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -33,6 +33,9 @@ extern "C" { #endif struct ARegion; +struct BlendDataReader; +struct BlendLibReader; +struct BlendWriter; struct Header; struct ID; struct LibraryForeachIDData; @@ -362,8 +365,8 @@ typedef struct Menu { /* spacetypes */ struct SpaceType *BKE_spacetype_from_id(int spaceid); -struct ARegionType *BKE_regiontype_from_id_or_first(struct SpaceType *st, int regionid); -struct ARegionType *BKE_regiontype_from_id(struct SpaceType *st, int regionid); +struct ARegionType *BKE_regiontype_from_id_or_first(const struct SpaceType *st, int regionid); +struct ARegionType *BKE_regiontype_from_id(const struct SpaceType *st, int regionid); const struct ListBase *BKE_spacetypes_list(void); void BKE_spacetype_register(struct SpaceType *st); bool BKE_spacetype_exists(int spaceid); @@ -384,7 +387,7 @@ void BKE_spacedata_callback_id_remap_set(void (*func)( void BKE_spacedata_id_unref(struct ScrArea *area, struct SpaceLink *sl, struct ID *id); /* area/regions */ -struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *region); +struct ARegion *BKE_area_region_copy(const struct SpaceType *st, const struct ARegion *region); void BKE_area_region_free(struct SpaceType *st, struct ARegion *region); void BKE_area_region_panels_free(struct ListBase *panels); void BKE_screen_area_free(struct ScrArea *area); @@ -449,6 +452,21 @@ void BKE_screen_remove_unused_scrverts(struct bScreen *screen); void BKE_screen_header_alignment_reset(struct bScreen *screen); +/* .blend file I/O */ +void BKE_screen_view3d_shading_blend_write(struct BlendWriter *writer, + struct View3DShading *shading); +void BKE_screen_view3d_shading_blend_read_data(struct BlendDataReader *reader, + struct View3DShading *shading); + +void BKE_screen_area_map_blend_write(struct BlendWriter *writer, struct ScrAreaMap *area_map); +bool BKE_screen_area_map_blend_read_data(struct BlendDataReader *reader, + struct ScrAreaMap *area_map); +void BKE_screen_view3d_do_versions_250(struct View3D *v3d, ListBase *regions); +void BKE_screen_area_blend_read_lib(struct BlendLibReader *reader, + struct ID *parent_id, + struct ScrArea *area); +bool BKE_screen_blend_read_data(struct BlendDataReader *reader, struct bScreen *screen); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_sequencer_offscreen.h b/source/blender/blenkernel/BKE_sequencer_offscreen.h index 90d3f80320a..f5f6067b06e 100644 --- a/source/blender/blenkernel/BKE_sequencer_offscreen.h +++ b/source/blender/blenkernel/BKE_sequencer_offscreen.h @@ -33,6 +33,8 @@ extern "C" { #endif +struct GPUOffScreen; + typedef struct ImBuf *(*SequencerDrawView)(struct Depsgraph *depsgraph, struct Scene *scene, struct View3DShading *shading_override, diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index da14487c1f4..7c2d363be5c 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -33,6 +33,9 @@ struct ListBase; struct ModifierUpdateDepsgraphContext; struct Object; struct ShaderFxData; +struct BlendWriter; +struct BlendDataReader; +struct BlendLibReader; #define SHADER_FX_ACTIVE(_fx, _is_render) \ ((((_fx)->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \ @@ -151,6 +154,7 @@ typedef struct ShaderFxTypeInfo { void BKE_shaderfx_init(void); void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname); +void BKE_shaderfx_panel_expand(struct ShaderFxData *fx); const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type); struct ShaderFxData *BKE_shaderfx_new(int type); void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag); @@ -169,6 +173,10 @@ void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, vo bool BKE_shaderfx_has_gpencil(struct Object *ob); +void BKE_shaderfx_blend_write(struct BlendWriter *writer, struct ListBase *fxbase); +void BKE_shaderfx_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb); +void BKE_shaderfx_blend_read_lib(struct BlendLibReader *reader, struct Object *ob); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f6df3f1bb62..40b2d62baac 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -39,7 +39,7 @@ set(INC ../sequencer ../shader_fx ../simulation - ../render/extern/include + ../render ../../../intern/ghost ../../../intern/glew-mx ../../../intern/guardedalloc @@ -189,6 +189,7 @@ set(SRC intern/multires_reshape_vertcos.c intern/multires_subdiv.c intern/multires_unsubdivide.c + intern/multires_versioning.c intern/nla.c intern/node.c intern/object.c @@ -209,7 +210,7 @@ set(SRC intern/pbvh.c intern/pbvh_bmesh.c intern/pointcache.c - intern/pointcloud.c + intern/pointcloud.cc intern/report.c intern/rigidbody.c intern/scene.c @@ -705,7 +706,7 @@ endif() # # Warnings as errors, this is too strict! # if(MSVC) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") +# string(APPEND CMAKE_C_FLAGS " /WX") # endif() blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index d63c5fe12ab..67e7b890548 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -736,7 +736,7 @@ CCGError ccgSubSurf_syncFace( } } else { - if (ss->syncState == eSyncState_Vert || ss->syncState == eSyncState_Edge) { + if (ELEM(ss->syncState, eSyncState_Vert, eSyncState_Edge)) { ss->syncState = eSyncState_Face; } else if (ss->syncState != eSyncState_Face) { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d551eaf04e4..eeff04788f9 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1021,7 +1021,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && have_non_onlydeform_modifiers_appled) { - BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); continue; } @@ -1047,10 +1047,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (unsupported) { if (sculpt_dyntopo) { - BKE_modifier_set_error(md, "Not supported in dyntopo"); + BKE_modifier_set_error(ob, md, "Not supported in dyntopo"); } else { - BKE_modifier_set_error(md, "Not supported in sculpt mode"); + BKE_modifier_set_error(ob, md, "Not supported in sculpt mode"); } continue; } @@ -1378,7 +1378,10 @@ float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] return cos; } -bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev_mesh) +bool editbmesh_modifier_is_enabled(Scene *scene, + const Object *ob, + ModifierData *md, + bool has_prev_mesh) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; @@ -1388,7 +1391,7 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev } if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { - BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position"); return false; } @@ -1522,7 +1525,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) { + if (!editbmesh_modifier_is_enabled(scene, ob, md, mesh_final != NULL)) { continue; } @@ -2187,7 +2190,7 @@ static void mesh_init_origspace(Mesh *mesh) for (i = 0; i < numpoly; i++, mp++) { OrigSpaceLoop *lof = lof_array + mp->loopstart; - if (mp->totloop == 3 || mp->totloop == 4) { + if (ELEM(mp->totloop, 3, 4)) { for (j = 0; j < mp->totloop; j++, lof++) { copy_v2_v2(lof->uv, default_osf[j]); } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index cbecc91b4ec..126063288d8 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -61,6 +61,7 @@ #include "BKE_main.h" #include "BKE_object.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "BIK_api.h" @@ -295,6 +296,8 @@ IDTypeInfo IDType_ID_AC = { .blend_read_data = action_blend_read_data, .blend_read_lib = action_blend_read_lib, .blend_read_expand = action_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* ***************** Library data level operations on action ************** */ @@ -1844,3 +1847,174 @@ void BKE_pose_check_uuids_unique_and_report(const bPose *pose) BLI_gset_free(used_uuids, NULL); } + +void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm) +{ + /* Write each channel */ + if (pose == NULL) { + return; + } + + BLI_assert(arm != NULL); + + /* Write channels */ + LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) { + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + if (chan->prop) { + IDP_BlendWrite(writer, chan->prop); + } + + BKE_constraint_blend_write(writer, &chan->constraints); + + animviz_motionpath_blend_write(writer, chan->mpath); + + /* Prevent crashes with autosave, + * when a bone duplicated in edit-mode has not yet been assigned to its pose-channel. + * Also needed with memundo, in some cases we can store a step before pose has been + * properly rebuilt from previous undo step. */ + Bone *bone = (pose->flag & POSE_RECALC) ? BKE_armature_find_bone_name(arm, chan->name) : + chan->bone; + if (bone != NULL) { + /* gets restored on read, for library armatures */ + chan->selectflag = bone->flag & BONE_SELECTED; + } + + BLO_write_struct(writer, bPoseChannel, chan); + } + + /* Write groups */ + LISTBASE_FOREACH (bActionGroup *, grp, &pose->agroups) { + BLO_write_struct(writer, bActionGroup, grp); + } + + /* write IK param */ + if (pose->ikparam) { + const char *structname = BKE_pose_ikparam_get_name(pose); + if (structname) { + BLO_write_struct_by_name(writer, structname, pose->ikparam); + } + } + + /* Write this pose */ + BLO_write_struct(writer, bPose, pose); +} + +void BKE_pose_blend_read_data(BlendDataReader *reader, bPose *pose) +{ + if (!pose) { + return; + } + + BLO_read_list(reader, &pose->chanbase); + BLO_read_list(reader, &pose->agroups); + + pose->chanhash = NULL; + pose->chan_array = NULL; + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + BKE_pose_channel_runtime_reset(&pchan->runtime); + BKE_pose_channel_session_uuid_generate(pchan); + + pchan->bone = NULL; + BLO_read_data_address(reader, &pchan->parent); + BLO_read_data_address(reader, &pchan->child); + BLO_read_data_address(reader, &pchan->custom_tx); + + BLO_read_data_address(reader, &pchan->bbone_prev); + BLO_read_data_address(reader, &pchan->bbone_next); + + BKE_constraint_blend_read_data(reader, &pchan->constraints); + + BLO_read_data_address(reader, &pchan->prop); + IDP_BlendDataRead(reader, &pchan->prop); + + BLO_read_data_address(reader, &pchan->mpath); + if (pchan->mpath) { + animviz_motionpath_blend_read_data(reader, pchan->mpath); + } + + BLI_listbase_clear(&pchan->iktree); + BLI_listbase_clear(&pchan->siktree); + + /* in case this value changes in future, clamp else we get undefined behavior */ + CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX); + + pchan->draw_data = NULL; + } + pose->ikdata = NULL; + if (pose->ikparam != NULL) { + BLO_read_data_address(reader, &pose->ikparam); + } +} + +void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose) +{ + bArmature *arm = ob->data; + + if (!pose || !arm) { + return; + } + + /* always rebuild to match proxy or lib changes, but on Undo */ + bool rebuild = false; + + if (!BLO_read_lib_is_undo(reader)) { + if (ob->proxy || ob->id.lib != arm->id.lib) { + rebuild = true; + } + } + + if (ob->proxy) { + /* sync proxy layer */ + if (pose->proxy_layer) { + arm->layer = pose->proxy_layer; + } + + /* sync proxy active bone */ + if (pose->proxy_act_bone[0]) { + Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone); + if (bone) { + arm->act_bone = bone; + } + } + } + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints); + + pchan->bone = BKE_armature_find_bone_name(arm, pchan->name); + + IDP_BlendReadLib(reader, pchan->prop); + + BLO_read_id_address(reader, arm->id.lib, &pchan->custom); + if (UNLIKELY(pchan->bone == NULL)) { + rebuild = true; + } + else if ((ob->id.lib == NULL) && arm->id.lib) { + /* local pose selection copied to armature, bit hackish */ + pchan->bone->flag &= ~BONE_SELECTED; + pchan->bone->flag |= pchan->selectflag; + } + } + + if (rebuild) { + Main *bmain = BLO_read_lib_get_main(reader); + DEG_id_tag_update_ex( + bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + BKE_pose_tag_recalc(bmain, pose); + } +} + +void BKE_pose_blend_read_expand(BlendExpander *expander, bPose *pose) +{ + if (!pose) { + return; + } + + LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) { + BKE_constraint_blend_read_expand(expander, &chan->constraints); + IDP_BlendReadExpand(expander, chan->prop); + BLO_expand(expander, chan->custom); + } +} diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c index 5452e2513fb..ecd71ec08fe 100644 --- a/source/blender/blenkernel/intern/anim_visualization.c +++ b/source/blender/blenkernel/intern/anim_visualization.c @@ -34,6 +34,8 @@ #include "GPU_batch.h" +#include "BLO_read_write.h" + /* ******************************************************************** */ /* Animation Visualization */ @@ -224,3 +226,32 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, /* return it */ return mpath; } + +void animviz_motionpath_blend_write(BlendWriter *writer, bMotionPath *mpath) +{ + /* sanity checks */ + if (mpath == NULL) { + return; + } + + /* firstly, just write the motionpath struct */ + BLO_write_struct(writer, bMotionPath, mpath); + + /* now write the array of data */ + BLO_write_struct_array(writer, bMotionPathVert, mpath->length, mpath->points); +} + +void animviz_motionpath_blend_read_data(BlendDataReader *reader, bMotionPath *mpath) +{ + /* sanity check */ + if (mpath == NULL) { + return; + } + + /* relink points cache */ + BLO_read_data_address(reader, &mpath->points); + + mpath->points_vbo = NULL; + mpath->batch_line = NULL; + mpath->batch_points = NULL; +} diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index bad2ed53436..fb885527cce 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -329,6 +329,8 @@ IDTypeInfo IDType_ID_AR = { .blend_read_data = armature_blend_read_data, .blend_read_lib = armature_blend_read_lib, .blend_read_expand = armature_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /** \} */ @@ -576,7 +578,7 @@ void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do /* -------------------------------------------------------------------- */ /** \name Armature Bone Find by Name * - * Using fast #GHash look-ups when available. + * Using fast #GHash lookups when available. * \{ */ static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) @@ -799,7 +801,7 @@ bool bone_autoside_name( while (changed) { /* remove extensions */ changed = false; if (len > 2 && basename[len - 2] == '.') { - if (basename[len - 1] == 'L' || basename[len - 1] == 'R') { /* L R */ + if (ELEM(basename[len - 1], 'L', 'R')) { /* L R */ basename[len - 2] = '\0'; len -= 2; changed = true; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 1ad1a821129..f4f25c3a153 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -53,13 +53,14 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "BKE_studiolight.h" #include "DEG_depsgraph.h" #include "RE_pipeline.h" -#include "RE_render_ext.h" +#include "RE_texture.h" + +#include "SEQ_sequencer.h" #include "BLF_api.h" @@ -99,7 +100,7 @@ void BKE_blender_free(void) IMB_moviecache_destruct(); - free_nodesystem(); + BKE_node_system_exit(); } /** \} */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 78ce70a8448..96bf9fbe8d2 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -899,7 +899,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, for (coll = bbd->sim->colliders->first; coll; coll = coll->next) { col.current = coll->ob; col.md = coll->collmd; - col.fac1 = col.fac2 = 0.f; + col.fac1 = col.fac2 = 0.0f; if (col.md && col.md->bvhtree) { BLI_bvhtree_ray_cast_ex(col.md->bvhtree, diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 4ea9a26f0f8..f624d0ae057 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -73,12 +73,13 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_report.h" -#include "BKE_sequencer.h" #include "BKE_bpath.h" /* own include */ #include "CLG_log.h" +#include "SEQ_sequencer.h" + #ifndef _MSC_VER # include "BLI_strict_flags.h" #endif diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 17243b328e8..1b77989c2b8 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -50,7 +50,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "RE_render_ext.h" /* RE_texture_evaluate */ +#include "RE_texture.h" /* RE_texture_evaluate */ #include "BLO_read_write.h" @@ -355,6 +355,37 @@ static void brush_blend_read_expand(BlendExpander *expander, ID *id) } } +static int brush_undo_preserve_cb(LibraryIDLinkCallbackData *cb_data) +{ + BlendLibReader *reader = cb_data->user_data; + ID *id_old = *cb_data->id_pointer; + /* Old data has not been remapped to new values of the pointers, if we want to keep the old + * pointer here we need its new address. */ + ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) : + NULL; + BLI_assert(id_old_new == NULL || ELEM(id_old, id_old_new, id_old_new->orig_id)); + if (cb_data->cb_flag & IDWALK_CB_USER) { + id_us_plus_no_lib(id_old_new); + id_us_min(id_old); + } + *cb_data->id_pointer = id_old_new; + return IDWALK_RET_NOP; +} + +static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) +{ + /* Whole Brush is preserved accross undo's. */ + BKE_lib_id_swap(NULL, id_new, id_old); + + /* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid. + * Note: Since we want to re-use all old pointers here, code is much simpler than for Scene. */ + BKE_library_foreach_ID_link(NULL, id_new, brush_undo_preserve_cb, reader, IDWALK_NOP); + + /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be + * fairly delicate. */ + SWAP(IDProperty *, id_new->properties, id_old->properties); +} + IDTypeInfo IDType_ID_BR = { .id_code = ID_BR, .id_filter = FILTER_ID_BR, @@ -376,6 +407,8 @@ IDTypeInfo IDType_ID_BR = { .blend_read_data = brush_blend_read_data, .blend_read_lib = brush_blend_read_lib, .blend_read_expand = brush_blend_read_expand, + + .blend_read_undo_preserve = brush_undo_preserve, }; static RNG *brush_rng; diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 0ee0242866f..d6c31809a2e 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -140,6 +140,8 @@ IDTypeInfo IDType_ID_CF = { .blend_read_data = cache_file_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /* TODO: make this per cache file to avoid global locks. */ diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 3980a552855..0ca22e34973 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -201,6 +201,8 @@ IDTypeInfo IDType_ID_CA = { .blend_read_data = camera_blend_read_data, .blend_read_lib = camera_blend_read_lib, .blend_read_expand = camera_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /** \} */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 403722b80cf..e9df562a15f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -55,7 +55,7 @@ /* Prototypes for internal functions. */ static void cloth_to_object(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]); -static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh); +static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh); static bool cloth_from_object( Object *ob, ClothModifierData *clmd, Mesh *mesh, float framenr, int first); static void cloth_update_springs(ClothModifierData *clmd); @@ -234,13 +234,13 @@ static bool do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int if (clmd->clothObject == NULL) { if (!cloth_from_object(ob, clmd, result, framenr, 1)) { BKE_ptcache_invalidate(cache); - BKE_modifier_set_error(&(clmd->modifier), "Can't initialize cloth"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Can't initialize cloth"); return false; } if (clmd->clothObject == NULL) { BKE_ptcache_invalidate(cache); - BKE_modifier_set_error(&(clmd->modifier), "Null cloth object"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Null cloth object"); return false; } @@ -742,7 +742,7 @@ static bool cloth_from_object( clmd->clothObject->edgeset = NULL; } else { - BKE_modifier_set_error(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject"); return false; } @@ -751,7 +751,7 @@ static bool cloth_from_object( return false; } - cloth_from_mesh(clmd, mesh); + cloth_from_mesh(clmd, ob, mesh); /* create springs */ clmd->clothObject->springs = NULL; @@ -814,7 +814,7 @@ static bool cloth_from_object( if (!cloth_build_springs(clmd, mesh)) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), "Cannot build springs"); + BKE_modifier_set_error(ob, &(clmd->modifier), "Cannot build springs"); return false; } @@ -831,7 +831,7 @@ static bool cloth_from_object( return true; } -static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) +static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mesh) { const MLoop *mloop = mesh->mloop; const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); @@ -844,8 +844,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) "clothVertex"); if (clmd->clothObject->verts == NULL) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), - "Out of memory on allocating clmd->clothObject->verts"); + BKE_modifier_set_error( + ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -861,8 +861,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris"); if (clmd->clothObject->tri == NULL) { cloth_free_modifier(clmd); - BKE_modifier_set_error(&(clmd->modifier), - "Out of memory on allocating clmd->clothObject->looptri"); + BKE_modifier_set_error( + ob, &(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); printf("cloth_free_modifier clmd->clothObject->looptri\n"); return; } diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 0ed6f94ce79..7ab63810719 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -18,6 +18,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <string.h> #include "BLI_blenlib.h" @@ -55,6 +58,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* -------------------------------------------------------------------- */ /** \name Prototypes * \{ */ @@ -167,6 +172,173 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data) } } +void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) +{ + BKE_id_blend_write(writer, &collection->id); + + /* Shared function for collection data-blocks and scene master collection. */ + BKE_previewimg_blend_write(writer, collection->preview); + + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + BLO_write_struct(writer, CollectionObject, cob); + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_write_struct(writer, CollectionChild, child); + } +} + +static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Collection *collection = (Collection *)id; + if (collection->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + collection->tag = 0; + BLI_listbase_clear(&collection->object_cache); + BLI_listbase_clear(&collection->parents); + + /* write LibData */ + BLO_write_id_struct(writer, Collection, id_address, &collection->id); + + BKE_collection_blend_write_nolib(writer, collection); + } +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_data(BlendDataReader *reader, SceneCollection *sc) +{ + BLO_read_list(reader, &sc->objects); + BLO_read_list(reader, &sc->scene_collections); + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_data(reader, nsc); + } +} +#endif + +void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection) +{ + BLO_read_list(reader, &collection->gobject); + BLO_read_list(reader, &collection->children); + + BLO_read_data_address(reader, &collection->preview); + BKE_previewimg_blend_read(reader, collection->preview); + + collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + collection->tag = 0; + BLI_listbase_clear(&collection->object_cache); + BLI_listbase_clear(&collection->parents); + +#ifdef USE_COLLECTION_COMPAT_28 + /* This runs before the very first doversion. */ + BLO_read_data_address(reader, &collection->collection); + if (collection->collection != NULL) { + BKE_collection_compat_blend_read_data(reader, collection->collection); + } + + BLO_read_data_address(reader, &collection->view_layer); + if (collection->view_layer != NULL) { + BKE_view_layer_blend_read_data(reader, collection->view_layer); + } +#endif +} + +static void collection_blend_read_data(BlendDataReader *reader, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_data(reader, collection); +} + +static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection) +{ + LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) { + BLO_read_id_address(reader, lib, &cob->ob); + + if (cob->ob == NULL) { + BLI_freelinkN(&collection->gobject, cob); + } + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_read_id_address(reader, lib, &child->collection); + } +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_lib(BlendLibReader *reader, + Library *lib, + SceneCollection *sc) +{ + LISTBASE_FOREACH (LinkData *, link, &sc->objects) { + BLO_read_id_address(reader, lib, &link->data); + BLI_assert(link->data); + } + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_lib(reader, lib, nsc); + } +} +#endif + +void BKE_collection_blend_read_lib(BlendLibReader *reader, Collection *collection) +{ +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection) { + BKE_collection_compat_blend_read_lib(reader, collection->id.lib, collection->collection); + } + + if (collection->view_layer) { + BKE_view_layer_blend_read_lib(reader, collection->id.lib, collection->view_layer); + } +#endif + + lib_link_collection_data(reader, collection->id.lib, collection); +} + +static void collection_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_lib(reader, collection); +} + +#ifdef USE_COLLECTION_COMPAT_28 +void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander, + struct SceneCollection *sc) +{ + LISTBASE_FOREACH (LinkData *, link, &sc->objects) { + BLO_expand(expander, link->data); + } + + LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) { + BKE_collection_compat_blend_read_expand(expander, nsc); + } +} +#endif + +void BKE_collection_blend_read_expand(BlendExpander *expander, Collection *collection) +{ + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + BLO_expand(expander, cob->ob); + } + + LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { + BLO_expand(expander, child->collection); + } + +#ifdef USE_COLLECTION_COMPAT_28 + if (collection->collection != NULL) { + BKE_collection_compat_blend_read_expand(expander, collection->collection); + } +#endif +} + +static void collection_blend_read_expand(BlendExpander *expander, ID *id) +{ + Collection *collection = (Collection *)id; + BKE_collection_blend_read_expand(expander, collection); +} + IDTypeInfo IDType_ID_GR = { .id_code = ID_GR, .id_filter = FILTER_ID_GR, @@ -184,10 +356,12 @@ IDTypeInfo IDType_ID_GR = { .foreach_id = collection_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = collection_blend_write, + .blend_read_data = collection_blend_read_data, + .blend_read_lib = collection_blend_read_lib, + .blend_read_expand = collection_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /** \} */ @@ -301,6 +475,7 @@ void BKE_collection_add_from_collection(Main *bmain, /** Free (or release) any data used by this collection (does not free the collection itself). */ void BKE_collection_free(Collection *collection) { + BKE_libblock_free_data(&collection->id, false); collection_free_data(&collection->id); } diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 34e8e8bc6fb..3eb9fb6161d 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1257,7 +1257,7 @@ void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap) /* ***************** Histogram **************** */ -#define INV_255 (1.f / 255.f) +#define INV_255 (1.0f / 255.0f) BLI_INLINE int get_bin_float(float f) { @@ -1570,8 +1570,8 @@ void BKE_scopes_update(Scopes *scopes, return; } - if (scopes->hist.ymax == 0.f) { - scopes->hist.ymax = 1.f; + if (scopes->hist.ymax == 0.0f) { + scopes->hist.ymax = 1.0f; } /* hmmmm */ @@ -1819,6 +1819,24 @@ void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings) } } +void BKE_color_managed_view_settings_blend_write(BlendWriter *writer, + ColorManagedViewSettings *settings) +{ + if (settings->curve_mapping) { + BKE_curvemapping_blend_write(writer, settings->curve_mapping); + } +} + +void BKE_color_managed_view_settings_blend_read_data(BlendDataReader *reader, + ColorManagedViewSettings *settings) +{ + BLO_read_data_address(reader, &settings->curve_mapping); + + if (settings->curve_mapping) { + BKE_curvemapping_blend_read(reader, settings->curve_mapping); + } +} + void BKE_color_managed_colorspace_settings_init( ColorManagedColorspaceSettings *colorspace_settings) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 274546132fb..a1b53b721d3 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <float.h> #include <math.h> #include <stddef.h> @@ -45,6 +48,7 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_screen_types.h" #include "DNA_lattice_types.h" #include "DNA_movieclip_types.h" @@ -79,6 +83,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + #include "CLG_log.h" #ifdef WITH_PYTHON @@ -5406,6 +5412,11 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool return false; } +void BKE_constraint_panel_expand(bConstraint *con) +{ + con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; +} + /* ......... */ /* Creates a new constraint, initializes its data, and returns it */ @@ -5421,10 +5432,10 @@ static bConstraint *add_new_constraint_internal(const char *name, short type) con->enforce = 1.0f; /* Only open the main panel when constraints are created, not the sub-panels. */ - con->ui_expand_flag = (1 << 0); + con->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT; if (ELEM(type, CONSTRAINT_TYPE_ACTION, CONSTRAINT_TYPE_SPLINEIK)) { /* Expand the two sub-panels in the cases where the main panel barely has any properties. */ - con->ui_expand_flag |= (1 << 1) | (1 << 2); + con->ui_expand_flag |= UI_SUBPANEL_DATA_EXPAND_1 | UI_SUBPANEL_DATA_EXPAND_2; } /* Determine a basic name, and info */ @@ -6080,3 +6091,174 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, } } } + +void BKE_constraint_blend_write(BlendWriter *writer, ListBase *conlist) +{ + LISTBASE_FOREACH (bConstraint *, con, conlist) { + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + + /* Write the specific data */ + if (cti && con->data) { + /* firstly, just write the plain con->data struct */ + BLO_write_struct_by_name(writer, cti->structName, con->data); + + /* do any constraint specific stuff */ + switch (con->type) { + case CONSTRAINT_TYPE_PYTHON: { + bPythonConstraint *data = con->data; + + /* write targets */ + LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) { + BLO_write_struct(writer, bConstraintTarget, ct); + } + + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + IDP_BlendWrite(writer, data->prop); + + break; + } + case CONSTRAINT_TYPE_ARMATURE: { + bArmatureConstraint *data = con->data; + + /* write targets */ + LISTBASE_FOREACH (bConstraintTarget *, ct, &data->targets) { + BLO_write_struct(writer, bConstraintTarget, ct); + } + + break; + } + case CONSTRAINT_TYPE_SPLINEIK: { + bSplineIKConstraint *data = con->data; + + /* write points array */ + BLO_write_float_array(writer, data->numpoints, data->points); + + break; + } + } + } + + /* Write the constraint */ + BLO_write_struct(writer, bConstraint, con); + } +} + +void BKE_constraint_blend_read_data(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + LISTBASE_FOREACH (bConstraint *, con, lb) { + BLO_read_data_address(reader, &con->data); + + switch (con->type) { + case CONSTRAINT_TYPE_PYTHON: { + bPythonConstraint *data = con->data; + + BLO_read_list(reader, &data->targets); + + BLO_read_data_address(reader, &data->prop); + IDP_BlendDataRead(reader, &data->prop); + break; + } + case CONSTRAINT_TYPE_ARMATURE: { + bArmatureConstraint *data = con->data; + + BLO_read_list(reader, &data->targets); + + break; + } + case CONSTRAINT_TYPE_SPLINEIK: { + bSplineIKConstraint *data = con->data; + + BLO_read_data_address(reader, &data->points); + break; + } + case CONSTRAINT_TYPE_KINEMATIC: { + bKinematicConstraint *data = con->data; + + con->lin_error = 0.0f; + con->rot_error = 0.0f; + + /* version patch for runtime flag, was not cleared in some case */ + data->flag &= ~CONSTRAINT_IK_AUTO; + break; + } + case CONSTRAINT_TYPE_CHILDOF: { + /* XXX version patch, in older code this flag wasn't always set, and is inherent to type */ + if (con->ownspace == CONSTRAINT_SPACE_POSE) { + con->flag |= CONSTRAINT_SPACEONCE; + } + break; + } + case CONSTRAINT_TYPE_TRANSFORM_CACHE: { + bTransformCacheConstraint *data = con->data; + data->reader = NULL; + data->reader_object_path[0] = '\0'; + } + } + } +} + +/* temp struct used to transport needed info to lib_link_constraint_cb() */ +typedef struct tConstraintLinkData { + BlendLibReader *reader; + ID *id; +} tConstraintLinkData; +/* callback function used to relink constraint ID-links */ +static void lib_link_constraint_cb(bConstraint *UNUSED(con), + ID **idpoin, + bool UNUSED(is_reference), + void *userdata) +{ + tConstraintLinkData *cld = (tConstraintLinkData *)userdata; + BLO_read_id_address(cld->reader, cld->id->lib, idpoin); +} + +void BKE_constraint_blend_read_lib(BlendLibReader *reader, ID *id, ListBase *conlist) +{ + tConstraintLinkData cld; + + /* legacy fixes */ + LISTBASE_FOREACH (bConstraint *, con, conlist) { + /* patch for error introduced by changing constraints (dunno how) */ + /* if con->data type changes, dna cannot resolve the pointer! (ton) */ + if (con->data == NULL) { + con->type = CONSTRAINT_TYPE_NULL; + } + /* own ipo, all constraints have it */ + BLO_read_id_address(reader, id->lib, &con->ipo); /* XXX deprecated - old animation system */ + + /* If linking from a library, clear 'local' library override flag. */ + if (id->lib != NULL) { + con->flag &= ~CONSTRAINT_OVERRIDE_LIBRARY_LOCAL; + } + } + + /* relink all ID-blocks used by the constraints */ + cld.reader = reader; + cld.id = id; + + BKE_constraints_id_loop(conlist, lib_link_constraint_cb, &cld); +} + +/* callback function used to expand constraint ID-links */ +static void expand_constraint_cb(bConstraint *UNUSED(con), + ID **idpoin, + bool UNUSED(is_reference), + void *userdata) +{ + BlendExpander *expander = userdata; + BLO_expand(expander, *idpoin); +} + +void BKE_constraint_blend_read_expand(BlendExpander *expander, ListBase *lb) +{ + BKE_constraints_id_loop(lb, expand_constraint_cb, expander); + + /* deprecated manual expansion stuff */ + LISTBASE_FOREACH (bConstraint *, curcon, lb) { + if (curcon->ipo) { + BLO_expand(expander, curcon->ipo); /* XXX deprecated - old animation system */ + } + } +} diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 01c05c62b70..4e1ec9ba35e 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -273,7 +273,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra for (i = 0; md && i <= cageIndex; i++, md = md->next) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { + if (!editbmesh_modifier_is_enabled(scene, ob, md, me != NULL)) { continue; } @@ -302,7 +302,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra } for (; md && i <= cageIndex; md = md->next, i++) { - if (editbmesh_modifier_is_enabled(scene, md, me != NULL) && + if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) && BKE_modifier_is_correctable_deformed(md)) { numleft++; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b2ebb56d828..091d542c43d 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -325,6 +325,8 @@ IDTypeInfo IDType_ID_CU = { .blend_read_data = curve_blend_read_data, .blend_read_lib = curve_blend_read_lib, .blend_read_expand = curve_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; static int cu_isectLL(const float v1[3], @@ -438,7 +440,6 @@ ListBase *BKE_curve_editNurbs_get(Curve *cu) short BKE_curve_type_get(const Curve *cu) { - Nurb *nu; int type = cu->type; if (cu->vfont) { @@ -448,7 +449,7 @@ short BKE_curve_type_get(const Curve *cu) if (!cu->type) { type = OB_CURVE; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->pntsv > 1) { type = OB_SURF; } @@ -461,15 +462,14 @@ short BKE_curve_type_get(const Curve *cu) void BKE_curve_curve_dimension_update(Curve *cu) { ListBase *nurbs = BKE_curve_nurbs_get(cu); - Nurb *nu = nurbs->first; if (cu->flag & CU_3D) { - for (; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { nu->flag &= ~CU_2D; } } else { - for (; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { nu->flag |= CU_2D; BKE_nurb_test_2d(nu); @@ -569,10 +569,9 @@ void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3]) bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) { - Nurb *nu; int tot = 0; - for (nu = nurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { int tot_nu; if (nu->type == CU_BEZIER) { tot_nu = nu->pntsu; @@ -596,39 +595,33 @@ bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) int BKE_nurbList_verts_count(ListBase *nurb) { - Nurb *nu; int tot = 0; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { tot += 3 * nu->pntsu; } else if (nu->bp) { tot += nu->pntsu * nu->pntsv; } - - nu = nu->next; } + return tot; } int BKE_nurbList_verts_count_without_handles(ListBase *nurb) { - Nurb *nu; int tot = 0; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { tot += nu->pntsu; } else if (nu->bp) { tot += nu->pntsu * nu->pntsv; } - - nu = nu->next; } + return tot; } @@ -636,7 +629,6 @@ int BKE_nurbList_verts_count_without_handles(ListBase *nurb) void BKE_nurb_free(Nurb *nu) { - if (nu == NULL) { return; } @@ -664,17 +656,12 @@ void BKE_nurb_free(Nurb *nu) void BKE_nurbList_free(ListBase *lb) { - Nurb *nu, *next; - if (lb == NULL) { return; } - nu = lb->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, lb) { BKE_nurb_free(nu); - nu = next; } BLI_listbase_clear(lb); } @@ -747,16 +734,11 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv) void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2) { - Nurb *nu, *nun; - BKE_nurbList_free(lb1); - nu = lb2->first; - while (nu) { - nun = BKE_nurb_duplicate(nu); - BLI_addtail(lb1, nun); - - nu = nu->next; + LISTBASE_FOREACH (const Nurb *, nu, lb2) { + Nurb *nurb_new = BKE_nurb_duplicate(nu); + BLI_addtail(lb1, nurb_new); } } @@ -2202,6 +2184,22 @@ static void bevel_list_calc_bisect(BevList *bl) bevp1 = bevp2; bevp2++; } + + if (is_cyclic == false) { + bevp0 = &bl->bevpoints[0]; + bevp1 = &bl->bevpoints[1]; + sub_v3_v3v3(bevp0->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp0->dir) == 0.0f) { + copy_v3_v3(bevp0->dir, bevp1->dir); + } + + bevp0 = &bl->bevpoints[bl->nr - 2]; + bevp1 = &bl->bevpoints[bl->nr - 1]; + sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp0->vec); + if (normalize_v3(bevp1->dir) == 0.0f) { + copy_v3_v3(bevp1->dir, bevp0->dir); + } + } } static void bevel_list_flip_tangents(BevList *bl) { @@ -2625,9 +2623,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) void BKE_curve_bevelList_free(ListBase *bev) { - BevList *bl, *blnext; - for (bl = bev->first; bl != NULL; bl = blnext) { - blnext = bl->next; + LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) { if (bl->seglen != NULL) { MEM_freeN(bl->seglen); } @@ -2654,12 +2650,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* this function needs an object, because of tflag and upflag */ Curve *cu = ob->data; - Nurb *nu; BezTriple *bezt, *prevbezt; BPoint *bp; - BevList *bl, *blnew, *blnext; + BevList *blnew; BevPoint *bevp2, *bevp1 = NULL, *bevp0; - const float treshold = 0.00001f; + const float threshold = 0.00001f; float min, inp; float *seglen = NULL; struct BevelSort *sortdata, *sd, *sd1; @@ -2685,16 +2680,26 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 1: MAKE POLYS */ BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); - nu = nurbs->first; if (cu->editnurb && ob->type != OB_FONT) { is_editmode = 1; } - for (; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->hide && is_editmode) { continue; } + /* check we are a single point? also check we are not a surface and that the orderu is sane, + * enforced in the UI but can go wrong possibly */ + if (!BKE_nurb_check_valid_u(nu)) { + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList1"); + bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1"); + BLI_addtail(bev, bl); + bl->nr = 0; + bl->charidx = nu->charidx; + continue; + } + /* check if we will calculate tilt data */ do_tilt = CU_DO_TILT(cu, nu); @@ -2703,89 +2708,231 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) do_weight = true; - /* check we are a single point? also check we are not a surface and that the orderu is sane, - * enforced in the UI but can go wrong possibly */ - if (!BKE_nurb_check_valid_u(nu)) { - bl = MEM_callocN(sizeof(BevList), "makeBevelList1"); - bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1"); + BevPoint *bevp; + + if (for_render && cu->resolu_ren != 0) { + resolu = cu->resolu_ren; + } + else { + resolu = nu->resolu; + } + + segcount = SEGMENTSU(nu); + + if (nu->type == CU_POLY) { + len = nu->pntsu; + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList2"); + bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2"); + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { + bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen"); + bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList2_segbevcount"); + } BLI_addtail(bev, bl); - bl->nr = 0; + + bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; + bl->nr = len; + bl->dupe_nr = 0; bl->charidx = nu->charidx; + bevp = bl->bevpoints; + bevp->offset = 0; + bp = nu->bp; + seglen = bl->seglen; + segbevcount = bl->segbevcount; + + while (len--) { + copy_v3_v3(bevp->vec, bp->vec); + bevp->tilt = bp->tilt; + bevp->radius = bp->radius; + bevp->weight = bp->weight; + bevp->split_tag = true; + bp++; + if (seglen != NULL && len != 0) { + *seglen = len_v3v3(bevp->vec, bp->vec); + bevp++; + bevp->offset = *seglen; + if (*seglen > threshold) { + *segbevcount = 1; + } + else { + *segbevcount = 0; + } + seglen++; + segbevcount++; + } + else { + bevp++; + } + } + + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + bevlist_firstlast_direction_calc_from_bpoint(nu, bl); + } } - else { - BevPoint *bevp; + else if (nu->type == CU_BEZIER) { + /* in case last point is not cyclic */ + len = segcount * resolu + 1; - if (for_render && cu->resolu_ren != 0) { - resolu = cu->resolu_ren; + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints"); + bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints"); + if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { + bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen"); + bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelBPoints_segbevcount"); + } + BLI_addtail(bev, bl); + + bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; + bl->charidx = nu->charidx; + + bevp = bl->bevpoints; + seglen = bl->seglen; + segbevcount = bl->segbevcount; + + bevp->offset = 0; + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + } + + a = nu->pntsu - 1; + bezt = nu->bezt; + if (nu->flagu & CU_NURB_CYCLIC) { + a++; + prevbezt = nu->bezt + (nu->pntsu - 1); } else { - resolu = nu->resolu; + prevbezt = bezt; + bezt++; } - segcount = SEGMENTSU(nu); + sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]); + normalize_v3(bevp->dir); - if (nu->type == CU_POLY) { - len = nu->pntsu; - bl = MEM_callocN(sizeof(BevList), "makeBevelList2"); - bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2"); - if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { - bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen"); - bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList2_segbevcount"); - } - BLI_addtail(bev, bl); + BLI_assert(segcount >= a); - bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; - bl->nr = len; - bl->dupe_nr = 0; - bl->charidx = nu->charidx; - bevp = bl->bevpoints; - bevp->offset = 0; - bp = nu->bp; - seglen = bl->seglen; - segbevcount = bl->segbevcount; + while (a--) { + if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { - while (len--) { - copy_v3_v3(bevp->vec, bp->vec); - bevp->tilt = bp->tilt; - bevp->radius = bp->radius; - bevp->weight = bp->weight; + copy_v3_v3(bevp->vec, prevbezt->vec[1]); + bevp->tilt = prevbezt->tilt; + bevp->radius = prevbezt->radius; + bevp->weight = prevbezt->weight; bevp->split_tag = true; - bp++; - if (seglen != NULL && len != 0) { - *seglen = len_v3v3(bevp->vec, bp->vec); - bevp++; + bevp->dupe_tag = false; + bevp++; + bl->nr++; + bl->dupe_nr = 1; + if (seglen != NULL) { + *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]); bevp->offset = *seglen; - if (*seglen > treshold) { + seglen++; + /* match segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > threshold) { *segbevcount = 1; } - else { - *segbevcount = 0; + segbevcount++; + } + } + else { + /* always do all three, to prevent data hanging around */ + int j; + + /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */ + for (j = 0; j < 3; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + &(bevp->vec[j]), + resolu, + sizeof(BevPoint)); + } + + /* if both arrays are NULL do nothiong */ + tilt_bezpart(prevbezt, + bezt, + nu, + do_tilt ? &bevp->tilt : NULL, + do_radius ? &bevp->radius : NULL, + do_weight ? &bevp->weight : NULL, + resolu, + sizeof(BevPoint)); + + if (cu->twist_mode == CU_TWIST_TANGENT) { + forward_diff_bezier_cotangent(prevbezt->vec[1], + prevbezt->vec[2], + bezt->vec[0], + bezt->vec[1], + bevp->tan, + resolu, + sizeof(BevPoint)); + } + + /* indicate with handlecodes double points */ + if (prevbezt->h1 == prevbezt->h2) { + if (ELEM(prevbezt->h1, 0, HD_VECT)) { + bevp->split_tag = true; + } + } + else { + if (ELEM(prevbezt->h1, 0, HD_VECT)) { + bevp->split_tag = true; + } + else if (ELEM(prevbezt->h2, 0, HD_VECT)) { + bevp->split_tag = true; + } + } + + /* seglen */ + if (seglen != NULL) { + *seglen = 0; + *segbevcount = 0; + for (j = 0; j < resolu; j++) { + bevp0 = bevp; + bevp++; + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (bevp->offset > threshold) { + *seglen += bevp->offset; + *segbevcount += 1; + } } seglen++; segbevcount++; } else { - bevp++; + bevp += resolu; } + bl->nr += resolu; } + prevbezt = bezt; + bezt++; + } - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - bevlist_firstlast_direction_calc_from_bpoint(nu, bl); - } + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic: endpoint */ + copy_v3_v3(bevp->vec, prevbezt->vec[1]); + bevp->tilt = prevbezt->tilt; + bevp->radius = prevbezt->radius; + bevp->weight = prevbezt->weight; + + sub_v3_v3v3(bevp->dir, prevbezt->vec[1], prevbezt->vec[0]); + normalize_v3(bevp->dir); + + bl->nr++; } - else if (nu->type == CU_BEZIER) { - /* in case last point is not cyclic */ - len = segcount * resolu + 1; + } + else if (nu->type == CU_NURBS) { + if (nu->pntsv == 1) { + len = (resolu * segcount); - bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints"); - bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints"); + BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList3"); + bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3"); if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { - bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen"); - bl->segbevcount = MEM_malloc_arrayN( - segcount, sizeof(int), "makeBevelBPoints_segbevcount"); + bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen"); + bl->segbevcount = MEM_malloc_arrayN(segcount, sizeof(int), "makeBevelList3_segbevcount"); } BLI_addtail(bev, bl); - + bl->nr = len; + bl->dupe_nr = 0; bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; @@ -2793,292 +2940,134 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) seglen = bl->seglen; segbevcount = bl->segbevcount; - bevp->offset = 0; - if (seglen != NULL) { - *seglen = 0; - *segbevcount = 0; - } - - a = nu->pntsu - 1; - bezt = nu->bezt; - if (nu->flagu & CU_NURB_CYCLIC) { - a++; - prevbezt = nu->bezt + (nu->pntsu - 1); - } - else { - prevbezt = bezt; - bezt++; - } - - sub_v3_v3v3(bevp->dir, prevbezt->vec[2], prevbezt->vec[1]); - normalize_v3(bevp->dir); - - BLI_assert(segcount >= a); + BKE_nurb_makeCurve(nu, + &bevp->vec[0], + do_tilt ? &bevp->tilt : NULL, + do_radius ? &bevp->radius : NULL, + do_weight ? &bevp->weight : NULL, + resolu, + sizeof(BevPoint)); - while (a--) { - if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { - - copy_v3_v3(bevp->vec, prevbezt->vec[1]); - bevp->tilt = prevbezt->tilt; - bevp->radius = prevbezt->radius; - bevp->weight = prevbezt->weight; - bevp->split_tag = true; - bevp->dupe_tag = false; - bevp++; - bl->nr++; - bl->dupe_nr = 1; - if (seglen != NULL) { - *seglen = len_v3v3(prevbezt->vec[1], bezt->vec[1]); - bevp->offset = *seglen; - seglen++; - /* match segbevcount to the cleaned up bevel lists (see STEP 2) */ - if (bevp->offset > treshold) { - *segbevcount = 1; - } - segbevcount++; - } - } - else { - /* always do all three, to prevent data hanging around */ + /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ + if (seglen != NULL) { + nr = segcount; + bevp0 = bevp; + bevp++; + while (nr) { int j; - - /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */ - for (j = 0; j < 3; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], - prevbezt->vec[2][j], - bezt->vec[0][j], - bezt->vec[1][j], - &(bevp->vec[j]), - resolu, - sizeof(BevPoint)); - } - - /* if both arrays are NULL do nothiong */ - tilt_bezpart(prevbezt, - bezt, - nu, - do_tilt ? &bevp->tilt : NULL, - do_radius ? &bevp->radius : NULL, - do_weight ? &bevp->weight : NULL, - resolu, - sizeof(BevPoint)); - - if (cu->twist_mode == CU_TWIST_TANGENT) { - forward_diff_bezier_cotangent(prevbezt->vec[1], - prevbezt->vec[2], - bezt->vec[0], - bezt->vec[1], - bevp->tan, - resolu, - sizeof(BevPoint)); - } - - /* indicate with handlecodes double points */ - if (prevbezt->h1 == prevbezt->h2) { - if (prevbezt->h1 == 0 || prevbezt->h1 == HD_VECT) { - bevp->split_tag = true; - } - } - else { - if (prevbezt->h1 == 0 || prevbezt->h1 == HD_VECT) { - bevp->split_tag = true; - } - else if (prevbezt->h2 == 0 || prevbezt->h2 == HD_VECT) { - bevp->split_tag = true; - } - } - - /* seglen */ - if (seglen != NULL) { - *seglen = 0; - *segbevcount = 0; - for (j = 0; j < resolu; j++) { - bevp0 = bevp; - bevp++; - bevp->offset = len_v3v3(bevp0->vec, bevp->vec); - /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ - if (bevp->offset > treshold) { - *seglen += bevp->offset; - *segbevcount += 1; - } + *seglen = 0; + *segbevcount = 0; + /* We keep last bevel segment zero-length. */ + for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) { + bevp->offset = len_v3v3(bevp0->vec, bevp->vec); + if (bevp->offset > threshold) { + *seglen += bevp->offset; + *segbevcount += 1; } - seglen++; - segbevcount++; - } - else { - bevp += resolu; + bevp0 = bevp; + bevp++; } - bl->nr += resolu; + seglen++; + segbevcount++; + nr--; } - prevbezt = bezt; - bezt++; } - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic: endpoint */ - copy_v3_v3(bevp->vec, prevbezt->vec[1]); - bevp->tilt = prevbezt->tilt; - bevp->radius = prevbezt->radius; - bevp->weight = prevbezt->weight; - - sub_v3_v3v3(bevp->dir, prevbezt->vec[1], prevbezt->vec[0]); - normalize_v3(bevp->dir); - - bl->nr++; - } - } - else if (nu->type == CU_NURBS) { - if (nu->pntsv == 1) { - len = (resolu * segcount); - - bl = MEM_callocN(sizeof(BevList), "makeBevelList3"); - bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3"); - if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) { - bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen"); - bl->segbevcount = MEM_malloc_arrayN( - segcount, sizeof(int), "makeBevelList3_segbevcount"); - } - BLI_addtail(bev, bl); - bl->nr = len; - bl->dupe_nr = 0; - bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; - bl->charidx = nu->charidx; - - bevp = bl->bevpoints; - seglen = bl->seglen; - segbevcount = bl->segbevcount; - - BKE_nurb_makeCurve(nu, - &bevp->vec[0], - do_tilt ? &bevp->tilt : NULL, - do_radius ? &bevp->radius : NULL, - do_weight ? &bevp->weight : NULL, - resolu, - sizeof(BevPoint)); - - /* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */ - if (seglen != NULL) { - nr = segcount; - bevp0 = bevp; - bevp++; - while (nr) { - int j; - *seglen = 0; - *segbevcount = 0; - /* We keep last bevel segment zero-length. */ - for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) { - bevp->offset = len_v3v3(bevp0->vec, bevp->vec); - if (bevp->offset > treshold) { - *seglen += bevp->offset; - *segbevcount += 1; - } - bevp0 = bevp; - bevp++; - } - seglen++; - segbevcount++; - nr--; - } - } - - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - bevlist_firstlast_direction_calc_from_bpoint(nu, bl); - } + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + bevlist_firstlast_direction_calc_from_bpoint(nu, bl); } } } } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ - bl = bev->first; - while (bl) { - if (bl->nr) { /* null bevel items come from single points */ - /* Scale the threshold so high resolution shapes don't get over reduced, see: T49850. */ - const float threshold_resolu = 0.00001f / resolu; - bool is_cyclic = bl->poly != -1; - nr = bl->nr; - if (is_cyclic) { - bevp1 = bl->bevpoints; - bevp0 = bevp1 + (nr - 1); + LISTBASE_FOREACH (BevList *, bl, bev) { + if (bl->nr == 0) { /* null bevel items come from single points */ + continue; + } + + /* Scale the threshold so high resolution shapes don't get over reduced, see: T49850. */ + const float threshold_resolu = 0.00001f / resolu; + bool is_cyclic = bl->poly != -1; + nr = bl->nr; + if (is_cyclic) { + bevp1 = bl->bevpoints; + bevp0 = bevp1 + (nr - 1); + } + else { + bevp0 = bl->bevpoints; + bevp0->offset = 0; + bevp1 = bevp0 + 1; + } + nr--; + while (nr--) { + if (seglen != NULL) { + if (fabsf(bevp1->offset) < threshold) { + bevp0->dupe_tag = true; + bl->dupe_nr++; + } } else { - bevp0 = bl->bevpoints; - bevp0->offset = 0; - bevp1 = bevp0 + 1; - } - nr--; - while (nr--) { - if (seglen != NULL) { - if (fabsf(bevp1->offset) < treshold) { - bevp0->dupe_tag = true; - bl->dupe_nr++; - } - } - else { - if (compare_v3v3(bevp0->vec, bevp1->vec, threshold_resolu)) { - bevp0->dupe_tag = true; - bl->dupe_nr++; - } + if (compare_v3v3(bevp0->vec, bevp1->vec, threshold_resolu)) { + bevp0->dupe_tag = true; + bl->dupe_nr++; } - bevp0 = bevp1; - bevp1++; } + bevp0 = bevp1; + bevp1++; } - bl = bl->next; } - bl = bev->first; - while (bl) { - blnext = bl->next; - if (bl->nr && bl->dupe_nr) { - nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ - blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4"); - memcpy(blnew, bl, sizeof(BevList)); - blnew->bevpoints = MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4"); - if (!blnew->bevpoints) { - MEM_freeN(blnew); - break; - } - blnew->segbevcount = bl->segbevcount; - blnew->seglen = bl->seglen; - blnew->nr = 0; - BLI_remlink(bev, bl); - BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ - bevp0 = bl->bevpoints; - bevp1 = blnew->bevpoints; - nr = bl->nr; - while (nr--) { - if (bevp0->dupe_tag == 0) { - memcpy(bevp1, bevp0, sizeof(BevPoint)); - bevp1++; - blnew->nr++; - } - bevp0++; - } - if (bl->bevpoints != NULL) { - MEM_freeN(bl->bevpoints); + + LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) { + if (bl->nr == 0 || bl->dupe_nr == 0) { + continue; + } + + nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */ + blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4"); + memcpy(blnew, bl, sizeof(BevList)); + blnew->bevpoints = MEM_calloc_arrayN(nr, sizeof(BevPoint), "makeBevelPoints4"); + if (!blnew->bevpoints) { + MEM_freeN(blnew); + break; + } + blnew->segbevcount = bl->segbevcount; + blnew->seglen = bl->seglen; + blnew->nr = 0; + BLI_remlink(bev, bl); + BLI_insertlinkbefore(bev, bl->next, blnew); /* to make sure bevlist is tuned with nurblist */ + bevp0 = bl->bevpoints; + bevp1 = blnew->bevpoints; + nr = bl->nr; + while (nr--) { + if (bevp0->dupe_tag == 0) { + memcpy(bevp1, bevp0, sizeof(BevPoint)); + bevp1++; + blnew->nr++; } - MEM_freeN(bl); - blnew->dupe_nr = 0; + bevp0++; + } + if (bl->bevpoints != NULL) { + MEM_freeN(bl->bevpoints); } - bl = blnext; + MEM_freeN(bl); + blnew->dupe_nr = 0; } /* STEP 3: POLYS COUNT AND AUTOHOLE */ - bl = bev->first; poly = 0; - while (bl) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr && bl->poly >= 0) { poly++; bl->poly = poly; bl->hole = 0; } - bl = bl->next; } /* find extreme left points, also test (turning) direction */ if (poly > 0) { sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5"); - bl = bev->first; - while (bl) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->poly > 0) { BevPoint *bevp; @@ -3123,14 +3112,12 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sd++; } - - bl = bl->next; } qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev); sd = sortdata + 1; for (a = 1; a < poly; a++, sd++) { - bl = sd->bl; /* is bl a hole? */ + BevList *bl = sd->bl; /* is bl a hole? */ sd1 = sortdata + (a - 1); for (b = a - 1; b >= 0; b--, sd1--) { /* all polys to the left */ if (sd1->bl->charidx == bl->charidx) { /* for text, only check matching char */ @@ -3147,7 +3134,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) sd = sortdata; for (a = 0; a < poly; a++, sd++) { if (sd->bl->hole == sd->dir) { - bl = sd->bl; + BevList *bl = sd->bl; bevp1 = bl->bevpoints; bevp2 = bevp1 + (bl->nr - 1); nr = bl->nr / 2; @@ -3165,7 +3152,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) /* STEP 4: 2D-COSINES or 3D ORIENTATION */ if ((cu->flag & CU_3D) == 0) { /* 2D Curves */ - for (bl = bev->first; bl; bl = bl->next) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr < 2) { BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); @@ -3180,7 +3167,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) } else { /* 3D Curves */ - for (bl = bev->first; bl; bl = bl->next) { + LISTBASE_FOREACH (BevList *, bl, bev) { if (bl->nr < 2) { BevPoint *bevp = bl->bevpoints; unit_qt(bevp->quat); @@ -3674,7 +3661,7 @@ static bool tridiagonal_solve_with_limits(float *a, * is affected by all other points of the curve segment, in practice the influence * decreases exponentially with distance. * - * Note: this algorithm assumes that the handle horizontal size if always 1/3 of the + * Note: this algorithm assumes that the handle horizontal size is always 1/3 of the * of the interval to the next point. This rule ensures linear interpolation of time. * * ^ height (co 1) @@ -4314,12 +4301,8 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag) void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag) { - Nurb *nu; - - nu = editnurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BKE_nurb_handles_autocalc(nu, flag); - nu = nu->next; } } @@ -4331,13 +4314,11 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) /* code==4: sets icu flag to become IPO_AUTO_HORIZ, horizontal extremes on auto-handles */ /* code==5: Set align, like 3 but no toggle */ /* code==6: Clear align, like 3 but no toggle */ - Nurb *nu; BezTriple *bezt; int a; if (ELEM(code, HD_AUTO, HD_VECT)) { - nu = editnurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4364,7 +4345,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) /* like BKE_nurb_handles_calc but moves selected */ nurb_handles_calc__align_selected(nu); } - nu = nu->next; } } else { @@ -4379,7 +4359,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } else { /* Toggle */ - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4395,7 +4375,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code) } h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -4421,66 +4401,66 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length, const uint8_t flag) { - Nurb *nu; BezTriple *bezt; int a; - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bool changed = false; + LISTBASE_FOREACH (Nurb *, nu, editnurb) { + if (nu->type != CU_BEZIER) { + continue; + } - for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { + bool changed = false; - const bool h1_select = (bezt->f1 & flag) == flag; - const bool h2_select = (bezt->f3 & flag) == flag; + for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { - if (h1_select || h2_select) { + const bool h1_select = (bezt->f1 & flag) == flag; + const bool h2_select = (bezt->f3 & flag) == flag; - float co1_back[3], co2_back[3]; + if (h1_select || h2_select) { - copy_v3_v3(co1_back, bezt->vec[0]); - copy_v3_v3(co2_back, bezt->vec[2]); + float co1_back[3], co2_back[3]; - BKE_nurb_handle_calc_simple_auto(nu, bezt); + copy_v3_v3(co1_back, bezt->vec[0]); + copy_v3_v3(co2_back, bezt->vec[2]); - if (h1_select) { - if (!calc_length) { - dist_ensure_v3_v3fl(bezt->vec[0], bezt->vec[1], len_v3v3(co1_back, bezt->vec[1])); - } - } - else { - copy_v3_v3(bezt->vec[0], co1_back); - } + BKE_nurb_handle_calc_simple_auto(nu, bezt); - if (h2_select) { - if (!calc_length) { - dist_ensure_v3_v3fl(bezt->vec[2], bezt->vec[1], len_v3v3(co2_back, bezt->vec[1])); - } - } - else { - copy_v3_v3(bezt->vec[2], co2_back); + if (h1_select) { + if (!calc_length) { + dist_ensure_v3_v3fl(bezt->vec[0], bezt->vec[1], len_v3v3(co1_back, bezt->vec[1])); } + } + else { + copy_v3_v3(bezt->vec[0], co1_back); + } - changed = true; + if (h2_select) { + if (!calc_length) { + dist_ensure_v3_v3fl(bezt->vec[2], bezt->vec[1], len_v3v3(co2_back, bezt->vec[1])); + } + } + else { + copy_v3_v3(bezt->vec[2], co2_back); } - } - if (changed) { - /* Recalculate the whole curve */ - BKE_nurb_handles_calc(nu); + changed = true; } } + + if (changed) { + /* Recalculate the whole curve */ + BKE_nurb_handles_calc(nu); + } } } void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; @@ -4516,7 +4496,7 @@ bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint { bool changed = false; - for (Nurb *nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { for (int i = 0; i < nu->pntsu; i++) { BezTriple *bezt = &nu->bezt[i]; @@ -4981,7 +4961,7 @@ bool BKE_nurb_type_convert(Nurb *nu, } } else if (nu->type == CU_BEZIER) { /* Bezier */ - if (type == CU_POLY || type == CU_NURBS) { + if (ELEM(type, CU_POLY, CU_NURBS)) { nr = use_handles ? (3 * nu->pntsu) : nu->pntsu; nu->bp = MEM_calloc_arrayN(nr, sizeof(BPoint), "setsplinetype"); a = nu->pntsu; @@ -5230,12 +5210,11 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3]) bool BKE_curve_center_median(Curve *cu, float cent[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); - Nurb *nu; int total = 0; zero_v3(cent); - for (nu = nurb_lb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurb_lb) { int i; if (nu->type == CU_BEZIER) { @@ -5283,12 +5262,11 @@ void BKE_curve_transform_ex(Curve *cu, const bool do_props, const float unit_scale) { - Nurb *nu; BPoint *bp; BezTriple *bezt; int i; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->type == CU_BEZIER) { i = nu->pntsu; for (bezt = nu->bezt; i--; bezt++) { @@ -5313,12 +5291,11 @@ void BKE_curve_transform_ex(Curve *cu, } if (do_keys && cu->key) { - KeyBlock *kb; - for (kb = cu->key->block.first; kb; kb = kb->next) { + LISTBASE_FOREACH (KeyBlock *, kb, &cu->key->block) { float *fp = kb->data; int n = kb->totelem; - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->type == CU_BEZIER) { for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) { mul_m4_v3(mat, &fp[0]); @@ -5474,9 +5451,8 @@ bool BKE_curve_material_index_validate(Curve *cu) } } else { - Nurb *nu; const int max_idx = max_ii(0, cu->totcol - 1); - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { if (nu->mat_nr > max_idx) { nu->mat_nr = 0; is_valid = false; @@ -5542,12 +5518,12 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth) { if (use_smooth) { - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { nu->flag |= CU_SMOOTH; } } else { - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { nu->flag &= ~CU_SMOOTH; } } diff --git a/source/blender/blenkernel/intern/curve_decimate.c b/source/blender/blenkernel/intern/curve_decimate.c index 68c0d2a3cec..e4647908b58 100644 --- a/source/blender/blenkernel/intern/curve_decimate.c +++ b/source/blender/blenkernel/intern/curve_decimate.c @@ -269,11 +269,11 @@ uint BKE_curve_decimate_bezt_array(BezTriple *bezt_array, if (a == HD_VECT) { \ a = HD_FREE; \ } \ - else if (a == HD_AUTO || a == HD_AUTO_ANIM) { \ + else if (ELEM(a, HD_AUTO, HD_AUTO_ANIM)) { \ a = HD_ALIGN; \ } \ /* opposite handle */ \ - if (b == HD_AUTO || b == HD_AUTO_ANIM) { \ + if (ELEM(b, HD_AUTO, HD_AUTO_ANIM)) { \ b = HD_ALIGN; \ } \ } \ diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c index d4f197521a1..049bd46c434 100644 --- a/source/blender/blenkernel/intern/curve_deform.c +++ b/source/blender/blenkernel/intern/curve_deform.c @@ -222,10 +222,10 @@ static bool calc_curve_deform( /* zero the axis which is not used, * the big block of text above now applies to these 3 lines */ - quat_apply_track( - quat, - axis, - (axis == 0 || axis == 2) ? 1 : 0); /* up flag is a dummy, set so no rotation is done */ + quat_apply_track(quat, + axis, + (ELEM(axis, 0, 2)) ? 1 : + 0); /* up flag is a dummy, set so no rotation is done */ vec_apply_track(cent, axis); cent[index] = 0.0f; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d762b1b0604..fdb3e246382 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2509,7 +2509,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, return &data->layers[CustomData_get_layer_index(data, type)]; } - if ((alloctype == CD_ASSIGN) || (alloctype == CD_REFERENCE)) { + if (ELEM(alloctype, CD_ASSIGN, CD_REFERENCE)) { newlayerdata = layerdata; } else if (totelem > 0 && typeInfo->size > 0) { @@ -2997,7 +2997,7 @@ void CustomData_free_elem(CustomData *data, int index, int count) /** * Interpolate given custom data source items into a single destination one. * - * \param src_indices Indices of every source items to interpolate into the destination one. + * \param src_indices: Indices of every source items to interpolate into the destination one. * \param weights: The weight to apply to each source value individually. If NULL, they will be * averaged. * \param sub_weights: The weights of sub-items, only used to affect each corners of a diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index bcb467e1230..f5257eb12ab 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -92,17 +92,13 @@ void BKE_displist_free(ListBase *lb) DispList *BKE_displist_find_or_create(ListBase *lb, int type) { - DispList *dl; - - dl = lb->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == type) { return dl; } - dl = dl->next; } - dl = MEM_callocN(sizeof(DispList), "find_disp"); + DispList *dl = MEM_callocN(sizeof(DispList), "find_disp"); dl->type = type; BLI_addtail(lb, dl); @@ -111,14 +107,10 @@ DispList *BKE_displist_find_or_create(ListBase *lb, int type) DispList *BKE_displist_find(ListBase *lb, int type) { - DispList *dl; - - dl = lb->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == type) { return dl; } - dl = dl->next; } return NULL; @@ -126,9 +118,7 @@ DispList *BKE_displist_find(ListBase *lb, int type) bool BKE_displist_has_faces(ListBase *lb) { - DispList *dl; - - for (dl = lb->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { return true; } @@ -139,13 +129,10 @@ bool BKE_displist_has_faces(ListBase *lb) void BKE_displist_copy(ListBase *lbn, ListBase *lb) { - DispList *dln, *dl; - BKE_displist_free(lbn); - dl = lb->first; - while (dl) { - dln = MEM_dupallocN(dl); + LISTBASE_FOREACH (const DispList *, dl, lb) { + DispList *dln = MEM_dupallocN(dl); BLI_addtail(lbn, dln); dln->verts = MEM_dupallocN(dl->verts); dln->nors = MEM_dupallocN(dl->nors); @@ -154,22 +141,17 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb) if (dl->bevel_split) { dln->bevel_split = MEM_dupallocN(dl->bevel_split); } - - dl = dl->next; } } void BKE_displist_normals_add(ListBase *lb) { - DispList *dl = NULL; float *vdata, *ndata, nor[3]; float *v1, *v2, *v3, *v4; float *n1, *n2, *n3, *n4; int a, b, p1, p2, p3, p4; - dl = lb->first; - - while (dl) { + LISTBASE_FOREACH (DispList *, dl, lb) { if (dl->type == DL_INDEX3) { if (dl->nors == NULL) { dl->nors = MEM_callocN(sizeof(float[3]), "dlnors"); @@ -230,15 +212,12 @@ void BKE_displist_normals_add(ListBase *lb) } } } - dl = dl->next; } } void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri) { - DispList *dl; - - for (dl = lb->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, lb) { int vert_tot = 0; int face_tot = 0; int tri_tot = 0; @@ -318,7 +297,6 @@ static void curve_to_displist(Curve *cu, ListBase *dispbase, const bool for_render) { - Nurb *nu; DispList *dl; BezTriple *bezt, *prevbezt; BPoint *bp; @@ -326,154 +304,154 @@ static void curve_to_displist(Curve *cu, int a, len, resolu; const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); - nu = nubase->first; - while (nu) { - if (nu->hide == 0 || editmode == false) { - if (for_render && cu->resolu_ren != 0) { - resolu = cu->resolu_ren; - } - else { - resolu = nu->resolu; - } - - if (!BKE_nurb_check_valid_u(nu)) { - /* pass */ - } - else if (nu->type == CU_BEZIER) { - /* count */ - len = 0; - a = nu->pntsu - 1; - if (nu->flagu & CU_NURB_CYCLIC) { - a++; - } - - prevbezt = nu->bezt; - bezt = prevbezt + 1; - while (a--) { - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { - bezt = nu->bezt; - } + LISTBASE_FOREACH (Nurb *, nu, nubase) { + if (nu->hide != 0 && editmode) { + continue; + } - if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { - len++; - } - else { - len += resolu; - } + if (for_render && cu->resolu_ren != 0) { + resolu = cu->resolu_ren; + } + else { + resolu = nu->resolu; + } - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0) { - len++; - } + if (!BKE_nurb_check_valid_u(nu)) { + /* pass */ + } + else if (nu->type == CU_BEZIER) { + /* count */ + len = 0; + a = nu->pntsu - 1; + if (nu->flagu & CU_NURB_CYCLIC) { + a++; + } - prevbezt = bezt; - bezt++; + prevbezt = nu->bezt; + bezt = prevbezt + 1; + while (a--) { + if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { + bezt = nu->bezt; } - dl = MEM_callocN(sizeof(DispList), "makeDispListbez"); - /* len+1 because of 'forward_diff_bezier' function */ - dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); - dl->parts = 1; - dl->nr = len; - dl->col = nu->mat_nr; - dl->charidx = nu->charidx; - - data = dl->verts; - - /* check that (len != 2) so we don't immediately loop back on ourselves */ - if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) { - dl->type = DL_POLY; - a = nu->pntsu; + if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { + len++; } else { - dl->type = DL_SEGM; - a = nu->pntsu - 1; + len += resolu; } - prevbezt = nu->bezt; - bezt = prevbezt + 1; + if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0) { + len++; + } - while (a--) { - if (a == 0 && dl->type == DL_POLY) { - bezt = nu->bezt; - } + prevbezt = bezt; + bezt++; + } - if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { - copy_v3_v3(data, prevbezt->vec[1]); - data += 3; - } - else { - int j; - for (j = 0; j < 3; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], - prevbezt->vec[2][j], - bezt->vec[0][j], - bezt->vec[1][j], - data + j, - resolu, - sizeof(float[3])); - } + dl = MEM_callocN(sizeof(DispList), "makeDispListbez"); + /* len+1 because of 'forward_diff_bezier' function */ + dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts = 1; + dl->nr = len; + dl->col = nu->mat_nr; + dl->charidx = nu->charidx; + + data = dl->verts; + + /* check that (len != 2) so we don't immediately loop back on ourselves */ + if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) { + dl->type = DL_POLY; + a = nu->pntsu; + } + else { + dl->type = DL_SEGM; + a = nu->pntsu - 1; + } - data += 3 * resolu; - } + prevbezt = nu->bezt; + bezt = prevbezt + 1; + + while (a--) { + if (a == 0 && dl->type == DL_POLY) { + bezt = nu->bezt; + } - if (a == 0 && dl->type == DL_SEGM) { - copy_v3_v3(data, bezt->vec[1]); + if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) { + copy_v3_v3(data, prevbezt->vec[1]); + data += 3; + } + else { + int j; + for (j = 0; j < 3; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + data + j, + resolu, + sizeof(float[3])); } - prevbezt = bezt; - bezt++; + data += 3 * resolu; } + + if (a == 0 && dl->type == DL_SEGM) { + copy_v3_v3(data, bezt->vec[1]); + } + + prevbezt = bezt; + bezt++; } - else if (nu->type == CU_NURBS) { - len = (resolu * SEGMENTSU(nu)); + } + else if (nu->type == CU_NURBS) { + len = (resolu * SEGMENTSU(nu)); - dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); - dl->parts = 1; + dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts = 1; - dl->nr = len; - dl->col = nu->mat_nr; - dl->charidx = nu->charidx; + dl->nr = len; + dl->col = nu->mat_nr; + dl->charidx = nu->charidx; - data = dl->verts; - if (nu->flagu & CU_NURB_CYCLIC) { - dl->type = DL_POLY; - } - else { - dl->type = DL_SEGM; - } - BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, sizeof(float[3])); + data = dl->verts; + if (nu->flagu & CU_NURB_CYCLIC) { + dl->type = DL_POLY; + } + else { + dl->type = DL_SEGM; + } + BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, sizeof(float[3])); + } + else if (nu->type == CU_POLY) { + len = nu->pntsu; + dl = MEM_callocN(sizeof(DispList), "makeDispListpoly"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts = 1; + dl->nr = len; + dl->col = nu->mat_nr; + dl->charidx = nu->charidx; + + data = dl->verts; + if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) { + dl->type = DL_POLY; + } + else { + dl->type = DL_SEGM; } - else if (nu->type == CU_POLY) { - len = nu->pntsu; - dl = MEM_callocN(sizeof(DispList), "makeDispListpoly"); - dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); - dl->parts = 1; - dl->nr = len; - dl->col = nu->mat_nr; - dl->charidx = nu->charidx; - - data = dl->verts; - if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) { - dl->type = DL_POLY; - } - else { - dl->type = DL_SEGM; - } - a = len; - bp = nu->bp; - while (a--) { - copy_v3_v3(data, bp->vec); - bp++; - data += 3; - } + a = len; + bp = nu->bp; + while (a--) { + copy_v3_v3(data, bp->vec); + bp++; + data += 3; } } - nu = nu->next; } } @@ -491,7 +469,7 @@ void BKE_displist_fill(ListBase *dispbase, ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last; ScanFillFace *sf_tri; MemArena *sf_arena; - DispList *dlnew = NULL, *dl; + DispList *dlnew = NULL; float *f1; int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0; int totvert; @@ -515,8 +493,7 @@ void BKE_displist_fill(ListBase *dispbase, BLI_scanfill_begin_arena(&sf_ctx, sf_arena); - dl = dispbase->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { if (dl->type == DL_POLY) { if (charidx < dl->charidx) { cont = 1; @@ -558,7 +535,6 @@ void BKE_displist_fill(ListBase *dispbase, } dl_flag_accum |= dl->flag; } - dl = dl->next; } /* XXX (obedit && obedit->actcol) ? (obedit->actcol - 1) : 0)) { */ @@ -627,19 +603,17 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) { const float z_up[3] = {0.0f, 0.0f, -1.0f}; ListBase front, back; - DispList *dl, *dlnew; float *fp, *fp1; int a, dpoly; BLI_listbase_clear(&front); BLI_listbase_clear(&back); - dl = dispbase->first; - while (dl) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { if (dl->type == DL_SURF) { if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) { if ((cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) { - dlnew = MEM_callocN(sizeof(DispList), "filldisp"); + DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&front, dlnew); dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1"); dlnew->nr = dl->parts; @@ -660,7 +634,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } } if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) { - dlnew = MEM_callocN(sizeof(DispList), "filldisp"); + DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp"); BLI_addtail(&back, dlnew); dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1"); dlnew->nr = dl->parts; @@ -682,7 +656,6 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) } } } - dl = dl->next; } BKE_displist_fill(&front, dispbase, z_up, true); @@ -939,18 +912,17 @@ static bool curve_calc_modifiers_pre( static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3] { - DispList *dl; float(*allverts)[3], *fp; *r_vert_len = 0; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { *r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr; } allverts = MEM_mallocN(sizeof(float[3]) * (*r_vert_len), "displist_vert_coords_alloc allverts"); fp = (float *)allverts; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr); memcpy(fp, dl->verts, sizeof(float) * offs); fp += offs; @@ -961,11 +933,10 @@ static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[ static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3]) { - DispList *dl; const float *fp; fp = (float *)allverts; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr); memcpy(dl->verts, fp, sizeof(float) * offs); fp += offs; @@ -1218,7 +1189,6 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, const bool for_orco) { ListBase nubase = {NULL, NULL}; - Nurb *nu; Curve *cu = ob->data; DispList *dl; float *data; @@ -1236,76 +1206,78 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, force_mesh_conversion = curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render); } - for (nu = nubase.first; nu; nu = nu->next) { - if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) { - int resolu = nu->resolu, resolv = nu->resolv; + LISTBASE_FOREACH (Nurb *, nu, &nubase) { + if (!(for_render || nu->hide == 0) || !BKE_nurb_check_valid_uv(nu)) { + continue; + } + + int resolu = nu->resolu, resolv = nu->resolv; - if (for_render) { - if (cu->resolu_ren) { - resolu = cu->resolu_ren; - } - if (cu->resolv_ren) { - resolv = cu->resolv_ren; - } + if (for_render) { + if (cu->resolu_ren) { + resolu = cu->resolu_ren; + } + if (cu->resolv_ren) { + resolv = cu->resolv_ren; } + } - if (nu->pntsv == 1) { - len = SEGMENTSU(nu) * resolu; + if (nu->pntsv == 1) { + len = SEGMENTSU(nu) * resolu; - dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); + dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); - dl->parts = 1; - dl->nr = len; - dl->col = nu->mat_nr; - dl->charidx = nu->charidx; + BLI_addtail(dispbase, dl); + dl->parts = 1; + dl->nr = len; + dl->col = nu->mat_nr; + dl->charidx = nu->charidx; - /* dl->rt will be used as flag for render face and */ - /* CU_2D conflicts with R_NOPUNOFLIP */ - dl->rt = nu->flag & ~CU_2D; + /* dl->rt will be used as flag for render face and */ + /* CU_2D conflicts with R_NOPUNOFLIP */ + dl->rt = nu->flag & ~CU_2D; - data = dl->verts; - if (nu->flagu & CU_NURB_CYCLIC) { - dl->type = DL_POLY; - } - else { - dl->type = DL_SEGM; - } - - BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, sizeof(float[3])); + data = dl->verts; + if (nu->flagu & CU_NURB_CYCLIC) { + dl->type = DL_POLY; } else { - len = (nu->pntsu * resolu) * (nu->pntsv * resolv); + dl->type = DL_SEGM; + } - dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); - dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); - BLI_addtail(dispbase, dl); + BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, sizeof(float[3])); + } + else { + len = (nu->pntsu * resolu) * (nu->pntsv * resolv); - dl->col = nu->mat_nr; - dl->charidx = nu->charidx; + dl = MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts"); + BLI_addtail(dispbase, dl); - /* dl->rt will be used as flag for render face and */ - /* CU_2D conflicts with R_NOPUNOFLIP */ - dl->rt = nu->flag & ~CU_2D; + dl->col = nu->mat_nr; + dl->charidx = nu->charidx; - data = dl->verts; - dl->type = DL_SURF; + /* dl->rt will be used as flag for render face and */ + /* CU_2D conflicts with R_NOPUNOFLIP */ + dl->rt = nu->flag & ~CU_2D; - dl->parts = (nu->pntsu * resolu); /* in reverse, because makeNurbfaces works that way */ - dl->nr = (nu->pntsv * resolv); - if (nu->flagv & CU_NURB_CYCLIC) { - dl->flag |= DL_CYCL_U; /* reverse too! */ - } - if (nu->flagu & CU_NURB_CYCLIC) { - dl->flag |= DL_CYCL_V; - } + data = dl->verts; + dl->type = DL_SURF; - BKE_nurb_makeFaces(nu, data, 0, resolu, resolv); - - /* gl array drawing: using indices */ - displist_surf_indices(dl); + dl->parts = (nu->pntsu * resolu); /* in reverse, because makeNurbfaces works that way */ + dl->nr = (nu->pntsv * resolv); + if (nu->flagv & CU_NURB_CYCLIC) { + dl->flag |= DL_CYCL_U; /* reverse too! */ + } + if (nu->flagu & CU_NURB_CYCLIC) { + dl->flag |= DL_CYCL_V; } + + BKE_nurb_makeFaces(nu, data, 0, resolu, resolv); + + /* gl array drawing: using indices */ + displist_surf_indices(dl); } } @@ -1851,12 +1823,11 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph, void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) { - DispList *dl; const float *vert; int a, tot = 0; int doit = 0; - for (dl = dispbase->first; dl; dl = dl->next) { + LISTBASE_FOREACH (DispList *, dl, dispbase) { tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts; vert = dl->verts; for (a = 0; a < tot; a++, vert += 3) { diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index fef4b49de7e..b56a15b3d45 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -76,9 +76,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -/* to read material/texture color */ -#include "RE_render_ext.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" #include "atomic_ops.h" @@ -123,7 +121,7 @@ static int neighStraightY[8] = {0, 1, 0, -1, 1, 1, -1, -1}; /* paint effect default movement per frame in global units */ #define EFF_MOVEMENT_PER_FRAME 0.05f /* initial wave time factor */ -#define WAVE_TIME_FAC (1.0f / 24.f) +#define WAVE_TIME_FAC (1.0f / 24.0f) #define CANVAS_REL_SIZE 5.0f /* drying limits */ #define MIN_WETNESS 0.001f @@ -762,7 +760,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min); copy_v3_v3(td, dim); copy_v3_v3(bData->dim, dim); - min_dim = max_fff(td[0], td[1], td[2]) / 1000.f; + min_dim = max_fff(td[0], td[1], td[2]) / 1000.0f; /* deactivate zero axises */ for (i = 0; i < 3; i++) { @@ -2700,7 +2698,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa const int final_tri_index = tempPoints[final_index].tri_index; /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */ - if (final_tri_index != target_tri && final_tri_index != -1) { + if (!ELEM(final_tri_index, target_tri, -1)) { /* Check if it's close enough to likely touch the intended triangle. Any triangle * becomes thinner than a pixel at its vertices, so robustness requires some margin. */ const float final_pt[2] = {((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h}; @@ -3034,7 +3032,7 @@ int dynamicPaint_createUVSurface(Scene *scene, n_pos++; } } - else if (n_target == ON_MESH_EDGE || n_target == OUT_OF_TEXTURE) { + else if (ELEM(n_target, ON_MESH_EDGE, OUT_OF_TEXTURE)) { ed->flags[final_index[index]] |= ADJ_ON_MESH_EDGE; } } @@ -3736,7 +3734,7 @@ static bool meshBrush_boundsIntersect(Bounds3D *b1, if (brush->collision == MOD_DPAINT_COL_VOLUME) { return boundsIntersect(b1, b2); } - if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) { + if (ELEM(brush->collision, MOD_DPAINT_COL_DIST, MOD_DPAINT_COL_VOLDIST)) { return boundsIntersectDist(b1, b2, brush_radius); } return true; @@ -4710,8 +4708,7 @@ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, } /* Smooth range or color ramp */ - if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH || - brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) { + if (ELEM(brush->proximity_falloff, MOD_DPAINT_PRFALL_SMOOTH, MOD_DPAINT_PRFALL_RAMP)) { strength = 1.0f - distance / brush_radius; CLAMP(strength, 0.0f, 1.0f); } @@ -5116,7 +5113,7 @@ static void dynamic_paint_prepare_effect_cb(void *__restrict userdata, madd_v3_v3fl(forc, scene->physics_settings.gravity, surface->effector_weights->global_gravity * surface->effector_weights->weight[0] / - 10.f); + 10.0f); } /* add surface point velocity and acceleration if enabled */ diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c index b3f6b543daf..9656c20f0be 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.c +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -35,6 +35,7 @@ /* interface */ #include "mikktspace.h" +/* -------------------------------------------------------------------- */ /** \name Tangent Space Calculation * \{ */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 967b961dbea..13e9bb1bf24 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -68,8 +68,7 @@ #include "DEG_depsgraph_physics.h" #include "DEG_depsgraph_query.h" -#include "RE_render_ext.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" EffectorWeights *BKE_effector_add_weights(Collection *collection) { @@ -699,8 +698,8 @@ int get_effector_data(EffectorCache *eff, copy_v3_v3(efd->loc, state.co); /* rather than use the velocity use rotated x-axis (defaults to velocity) */ - efd->nor[0] = 1.f; - efd->nor[1] = efd->nor[2] = 0.f; + efd->nor[0] = 1.0f; + efd->nor[1] = efd->nor[2] = 0.0f; mul_qt_v3(state.rot, efd->nor); if (real_velocity) { @@ -1009,9 +1008,12 @@ static void do_physical_effector(EffectorCache *eff, else { add_v3_v3v3(temp, efd->vec_to_point2, efd->nor2); } - force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2, 0, 2); - force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2, 0, 2); - force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2, 0, 2); + force[0] = -1.0f + 2.0f * BLI_noise_generic_turbulence( + pd->f_size, temp[0], temp[1], temp[2], 2, 0, 2); + force[1] = -1.0f + 2.0f * BLI_noise_generic_turbulence( + pd->f_size, temp[1], temp[2], temp[0], 2, 0, 2); + force[2] = -1.0f + 2.0f * BLI_noise_generic_turbulence( + pd->f_size, temp[2], temp[0], temp[1], 2, 0, 2); mul_v3_fl(force, strength * efd->falloff); break; case PFIELD_DRAG: diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 003e926e0ae..8bfc626379f 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1076,6 +1076,84 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample fcu->totvert = end - start + 1; } +static void init_unbaked_bezt_data(BezTriple *bezt) +{ + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + /* Baked FCurve points always use linear interpolation. */ + bezt->ipo = BEZT_IPO_LIN; + bezt->h1 = bezt->h2 = HD_AUTO_ANIM; +} + +/* Convert baked/sampled fcurves into bezt/regular fcurves. */ +void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end) +{ + + /* Sanity checks. */ + /* TODO: make these tests report errors using reports not CLOG's (Joshua Leung 2009). */ + if (fcu == NULL) { + CLOG_ERROR(&LOG, "No F-Curve with F-Curve Modifiers to Un-Bake"); + return; + } + + if (start > end) { + CLOG_ERROR(&LOG, "Error: Frame range to unbake F-Curve is inappropriate"); + return; + } + + if (fcu->fpt == NULL) { + /* No data to unbake. */ + CLOG_ERROR(&LOG, "Error: Curve containts no baked keyframes"); + return; + } + + /* Free any existing sample/keyframe data on the curve. */ + if (fcu->bezt) { + MEM_freeN(fcu->bezt); + } + + BezTriple *bezt; + FPoint *fpt = fcu->fpt; + int keyframes_to_insert = end - start; + int sample_points = fcu->totvert; + + bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)keyframes_to_insert, __func__); + fcu->totvert = keyframes_to_insert; + + /* Get first sample point to 'copy' as keyframe. */ + for (; sample_points && (fpt->vec[0] < start); fpt++, sample_points--) { + /* pass */ + } + + /* Current position in the timeline. */ + int cur_pos = start; + + /* Add leading dummy flat points if needed. */ + for (; keyframes_to_insert && (fpt->vec[0] > start); cur_pos++, bezt++, keyframes_to_insert--) { + init_unbaked_bezt_data(bezt); + bezt->vec[1][0] = (float)cur_pos; + bezt->vec[1][1] = fpt->vec[1]; + } + + /* Copy actual sample points. */ + for (; keyframes_to_insert && sample_points; + cur_pos++, bezt++, keyframes_to_insert--, fpt++, sample_points--) { + init_unbaked_bezt_data(bezt); + copy_v2_v2(bezt->vec[1], fpt->vec); + } + + /* Add trailing dummy flat points if needed. */ + for (fpt--; keyframes_to_insert; cur_pos++, bezt++, keyframes_to_insert--) { + init_unbaked_bezt_data(bezt); + bezt->vec[1][0] = (float)cur_pos; + bezt->vec[1][1] = fpt->vec[1]; + } + + MEM_SAFE_FREE(fcu->fpt); + + /* Not strictly needed since we use linear interpolation, but better be consistent here. */ + calchandles_fcurve(fcu); +} + /* ***************************** F-Curve Sanity ********************************* */ /* The functions here are used in various parts of Blender, usually after some editing * of keyframe data has occurred. They ensure that keyframe data is properly ordered and @@ -1194,7 +1272,7 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) /* For automatic ease in and out. */ if (BEZT_IS_AUTOH(bezt) && !cycle) { /* Only do this on first or last beztriple. */ - if ((a == 0) || (a == fcu->totvert - 1)) { + if (ELEM(a, 0, fcu->totvert - 1)) { /* Set both handles to have same horizontal value as keyframe. */ if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) { bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1]; @@ -1658,7 +1736,7 @@ static float fcurve_eval_keyframes_extrapolate( return endpoint_bezt->vec[1][1] - (fac * dx); } - /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus + /* Use the gradient of the second handle (later) of neighbor to calculate the gradient and thus * the value of the curve at evaluation time. */ int handle = direction_to_neighbor > 0 ? 0 : 2; float dx = endpoint_bezt->vec[1][0] - evaltime; @@ -1934,7 +2012,7 @@ static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, fl return 0.0f; } -/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes. */ +/* Calculate F-Curve value for 'evaltime' using #BezTriple keyframes. */ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) { if (evaltime <= bezts->vec[1][0]) { @@ -1949,7 +2027,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime return fcurve_eval_keyframes_interpolate(fcu, bezts, evaltime); } -/* Calculate F-Curve value for 'evaltime' using FPoint samples. */ +/* Calculate F-Curve value for 'evaltime' using #FPoint samples. */ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime) { FPoint *prevfpt, *lastfpt, *fpt; diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index a230c8f2e96..97dd541e2b9 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -290,7 +290,7 @@ TEST(fcurve_active_keyframe, ActiveKeyframe) EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), 2); /* Check clearing the index. */ - BKE_fcurve_active_keyframe_set(fcu, NULL); + BKE_fcurve_active_keyframe_set(fcu, nullptr); EXPECT_EQ(fcu->active_keyframe_index, FCURVE_ACTIVE_KEYFRAME_NONE); EXPECT_EQ(BKE_fcurve_active_keyframe_index(fcu), FCURVE_ACTIVE_KEYFRAME_NONE); diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index d93b635d67d..eb1d77eb0f4 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -80,7 +80,7 @@ # include "DEG_depsgraph.h" # include "DEG_depsgraph_query.h" -# include "RE_shader_ext.h" +# include "RE_texture.h" # include "CLG_log.h" @@ -343,32 +343,37 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } fds->cache_frame_pause_data = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) { flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE); BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } fds->cache_frame_pause_noise = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) { flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH); BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } fds->cache_frame_pause_mesh = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_PARTICLES) { @@ -377,17 +382,18 @@ void BKE_fluid_cache_free(FluidDomainSettings *fds, Object *ob, int cache_map) BLI_path_join( temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } fds->cache_frame_pause_particles = 0; } - if (cache_map & FLUID_DOMAIN_OUTDATED_GUIDE) { flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE); BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL); BLI_path_abs(temp_dir, relbase); - BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ - + if (BLI_exists(temp_dir)) { + BLI_delete(temp_dir, true, true); + } fds->cache_frame_pause_guide = 0; } fds->cache_flag = flags; @@ -1987,7 +1993,7 @@ static void sample_mesh(FluidFlowSettings *ffs, /* Convert xyz velocities flow settings from world to grid space. */ float convert_vel[3]; copy_v3_v3(convert_vel, ffs->vel_coord); - float time_mult = 1.0 / (25.f * DT_DEFAULT); + float time_mult = 1.0 / (25.0f * DT_DEFAULT); float size_mult = MAX3(base_res[0], base_res[1], base_res[2]) / MAX3(global_size[0], global_size[1], global_size[2]); mul_v3_v3fl(convert_vel, ffs->vel_coord, size_mult * time_mult); @@ -3296,7 +3302,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj /* If needed, vertex velocities will be read too. */ bool use_speedvectors = fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS; FluidDomainVertexVelocity *velarray = NULL; - float time_mult = 25.f * DT_DEFAULT; + float time_mult = 25.0f * DT_DEFAULT; if (use_speedvectors) { if (fds->mesh_velocities) { @@ -4433,7 +4439,7 @@ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velo if (fmd && (fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain && fmd->domain->fluid) { FluidDomainSettings *fds = fmd->domain; - float time_mult = 25.f * DT_DEFAULT; + float time_mult = 25.0f * DT_DEFAULT; float size_mult = MAX3(fds->global_size[0], fds->global_size[1], fds->global_size[2]) / MAX3(fds->base_res[0], fds->base_res[1], fds->base_res[2]); float vel_mag; @@ -4700,9 +4706,11 @@ void BKE_fluid_fields_sanitize(FluidDomainSettings *settings) const char data_depth = settings->openvdb_data_depth; if (settings->type == FLUID_DOMAIN_TYPE_GAS) { - if (coba_field == FLUID_DOMAIN_FIELD_PHI || coba_field == FLUID_DOMAIN_FIELD_PHI_IN || - coba_field == FLUID_DOMAIN_FIELD_PHI_OUT || - coba_field == FLUID_DOMAIN_FIELD_PHI_OBSTACLE) { + if (ELEM(coba_field, + FLUID_DOMAIN_FIELD_PHI, + FLUID_DOMAIN_FIELD_PHI_IN, + FLUID_DOMAIN_FIELD_PHI_OUT, + FLUID_DOMAIN_FIELD_PHI_OBSTACLE)) { /* Defaulted to density for gas domain. */ settings->coba_field = FLUID_DOMAIN_FIELD_DENSITY; } @@ -4713,10 +4721,14 @@ void BKE_fluid_fields_sanitize(FluidDomainSettings *settings) } } else if (settings->type == FLUID_DOMAIN_TYPE_LIQUID) { - if (coba_field == FLUID_DOMAIN_FIELD_COLOR_R || coba_field == FLUID_DOMAIN_FIELD_COLOR_G || - coba_field == FLUID_DOMAIN_FIELD_COLOR_B || coba_field == FLUID_DOMAIN_FIELD_DENSITY || - coba_field == FLUID_DOMAIN_FIELD_FLAME || coba_field == FLUID_DOMAIN_FIELD_FUEL || - coba_field == FLUID_DOMAIN_FIELD_HEAT) { + if (ELEM(coba_field, + FLUID_DOMAIN_FIELD_COLOR_R, + FLUID_DOMAIN_FIELD_COLOR_G, + FLUID_DOMAIN_FIELD_COLOR_B, + FLUID_DOMAIN_FIELD_DENSITY, + FLUID_DOMAIN_FIELD_FLAME, + FLUID_DOMAIN_FIELD_FUEL, + FLUID_DOMAIN_FIELD_HEAT)) { /* Defaulted to phi for liquid domain. */ settings->coba_field = FLUID_DOMAIN_FIELD_PHI; } @@ -4996,6 +5008,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->fractions_threshold = fds->fractions_threshold; tfds->fractions_distance = fds->fractions_distance; tfds->sys_particle_maximum = fds->sys_particle_maximum; + tfds->simulation_method = fds->simulation_method; /* diffusion options*/ tfds->surface_tension = fds->surface_tension; diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index d13425f5ec9..6ebcef5caef 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -824,7 +824,8 @@ static void fcm_noise_evaluate( * - 0.1 is passed as the 'z' value, otherwise evaluation fails for size = phase = 1 * with evaltime being an integer (which happens when evaluating on frame by frame basis) */ - noise = BLI_turbulence(data->size, evaltime - data->offset, data->phase, 0.1f, data->depth); + noise = BLI_noise_turbulence( + data->size, evaltime - data->offset, data->phase, 0.1f, data->depth); /* combine the noise with existing motion data */ switch (data->modification) { diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index e0bbdfaeed6..9431915b4e4 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -168,6 +168,8 @@ IDTypeInfo IDType_ID_VF = { .blend_read_data = vfont_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /***************************** VFont *******************************/ @@ -947,7 +949,7 @@ static bool vfont_to_curve(Object *ob, // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]); for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) { bool dobreak = false; - if (mem[j] == ' ' || mem[j] == '-') { + if (ELEM(mem[j], ' ', '-')) { ct -= (i - (j - 1)); cnr -= (i - (j - 1)); if (mem[j] == ' ') { diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 6c6ca996caa..4cf8e365cf6 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -288,6 +288,8 @@ IDTypeInfo IDType_ID_GD = { .blend_read_data = greasepencil_blend_read_data, .blend_read_lib = greasepencil_blend_read_lib, .blend_read_expand = greasepencil_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* ************************************************** */ @@ -2009,12 +2011,12 @@ void BKE_gpencil_material_remap(struct bGPdata *gpd, /** * Load a table with material conversion index for merged materials. - * \param ob: Grease pencil object - * \param hue_threshold: Threshold for Hue - * \param sat_threshold: Threshold for Saturation - * \param val_threshold: Threshold for Value - * \param r_mat_table : return material table - * \return True if done + * \param ob: Grease pencil object. + * \param hue_threshold: Threshold for Hue. + * \param sat_threshold: Threshold for Saturation. + * \param val_threshold: Threshold for Value. + * \param r_mat_table: return material table. + * \return True if done. */ bool BKE_gpencil_merge_materials_table_get(Object *ob, const float hue_threshold, @@ -2668,7 +2670,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, return; } - if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); return; @@ -2710,7 +2712,7 @@ void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) if ((gpl->parent != NULL) && (gpl->actframe != NULL)) { Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); /* calculate new matrix */ - if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { copy_m4_m4(cur_mat, ob_parent->obmat); } else if (gpl->partype == PARBONE) { diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 66a7ae757a2..ff7dde27db8 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -189,7 +189,7 @@ BoundBox *BKE_gpencil_boundbox_get(Object *ob) /* Update orig object's boundbox with re-computed evaluated values. This function can be * called with the evaluated object and need update the original object bound box data * to keep both values synchronized. */ - if ((ob_orig != NULL) && (ob != ob_orig)) { + if (!ELEM(ob_orig, NULL, ob)) { if (ob_orig->runtime.bb == NULL) { ob_orig->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox"); } @@ -778,7 +778,7 @@ bool BKE_gpencil_stroke_smooth(bGPDstroke *gps, int i, float inf) /* Only affect endpoints by a fraction of the normal strength, * to prevent the stroke from shrinking too much */ - if ((i == 0) || (i == gps->totpoints - 1)) { + if (ELEM(i, 0, gps->totpoints - 1)) { inf *= 0.1f; } @@ -838,7 +838,7 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float } /* Only affect endpoints by a fraction of the normal influence */ float inf = influence; - if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + if (ELEM(point_index, 0, gps->totpoints - 1)) { inf *= 0.01f; } /* Limit max influence to reduce pop effect. */ @@ -902,7 +902,7 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float } /* Only affect endpoints by a fraction of the normal influence */ float inf = influence; - if ((point_index == 0) || (point_index == gps->totpoints - 1)) { + if (ELEM(point_index, 0, gps->totpoints - 1)) { inf *= 0.01f; } /* Limit max influence to reduce pop effect. */ @@ -1402,7 +1402,7 @@ bool BKE_gpencil_stroke_trim(bGPDstroke *gps) memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight)); } } - if (idx == start || idx == end) { + if (ELEM(idx, start, end)) { copy_v3_v3(&pt_new->x, point); } } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index d12e445fe99..be06638ab64 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -37,9 +37,12 @@ #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "BKE_colortools.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" @@ -54,6 +57,8 @@ #include "MOD_gpencil_modifiertypes.h" +#include "BLO_read_write.h" + #include "CLG_log.h" static CLG_LogRef LOG = {"bke.gpencil_modifier"}; @@ -411,6 +416,11 @@ void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname) strcat(r_idname, mti->name); } +void BKE_gpencil_modifier_panel_expand(GpencilModifierData *md) +{ + md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; +} + /** * Generic grease pencil modifier copy data. * \param md_src: Source modifier data @@ -771,3 +781,159 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) /* Clear any lattice data. */ BKE_gpencil_lattice_clear(ob); } + +void BKE_gpencil_modifier_blend_write(BlendWriter *writer, ListBase *modbase) +{ + if (modbase == NULL) { + return; + } + + LISTBASE_FOREACH (GpencilModifierData *, md, modbase) { + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); + if (mti == NULL) { + return; + } + + BLO_write_struct_by_name(writer, mti->struct_name, md); + + if (md->type == eGpencilModifierType_Thick) { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + + if (gpmd->curve_thickness) { + BKE_curvemapping_blend_write(writer, gpmd->curve_thickness); + } + } + else if (md->type == eGpencilModifierType_Noise) { + NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md; + + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_write(writer, gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Hook) { + HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; + + if (gpmd->curfalloff) { + BKE_curvemapping_blend_write(writer, gpmd->curfalloff); + } + } + else if (md->type == eGpencilModifierType_Tint) { + TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md; + if (gpmd->colorband) { + BLO_write_struct(writer, ColorBand, gpmd->colorband); + } + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_write(writer, gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Smooth) { + SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md; + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_write(writer, gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Color) { + ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_write(writer, gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Opacity) { + OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md; + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_write(writer, gpmd->curve_intensity); + } + } + } +} + +void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (GpencilModifierData *, md, lb) { + md->error = NULL; + + /* if modifiers disappear, or for upward compatibility */ + if (NULL == BKE_gpencil_modifier_get_info(md->type)) { + md->type = eModifierType_None; + } + + if (md->type == eGpencilModifierType_Lattice) { + LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; + gpmd->cache_data = NULL; + } + else if (md->type == eGpencilModifierType_Hook) { + HookGpencilModifierData *hmd = (HookGpencilModifierData *)md; + + BLO_read_data_address(reader, &hmd->curfalloff); + if (hmd->curfalloff) { + BKE_curvemapping_blend_read(reader, hmd->curfalloff); + } + } + else if (md->type == eGpencilModifierType_Noise) { + NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md; + + BLO_read_data_address(reader, &gpmd->curve_intensity); + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); + /* initialize the curve. Maybe this could be moved to modififer logic */ + BKE_curvemapping_init(gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Thick) { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + + BLO_read_data_address(reader, &gpmd->curve_thickness); + if (gpmd->curve_thickness) { + BKE_curvemapping_blend_read(reader, gpmd->curve_thickness); + BKE_curvemapping_init(gpmd->curve_thickness); + } + } + else if (md->type == eGpencilModifierType_Tint) { + TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md; + BLO_read_data_address(reader, &gpmd->colorband); + BLO_read_data_address(reader, &gpmd->curve_intensity); + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); + BKE_curvemapping_init(gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Smooth) { + SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md; + BLO_read_data_address(reader, &gpmd->curve_intensity); + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); + BKE_curvemapping_init(gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Color) { + ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; + BLO_read_data_address(reader, &gpmd->curve_intensity); + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); + BKE_curvemapping_init(gpmd->curve_intensity); + } + } + else if (md->type == eGpencilModifierType_Opacity) { + OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md; + BLO_read_data_address(reader, &gpmd->curve_intensity); + if (gpmd->curve_intensity) { + BKE_curvemapping_blend_read(reader, gpmd->curve_intensity); + BKE_curvemapping_init(gpmd->curve_intensity); + } + } + } +} + +void BKE_gpencil_modifier_blend_read_lib(BlendLibReader *reader, Object *ob) +{ + BKE_gpencil_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 (GpencilModifierData *, mod, &ob->greasepencil_modifiers) { + mod->flag &= ~eGpencilModifierFlag_OverrideLibrary_Local; + } + } +} diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 313b0d192dc..554919ad1a0 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -195,6 +195,8 @@ IDTypeInfo IDType_ID_HA = { .blend_read_data = hair_blend_read_data, .blend_read_lib = hair_blend_read_lib, .blend_read_expand = hair_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; static void hair_random(Hair *hair) diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index bcec90cf0cf..eec9013d067 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -899,8 +899,10 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) /** \} */ +/* -------------------------------------------------------------------- */ /** \name Studio Light Icon * \{ */ + int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type) { int icon_id = get_next_free_id(); diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 113d4cf50d7..b0991f1d343 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -68,9 +68,7 @@ static size_t idp_size_table[] = { }; /* -------------------------------------------------------------------- */ -/* Array Functions */ - -/** \name IDP Array API +/** \name Array Functions (IDP Array API) * \{ */ #define GETPROP(prop, i) &(IDP_IDPArray(prop)[i]) @@ -323,9 +321,7 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop, const int flag) /** \} */ /* -------------------------------------------------------------------- */ -/* String Functions */ - -/** \name IDProperty String API +/** \name String Functions (IDProperty String API) * \{ */ /** @@ -439,9 +435,7 @@ void IDP_FreeString(IDProperty *prop) /** \} */ /* -------------------------------------------------------------------- */ -/* ID Type */ - -/** \name IDProperty ID API +/** \name ID Type (IDProperty ID API) * \{ */ static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag) @@ -477,9 +471,7 @@ void IDP_AssignID(IDProperty *prop, ID *id, const int flag) /** \} */ /* -------------------------------------------------------------------- */ -/* Group Functions */ - -/** \name IDProperty Group API +/** \name Group Functions (IDProperty Group API) * \{ */ /** @@ -760,10 +752,9 @@ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user) /** \} */ /* -------------------------------------------------------------------- */ -/* Main Functions */ - -/** \name IDProperty Main API +/** \name Main Functions (IDProperty Main API) * \{ */ + IDProperty *IDP_CopyProperty_ex(const IDProperty *prop, const int flag) { switch (prop->type) { @@ -800,43 +791,6 @@ void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src) IDP_FreeProperty(idprop_tmp); } -/* Updates ID pointers after an object has been copied */ -/* TODO Nuke this once its only user has been correctly converted - * to use generic ID management from BKE_library! */ -void IDP_RelinkProperty(struct IDProperty *prop) -{ - if (!prop) { - return; - } - - switch (prop->type) { - case IDP_GROUP: { - LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) { - IDP_RelinkProperty(loop); - } - break; - } - case IDP_IDPARRAY: { - IDProperty *idp_array = IDP_Array(prop); - for (int i = 0; i < prop->len; i++) { - IDP_RelinkProperty(&idp_array[i]); - } - break; - } - case IDP_ID: { - ID *id = IDP_Id(prop); - if (id && id->newid) { - id_us_min(IDP_Id(prop)); - prop->data.pointer = id->newid; - id_us_plus(IDP_Id(prop)); - } - break; - } - default: - break; /* Nothing to do for other IDProp types. */ - } -} - /** * Get the Group property that contains the id properties for ID id. Set create_if_needed * to create the Group property and attach it to id if it doesn't exist; otherwise @@ -961,7 +915,7 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) * This function takes three arguments: the ID property type, a union which defines * its initial value, and a name. * - * The union is simple to use; see the top of this header file for its definition. + * The union is simple to use; see the top of BKE_idprop.h for its definition. * An example of using this function: * * \code{.c} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 187908573dd..f87b1b5ff45 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -84,7 +84,6 @@ #include "BKE_packedFile.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" /* seq_foreground_frame_get() */ #include "BKE_workspace.h" #include "BLF_api.h" @@ -93,6 +92,8 @@ #include "RE_pipeline.h" +#include "SEQ_sequencer.h" /* seq_foreground_frame_get() */ + #include "GPU_texture.h" #include "BLI_sys_types.h" /* for intptr_t support */ @@ -324,6 +325,8 @@ IDTypeInfo IDType_ID_IM = { .blend_read_data = image_blend_read_data, .blend_read_lib = image_blend_read_lib, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /* prototypes */ @@ -665,7 +668,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number) /* Tile number 0 is a special case and refers to the first tile, typically * coming from non-UDIM-aware code. */ - if (tile_number == 0 || tile_number == 1001) { + if (ELEM(tile_number, 0, 1001)) { return ima->tiles.first; } @@ -802,7 +805,7 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist /* first search an identical filepath */ for (ima = bmain->images.first; ima; ima = ima->id.next) { - if (ima->source != IMA_SRC_VIEWER && ima->source != IMA_SRC_GENERATED) { + if (!ELEM(ima->source, IMA_SRC_VIEWER, IMA_SRC_GENERATED)) { STRNCPY(strtest, ima->filepath); BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &ima->id)); @@ -1313,7 +1316,7 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options) return IMB_FTYPE_TIF; } #endif - if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) { + if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { return IMB_FTYPE_OPENEXR; } #ifdef WITH_CINEON @@ -1663,7 +1666,7 @@ static bool do_add_image_extension(char *string, } #endif #ifdef WITH_OPENEXR - else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) { + else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { if (!BLI_path_extension_check(string, extension_test = ".exr")) { extension = extension_test; } diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 877747a257e..ceb13c4955e 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -379,10 +379,16 @@ static void checker_board_text( const float text_color[4] = {0.0, 0.0, 0.0, 1.0}; const float text_outline[4] = {1.0, 1.0, 1.0, 1.0}; + const char char_array[36] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + int first_char_index = 0; for (y = 0; y < height; y += step) { - text[1] = '1'; + text[0] = char_array[first_char_index]; + int second_char_index = 27; for (x = 0; x < width; x += step) { + text[1] = char_array[second_char_index]; + /* hard coded offset */ pen_x = x + 33; pen_y = y + 44; @@ -412,9 +418,9 @@ static void checker_board_text( BLF_position(mono, pen_x, pen_y, 0.0); BLF_draw_buffer(mono, text, 2); - text[1]++; + second_char_index = (second_char_index + 1) % ARRAY_SIZE(char_array); } - text[0]++; + first_char_index = (first_char_index + 1) % ARRAY_SIZE(char_array); } /* cleanup the buffer. */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 1a87b931689..9696d920640 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -52,6 +52,7 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_endian_switch.h" #include "BLI_string_utils.h" #include "BLI_utildefines.h" @@ -68,12 +69,15 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_nla.h" -#include "BKE_sequencer.h" #include "CLG_log.h" #include "MEM_guardedalloc.h" +#include "SEQ_sequencer.h" + +#include "BLO_read_write.h" + #ifdef WIN32 # include "BLI_math_base.h" /* M_PI */ #endif @@ -109,6 +113,69 @@ static void ipo_free_data(ID *id) } } +static void ipo_blend_read_data(BlendDataReader *reader, ID *id) +{ + Ipo *ipo = (Ipo *)id; + + BLO_read_list(reader, &(ipo->curve)); + + LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) { + BLO_read_data_address(reader, &icu->bezt); + BLO_read_data_address(reader, &icu->bp); + BLO_read_data_address(reader, &icu->driver); + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&icu->blocktype); + if (icu->driver != NULL) { + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&icu->blocktype); + if (icu->driver != NULL) { + BLI_endian_switch_int16(&icu->driver->blocktype); + } + } + } + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&ipo->blocktype); + if (icu->driver != NULL) { + BLI_endian_switch_int16(&icu->driver->blocktype); + } + } + } + } + + /* Undo generic endian switching. */ + if (BLO_read_requires_endian_switch(reader)) { + BLI_endian_switch_int16(&ipo->blocktype); + } +} + +static void ipo_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Ipo *ipo = (Ipo *)id; + + LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) { + if (icu->driver) { + BLO_read_id_address(reader, ipo->id.lib, &icu->driver->ob); + } + } +} + +static void ipo_blend_read_expand(BlendExpander *expander, ID *id) +{ + Ipo *ipo = (Ipo *)id; + + LISTBASE_FOREACH (IpoCurve *, icu, &ipo->curve) { + if (icu->driver) { + BLO_expand(expander, icu->driver->ob); + } + } +} + IDTypeInfo IDType_ID_IP = { .id_code = ID_IP, .id_filter = 0, @@ -128,9 +195,11 @@ IDTypeInfo IDType_ID_IP = { .foreach_cache = NULL, .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_read_data = ipo_blend_read_data, + .blend_read_lib = ipo_blend_read_lib, + .blend_read_expand = ipo_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* *************************************************** */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 95a8419b95d..7468112b40e 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -214,6 +214,8 @@ IDTypeInfo IDType_ID_KE = { .blend_read_data = shapekey_blend_read_data, .blend_read_lib = shapekey_blend_read_lib, .blend_read_expand = shapekey_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; #define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */ @@ -1614,7 +1616,7 @@ int BKE_keyblock_element_count_from_shape(const Key *key, const int shape_index) int result = 0; int index = 0; for (const KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { - if ((shape_index == -1) || (index == shape_index)) { + if (ELEM(shape_index, -1, index)) { result += kb->totelem; } } @@ -1654,7 +1656,7 @@ void BKE_keyblock_data_get_from_shape(const Key *key, float (*arr)[3], const int uint8_t *elements = (uint8_t *)arr; int index = 0; for (const KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { - if ((shape_index == -1) || (index == shape_index)) { + if (ELEM(shape_index, -1, index)) { const int block_elem_len = kb->totelem * key->elemsize; memcpy(elements, kb->data, block_elem_len); elements += block_elem_len; @@ -1684,7 +1686,7 @@ void BKE_keyblock_data_set_with_mat4(Key *key, int index = 0; for (KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { - if ((shape_index == -1) || (index == shape_index)) { + if (ELEM(shape_index, -1, index)) { const int block_elem_len = kb->totelem; float(*block_data)[3] = (float(*)[3])kb->data; for (int data_offset = 0; data_offset < block_elem_len; ++data_offset) { @@ -1708,7 +1710,7 @@ void BKE_keyblock_curve_data_set_with_mat4( int index = 0; for (KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { - if ((shape_index == -1) || (index == shape_index)) { + if (ELEM(shape_index, -1, index)) { const int block_elem_size = kb->totelem * key->elemsize; BKE_keyblock_curve_data_transform(nurb, mat, elements, kb->data); elements += block_elem_size; @@ -1724,7 +1726,7 @@ void BKE_keyblock_data_set(Key *key, const int shape_index, const void *data) const uint8_t *elements = data; int index = 0; for (KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { - if ((shape_index == -1) || (index == shape_index)) { + if (ELEM(shape_index, -1, index)) { const int block_elem_size = kb->totelem * key->elemsize; memcpy(kb->data, elements, block_elem_size); elements += block_elem_size; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index c0eb6b4b134..74f78106be5 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -203,6 +203,8 @@ IDTypeInfo IDType_ID_LT = { .blend_read_data = lattice_blend_read_data, .blend_read_lib = lattice_blend_read_lib, .blend_read_expand = lattice_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w) diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index 382661ff070..14c600caa46 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -169,7 +169,7 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data, int ui, vi, wi, uu, vv, ww; /* vgroup influence */ - float co_prev[3], weight_blend = 0.0f; + float co_prev[4] = {0}, weight_blend = 0.0f; copy_v3_v3(co_prev, co); #ifdef __SSE2__ __m128 co_vec = _mm_loadu_ps(co_prev); diff --git a/source/blender/blenkernel/intern/lattice_deform_test.cc b/source/blender/blenkernel/intern/lattice_deform_test.cc index 7db9d941458..f08d0349598 100644 --- a/source/blender/blenkernel/intern/lattice_deform_test.cc +++ b/source/blender/blenkernel/intern/lattice_deform_test.cc @@ -83,7 +83,7 @@ static void test_lattice_deform_free(LatticeDeformTestContext *ctx) TEST(lattice_deform_performance, performance_no_dvert_1) { const int32_t num_items = 1; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); @@ -92,7 +92,7 @@ TEST(lattice_deform_performance, performance_no_dvert_1) TEST(lattice_deform_performance, performance_no_dvert_1000) { const int32_t num_items = 1000; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); @@ -101,7 +101,7 @@ TEST(lattice_deform_performance, performance_no_dvert_1000) TEST(lattice_deform_performance, performance_no_dvert_10000) { const int32_t num_items = 10000; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); @@ -110,7 +110,7 @@ TEST(lattice_deform_performance, performance_no_dvert_10000) TEST(lattice_deform_performance, performance_no_dvert_100000) { const int32_t num_items = 100000; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); @@ -119,7 +119,7 @@ TEST(lattice_deform_performance, performance_no_dvert_100000) TEST(lattice_deform_performance, performance_no_dvert_1000000) { const int32_t num_items = 1000000; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); @@ -128,7 +128,7 @@ TEST(lattice_deform_performance, performance_no_dvert_1000000) TEST(lattice_deform_performance, performance_no_dvert_10000000) { const int32_t num_items = 10000000; - LatticeDeformTestContext ctx = {{{0}}}; + LatticeDeformTestContext ctx = {{{nullptr}}}; RandomNumberGenerator rng; test_lattice_deform_init(&ctx, &rng, num_items); test_lattice_deform(&ctx, num_items); diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 6efc9d0753e..784cd5b2edf 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -18,6 +18,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <string.h> #include "BLI_listbase.h" @@ -56,6 +59,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* Set of flags which are dependent on a collection settings. */ static const short g_base_collection_flags = (BASE_VISIBLE_DEPSGRAPH | BASE_VISIBLE_VIEWLAYER | BASE_SELECTABLE | BASE_ENABLED_VIEWPORT | @@ -1445,12 +1450,9 @@ static LayerCollection *find_layer_collection_by_scene_collection(LayerCollectio LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const Collection *collection) { - for (LayerCollection *layer_collection = view_layer->layer_collections.first; - layer_collection != NULL; - layer_collection = layer_collection->next) { + LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) { LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, collection); - if (found != NULL) { return found; } @@ -1830,3 +1832,117 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph, BLI_assert(view_layer != NULL); layer_eval_view_layer(depsgraph, scene, view_layer); } + +static void write_layer_collections(BlendWriter *writer, ListBase *lb) +{ + LISTBASE_FOREACH (LayerCollection *, lc, lb) { + BLO_write_struct(writer, LayerCollection, lc); + + write_layer_collections(writer, &lc->layer_collections); + } +} + +void BKE_view_layer_blend_write(BlendWriter *writer, ViewLayer *view_layer) +{ + BLO_write_struct(writer, ViewLayer, view_layer); + BLO_write_struct_list(writer, Base, &view_layer->object_bases); + + if (view_layer->id_properties) { + IDP_BlendWrite(writer, view_layer->id_properties); + } + + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { + BLO_write_struct(writer, FreestyleModuleConfig, fmc); + } + + LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { + BLO_write_struct(writer, FreestyleLineSet, fls); + } + write_layer_collections(writer, &view_layer->layer_collections); +} + +static void direct_link_layer_collections(BlendDataReader *reader, ListBase *lb, bool master) +{ + BLO_read_list(reader, lb); + LISTBASE_FOREACH (LayerCollection *, lc, lb) { +#ifdef USE_COLLECTION_COMPAT_28 + BLO_read_data_address(reader, &lc->scene_collection); +#endif + + /* Master collection is not a real data-lock. */ + if (master) { + BLO_read_data_address(reader, &lc->collection); + } + + direct_link_layer_collections(reader, &lc->layer_collections, false); + } +} + +void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_layer) +{ + view_layer->stats = NULL; + BLO_read_list(reader, &view_layer->object_bases); + BLO_read_data_address(reader, &view_layer->basact); + + direct_link_layer_collections(reader, &view_layer->layer_collections, true); + BLO_read_data_address(reader, &view_layer->active_collection); + + BLO_read_data_address(reader, &view_layer->id_properties); + IDP_BlendDataRead(reader, &view_layer->id_properties); + + BLO_read_list(reader, &(view_layer->freestyle_config.modules)); + BLO_read_list(reader, &(view_layer->freestyle_config.linesets)); + + BLI_listbase_clear(&view_layer->drawdata); + view_layer->object_bases_array = NULL; + view_layer->object_bases_hash = NULL; +} + +static void lib_link_layer_collection(BlendLibReader *reader, + Library *lib, + LayerCollection *layer_collection, + bool master) +{ + /* Master collection is not a real data-lock. */ + if (!master) { + BLO_read_id_address(reader, lib, &layer_collection->collection); + } + + LISTBASE_FOREACH ( + LayerCollection *, layer_collection_nested, &layer_collection->layer_collections) { + lib_link_layer_collection(reader, lib, layer_collection_nested, false); + } +} + +void BKE_view_layer_blend_read_lib(BlendLibReader *reader, Library *lib, ViewLayer *view_layer) +{ + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) { + BLO_read_id_address(reader, lib, &fmc->script); + } + + LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) { + BLO_read_id_address(reader, lib, &fls->linestyle); + BLO_read_id_address(reader, lib, &fls->group); + } + + LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) { + /* we only bump the use count for the collection objects */ + BLO_read_id_address(reader, lib, &base->object); + + if (base->object == NULL) { + /* Free in case linked object got lost. */ + BLI_freelinkN(&view_layer->object_bases, base); + if (view_layer->basact == base) { + view_layer->basact = NULL; + } + } + } + + LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) { + lib_link_layer_collection(reader, lib, layer_collection, true); + } + + BLO_read_id_address(reader, lib, &view_layer->mat_override); + + IDP_BlendReadLib(reader, view_layer->id_properties); +} diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index ae6ee71da82..cf9fff811ce 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -101,6 +101,15 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = { .copy_data = NULL, .free_data = NULL, .make_local = NULL, + .foreach_id = NULL, + .foreach_cache = NULL, + + .blend_write = NULL, + .blend_read_data = NULL, + .blend_read_lib = NULL, + .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /* GS reads the memory pointed at in a specific ordering. @@ -1322,7 +1331,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) BLI_remlink(lb, id); /* Check if we can actually insert id before or after id_sorting_hint, if given. */ - if (id_sorting_hint != NULL && id_sorting_hint != id) { + if (!ELEM(id_sorting_hint, NULL, id)) { BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0); ID *id_sorting_hint_next = id_sorting_hint->next; @@ -1560,7 +1569,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_ char base_name_test[MAX_ID_NAME - 2]; int number_test; if ((id != id_test) && !ID_IS_LINKED(id_test) && (name[0] == id_test->name[2]) && - (id_test->name[base_name_len + 2] == '.' || id_test->name[base_name_len + 2] == '\0') && + (ELEM(id_test->name[base_name_len + 2], '.', '\0')) && STREQLEN(name, id_test->name + 2, base_name_len) && (BLI_split_name_num(base_name_test, &number_test, id_test->name + 2, '.') == base_name_len)) { diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index f19ab96588e..aa5e28b35bf 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1359,7 +1359,7 @@ bool BKE_lib_override_library_operations_create(Main *bmain, ID *local) } if (GS(local->name) == ID_OB) { - /* Our beloved pose's bone cross-data pointers.. Usually, depsgraph evaluation would + /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would * ensure this is valid, but in some situations (like hidden collections etc.) this won't * be the case, so we need to take care of this ourselves. */ Object *ob_local = (Object *)local; @@ -1427,9 +1427,9 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for } /* Usual pose bones issue, need to be done outside of the threaded process or we may run into - * concurency issues here. + * concurrency issues here. * Note that calling #BKE_pose_ensure again in thread in - * #BKE_lib_override_library_operations_create is not a problem then.. */ + * #BKE_lib_override_library_operations_create is not a problem then. */ LISTBASE_FOREACH (Object *, ob, &bmain->objects) { if (ob->type == OB_ARMATURE) { BLI_assert(ob->data != NULL); @@ -1442,6 +1442,15 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for FOREACH_MAIN_ID_BEGIN (bmain, id) { if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && (force_auto || (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) { + /* Usual issue with pose, it's quiet rare but sometimes they may not be up to date when this + * function is called. */ + if (GS(id->name) == ID_OB) { + Object *ob = (Object *)id; + if (ob->type == OB_ARMATURE) { + BLI_assert(ob->data != NULL); + BKE_pose_ensure(bmain, ob, ob->data, true); + } + } /* Only check overrides if we do have the real reference data available, and not some empty * 'placeholder' for missing data (broken links). */ if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 949e10d4721..6a560d51362 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -82,6 +82,8 @@ IDTypeInfo IDType_ID_LI = { .blend_read_data = NULL, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath) diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 4780f0cf208..a47a0c043ff 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -207,6 +207,8 @@ IDTypeInfo IDType_ID_LA = { .blend_read_data = light_blend_read_data, .blend_read_lib = light_blend_read_lib, .blend_read_expand = light_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; Light *BKE_light_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c index 31653a9a0ac..0553c070fdf 100644 --- a/source/blender/blenkernel/intern/lightprobe.c +++ b/source/blender/blenkernel/intern/lightprobe.c @@ -105,6 +105,8 @@ IDTypeInfo IDType_ID_LP = { .blend_read_data = lightprobe_blend_read_data, .blend_read_lib = lightprobe_blend_read_lib, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type) diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 733a2bcd1e1..69e6535a59f 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -765,6 +765,8 @@ IDTypeInfo IDType_ID_LS = { .blend_read_data = linestyle_blend_read_data, .blend_read_lib = linestyle_blend_read_lib, .blend_read_expand = linestyle_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; static const char *modifier_name[LS_MODIFIER_NUM] = { diff --git a/source/blender/blenkernel/intern/main_idmap.c b/source/blender/blenkernel/intern/main_idmap.c index 9a6ead7eb2b..21f5e9c6fb2 100644 --- a/source/blender/blenkernel/intern/main_idmap.c +++ b/source/blender/blenkernel/intern/main_idmap.c @@ -36,6 +36,7 @@ * Utility functions for faster ID lookups. */ +/* -------------------------------------------------------------------- */ /** \name BKE_main_idmap API * * Cache ID (name, library lookups). diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 1f9f155ee55..04fec1e57c4 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -268,6 +268,8 @@ IDTypeInfo IDType_ID_MSK = { .blend_read_data = mask_blend_read_data, .blend_read_lib = mask_blend_read_lib, .blend_read_expand = mask_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; static struct { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 4a85fab4e18..e892a3f4d53 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -272,6 +272,8 @@ IDTypeInfo IDType_ID_MA = { .blend_read_data = material_blend_read_data, .blend_read_lib = material_blend_read_lib, .blend_read_expand = material_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; void BKE_gpencil_material_attr_init(Material *ma) diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index d2bacb7d3bc..65ec91c57cf 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -202,6 +202,8 @@ IDTypeInfo IDType_ID_MB = { .blend_read_data = metaball_blend_read_data, .blend_read_lib = metaball_blend_read_lib, .blend_read_expand = metaball_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* Functions */ diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 7273d2a920d..cb01927d992 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -807,22 +807,22 @@ static void makecubetable(void) INTLIST *edges; for (edges = polys->list; edges; edges = edges->next) { - if (edges->i == LB || edges->i == LT || edges->i == LN || edges->i == LF) { + if (ELEM(edges->i, LB, LT, LN, LF)) { faces[i] |= 1 << L; } - if (edges->i == RB || edges->i == RT || edges->i == RN || edges->i == RF) { + if (ELEM(edges->i, RB, RT, RN, RF)) { faces[i] |= 1 << R; } - if (edges->i == LB || edges->i == RB || edges->i == BN || edges->i == BF) { + if (ELEM(edges->i, LB, RB, BN, BF)) { faces[i] |= 1 << B; } - if (edges->i == LT || edges->i == RT || edges->i == TN || edges->i == TF) { + if (ELEM(edges->i, LT, RT, TN, TF)) { faces[i] |= 1 << T; } - if (edges->i == LN || edges->i == RN || edges->i == BN || edges->i == TN) { + if (ELEM(edges->i, LN, RN, BN, TN)) { faces[i] |= 1 << N; } - if (edges->i == LF || edges->i == RF || edges->i == BF || edges->i == TF) { + if (ELEM(edges->i, LF, RF, BF, TF)) { faces[i] |= 1 << F; } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index ba47b8fc4af..9ccdf5189d1 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -275,50 +275,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) mesh->totselect = 0; } - /* Multires data */ - BLO_read_data_address(reader, &mesh->mr); - if (mesh->mr) { - BLO_read_list(reader, &mesh->mr->levels); - MultiresLevel *lvl = mesh->mr->levels.first; - - CustomData_blend_read(reader, &mesh->mr->vdata, lvl->totvert); - BKE_defvert_blend_read( - reader, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT)); - CustomData_blend_read(reader, &mesh->mr->fdata, lvl->totface); - - BLO_read_data_address(reader, &mesh->mr->edge_flags); - BLO_read_data_address(reader, &mesh->mr->edge_creases); - - BLO_read_data_address(reader, &mesh->mr->verts); - - /* If mesh has the same number of vertices as the - * highest multires level, load the current mesh verts - * into multires and discard the old data. Needed - * because some saved files either do not have a verts - * array, or the verts array contains out-of-date - * data. */ - if (mesh->totvert == ((MultiresLevel *)mesh->mr->levels.last)->totvert) { - if (mesh->mr->verts) { - MEM_freeN(mesh->mr->verts); - } - mesh->mr->verts = MEM_dupallocN(mesh->mvert); - } - - for (; lvl; lvl = lvl->next) { - BLO_read_data_address(reader, &lvl->verts); - BLO_read_data_address(reader, &lvl->faces); - BLO_read_data_address(reader, &lvl->edges); - BLO_read_data_address(reader, &lvl->colfaces); - } - } - - /* if multires is present but has no valid vertex data, - * there's no way to recover it; silently remove multires */ - if (mesh->mr && !mesh->mr->verts) { - multires_free(mesh->mr); - mesh->mr = NULL; - } - if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) { TFace *tf = mesh->tface; for (int i = 0; i < mesh->totface; i++, tf++) { @@ -377,6 +333,8 @@ IDTypeInfo IDType_ID_ME = { .blend_read_data = mesh_blend_read_data, .blend_read_lib = mesh_blend_read_lib, .blend_read_expand = mesh_read_expand, + + .blend_read_undo_preserve = NULL, }; enum { @@ -1540,8 +1498,11 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) { + MVert *mvert = CustomData_duplicate_referenced_layer(&me->vdata, CD_MVERT, me->totvert); + /* If the referenced layer has been re-allocated need to update pointers stored in the mesh. */ + BKE_mesh_update_customdata_pointers(me, false); + int i = me->totvert; - MVert *mvert; for (mvert = me->mvert; i--; mvert++) { add_v3_v3(mvert->co, offset); } diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index ae301aca25a..8272bd07411 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -949,7 +949,7 @@ void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(sce BKE_object_free_derived_caches(ob); } -void BKE_mesh_from_pointcloud(PointCloud *pointcloud, Mesh *me) +void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me) { BLI_assert(pointcloud != NULL); diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c index 868694931cb..e118c1b6f6e 100644 --- a/source/blender/blenkernel/intern/mesh_merge.c +++ b/source/blender/blenkernel/intern/mesh_merge.c @@ -61,7 +61,7 @@ static int cddm_poly_compare(MLoop *mloop_array, MLoop *mloop_source, *mloop_target; - BLI_assert(direct_reverse == 1 || direct_reverse == -1); + BLI_assert(ELEM(direct_reverse, 1, -1)); i_loop_source = 0; mloop_source = mloop_array + mpoly_source->loopstart; diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 1c48cf6f3cb..f3b29171762 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -327,6 +327,7 @@ void BKE_mesh_remap_find_best_match_from_mesh(const MVert *verts_dst, /** \} */ +/* -------------------------------------------------------------------- */ /** \name Mesh to mesh mapping * \{ */ diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 150f7f19edc..f35f4ae3501 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -267,6 +267,7 @@ void BKE_mesh_batch_cache_free(Mesh *me) /** \} */ +/* -------------------------------------------------------------------- */ /** \name Mesh runtime debug helpers. * \{ */ /* evaluated mesh info printing function, diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 6fea2cc8bf5..b3c53df2d5f 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -52,6 +52,7 @@ static CLG_LogRef LOG = {"bke.mesh"}; +/* -------------------------------------------------------------------- */ /** \name Internal functions * \{ */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 0aa85f0ad50..3c8b685a0e0 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -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,10 +37,15 @@ #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" #include "BLI_linklist.h" #include "BLI_listbase.h" @@ -53,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" @@ -63,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" @@ -73,6 +84,8 @@ #include "MOD_modifiertypes.h" +#include "BLO_read_write.h" + #include "CLG_log.h" static CLG_LogRef LOG = {"bke.modifier"}; @@ -130,6 +143,11 @@ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname) strcat(r_idname, mti->name); } +void BKE_modifier_panel_expand(ModifierData *md) +{ + md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; +} + /***/ ModifierData *BKE_modifier_new(int type) @@ -389,7 +407,7 @@ bool BKE_modifier_is_non_geometrical(ModifierData *md) return (mti->type == eModifierTypeType_NonGeometrical); } -void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) +void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_format, ...) { char buffer[512]; va_list ap; @@ -406,7 +424,16 @@ void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) md->error = BLI_strdup(buffer); - CLOG_STR_ERROR(&LOG, md->error); +#ifndef NDEBUG + if ((md->mode & eModifierMode_Virtual) == 0) { + /* Ensure correct object is passed in. */ + const Object *ob_orig = (Object *)DEG_get_original_id((ID *)&ob->id); + const ModifierData *md_orig = md->orig_modifier_data ? md->orig_modifier_data : md; + BLI_assert(BLI_findindex(&ob_orig->modifiers, md_orig) != -1); + } +#endif + + CLOG_ERROR(&LOG, "Object: \"%s\", Modifier: \"%s\", %s", ob->id.name + 2, md->name, md->error); } /* used for buttons, to find out if the 'draw deformed in editmode' option is @@ -1101,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; + } + } +} diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 40b12d8a777..564496744df 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -359,6 +359,8 @@ IDTypeInfo IDType_ID_MC = { .blend_read_data = movieclip_blend_read_data, .blend_read_lib = movieclip_blend_read_lib, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /*********************** movieclip buffer loaders *************************/ @@ -519,7 +521,7 @@ static void movieclip_convert_multilayer_add_pass(void *UNUSED(layer), MEM_freeN(rect); return; } - if (STREQ(pass_name, RE_PASSNAME_COMBINED) || STREQ(chan_id, "RGBA") || STREQ(chan_id, "RGB")) { + if (STREQ(pass_name, RE_PASSNAME_COMBINED) || STR_ELEM(chan_id, "RGBA", "RGB")) { ctx->combined_pass = rect; ctx->num_combined_channels = num_channels; } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 6e1168d8a16..441da8b134a 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -63,7 +63,6 @@ #include <string.h> /* MULTIRES MODIFIER */ -static const int multires_max_levels = 13; static const int multires_grid_tot[] = { 0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; static const int multires_side_tot[] = { @@ -76,7 +75,6 @@ typedef enum { ADD_DISPLACEMENTS, } DispOp; -static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert); static void multiresModifier_disp_run( DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl); @@ -241,40 +239,6 @@ static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level) md->hidden = subd; } -static MDisps *multires_mdisps_init_hidden(Mesh *me, int level) -{ - MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); - int gridsize = BKE_ccg_gridsize(level); - int gridarea = square_i(gridsize); - int i, j; - - for (i = 0; i < me->totpoly; i++) { - bool hide = false; - - for (j = 0; j < me->mpoly[i].totloop; j++) { - if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) { - hide = true; - break; - } - } - - if (!hide) { - continue; - } - - for (j = 0; j < me->mpoly[i].totloop; j++) { - MDisps *md = &mdisps[me->mpoly[i].loopstart + j]; - - BLI_assert(!md->hidden); - - md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize"); - BLI_bitmap_set_all(md->hidden, true, gridarea); - } - } - - return mdisps; -} - Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd) @@ -429,12 +393,6 @@ void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl); } -static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags flags) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - ccgdm->multires.modified_flags |= flags; -} - static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, MultiresModifiedFlags flags) { if (flags & MULTIRES_COORDS_MODIFIED) { @@ -789,7 +747,6 @@ static DerivedMesh *multires_dm_create_local(Scene *scene, DerivedMesh *dm, int lvl, int totlvl, - int simple, bool alloc_paint_mask, int flags) { @@ -799,7 +756,6 @@ static DerivedMesh *multires_dm_create_local(Scene *scene, mmd.sculptlvl = lvl; mmd.renderlvl = lvl; mmd.totlvl = totlvl; - mmd.simple = simple; flags |= MULTIRES_USE_LOCAL_MMD; if (alloc_paint_mask) { @@ -850,110 +806,6 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene, return subsurf_make_derived_from_derived(dm, &smd, scene, NULL, flags); } -static void multires_subdivide_legacy( - MultiresModifierData *mmd, Scene *scene, Object *ob, int totlvl, int updateblock, int simple) -{ - Mesh *me = ob->data; - MDisps *mdisps; - const int lvl = mmd->totlvl; - - if ((totlvl > multires_max_levels) || (me->totpoly == 0)) { - return; - } - - BLI_assert(totlvl > lvl); - - multires_force_sculpt_rebuild(ob); - - mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); - if (!mdisps) { - mdisps = multires_mdisps_init_hidden(me, totlvl); - } - - if (mdisps->disps && !updateblock && lvl != 0) { - /* upsample */ - DerivedMesh *lowdm, *cddm, *highdm; - CCGElem **highGridData, **lowGridData, **subGridData; - CCGKey highGridKey, lowGridKey; - CCGSubSurf *ss; - int i, numGrids, highGridSize; - const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); - - /* create subsurf DM from original mesh at high level */ - cddm = CDDM_from_mesh(me); - DM_set_only_copy(cddm, &CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(NULL, - ob, - cddm, - totlvl, - simple, - 0, - mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE, - has_mask, - false, - SUBSURF_IGNORE_SIMPLIFY); - ss = ((CCGDerivedMesh *)highdm)->ss; - - /* create multires DM from original mesh at low level */ - lowdm = multires_dm_create_local( - scene, ob, cddm, lvl, lvl, simple, has_mask, MULTIRES_IGNORE_SIMPLIFY); - BLI_assert(lowdm != cddm); - cddm->release(cddm); - - /* copy subsurf grids and replace them with low displaced grids */ - numGrids = highdm->getNumGrids(highdm); - highGridSize = highdm->getGridSize(highdm); - highGridData = highdm->getGridData(highdm); - highdm->getGridKey(highdm, &highGridKey); - lowGridData = lowdm->getGridData(lowdm); - lowdm->getGridKey(lowdm, &lowGridKey); - - subGridData = MEM_calloc_arrayN(numGrids, sizeof(float *), "subGridData*"); - - for (i = 0; i < numGrids; i++) { - /* backup subsurf grids */ - subGridData[i] = MEM_calloc_arrayN( - highGridKey.elem_size, highGridSize * highGridSize, "subGridData"); - memcpy(subGridData[i], highGridData[i], highGridKey.elem_size * highGridSize * highGridSize); - - /* overwrite with current displaced grids */ - multires_copy_dm_grid(highGridData[i], lowGridData[i], &highGridKey, &lowGridKey); - } - - /* low lower level dm no longer needed at this point */ - lowdm->release(lowdm); - - /* subsurf higher levels again with displaced data */ - ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0); - ccgSubSurf_updateLevels(ss, lvl, NULL, 0); - - /* reallocate displacements */ - multires_reallocate_mdisps(me->totloop, mdisps, totlvl); - - /* compute displacements */ - multiresModifier_disp_run(highdm, me, NULL, CALC_DISPLACEMENTS, subGridData, totlvl); - - /* free */ - highdm->release(highdm); - for (i = 0; i < numGrids; i++) { - MEM_freeN(subGridData[i]); - } - MEM_freeN(subGridData); - } - else { - /* only reallocate, nothing to upsample */ - multires_reallocate_mdisps(me->totloop, mdisps, totlvl); - } - - multires_set_tot_level(ob, mmd, totlvl); -} - -void multiresModifier_subdivide_legacy( - MultiresModifierData *mmd, Scene *scene, Object *ob, int updateblock, int simple) -{ - multires_subdivide_legacy(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple); -} - static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3]) { if (axis == 0) { @@ -1227,7 +1079,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene) ob, cddm, totlvl, - mmd->simple, + false, 0, mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE, has_mask, @@ -1237,7 +1089,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene) /* create multires DM from original mesh and displacements */ lowdm = multires_dm_create_local( - scene, ob, cddm, lvl, totlvl, mmd->simple, has_mask, MULTIRES_IGNORE_SIMPLIFY); + scene, ob, cddm, lvl, totlvl, has_mask, MULTIRES_IGNORE_SIMPLIFY); cddm->release(cddm); /* gather grid data */ @@ -1302,7 +1154,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene) ob, cddm, mmd->totlvl, - mmd->simple, + false, 0, mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE, has_mask, @@ -1400,7 +1252,7 @@ DerivedMesh *multires_make_derived_from_derived( ob, dm, lvl, - mmd->simple, + false, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE, flags & MULTIRES_ALLOC_PAINT_MASK, @@ -1449,9 +1301,6 @@ DerivedMesh *multires_make_derived_from_derived( return result; } -/**** Old Multires code **** - ***************************/ - /* Adapted from sculptmode.c */ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v) { @@ -1506,723 +1355,6 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, add_v3_v3v3(out, d2[0], d2[1]); } -static void old_mdisps_rotate( - int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v) -{ - float offset = oldside * 0.5f - 0.5f; - - if (S == 1) { - *u = offset + x; - *v = offset - y; - } - if (S == 2) { - *u = offset + y; - *v = offset + x; - } - if (S == 3) { - *u = offset - x; - *v = offset + y; - } - if (S == 0) { - *u = offset - y; - *v = offset - x; - } -} - -static void old_mdisps_convert(MFace *mface, MDisps *mdisp) -{ - int newlvl = log(sqrt(mdisp->totdisp) - 1) / M_LN2; - int oldlvl = newlvl + 1; - int oldside = multires_side_tot[oldlvl]; - int newside = multires_side_tot[newlvl]; - int nvert = (mface->v4) ? 4 : 3; - int newtotdisp = multires_grid_tot[newlvl] * nvert; - int x, y, S; - float(*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */ - - disps = MEM_calloc_arrayN(newtotdisp, sizeof(float[3]), "multires disps"); - - out = disps; - for (S = 0; S < nvert; S++) { - for (y = 0; y < newside; y++) { - for (x = 0; x < newside; x++, out++) { - old_mdisps_rotate(S, newside, oldside, x, y, &u, &v); - old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v); - - if (S == 1) { - (*out)[1] = -(*out)[1]; - } - else if (S == 2) { - SWAP(float, (*out)[0], (*out)[1]); - } - else if (S == 3) { - (*out)[0] = -(*out)[0]; - } - else if (S == 0) { - SWAP(float, (*out)[0], (*out)[1]); - (*out)[0] = -(*out)[0]; - (*out)[1] = -(*out)[1]; - } - } - } - } - - MEM_freeN(mdisp->disps); - - mdisp->totdisp = newtotdisp; - mdisp->level = newlvl; - mdisp->disps = disps; -} - -void multires_load_old_250(Mesh *me) -{ - MDisps *mdisps, *mdisps2; - MFace *mf; - int i, j, k; - - mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); - - if (mdisps) { - for (i = 0; i < me->totface; i++) { - if (mdisps[i].totdisp) { - old_mdisps_convert(&me->mface[i], &mdisps[i]); - } - } - - CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); - mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS); - - k = 0; - mf = me->mface; - for (i = 0; i < me->totface; i++, mf++) { - int nvert = mf->v4 ? 4 : 3; - int totdisp = mdisps[i].totdisp / nvert; - - for (j = 0; j < nvert; j++, k++) { - mdisps2[k].disps = MEM_calloc_arrayN( - totdisp, sizeof(float[3]), "multires disp in conversion"); - mdisps2[k].totdisp = totdisp; - mdisps2[k].level = mdisps[i].level; - memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp * j, totdisp); - } - } - } -} - -/* Does not actually free lvl itself */ -static void multires_free_level(MultiresLevel *lvl) -{ - if (lvl) { - if (lvl->faces) { - MEM_freeN(lvl->faces); - } - if (lvl->edges) { - MEM_freeN(lvl->edges); - } - if (lvl->colfaces) { - MEM_freeN(lvl->colfaces); - } - } -} - -void multires_free(Multires *mr) -{ - if (mr) { - MultiresLevel *lvl = mr->levels.first; - - /* Free the first-level data */ - if (lvl) { - CustomData_free(&mr->vdata, lvl->totvert); - CustomData_free(&mr->fdata, lvl->totface); - if (mr->edge_flags) { - MEM_freeN(mr->edge_flags); - } - if (mr->edge_creases) { - MEM_freeN(mr->edge_creases); - } - } - - while (lvl) { - multires_free_level(lvl); - lvl = lvl->next; - } - - /* mr->verts may be NULL when loading old files, - * see direct_link_mesh() in readfile.c, and T43560. */ - MEM_SAFE_FREE(mr->verts); - - BLI_freelistN(&mr->levels); - - MEM_freeN(mr); - } -} - -typedef struct IndexNode { - struct IndexNode *next, *prev; - int index; -} IndexNode; - -static void create_old_vert_face_map(ListBase **map, - IndexNode **mem, - const MultiresFace *mface, - const int totvert, - const int totface) -{ - int i, j; - IndexNode *node = NULL; - - (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert face map"); - (*mem) = MEM_calloc_arrayN(totface, sizeof(IndexNode[4]), "vert face map mem"); - node = *mem; - - /* Find the users */ - for (i = 0; i < totface; i++) { - for (j = 0; j < (mface[i].v[3] ? 4 : 3); j++, node++) { - node->index = i; - BLI_addtail(&(*map)[mface[i].v[j]], node); - } - } -} - -static void create_old_vert_edge_map(ListBase **map, - IndexNode **mem, - const MultiresEdge *medge, - const int totvert, - const int totedge) -{ - int i, j; - IndexNode *node = NULL; - - (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert edge map"); - (*mem) = MEM_calloc_arrayN(totedge, sizeof(IndexNode[2]), "vert edge map mem"); - node = *mem; - - /* Find the users */ - for (i = 0; i < totedge; i++) { - for (j = 0; j < 2; j++, node++) { - node->index = i; - BLI_addtail(&(*map)[medge[i].v[j]], node); - } - } -} - -static MultiresFace *find_old_face( - ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) -{ - IndexNode *n1; - int v[4], i, j; - - v[0] = v1; - v[1] = v2; - v[2] = v3; - v[3] = v4; - - for (n1 = map[v1].first; n1; n1 = n1->next) { - int fnd[4] = {0, 0, 0, 0}; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - if (v[i] == faces[n1->index].v[j]) { - fnd[i] = 1; - } - } - } - - if (fnd[0] && fnd[1] && fnd[2] && fnd[3]) { - return &faces[n1->index]; - } - } - - return NULL; -} - -static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) -{ - IndexNode *n1, *n2; - - for (n1 = map[v1].first; n1; n1 = n1->next) { - for (n2 = map[v2].first; n2; n2 = n2->next) { - if (n1->index == n2->index) { - return &edges[n1->index]; - } - } - } - - return NULL; -} - -static void multires_load_old_edges( - ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) -{ - int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid; - vvmap[dst + mov] = emid; - - if (lvl->next->next) { - multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2); - multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2); - } -} - -static void multires_load_old_faces(ListBase **fmap, - ListBase **emap, - MultiresLevel *lvl, - int *vvmap, - int dst, - int v1, - int v2, - int v3, - int v4, - int st2, - int st3) -{ - int fmid; - int emid13, emid14, emid23, emid24; - - if (lvl && lvl->next) { - fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; - vvmap[dst] = fmid; - - emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid; - emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid; - emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid; - emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid; - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst + st2 * st3 + st3, - fmid, - v2, - emid23, - emid24, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst - st2 * st3 + st3, - emid14, - emid24, - fmid, - v4, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst + st2 * st3 - st3, - emid13, - emid23, - v3, - fmid, - st2, - st3 / 2); - - multires_load_old_faces(fmap + 1, - emap + 1, - lvl->next, - vvmap, - dst - st2 * st3 - st3, - v1, - fmid, - emid13, - emid14, - st2, - st3 / 2); - - if (lvl->next->next) { - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3); - multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3); - } - } -} - -static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; - CCGElem *vd; - CCGKey key; - int index; - int totvert, totedge, totface; - int gridSize = ccgSubSurf_getGridSize(ss); - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; - - dm->getGridKey(dm, &key); - - totface = ccgSubSurf_getNumFaces(ss); - for (index = 0; index < totface; index++) { - CCGFace *f = ccgdm->faceMap[index].face; - int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - - vd = ccgSubSurf_getFaceCenterData(f); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - i++; - - for (S = 0; S < numVerts; S++) { - for (x = 1; x < gridSize - 1; x++, i++) { - vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - - for (S = 0; S < numVerts; S++) { - for (y = 1; y < gridSize - 1; y++) { - for (x = 1; x < gridSize - 1; x++, i++) { - vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - } - } - - totedge = ccgSubSurf_getNumEdges(ss); - for (index = 0; index < totedge; index++) { - CCGEdge *e = ccgdm->edgeMap[index].edge; - int x; - - for (x = 1; x < edgeSize - 1; x++, i++) { - vd = ccgSubSurf_getEdgeData(ss, e, x); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - } - } - - totvert = ccgSubSurf_getNumVerts(ss); - for (index = 0; index < totvert; index++) { - CCGVert *v = ccgdm->vertMap[index].vert; - - vd = ccgSubSurf_getVertData(ss, v); - copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co); - i++; - } - - ccgSubSurf_updateToFaces(ss, 0, NULL, 0); -} - -/* Loads a multires object stored in the old Multires struct into the new format */ -static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl) -{ - MultiresLevel *lvl, *lvl1; - Multires *mr = me->mr; - MVert *vsrc, *vdst; - unsigned int src, dst; - int st_last = multires_side_tot[totlvl - 1] - 1; - int extedgelen = multires_side_tot[totlvl] - 2; - int *vvmap; // inorder for dst, map to src - int crossedgelen; - int s, x, tottri, totquad; - unsigned int i, j, totvert; - - src = 0; - vsrc = mr->verts; - vdst = dm->getVertArray(dm); - totvert = (unsigned int)dm->getNumVerts(dm); - vvmap = MEM_calloc_arrayN(totvert, sizeof(int), "multires vvmap"); - - if (!vvmap) { - return; - } - - lvl1 = mr->levels.first; - /* Load base verts */ - for (i = 0; i < lvl1->totvert; i++) { - vvmap[totvert - lvl1->totvert + i] = src; - src++; - } - - /* Original edges */ - dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge; - for (i = 0; i < lvl1->totedge; i++) { - int ldst = dst + extedgelen * i; - int lsrc = src; - lvl = lvl1->next; - - for (j = 2; j <= mr->level_count; j++) { - int base = multires_side_tot[totlvl - j + 1] - 2; - int skip = multires_side_tot[totlvl - j + 2] - 1; - int st = multires_side_tot[j - 1] - 1; - - for (x = 0; x < st; x++) { - vvmap[ldst + base + x * skip] = lsrc + st * i + x; - } - - lsrc += lvl->totvert - lvl->prev->totvert; - lvl = lvl->next; - } - } - - /* Center points */ - dst = 0; - for (i = 0; i < lvl1->totface; i++) { - int sides = lvl1->faces[i].v[3] ? 4 : 3; - - vvmap[dst] = src + lvl1->totedge + i; - dst += 1 + sides * (st_last - 1) * st_last; - } - - /* The rest is only for level 3 and up */ - if (lvl1->next && lvl1->next->next) { - ListBase **fmap, **emap; - IndexNode **fmem, **emem; - - /* Face edge cross */ - tottri = totquad = 0; - crossedgelen = multires_side_tot[totlvl - 1] - 2; - dst = 0; - for (i = 0; i < lvl1->totface; i++) { - int sides = lvl1->faces[i].v[3] ? 4 : 3; - - lvl = lvl1->next->next; - dst++; - - for (j = 3; j <= mr->level_count; j++) { - int base = multires_side_tot[totlvl - j + 1] - 2; - int skip = multires_side_tot[totlvl - j + 2] - 1; - int st = pow(2, j - 2); - int st2 = pow(2, j - 3); - int lsrc = lvl->prev->totvert; - - /* Skip exterior edge verts */ - lsrc += lvl1->totedge * st; - - /* Skip earlier face edge crosses */ - lsrc += st2 * (tottri * 3 + totquad * 4); - - for (s = 0; s < sides; s++) { - for (x = 0; x < st2; x++) { - vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc; - lsrc++; - } - } - - lvl = lvl->next; - } - - dst += sides * (st_last - 1) * st_last; - - if (sides == 4) { - totquad++; - } - else { - tottri++; - } - } - - /* calculate vert to edge/face maps for each level (except the last) */ - fmap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires fmap"); - emap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires emap"); - fmem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires fmem"); - emem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires emem"); - lvl = lvl1; - for (i = 0; i < (unsigned int)mr->level_count - 1; i++) { - create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); - create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); - lvl = lvl->next; - } - - /* Interior face verts */ - /* lvl = lvl1->next->next; */ /* UNUSED */ - dst = 0; - for (j = 0; j < lvl1->totface; j++) { - int sides = lvl1->faces[j].v[3] ? 4 : 3; - int ldst = dst + 1 + sides * (st_last - 1); - - for (s = 0; s < sides; s++) { - int st2 = multires_side_tot[totlvl - 1] - 2; - int st3 = multires_side_tot[totlvl - 2] - 2; - int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; - int mid = ldst + st2 * st3 + st3; - int cv = lvl1->faces[j].v[s]; - int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1]; - int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1]; - - multires_load_old_faces(fmap, - emap, - lvl1->next, - vvmap, - mid, - vvmap[dst], - cv, - find_old_edge(emap[0], lvl1->edges, pv, cv)->mid, - find_old_edge(emap[0], lvl1->edges, cv, nv)->mid, - st2, - st4); - - ldst += (st_last - 1) * (st_last - 1); - } - - dst = ldst; - } - - /*lvl = lvl->next;*/ /*UNUSED*/ - - for (i = 0; i < (unsigned int)(mr->level_count - 1); i++) { - MEM_freeN(fmap[i]); - MEM_freeN(fmem[i]); - MEM_freeN(emap[i]); - MEM_freeN(emem[i]); - } - - MEM_freeN(fmap); - MEM_freeN(emap); - MEM_freeN(fmem); - MEM_freeN(emem); - } - - /* Transfer verts */ - for (i = 0; i < totvert; i++) { - copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co); - } - - MEM_freeN(vvmap); - - multires_mvert_to_ss(dm, vdst); -} - -/* Copy the first-level vcol data to the mesh, if it exists */ -/* Warning: higher-level vcol data will be lost */ -static void multires_load_old_vcols(Mesh *me) -{ - MultiresLevel *lvl; - MultiresColFace *colface; - MCol *mcol; - int i, j; - - if (!(lvl = me->mr->levels.first)) { - return; - } - - if (!(colface = lvl->colfaces)) { - return; - } - - /* older multires format never supported multiple vcol layers, - * so we can assume the active vcol layer is the correct one */ - if (!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) { - return; - } - - for (i = 0; i < me->totface; i++) { - for (j = 0; j < 4; j++) { - mcol[i * 4 + j].a = colface[i].col[j].a; - mcol[i * 4 + j].r = colface[i].col[j].r; - mcol[i * 4 + j].g = colface[i].col[j].g; - mcol[i * 4 + j].b = colface[i].col[j].b; - } - } -} - -/* Copy the first-level face-flag data to the mesh */ -static void multires_load_old_face_flags(Mesh *me) -{ - MultiresLevel *lvl; - MultiresFace *faces; - int i; - - if (!(lvl = me->mr->levels.first)) { - return; - } - - if (!(faces = lvl->faces)) { - return; - } - - for (i = 0; i < me->totface; i++) { - me->mface[i].flag = faces[i].flag; - } -} - -void multires_load_old(Object *ob, Mesh *me) -{ - MultiresLevel *lvl; - ModifierData *md; - MultiresModifierData *mmd; - DerivedMesh *dm, *orig; - CustomDataLayer *l; - int i; - - /* Load original level into the mesh */ - lvl = me->mr->levels.first; - CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert); - CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge); - CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface); - me->totvert = lvl->totvert; - me->totedge = lvl->totedge; - me->totface = lvl->totface; - me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); - me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert); - for (i = 0; i < me->totedge; i++) { - me->medge[i].v1 = lvl->edges[i].v[0]; - me->medge[i].v2 = lvl->edges[i].v[1]; - } - for (i = 0; i < me->totface; i++) { - me->mface[i].v1 = lvl->faces[i].v[0]; - me->mface[i].v2 = lvl->faces[i].v[1]; - me->mface[i].v3 = lvl->faces[i].v[2]; - me->mface[i].v4 = lvl->faces[i].v[3]; - me->mface[i].mat_nr = lvl->faces[i].mat_nr; - } - - /* Copy the first-level data to the mesh */ - /* XXX We must do this before converting tessfaces to polys/lopps! */ - for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; i++, l++) { - CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert); - } - for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; i++, l++) { - CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface); - } - CustomData_reset(&me->mr->vdata); - CustomData_reset(&me->mr->fdata); - - multires_load_old_vcols(me); - multires_load_old_face_flags(me); - - /* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not - * tessfaces! */ - BKE_mesh_convert_mfaces_to_mpolys(me); - - /* Add a multires modifier to the object */ - md = ob->modifiers.first; - while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { - md = md->next; - } - mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires); - BLI_insertlinkbefore(&ob->modifiers, md, mmd); - - for (i = 0; i < me->mr->level_count - 1; i++) { - multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0); - } - - mmd->lvl = mmd->totlvl; - orig = CDDM_from_mesh(me); - /* XXX We *must* alloc paint mask here, else we have some kind of mismatch in - * multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the - * reference subsurfed dm with this option, before calling multiresModifier_disp_run(), - * which implicitly expects both subsurfs from its first dm and oldGridData parameters to - * be of the same "format"! */ - dm = multires_make_derived_from_derived(orig, mmd, NULL, ob, 0); - - multires_load_old_dm(dm, me, mmd->totlvl + 1); - - multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED); - dm->release(dm); - orig->release(orig); - - /* Remove the old multires */ - multires_free(me->mr); - me->mr = NULL; -} - /* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them * such that 'ob_dst' has the same total number of levels as 'ob_src'. */ void multiresModifier_sync_levels_ex(Object *ob_dst, @@ -2234,14 +1366,8 @@ void multiresModifier_sync_levels_ex(Object *ob_dst, } if (mmd_src->totlvl > mmd_dst->totlvl) { - if (mmd_dst->simple) { - multiresModifier_subdivide_to_level( - ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_SIMPLE); - } - else { - multiresModifier_subdivide_to_level( - ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK); - } + multiresModifier_subdivide_to_level( + ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK); } else { multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl); diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 5bcf8f62f86..04ad78ec0de 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -225,7 +225,7 @@ void multiresModifier_subdivide_to_level(struct Object *object, multires_flush_sculpt_updates(object); - if (!multires_reshape_context_create_from_subdivide(&reshape_context, object, mmd, top_level)) { + if (!multires_reshape_context_create_from_modifier(&reshape_context, object, mmd, top_level)) { return; } diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index d6c1d79dfd7..36ecf1a6395 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -167,10 +167,16 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co struct Mesh *base_mesh, int top_level); -bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *reshape_context, - struct Object *object, - struct MultiresModifierData *mmd, - int top_level); +bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *reshape_context, + struct Object *object, + struct MultiresModifierData *mmd, + int top_level); + +bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context, + struct Object *object, + struct MultiresModifierData *mmd, + struct Subdiv *subdiv, + int top_level); void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context); void multires_reshape_context_free(MultiresReshapeContext *reshape_context); diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.c b/source/blender/blenkernel/intern/multires_reshape_apply_base.c index 6e7e2b90c05..b693b1114ba 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.c +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.c @@ -81,11 +81,6 @@ static float v3_dist_from_plane(const float v[3], const float center[3], const f void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context) { - if (reshape_context->mmd->simple) { - /* Simple subdivisions does not move base mesh verticies, so no refitting is needed. */ - return; - } - Mesh *base_mesh = reshape_context->base_mesh; MeshElemMap *pmap; diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.c b/source/blender/blenkernel/intern/multires_reshape_subdivide.c index 7b7c1efc533..d42a061084f 100644 --- a/source/blender/blenkernel/intern/multires_reshape_subdivide.c +++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.c @@ -96,7 +96,7 @@ void multires_subdivide_create_tangent_displacement_linear_grids(Object *object, /* Convert the new grids to tangent displacement. */ multires_set_tot_level(object, mmd, new_top_level); - if (!multires_reshape_context_create_from_subdivide( + if (!multires_reshape_context_create_from_modifier( &reshape_context, object, mmd, new_top_level)) { return; } diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c index c8179dd8a2d..8fb406e54a5 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.c +++ b/source/blender/blenkernel/intern/multires_reshape_util.c @@ -242,10 +242,26 @@ bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_co return context_verify_or_free(reshape_context); } -bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *reshape_context, - struct Object *object, - struct MultiresModifierData *mmd, - int top_level) +bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *reshape_context, + struct Object *object, + struct MultiresModifierData *mmd, + int top_level) +{ + Subdiv *subdiv = multires_reshape_create_subdiv(NULL, object, mmd); + + const bool result = multires_reshape_context_create_from_subdiv( + reshape_context, object, mmd, subdiv, top_level); + + reshape_context->need_free_subdiv = true; + + return result; +} + +bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context, + struct Object *object, + struct MultiresModifierData *mmd, + struct Subdiv *subdiv, + int top_level) { context_zero(reshape_context); @@ -254,8 +270,8 @@ bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *resh reshape_context->mmd = mmd; reshape_context->base_mesh = base_mesh; - reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd); - reshape_context->need_free_subdiv = true; + reshape_context->subdiv = subdiv; + reshape_context->need_free_subdiv = false; reshape_context->reshape.level = mmd->totlvl; reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level( diff --git a/source/blender/blenkernel/intern/multires_subdiv.c b/source/blender/blenkernel/intern/multires_subdiv.c index 73ef623fbfd..8156814d9f1 100644 --- a/source/blender/blenkernel/intern/multires_subdiv.c +++ b/source/blender/blenkernel/intern/multires_subdiv.c @@ -36,7 +36,7 @@ void BKE_multires_subdiv_settings_init(SubdivSettings *settings, const MultiresModifierData *mmd) { - settings->is_simple = (mmd->simple != 0); + settings->is_simple = false; settings->is_adaptive = true; settings->level = settings->is_simple ? 1 : mmd->quality; settings->use_creases = (mmd->flags & eMultiresModifierFlag_UseCrease); diff --git a/source/blender/blenkernel/intern/multires_versioning.c b/source/blender/blenkernel/intern/multires_versioning.c new file mode 100644 index 00000000000..4c0d7165cd0 --- /dev/null +++ b/source/blender/blenkernel/intern/multires_versioning.c @@ -0,0 +1,106 @@ +/* + * 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. + * + * The Original Code is Copyright (C) 2020 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" + +#include "BKE_subdiv.h" +#include "BKE_subdiv_eval.h" + +#include "multires_reshape.h" +#include "opensubdiv_converter_capi.h" +#include "subdiv_converter.h" + +static float simple_to_catmull_clark_get_edge_sharpness( + const OpenSubdiv_Converter *UNUSED(converter), int UNUSED(manifold_edge_index)) +{ + return 10.0f; +} + +static bool simple_to_catmull_clark_is_infinite_sharp_vertex( + const OpenSubdiv_Converter *UNUSED(converter), int UNUSED(manifold_vertex_index)) +{ + return true; +} + +static Subdiv *subdiv_for_simple_to_catmull_clark(Object *object, MultiresModifierData *mmd) +{ + SubdivSettings subdiv_settings; + BKE_multires_subdiv_settings_init(&subdiv_settings, mmd); + + Mesh *base_mesh = object->data; + + OpenSubdiv_Converter converter; + BKE_subdiv_converter_init_for_mesh(&converter, &subdiv_settings, base_mesh); + converter.getEdgeSharpness = simple_to_catmull_clark_get_edge_sharpness; + converter.isInfiniteSharpVertex = simple_to_catmull_clark_is_infinite_sharp_vertex; + + Subdiv *subdiv = BKE_subdiv_new_from_converter(&subdiv_settings, &converter); + BKE_subdiv_converter_free(&converter); + + if (!BKE_subdiv_eval_begin_from_mesh(subdiv, base_mesh, NULL)) { + BKE_subdiv_free(subdiv); + return NULL; + } + + return subdiv; +} + +void multires_do_versions_simple_to_catmull_clark(Object *object, MultiresModifierData *mmd) +{ + const Mesh *base_mesh = object->data; + if (base_mesh->totloop == 0) { + return; + } + + /* Store the grids displacement in object space against the simple limit surface. */ + { + Subdiv *subdiv = subdiv_for_simple_to_catmull_clark(object, mmd); + MultiresReshapeContext reshape_context; + if (!multires_reshape_context_create_from_subdiv( + &reshape_context, object, mmd, subdiv, mmd->totlvl)) { + BKE_subdiv_free(subdiv); + return; + } + + multires_reshape_store_original_grids(&reshape_context); + multires_reshape_assign_final_coords_from_mdisps(&reshape_context); + multires_reshape_context_free(&reshape_context); + + BKE_subdiv_free(subdiv); + } + + /* Calculate the new tangent displacement against the new Catmull-Clark limit surface. */ + { + MultiresReshapeContext reshape_context; + if (!multires_reshape_context_create_from_modifier( + &reshape_context, object, mmd, mmd->totlvl)) { + return; + } + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_reshape_context_free(&reshape_context); + } +} diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 80a553ff525..e2e61284d2e 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -404,6 +404,8 @@ static void write_node_socket_interface(BlendWriter *writer, bNodeSocket *sock) /* this is only direct data, tree itself should have been written */ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) { + BKE_id_blend_write(writer, &ntree->id); + /* for link_list() speed, we write per list */ if (ntree->adt) { @@ -525,9 +527,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres ntree->execdata = NULL; BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id); - /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot - * be linked, etc., so we write actual id data here only, for 'real' ID trees. */ - BKE_id_blend_write(writer, &ntree->id); ntreeBlendWrite(writer, ntree); } @@ -853,6 +852,8 @@ IDTypeInfo IDType_ID_NT = { .blend_read_data = ntree_blend_read_data, .blend_read_lib = ntree_blend_read_lib, .blend_read_expand = ntree_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) @@ -4662,7 +4663,7 @@ static void registerFunctionNodes(void) register_node_type_fn_random_float(); } -void init_nodesystem(void) +void BKE_node_system_init(void) { nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh"); nodetypes_hash = BLI_ghash_str_new("nodetypes_hash gh"); @@ -4689,7 +4690,7 @@ void init_nodesystem(void) registerFunctionNodes(); } -void free_nodesystem(void) +void BKE_node_system_exit(void) { if (nodetypes_hash) { NODE_TYPES_BEGIN (nt) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 971f79e296f..5b0b1f333f4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <math.h> #include <stdio.h> #include <string.h> @@ -35,6 +38,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_defaults.h" +#include "DNA_effect_types.h" #include "DNA_fluid_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" @@ -47,6 +51,8 @@ #include "DNA_meshdata_types.h" #include "DNA_meta_types.h" #include "DNA_movieclip_types.h" +#include "DNA_nla_types.h" +#include "DNA_object_fluidsim_types.h" #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" #include "DNA_rigidbody_types.h" @@ -123,7 +129,6 @@ #include "BKE_pointcloud.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_softbody.h" #include "BKE_speaker.h" @@ -136,6 +141,10 @@ #include "DRW_engine.h" +#include "BLO_read_write.h" + +#include "SEQ_sequencer.h" + #ifdef WITH_PYTHON # include "BPY_extern.h" #endif @@ -516,6 +525,614 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void write_defgroups(BlendWriter *writer, ListBase *defbase) +{ + LISTBASE_FOREACH (bDeformGroup *, defgroup, defbase) { + BLO_write_struct(writer, bDeformGroup, defgroup); + } +} + +static void write_fmaps(BlendWriter *writer, ListBase *fbase) +{ + LISTBASE_FOREACH (bFaceMap *, fmap, fbase) { + BLO_write_struct(writer, bFaceMap, fmap); + } +} + +static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Object *ob = (Object *)id; + + const bool is_undo = BLO_write_is_undo(writer); + if (ob->id.us > 0 || is_undo) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + BKE_object_runtime_reset(ob); + + if (is_undo) { + /* For undo we stay in object mode during undo presses, so keep edit-mode disabled on save as + * well, can help reducing false detection of changed data-blocks. */ + ob->mode &= ~OB_MODE_EDIT; + } + + /* write LibData */ + BLO_write_id_struct(writer, Object, id_address, &ob->id); + BKE_id_blend_write(writer, &ob->id); + + if (ob->adt) { + BKE_animdata_blend_write(writer, ob->adt); + } + + /* direct data */ + BLO_write_pointer_array(writer, ob->totcol, ob->mat); + BLO_write_raw(writer, sizeof(char) * ob->totcol, ob->matbits); + + bArmature *arm = NULL; + if (ob->type == OB_ARMATURE) { + arm = ob->data; + if (arm && ob->pose && arm->act_bone) { + BLI_strncpy( + ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone)); + } + } + + BKE_pose_blend_write(writer, ob->pose, arm); + write_defgroups(writer, &ob->defbase); + write_fmaps(writer, &ob->fmaps); + BKE_constraint_blend_write(writer, &ob->constraints); + animviz_motionpath_blend_write(writer, ob->mpath); + + BLO_write_struct(writer, PartDeflect, ob->pd); + if (ob->soft) { + /* Set deprecated pointers to prevent crashes of older Blenders */ + ob->soft->pointcache = ob->soft->shared->pointcache; + ob->soft->ptcaches = ob->soft->shared->ptcaches; + BLO_write_struct(writer, SoftBody, ob->soft); + BLO_write_struct(writer, SoftBody_Shared, ob->soft->shared); + BKE_ptcache_blend_write(writer, &(ob->soft->shared->ptcaches)); + BLO_write_struct(writer, EffectorWeights, ob->soft->effector_weights); + } + + if (ob->rigidbody_object) { + /* TODO: if any extra data is added to handle duplis, will need separate function then */ + BLO_write_struct(writer, RigidBodyOb, ob->rigidbody_object); + } + if (ob->rigidbody_constraint) { + BLO_write_struct(writer, RigidBodyCon, ob->rigidbody_constraint); + } + + if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { + BLO_write_struct(writer, ImageUser, ob->iuser); + } + + BKE_particle_system_blend_write(writer, &ob->particlesystem); + BKE_modifier_blend_write(writer, &ob->modifiers); + BKE_gpencil_modifier_blend_write(writer, &ob->greasepencil_modifiers); + BKE_shaderfx_blend_write(writer, &ob->shader_fx); + + BLO_write_struct_list(writer, LinkData, &ob->pc_ids); + + BKE_previewimg_blend_write(writer, ob->preview); + } +} + +/* XXX deprecated - old animation system */ +static void direct_link_nlastrips(BlendDataReader *reader, ListBase *strips) +{ + BLO_read_list(reader, strips); + + LISTBASE_FOREACH (bActionStrip *, strip, strips) { + BLO_read_list(reader, &strip->modifiers); + } +} + +static void object_blend_read_data(BlendDataReader *reader, ID *id) +{ + Object *ob = (Object *)id; + + PartEff *paf; + + /* XXX This should not be needed - but seems like it can happen in some cases, + * so for now play safe. */ + ob->proxy_from = NULL; + + const bool is_undo = BLO_read_data_is_undo(reader); + if (ob->id.tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT)) { + /* Do not allow any non-object mode for linked data. + * See T34776, T42780, T81027 for more information. */ + ob->mode &= ~OB_MODE_ALL_MODE_DATA; + } + else if (is_undo) { + /* For undo we want to stay in object mode during undo presses, so keep some edit modes + * disabled. + * TODO: Check if we should not disable more edit modes here? */ + ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT); + } + + BLO_read_data_address(reader, &ob->adt); + BKE_animdata_blend_read_data(reader, ob->adt); + + BLO_read_data_address(reader, &ob->pose); + BKE_pose_blend_read_data(reader, ob->pose); + + BLO_read_data_address(reader, &ob->mpath); + if (ob->mpath) { + animviz_motionpath_blend_read_data(reader, ob->mpath); + } + + BLO_read_list(reader, &ob->defbase); + BLO_read_list(reader, &ob->fmaps); + /* XXX deprecated - old animation system <<< */ + direct_link_nlastrips(reader, &ob->nlastrips); + BLO_read_list(reader, &ob->constraintChannels); + /* >>> XXX deprecated - old animation system */ + + BLO_read_pointer_array(reader, (void **)&ob->mat); + BLO_read_data_address(reader, &ob->matbits); + + /* do it here, below old data gets converted */ + BKE_modifier_blend_read_data(reader, &ob->modifiers, ob); + BKE_gpencil_modifier_blend_read_data(reader, &ob->greasepencil_modifiers); + BKE_shaderfx_blend_read_data(reader, &ob->shader_fx); + + BLO_read_list(reader, &ob->effect); + paf = ob->effect.first; + while (paf) { + if (paf->type == EFF_PARTICLE) { + paf->keys = NULL; + } + if (paf->type == EFF_WAVE) { + WaveEff *wav = (WaveEff *)paf; + PartEff *next = paf->next; + WaveModifierData *wmd = (WaveModifierData *)BKE_modifier_new(eModifierType_Wave); + + wmd->damp = wav->damp; + wmd->flag = wav->flag; + wmd->height = wav->height; + wmd->lifetime = wav->lifetime; + wmd->narrow = wav->narrow; + wmd->speed = wav->speed; + wmd->startx = wav->startx; + wmd->starty = wav->startx; + wmd->timeoffs = wav->timeoffs; + wmd->width = wav->width; + + BLI_addtail(&ob->modifiers, wmd); + + BLI_remlink(&ob->effect, paf); + MEM_freeN(paf); + + paf = next; + continue; + } + if (paf->type == EFF_BUILD) { + BuildEff *baf = (BuildEff *)paf; + PartEff *next = paf->next; + BuildModifierData *bmd = (BuildModifierData *)BKE_modifier_new(eModifierType_Build); + + bmd->start = baf->sfra; + bmd->length = baf->len; + bmd->randomize = 0; + bmd->seed = 1; + + BLI_addtail(&ob->modifiers, bmd); + + BLI_remlink(&ob->effect, paf); + MEM_freeN(paf); + + paf = next; + continue; + } + paf = paf->next; + } + + BLO_read_data_address(reader, &ob->pd); + BKE_particle_partdeflect_blend_read_data(reader, ob->pd); + BLO_read_data_address(reader, &ob->soft); + if (ob->soft) { + SoftBody *sb = ob->soft; + + sb->bpoint = NULL; /* init pointers so it gets rebuilt nicely */ + sb->bspring = NULL; + sb->scratch = NULL; + /* although not used anymore */ + /* still have to be loaded to be compatible with old files */ + BLO_read_pointer_array(reader, (void **)&sb->keys); + if (sb->keys) { + for (int a = 0; a < sb->totkey; a++) { + BLO_read_data_address(reader, &sb->keys[a]); + } + } + + BLO_read_data_address(reader, &sb->effector_weights); + if (!sb->effector_weights) { + sb->effector_weights = BKE_effector_add_weights(NULL); + } + + BLO_read_data_address(reader, &sb->shared); + if (sb->shared == NULL) { + /* Link deprecated caches if they exist, so we can use them for versioning. + * We should only do this when sb->shared == NULL, because those pointers + * are always set (for compatibility with older Blenders). We mustn't link + * the same pointcache twice. */ + BKE_ptcache_blend_read_data(reader, &sb->ptcaches, &sb->pointcache, false); + } + else { + /* link caches */ + BKE_ptcache_blend_read_data(reader, &sb->shared->ptcaches, &sb->shared->pointcache, false); + } + } + BLO_read_data_address(reader, &ob->fluidsimSettings); /* NT */ + + BLO_read_data_address(reader, &ob->rigidbody_object); + if (ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + /* Allocate runtime-only struct */ + rbo->shared = MEM_callocN(sizeof(*rbo->shared), "RigidBodyObShared"); + } + BLO_read_data_address(reader, &ob->rigidbody_constraint); + if (ob->rigidbody_constraint) { + ob->rigidbody_constraint->physics_constraint = NULL; + } + + BLO_read_list(reader, &ob->particlesystem); + BKE_particle_system_blend_read_data(reader, &ob->particlesystem); + + BKE_constraint_blend_read_data(reader, &ob->constraints); + + BLO_read_list(reader, &ob->hooks); + while (ob->hooks.first) { + ObHook *hook = ob->hooks.first; + HookModifierData *hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook); + + BLO_read_int32_array(reader, hook->totindex, &hook->indexar); + + /* Do conversion here because if we have loaded + * a hook we need to make sure it gets converted + * and freed, regardless of version. + */ + copy_v3_v3(hmd->cent, hook->cent); + hmd->falloff = hook->falloff; + hmd->force = hook->force; + hmd->indexar = hook->indexar; + hmd->object = hook->parent; + memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv)); + hmd->totindex = hook->totindex; + + BLI_addhead(&ob->modifiers, hmd); + BLI_remlink(&ob->hooks, hook); + + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)hmd); + + MEM_freeN(hook); + } + + BLO_read_data_address(reader, &ob->iuser); + if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE && !ob->iuser) { + BKE_object_empty_draw_type_set(ob, ob->empty_drawtype); + } + + BKE_object_runtime_reset(ob); + BLO_read_list(reader, &ob->pc_ids); + + /* in case this value changes in future, clamp else we get undefined behavior */ + CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX); + + if (ob->sculpt) { + ob->sculpt = NULL; + /* Only create data on undo, otherwise rely on editor mode switching. */ + if (BLO_read_data_is_undo(reader) && (ob->mode & OB_MODE_ALL_SCULPT)) { + BKE_object_sculpt_data_create(ob); + } + } + + BLO_read_data_address(reader, &ob->preview); + BKE_previewimg_blend_read(reader, ob->preview); +} + +/* XXX deprecated - old animation system */ +static void lib_link_nlastrips(BlendLibReader *reader, ID *id, ListBase *striplist) +{ + LISTBASE_FOREACH (bActionStrip *, strip, striplist) { + BLO_read_id_address(reader, id->lib, &strip->object); + BLO_read_id_address(reader, id->lib, &strip->act); + BLO_read_id_address(reader, id->lib, &strip->ipo); + LISTBASE_FOREACH (bActionModifier *, amod, &strip->modifiers) { + BLO_read_id_address(reader, id->lib, &amod->ob); + } + } +} + +/* XXX deprecated - old animation system */ +static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBase *chanbase) +{ + LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) { + BLO_read_id_address(reader, id->lib, &chan->ipo); + } +} + +static void object_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Object *ob = (Object *)id; + + bool warn = false; + + /* XXX deprecated - old animation system <<< */ + BLO_read_id_address(reader, ob->id.lib, &ob->ipo); + BLO_read_id_address(reader, ob->id.lib, &ob->action); + /* >>> XXX deprecated - old animation system */ + + BLO_read_id_address(reader, ob->id.lib, &ob->parent); + BLO_read_id_address(reader, ob->id.lib, &ob->track); + BLO_read_id_address(reader, ob->id.lib, &ob->poselib); + + /* 2.8x drops support for non-empty dupli instances. */ + if (ob->type == OB_EMPTY) { + BLO_read_id_address(reader, ob->id.lib, &ob->instance_collection); + } + else { + if (ob->instance_collection != NULL) { + ID *new_id = BLO_read_get_new_id_address(reader, ob->id.lib, &ob->instance_collection->id); + BLO_reportf_wrap(BLO_read_lib_reports(reader), + RPT_WARNING, + TIP_("Non-Empty object '%s' cannot duplicate collection '%s' " + "anymore in Blender 2.80, removed instancing"), + ob->id.name + 2, + new_id->name + 2); + } + ob->instance_collection = NULL; + ob->transflag &= ~OB_DUPLICOLLECTION; + } + + BLO_read_id_address(reader, ob->id.lib, &ob->proxy); + if (ob->proxy) { + /* paranoia check, actually a proxy_from pointer should never be written... */ + if (ob->proxy->id.lib == NULL) { + ob->proxy->proxy_from = NULL; + ob->proxy = NULL; + + if (ob->id.lib) { + printf("Proxy lost from object %s lib %s\n", ob->id.name + 2, ob->id.lib->filepath); + } + else { + printf("Proxy lost from object %s lib <NONE>\n", ob->id.name + 2); + } + } + else { + /* this triggers object_update to always use a copy */ + ob->proxy->proxy_from = ob; + } + } + BLO_read_id_address(reader, ob->id.lib, &ob->proxy_group); + + void *poin = ob->data; + BLO_read_id_address(reader, ob->id.lib, &ob->data); + + if (ob->data == NULL && poin != NULL) { + if (ob->id.lib) { + printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->filepath); + } + else { + printf("Object %s lost data.\n", ob->id.name + 2); + } + + ob->type = OB_EMPTY; + warn = true; + + if (ob->pose) { + /* we can't call #BKE_pose_free() here because of library linking + * freeing will recurse down into every pose constraints ID pointers + * which are not always valid, so for now free directly and suffer + * some leaked memory rather than crashing immediately + * while bad this _is_ an exceptional case - campbell */ +#if 0 + BKE_pose_free(ob->pose); +#else + MEM_freeN(ob->pose); +#endif + ob->pose = NULL; + ob->mode &= ~OB_MODE_POSE; + } + } + for (int a = 0; a < ob->totcol; a++) { + BLO_read_id_address(reader, ob->id.lib, &ob->mat[a]); + } + + /* When the object is local and the data is library its possible + * the material list size gets out of sync. T22663. */ + if (ob->data && ob->id.lib != ((ID *)ob->data)->lib) { + const short *totcol_data = BKE_object_material_len_p(ob); + /* Only expand so as not to lose any object materials that might be set. */ + if (totcol_data && (*totcol_data > ob->totcol)) { + /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */ + BKE_object_material_resize(BLO_read_lib_get_main(reader), ob, *totcol_data, false); + } + } + + BLO_read_id_address(reader, ob->id.lib, &ob->gpd); + + /* if id.us==0 a new base will be created later on */ + + /* WARNING! Also check expand_object(), should reflect the stuff below. */ + BKE_pose_blend_read_lib(reader, ob, ob->pose); + BKE_constraint_blend_read_lib(reader, &ob->id, &ob->constraints); + + /* XXX deprecated - old animation system <<< */ + lib_link_constraint_channels(reader, &ob->id, &ob->constraintChannels); + lib_link_nlastrips(reader, &ob->id, &ob->nlastrips); + /* >>> XXX deprecated - old animation system */ + + LISTBASE_FOREACH (PartEff *, paf, &ob->effect) { + if (paf->type == EFF_PARTICLE) { + BLO_read_id_address(reader, ob->id.lib, &paf->group); + } + } + + { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Fluidsim); + + if (fluidmd && fluidmd->fss) { + BLO_read_id_address( + reader, ob->id.lib, &fluidmd->fss->ipo); /* XXX deprecated - old animation system */ + } + } + + { + FluidModifierData *fmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Fluid); + + if (fmd && (fmd->type == MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { + /* Flag for refreshing the simulation after loading */ + fmd->domain->flags |= FLUID_DOMAIN_FILE_LOAD; + } + else if (fmd && (fmd->type == MOD_FLUID_TYPE_FLOW) && fmd->flow) { + fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE; + } + else if (fmd && (fmd->type == MOD_FLUID_TYPE_EFFEC) && fmd->effector) { + fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE; + } + } + + /* texture field */ + if (ob->pd) { + BKE_particle_partdeflect_blend_read_lib(reader, &ob->id, ob->pd); + } + + if (ob->soft) { + BLO_read_id_address(reader, ob->id.lib, &ob->soft->collision_group); + + BLO_read_id_address(reader, ob->id.lib, &ob->soft->effector_weights->group); + } + + BKE_particle_system_blend_read_lib(reader, ob, &ob->id, &ob->particlesystem); + BKE_modifier_blend_read_lib(reader, ob); + BKE_gpencil_modifier_blend_read_lib(reader, ob); + BKE_shaderfx_blend_read_lib(reader, ob); + + if (ob->rigidbody_constraint) { + BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob1); + BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob2); + } + + if (warn) { + BLO_reportf_wrap(BLO_read_lib_reports(reader), RPT_WARNING, "Warning in console"); + } +} + +/* XXX deprecated - old animation system */ +static void expand_constraint_channels(BlendExpander *expander, ListBase *chanbase) +{ + LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) { + BLO_expand(expander, chan->ipo); + } +} + +static void expand_object_expandModifiers(void *userData, + Object *UNUSED(ob), + ID **idpoin, + int UNUSED(cb_flag)) +{ + BlendExpander *expander = userData; + BLO_expand(expander, *idpoin); +} + +PartEff *BKE_object_do_version_give_parteff_245(Object *ob) +{ + PartEff *paf; + + paf = ob->effect.first; + while (paf) { + if (paf->type == EFF_PARTICLE) { + return paf; + } + paf = paf->next; + } + return NULL; +} + +static void object_blend_read_expand(BlendExpander *expander, ID *id) +{ + Object *ob = (Object *)id; + + BLO_expand(expander, ob->data); + + /* expand_object_expandModifier() */ + if (ob->modifiers.first) { + BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander); + } + + /* expand_object_expandModifier() */ + if (ob->greasepencil_modifiers.first) { + BKE_gpencil_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, expander); + } + + /* expand_object_expandShaderFx() */ + if (ob->shader_fx.first) { + BKE_shaderfx_foreach_ID_link(ob, expand_object_expandModifiers, expander); + } + + BKE_pose_blend_read_expand(expander, ob->pose); + BLO_expand(expander, ob->poselib); + BKE_constraint_blend_read_expand(expander, &ob->constraints); + + BLO_expand(expander, ob->gpd); + + /* XXX deprecated - old animation system (for version patching only) */ + BLO_expand(expander, ob->ipo); + BLO_expand(expander, ob->action); + + expand_constraint_channels(expander, &ob->constraintChannels); + + LISTBASE_FOREACH (bActionStrip *, strip, &ob->nlastrips) { + BLO_expand(expander, strip->object); + BLO_expand(expander, strip->act); + BLO_expand(expander, strip->ipo); + } + /* XXX deprecated - old animation system (for version patching only) */ + + for (int a = 0; a < ob->totcol; a++) { + BLO_expand(expander, ob->mat[a]); + } + + PartEff *paf = BKE_object_do_version_give_parteff_245(ob); + if (paf && paf->group) { + BLO_expand(expander, paf->group); + } + + if (ob->instance_collection) { + BLO_expand(expander, ob->instance_collection); + } + + if (ob->proxy) { + BLO_expand(expander, ob->proxy); + } + if (ob->proxy_group) { + BLO_expand(expander, ob->proxy_group); + } + + LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { + BLO_expand(expander, psys->part); + } + + if (ob->pd) { + BLO_expand(expander, ob->pd->tex); + BLO_expand(expander, ob->pd->f_source); + } + + if (ob->soft) { + BLO_expand(expander, ob->soft->collision_group); + + if (ob->soft->effector_weights) { + BLO_expand(expander, ob->soft->effector_weights->group); + } + } + + if (ob->rigidbody_constraint) { + BLO_expand(expander, ob->rigidbody_constraint->ob1); + BLO_expand(expander, ob->rigidbody_constraint->ob2); + } +} + IDTypeInfo IDType_ID_OB = { .id_code = ID_OB, .id_filter = FILTER_ID_OB, @@ -533,10 +1150,12 @@ IDTypeInfo IDType_ID_OB = { .foreach_id = object_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = object_blend_write, + .blend_read_data = object_blend_read_data, + .blend_read_lib = object_blend_read_lib, + .blend_read_expand = object_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; void BKE_object_workob_clear(Object *workob) @@ -4806,3 +5425,16 @@ void BKE_object_check_uuids_unique_and_report(const Object *object) BKE_pose_check_uuids_unique_and_report(object->pose); BKE_modifier_check_uuids_unique_and_report(object); } + +void BKE_object_modifiers_lib_link_common(void *userData, + struct Object *ob, + struct ID **idpoin, + int cb_flag) +{ + BlendLibReader *reader = userData; + + BLO_read_id_address(reader, ob->id.lib, idpoin); + if (*idpoin != NULL && (cb_flag & IDWALK_CB_USER) != 0) { + id_us_plus_no_lib(*idpoin); + } +} diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 04f7529c6cd..1e7624d0d7d 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -51,6 +51,7 @@ #include "BKE_object.h" #include "BKE_object_deform.h" /* own include */ +/* -------------------------------------------------------------------- */ /** \name Misc helpers * \{ */ @@ -106,6 +107,7 @@ void BKE_object_defgroup_remap_update_users(Object *ob, const int *map) } /** \} */ +/* -------------------------------------------------------------------- */ /** \name Group creation * \{ */ @@ -156,6 +158,7 @@ MDeformVert *BKE_object_defgroup_data_create(ID *id) } /** \} */ +/* -------------------------------------------------------------------- */ /** \name Group clearing * \{ */ @@ -256,6 +259,7 @@ bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection) } /** \} */ +/* -------------------------------------------------------------------- */ /** \name Group removal * \{ */ diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 39d6ee2700c..a1b01bce6c9 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -1392,7 +1392,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem mat4_to_size(original_size, obmat); size_to_mat4(size_mat, original_size); - xvec[0] = -1.f; + xvec[0] = -1.0f; xvec[1] = xvec[2] = 0; vec_to_quat(q, xvec, ob->trackflag, ob->upflag); quat_to_mat4(obmat, q); diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 6c770e53000..1d62a1cce2a 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -47,7 +47,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "RE_render_ext.h" +#include "RE_texture.h" #include "BLI_hash.h" diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 42749a93988..d726a4b1e37 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -125,6 +125,16 @@ static void palette_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_list(reader, &palette->colors); } +static void palette_undo_preserve(BlendLibReader *UNUSED(reader), ID *id_new, ID *id_old) +{ + /* Whole Palette is preserved accross undo's, and it has no extra pointer, simple. */ + /* Note: We do not care about potential internal references to self here, Palette has none. */ + /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be + * fairly delicate. */ + BKE_lib_id_swap(NULL, id_new, id_old); + SWAP(IDProperty *, id_new->properties, id_old->properties); +} + IDTypeInfo IDType_ID_PAL = { .id_code = ID_PAL, .id_filter = FILTER_ID_PAL, @@ -146,6 +156,8 @@ IDTypeInfo IDType_ID_PAL = { .blend_read_data = palette_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = palette_undo_preserve, }; static void paint_curve_copy_data(Main *UNUSED(bmain), @@ -207,6 +219,8 @@ IDTypeInfo IDType_ID_PC = { .blend_read_data = paint_curve_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100}; @@ -1162,6 +1176,56 @@ void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3]) } } +void BKE_paint_blend_write(BlendWriter *writer, Paint *p) +{ + if (p->cavity_curve) { + BKE_curvemapping_blend_write(writer, p->cavity_curve); + } + BLO_write_struct_array(writer, PaintToolSlot, p->tool_slots_len, p->tool_slots); +} + +void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Paint *p) +{ + if (p->num_input_samples < 1) { + p->num_input_samples = 1; + } + + BLO_read_data_address(reader, &p->cavity_curve); + if (p->cavity_curve) { + BKE_curvemapping_blend_read(reader, p->cavity_curve); + } + else { + BKE_paint_cavity_curve_preset(p, CURVE_PRESET_LINE); + } + + BLO_read_data_address(reader, &p->tool_slots); + + /* Workaround for invalid data written in older versions. */ + const size_t expected_size = sizeof(PaintToolSlot) * p->tool_slots_len; + if (p->tool_slots && MEM_allocN_len(p->tool_slots) < expected_size) { + MEM_freeN(p->tool_slots); + p->tool_slots = MEM_callocN(expected_size, "PaintToolSlot"); + } + + BKE_paint_runtime_init(scene->toolsettings, p); +} + +void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p) +{ + if (p) { + BLO_read_id_address(reader, sce->id.lib, &p->brush); + for (int i = 0; i < p->tool_slots_len; i++) { + if (p->tool_slots[i].brush != NULL) { + BLO_read_id_address(reader, sce->id.lib, &p->tool_slots[i].brush); + } + } + BLO_read_id_address(reader, sce->id.lib, &p->palette); + p->paint_cursor = NULL; + + BKE_paint_runtime_init(sce->toolsettings, p); + } +} + /* returns non-zero if any of the face's vertices * are hidden, zero otherwise */ bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop) @@ -1734,17 +1798,16 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object) DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); } +/** \warning Expects a fully evaluated depsgraph. */ void BKE_sculpt_update_object_for_edit( Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors) { - /* Update from sculpt operators and undo, to update sculpt session - * and PBVH after edits. */ - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig); - Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - BLI_assert(ob_orig == DEG_get_original_object(ob_orig)); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig); + Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); + BLI_assert(me_eval != NULL); + sculpt_update_object(depsgraph, ob_orig, me_eval, need_pmap, need_mask, need_colors); } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 7b8ee7343ee..0b331fb88d2 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <math.h> #include <stdlib.h> #include <string.h> @@ -29,6 +32,7 @@ #include "DNA_defaults.h" +#include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_dynamicpaint_types.h" @@ -52,6 +56,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_anim_path.h" #include "BKE_boids.h" #include "BKE_cloth.h" @@ -78,7 +83,9 @@ #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" -#include "RE_render_ext.h" +#include "RE_texture.h" + +#include "BLO_read_write.h" #include "particle_private.h" @@ -206,6 +213,279 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void write_boid_state(BlendWriter *writer, BoidState *state) +{ + BLO_write_struct(writer, BoidState, state); + + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: + BLO_write_struct(writer, BoidRuleGoalAvoid, rule); + break; + case eBoidRuleType_AvoidCollision: + BLO_write_struct(writer, BoidRuleAvoidCollision, rule); + break; + case eBoidRuleType_FollowLeader: + BLO_write_struct(writer, BoidRuleFollowLeader, rule); + break; + case eBoidRuleType_AverageSpeed: + BLO_write_struct(writer, BoidRuleAverageSpeed, rule); + break; + case eBoidRuleType_Fight: + BLO_write_struct(writer, BoidRuleFight, rule); + break; + default: + BLO_write_struct(writer, BoidRule, rule); + break; + } + } +#if 0 + BoidCondition *cond = state->conditions.first; + for (; cond; cond = cond->next) { + BLO_write_struct(writer, BoidCondition, cond); + } +#endif +} + +static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + ParticleSettings *part = (ParticleSettings *)id; + if (part->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id); + BKE_id_blend_write(writer, &part->id); + + if (part->adt) { + BKE_animdata_blend_write(writer, part->adt); + } + BLO_write_struct(writer, PartDeflect, part->pd); + BLO_write_struct(writer, PartDeflect, part->pd2); + BLO_write_struct(writer, EffectorWeights, part->effector_weights); + + if (part->clumpcurve) { + BKE_curvemapping_blend_write(writer, part->clumpcurve); + } + if (part->roughcurve) { + BKE_curvemapping_blend_write(writer, part->roughcurve); + } + if (part->twistcurve) { + BKE_curvemapping_blend_write(writer, part->twistcurve); + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ + if (dw->ob != NULL) { + dw->index = 0; + if (part->instance_collection) { /* can be NULL if lining fails or set to None */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) { + if (object == dw->ob) { + break; + } + dw->index++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + } + BLO_write_struct(writer, ParticleDupliWeight, dw); + } + + if (part->boids && part->phystype == PART_PHYS_BOIDS) { + BLO_write_struct(writer, BoidSettings, part->boids); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + write_boid_state(writer, state); + } + } + if (part->fluid && part->phystype == PART_PHYS_FLUID) { + BLO_write_struct(writer, SPHFluidSettings, part->fluid); + } + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_write_struct(writer, MTex, part->mtex[a]); + } + } + } +} + +void BKE_particle_partdeflect_blend_read_data(BlendDataReader *UNUSED(reader), PartDeflect *pd) +{ + if (pd) { + pd->rng = NULL; + } +} + +static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_data_address(reader, &part->adt); + BLO_read_data_address(reader, &part->pd); + BLO_read_data_address(reader, &part->pd2); + + BKE_animdata_blend_read_data(reader, part->adt); + BKE_particle_partdeflect_blend_read_data(reader, part->pd); + BKE_particle_partdeflect_blend_read_data(reader, part->pd2); + + BLO_read_data_address(reader, &part->clumpcurve); + if (part->clumpcurve) { + BKE_curvemapping_blend_read(reader, part->clumpcurve); + } + BLO_read_data_address(reader, &part->roughcurve); + if (part->roughcurve) { + BKE_curvemapping_blend_read(reader, part->roughcurve); + } + BLO_read_data_address(reader, &part->twistcurve); + if (part->twistcurve) { + BKE_curvemapping_blend_read(reader, part->twistcurve); + } + + BLO_read_data_address(reader, &part->effector_weights); + if (!part->effector_weights) { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + BLO_read_list(reader, &part->instance_weights); + + BLO_read_data_address(reader, &part->boids); + BLO_read_data_address(reader, &part->fluid); + + if (part->boids) { + BLO_read_list(reader, &part->boids->states); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + BLO_read_list(reader, &state->rules); + BLO_read_list(reader, &state->conditions); + BLO_read_list(reader, &state->actions); + } + } + for (int a = 0; a < MAX_MTEX; a++) { + BLO_read_data_address(reader, &part->mtex[a]); + } + + /* Protect against integer overflow vulnerability. */ + CLAMP(part->trail_count, 1, 100000); +} + +void BKE_particle_partdeflect_blend_read_lib(BlendLibReader *reader, ID *id, PartDeflect *pd) +{ + if (pd && pd->tex) { + BLO_read_id_address(reader, id->lib, &pd->tex); + } + if (pd && pd->f_source) { + BLO_read_id_address(reader, id->lib, &pd->f_source); + } +} + +static void particle_settings_blend_read_lib(BlendLibReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_id_address( + reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */ + + BLO_read_id_address(reader, part->id.lib, &part->instance_object); + BLO_read_id_address(reader, part->id.lib, &part->instance_collection); + BLO_read_id_address(reader, part->id.lib, &part->force_group); + BLO_read_id_address(reader, part->id.lib, &part->bb_ob); + BLO_read_id_address(reader, part->id.lib, &part->collision_group); + + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd); + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd2); + + if (part->effector_weights) { + BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group); + } + else { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + if (part->instance_weights.first && part->instance_collection) { + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_read_id_address(reader, part->id.lib, &dw->ob); + } + } + else { + BLI_listbase_clear(&part->instance_weights); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: { + BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule; + BLO_read_id_address(reader, part->id.lib, &brga->ob); + break; + } + case eBoidRuleType_FollowLeader: { + BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule; + BLO_read_id_address(reader, part->id.lib, &brfl->ob); + break; + } + } + } + } + } + + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = part->mtex[a]; + if (mtex) { + BLO_read_id_address(reader, part->id.lib, &mtex->tex); + BLO_read_id_address(reader, part->id.lib, &mtex->object); + } + } +} + +static void particle_settings_blend_read_expand(BlendExpander *expander, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_expand(expander, part->instance_object); + BLO_expand(expander, part->instance_collection); + BLO_expand(expander, part->force_group); + BLO_expand(expander, part->bb_ob); + BLO_expand(expander, part->collision_group); + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_expand(expander, part->mtex[a]->tex); + BLO_expand(expander, part->mtex[a]->object); + } + } + + if (part->effector_weights) { + BLO_expand(expander, part->effector_weights->group); + } + + if (part->pd) { + BLO_expand(expander, part->pd->tex); + BLO_expand(expander, part->pd->f_source); + } + if (part->pd2) { + BLO_expand(expander, part->pd2->tex); + BLO_expand(expander, part->pd2->f_source); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + BLO_expand(expander, gabr->ob); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + BLO_expand(expander, flbr->ob); + } + } + } + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_expand(expander, dw->ob); + } +} + IDTypeInfo IDType_ID_PA = { .id_code = ID_PA, .id_filter = FILTER_ID_PA, @@ -223,17 +503,19 @@ IDTypeInfo IDType_ID_PA = { .foreach_id = particle_settings_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = particle_settings_blend_write, + .blend_read_data = particle_settings_blend_read_data, + .blend_read_lib = particle_settings_blend_read_lib, + .blend_read_expand = particle_settings_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]; float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; -void psys_init_rng(void) +void BKE_particle_init_rng(void) { RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */ for (int i = 0; i < PSYS_FRAND_COUNT; i++) { @@ -917,7 +1199,7 @@ static float interpolate_particle_value( value += w[3] * v4; } - CLAMP(value, 0.f, 1.f); + CLAMP(value, 0.0f, 1.0f); return value; } @@ -1146,7 +1428,7 @@ static void do_particle_interpolation(ParticleSystem *psys, PTCacheEditPoint *point = pind->epoint; ParticleKey keys[4]; int point_vel = (point && point->keys->vel); - float real_t, dfra, keytime, invdt = 1.f; + float real_t, dfra, keytime, invdt = 1.0f; /* billboards wont fill in all of these, so start cleared */ memset(keys, 0, sizeof(keys)); @@ -1316,7 +1598,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* Convert velocity to time-step size. */ if (pind->keyed || pind->cache || point_vel) { - invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f); + invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.0f); mul_v3_fl(keys[1].vel, invdt); mul_v3_fl(keys[2].vel, invdt); interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime); @@ -1335,7 +1617,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* the velocity needs to be converted back from cubic interpolation */ if (pind->keyed || pind->cache || point_vel) { - mul_v3_fl(result->vel, 1.f / invdt); + mul_v3_fl(result->vel, 1.0f / invdt); } } @@ -2200,7 +2482,7 @@ int do_guides(Depsgraph *depsgraph, pd->kink_freq, pd->kink_shape, pd->kink_amp, - 0.f, + 0.0f, pd->kink, pd->kink_axis, 0, @@ -2550,12 +2832,12 @@ static void psys_thread_create_path(ParticleTask *task, if (ctx->between) { ParticleData *pa = psys->particles + cpa->pa[0]; int w, needupdate; - float foffset, wsum = 0.f; + float foffset, wsum = 0.0f; float co[3]; float p_min = part->parting_min; float p_max = part->parting_max; /* Virtual parents don't work nicely with parting. */ - float p_fac = part->parents > 0.f ? 0.f : part->parting_fac; + float p_fac = part->parents > 0.0f ? 0.0f : part->parting_fac; if (ctx->editupdate) { needupdate = 0; @@ -2583,15 +2865,15 @@ static void psys_thread_create_path(ParticleTask *task, } else { key[w] = pcache[0]; - weight[w] = 0.f; + weight[w] = 0.0f; } } /* modify weights to create parting */ - if (p_fac > 0.f) { + if (p_fac > 0.0f) { const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]); for (w = 0; w < 4; w++) { - if (w && (weight[w] > 0.f)) { + if (w && (weight[w] > 0.0f)) { const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]); float d; if (part->flag & PART_CHILD_LONG_HAIR) { @@ -2600,7 +2882,7 @@ static void psys_thread_create_path(ParticleTask *task, float d1 = len_v3v3(key[0]->co, key[w]->co); float d2 = len_v3v3(key_0_last->co, key_w_last->co); - d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f; + d = d1 > 0.0f ? d2 / d1 - 1.0f : 10000.0f; } else { float v1[3], v2[3]; @@ -2616,13 +2898,13 @@ static void psys_thread_create_path(ParticleTask *task, d = (d - p_min) / (p_max - p_min); } else { - d = (d - p_min) <= 0.f ? 0.f : 1.f; + d = (d - p_min) <= 0.0f ? 0.0f : 1.0f; } - CLAMP(d, 0.f, 1.f); + CLAMP(d, 0.0f, 1.0f); - if (d > 0.f) { - weight[w] *= (1.f - d); + if (d > 0.0f) { + weight[w] *= (1.0f - d); } } wsum += weight[w]; @@ -3059,7 +3341,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re LOOP_PARTICLES { if (!psys->totchild) { - psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f); + psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.0f); pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p)); if (vg_length) { pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length); @@ -3716,19 +3998,25 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob if (psys->part->type == PART_FLUID_FLIP) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP; } - if (psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAY, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY; } - if (psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_FOAM, + PART_FLUID_SPRAYFOAM, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM; } - if (psys->part->type == PART_FLUID_BUBBLE || psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_BUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE; } if (psys->part->type == PART_FLUID_TRACER) { @@ -3736,9 +4024,11 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } /* Disable combined export if combined particle system was deleted. */ - if (psys->part->type == PART_FLUID_SPRAYFOAM || psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF; } } @@ -3992,9 +4282,9 @@ static void get_cpa_texture(Mesh *mesh, break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ - texvec[0] = 2.f * (cfra - par->time) / (par->dietime - par->time) - 1.f; - texvec[1] = 0.f; - texvec[2] = 0.f; + texvec[0] = 2.0f * (cfra - par->time) / (par->dietime - par->time) - 1.0f; + texvec[1] = 0.0f; + texvec[2] = 0.0f; break; } @@ -4102,14 +4392,15 @@ void psys_get_texture( break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ - texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f; + texvec[0] = 2.0f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.0f; if (sim->psys->totpart > 0) { - texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f; + texvec[1] = 2.0f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - + 1.0f; } else { texvec[1] = 0.0f; } - texvec[2] = 0.f; + texvec[2] = 0.0f; break; } @@ -4654,8 +4945,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta else { float dfra, frs_sec = sim->scene->r.frs_sec; /* let's interpolate to try to be as accurate as possible */ - if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) { - if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) { + if (pa->state.time + 2.0f >= state->time && pa->prev_state.time - 2.0f <= state->time) { + if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.0f) { /* prev_state is wrong so let's not use it, * this can happen at frames 1, 0 or particle birth. */ dfra = state->time - pa->state.time; @@ -4682,13 +4973,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - mul_v3_fl(state->vel, 1.f / (dfra * timestep)); + mul_v3_fl(state->vel, 1.0f / (dfra * timestep)); interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime); interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime); } } - else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) { + else if (pa->state.time + 1.0f >= state->time && pa->state.time - 1.0f <= state->time) { /* linear interpolation using only pa->state */ dfra = state->time - pa->state.time; @@ -4949,3 +5240,172 @@ void BKE_particle_batch_cache_free(ParticleSystem *psys) BKE_particle_batch_cache_free_cb(psys); } } + +void BKE_particle_system_blend_write(BlendWriter *writer, ListBase *particles) +{ + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_write_struct(writer, ParticleSystem, psys); + + if (psys->particles) { + BLO_write_struct_array(writer, ParticleData, psys->totpart, psys->particles); + + if (psys->particles->hair) { + ParticleData *pa = psys->particles; + + for (int a = 0; a < psys->totpart; a++, pa++) { + BLO_write_struct_array(writer, HairKey, pa->totkey, pa->hair); + } + } + + if (psys->particles->boid && (psys->part->phystype == PART_PHYS_BOIDS)) { + BLO_write_struct_array(writer, BoidParticle, psys->totpart, psys->particles->boid); + } + + if (psys->part->fluid && (psys->part->phystype == PART_PHYS_FLUID) && + (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) { + BLO_write_struct_array( + writer, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs); + } + } + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_write_struct(writer, ParticleTarget, pt); + } + + if (psys->child) { + BLO_write_struct_array(writer, ChildParticle, psys->totchild, psys->child); + } + + if (psys->clmd) { + BLO_write_struct(writer, ClothModifierData, psys->clmd); + BLO_write_struct(writer, ClothSimSettings, psys->clmd->sim_parms); + BLO_write_struct(writer, ClothCollSettings, psys->clmd->coll_parms); + } + + BKE_ptcache_blend_write(writer, &psys->ptcaches); + } +} + +void BKE_particle_system_blend_read_data(BlendDataReader *reader, ListBase *particles) +{ + ParticleData *pa; + int a; + + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_read_data_address(reader, &psys->particles); + + if (psys->particles && psys->particles->hair) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + BLO_read_data_address(reader, &pa->hair); + } + } + + if (psys->particles && psys->particles->keys) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->keys = NULL; + pa->totkey = 0; + } + + psys->flag &= ~PSYS_KEYED; + } + + if (psys->particles && psys->particles->boid) { + pa = psys->particles; + BLO_read_data_address(reader, &pa->boid); + + /* This is purely runtime data, but still can be an issue if left dangling. */ + pa->boid->ground = NULL; + + for (a = 1, pa++; a < psys->totpart; a++, pa++) { + pa->boid = (pa - 1)->boid + 1; + pa->boid->ground = NULL; + } + } + else if (psys->particles) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->boid = NULL; + } + } + + BLO_read_data_address(reader, &psys->fluid_springs); + + BLO_read_data_address(reader, &psys->child); + psys->effectors = NULL; + + BLO_read_list(reader, &psys->targets); + + psys->edit = NULL; + psys->free_edit = NULL; + psys->pathcache = NULL; + psys->childcache = NULL; + BLI_listbase_clear(&psys->pathcachebufs); + BLI_listbase_clear(&psys->childcachebufs); + psys->pdd = NULL; + + if (psys->clmd) { + BLO_read_data_address(reader, &psys->clmd); + psys->clmd->clothObject = NULL; + psys->clmd->hairdata = NULL; + + BLO_read_data_address(reader, &psys->clmd->sim_parms); + BLO_read_data_address(reader, &psys->clmd->coll_parms); + + if (psys->clmd->sim_parms) { + psys->clmd->sim_parms->effector_weights = NULL; + if (psys->clmd->sim_parms->presets > 10) { + psys->clmd->sim_parms->presets = 0; + } + } + + psys->hair_in_mesh = psys->hair_out_mesh = NULL; + psys->clmd->solver_result = NULL; + } + + BKE_ptcache_blend_read_data(reader, &psys->ptcaches, &psys->pointcache, 0); + if (psys->clmd) { + psys->clmd->point_cache = psys->pointcache; + } + + psys->tree = NULL; + psys->bvhtree = NULL; + + psys->orig_psys = NULL; + psys->batch_cache = NULL; + } +} + +void BKE_particle_system_blend_read_lib(BlendLibReader *reader, + Object *ob, + ID *id, + ListBase *particles) +{ + LISTBASE_FOREACH_MUTABLE (ParticleSystem *, psys, particles) { + + BLO_read_id_address(reader, id->lib, &psys->part); + if (psys->part) { + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_read_id_address(reader, id->lib, &pt->ob); + } + + BLO_read_id_address(reader, id->lib, &psys->parent); + BLO_read_id_address(reader, id->lib, &psys->target_ob); + + if (psys->clmd) { + /* XXX - from reading existing code this seems correct but intended usage of + * pointcache /w cloth should be added in 'ParticleSystem' - campbell */ + psys->clmd->point_cache = psys->pointcache; + psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL; + BLO_read_id_address(reader, id->lib, &psys->clmd->coll_parms->group); + psys->clmd->modifier.error = NULL; + } + } + else { + /* particle modifier must be removed before particle system */ + ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + BLI_remlink(&ob->modifiers, psmd); + BKE_modifier_free((ModifierData *)psmd); + + BLI_remlink(particles, psys); + MEM_freeN(psys); + } + } +} diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index da5fdc85561..98a55c3de95 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -88,7 +88,7 @@ static void do_kink_spiral_deform(ParticleKey *state, { float result[3]; - CLAMP(time, 0.f, 1.f); + CLAMP(time, 0.0f, 1.0f); copy_v3_v3(result, state->co); @@ -426,21 +426,21 @@ void do_kink(ParticleKey *state, float obmat[4][4], int smooth_start) { - float kink[3] = {1.f, 0.f, 0.f}, par_vec[3], q1[4] = {1.f, 0.f, 0.f, 0.f}; - float t, dt = 1.f, result[3]; + float kink[3] = {1.0f, 0.0f, 0.0f}, par_vec[3], q1[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + float t, dt = 1.0f, result[3]; if (ELEM(type, PART_KINK_NO, PART_KINK_SPIRAL)) { return; } - CLAMP(time, 0.f, 1.f); + CLAMP(time, 0.0f, 1.0f); if (shape != 0.0f && !ELEM(type, PART_KINK_BRAID)) { if (shape < 0.0f) { - time = (float)pow(time, 1.f + shape); + time = (float)pow(time, 1.0f + shape); } else { - time = (float)pow(time, 1.f / (1.f - shape)); + time = (float)pow(time, 1.0f / (1.0f - shape)); } } @@ -449,14 +449,14 @@ void do_kink(ParticleKey *state, if (smooth_start) { dt = fabsf(t); /* smooth the beginning of kink */ - CLAMP(dt, 0.f, (float)M_PI); - dt = sinf(dt / 2.f); + CLAMP(dt, 0.0f, (float)M_PI); + dt = sinf(dt / 2.0f); } if (!ELEM(type, PART_KINK_RADIAL)) { float temp[3]; - kink[axis] = 1.f; + kink[axis] = 1.0f; if (obmat) { mul_mat3_m4_v3(obmat, kink); @@ -487,7 +487,7 @@ void do_kink(ParticleKey *state, break; } case PART_KINK_RADIAL: { - if (flat > 0.f) { + if (flat > 0.0f) { float proj[3]; /* flatten along strand */ project_v3_v3v3(proj, par_vec, par_vel); @@ -500,7 +500,7 @@ void do_kink(ParticleKey *state, case PART_KINK_WAVE: { madd_v3_v3fl(result, kink, amplitude * sinf(t)); - if (flat > 0.f) { + if (flat > 0.0f) { float proj[3]; /* flatten along wave */ project_v3_v3v3(proj, par_vec, kink); @@ -513,8 +513,8 @@ void do_kink(ParticleKey *state, break; } case PART_KINK_BRAID: { - float y_vec[3] = {0.f, 1.f, 0.f}; - float z_vec[3] = {0.f, 0.f, 1.f}; + float y_vec[3] = {0.0f, 1.0f, 0.0f}; + float z_vec[3] = {0.0f, 0.0f, 1.0f}; float vec_one[3], state_co[3]; float inp_y, inp_z, length; @@ -533,21 +533,21 @@ void do_kink(ParticleKey *state, copy_v3_v3(state_co, y_vec); mul_v3_fl(y_vec, amplitude * cosf(t)); - mul_v3_fl(z_vec, amplitude / 2.f * sinf(2.f * t)); + mul_v3_fl(z_vec, amplitude / 2.0f * sinf(2.0f * t)); } else if (inp_z > 0.0f) { - mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, sinf((float)M_PI / 3.0f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.f)); - mul_v3_fl(z_vec, amplitude / 2.f * cosf(2.f * t + (float)M_PI / 6.f)); + mul_v3_fl(y_vec, -amplitude * cosf(t + (float)M_PI / 3.0f)); + mul_v3_fl(z_vec, amplitude / 2.0f * cosf(2.0f * t + (float)M_PI / 6.0f)); } else { - mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.f)); + mul_v3_v3fl(state_co, z_vec, -sinf((float)M_PI / 3.0f)); madd_v3_v3fl(state_co, y_vec, -0.5f); - mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.f)); - mul_v3_fl(z_vec, amplitude / 2.f * -sinf(2.f * t + (float)M_PI / 3.f)); + mul_v3_fl(y_vec, amplitude * -sinf(t + (float)M_PI / 6.0f)); + mul_v3_fl(z_vec, amplitude / 2.0f * -sinf(2.0f * t + (float)M_PI / 3.0f)); } mul_v3_fl(state_co, amplitude); @@ -555,13 +555,13 @@ void do_kink(ParticleKey *state, sub_v3_v3v3(par_vec, state->co, state_co); length = normalize_v3(par_vec); - mul_v3_fl(par_vec, MIN2(length, amplitude / 2.f)); + mul_v3_fl(par_vec, MIN2(length, amplitude / 2.0f)); add_v3_v3v3(state_co, par_co, y_vec); add_v3_v3(state_co, z_vec); add_v3_v3(state_co, par_vec); - shape = 2.f * (float)M_PI * (1.f + shape); + shape = 2.0f * (float)M_PI * (1.0f + shape); if (t < shape) { shape = t / shape; @@ -576,7 +576,7 @@ void do_kink(ParticleKey *state, } /* blend the start of the kink */ - if (dt < 1.f) { + if (dt < 1.0f) { interp_v3_v3v3(state->co, state->co, result, dt); } else { @@ -642,7 +642,7 @@ float do_clump(ParticleKey *state, float da[4], pa[12]; mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size); - voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0); + BLI_noise_voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0); mul_v3_fl(&pa[0], clump_noise_size); add_v3_v3v3(center, par_co, &pa[0]); @@ -674,9 +674,9 @@ static void do_rough(const float loc[3], copy_v3_v3(rco, loc); mul_v3_fl(rco, t); - rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2); - rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2); - rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2); + rough[0] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[0], rco[1], rco[2], 2, 0, 2); + rough[1] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[1], rco[2], rco[0], 2, 0, 2); + rough[2] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[2], rco[0], rco[1], 2, 0, 2); madd_v3_v3fl(state->co, mat[0], fac * rough[0]); madd_v3_v3fl(state->co, mat[1], fac * rough[1]); @@ -718,9 +718,9 @@ static void do_rough_curve(const float loc[3], copy_v3_v3(rco, loc); mul_v3_fl(rco, time); - rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2); - rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2); - rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2); + rough[0] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[0], rco[1], rco[2], 2, 0, 2); + rough[1] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[1], rco[2], rco[0], 2, 0, 2); + rough[2] = -1.0f + 2.0f * BLI_noise_generic_turbulence(size, rco[2], rco[0], rco[1], 2, 0, 2); madd_v3_v3fl(state->co, mat[0], fac * rough[0]); madd_v3_v3fl(state->co, mat[1], fac * rough[1]); @@ -881,8 +881,8 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, part->clump_noise_size, clumpcurve); - if (kink_freq != 0.f) { - kink_amp *= (1.f - kink_amp_clump * clump); + if (kink_freq != 0.0f) { + kink_amp *= (1.0f - kink_amp_clump * clump); do_kink(state, modifier_ctx->par_co, @@ -904,17 +904,17 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, do_rough_curve(modifier_ctx->orco, mat, t, rough1, part->rough1_size, roughcurve, state); } else { - if (rough1 > 0.f) { + if (rough1 > 0.0f) { do_rough(modifier_ctx->orco, mat, t, rough1, part->rough1_size, 0.0, state); } - if (rough2 > 0.f) { + if (rough2 > 0.0f) { float vec[3]; psys_frand_vec(sim->psys, i + 27, vec); do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state); } - if (rough_end > 0.f) { + if (rough_end > 0.0f) { float vec[3]; psys_frand_vec(sim->psys, i + 27, vec); do_rough_end(vec, mat, t, rough_end, part->rough_end_shape, state); diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index d5999196b60..194593be4ff 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -150,9 +150,9 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) size[2] = MAX2(size[2], 1); /* no full offset for flat/thin objects */ - min[0] += d < delta[0] ? d / 2.f : delta[0] / 2.f; - min[1] += d < delta[1] ? d / 2.f : delta[1] / 2.f; - min[2] += d < delta[2] ? d / 2.f : delta[2] / 2.f; + min[0] += d < delta[0] ? d / 2.0f : delta[0] / 2.0f; + min[1] += d < delta[1] ? d / 2.0f : delta[1] / 2.0f; + min[2] += d < delta[2] ? d / 2.0f : delta[2] / 2.0f; for (i = 0, p = 0, pa = psys->particles; i < res; i++) { for (j = 0; j < res; j++) { @@ -220,7 +220,7 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) pa = psys->particles + a1 * a1mul + a2 * a2mul; copy_v3_v3(co1, pa->fuv); - co1[a] -= d < delta[a] ? d / 2.f : delta[a] / 2.f; + co1[a] -= d < delta[a] ? d / 2.0f : delta[a] / 2.0f; copy_v3_v3(co2, co1); co2[a] += delta[a] + 0.001f * d; co1[a] -= 0.001f * d; @@ -295,12 +295,12 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) for (j = 0; j < res; j++) { for (k = 0; k < res; k++, p++, pa++) { if (j % 2) { - pa->fuv[0] += d / 2.f; + pa->fuv[0] += d / 2.0f; } if (k % 2) { - pa->fuv[0] += d / 2.f; - pa->fuv[1] += d / 2.f; + pa->fuv[0] += d / 2.0f; + pa->fuv[1] += d / 2.0f; } } } @@ -318,7 +318,7 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys) } } - if (psys->part->grid_rand > 0.f) { + if (psys->part->grid_rand > 0.0f) { float rfac = d * psys->part->grid_rand; for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) { if (pa->flag & PARS_UNEXIST) { @@ -1052,7 +1052,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, /* Calculate weights from face areas */ if ((part->flag & PART_EDISTR || children) && from != PART_FROM_VERT) { MVert *v1, *v2, *v3, *v4; - float totarea = 0.f, co1[3], co2[3], co3[3], co4[3]; + float totarea = 0.0f, co1[3], co2[3], co3[3], co4[3]; float(*orcodata)[3]; orcodata = CustomData_get_layer(&mesh->vdata, CD_ORCO); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 060a9b4d794..4117dfc0b23 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -83,7 +83,7 @@ #include "PIL_time.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" /* FLUID sim particle import */ #ifdef WITH_FLUID @@ -574,7 +574,7 @@ static void init_particle_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleSettings *part = psys->part; ParticleTexture ptex; - psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); + psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.0f); switch (part->type) { case PART_EMITTER: @@ -587,7 +587,7 @@ static void init_particle_texture(ParticleSimulationData *sim, ParticleData *pa, if (ptex.exist < psys_frand(psys, p + 125)) { pa->flag |= PARS_UNEXIST; } - pa->time = 0.f; + pa->time = 0.0f; break; } } @@ -697,28 +697,28 @@ static void get_angular_velocity_vector(short avemode, ParticleKey *state, float case PART_AVE_HORIZONTAL: { float zvec[3]; zvec[0] = zvec[1] = 0; - zvec[2] = 1.f; + zvec[2] = 1.0f; cross_v3_v3v3(vec, state->vel, zvec); break; } case PART_AVE_VERTICAL: { float zvec[3], temp[3]; zvec[0] = zvec[1] = 0; - zvec[2] = 1.f; + zvec[2] = 1.0f; cross_v3_v3v3(temp, state->vel, zvec); cross_v3_v3v3(vec, temp, state->vel); break; } case PART_AVE_GLOBAL_X: - vec[0] = 1.f; + vec[0] = 1.0f; vec[1] = vec[2] = 0; break; case PART_AVE_GLOBAL_Y: - vec[1] = 1.f; + vec[1] = 1.0f; vec[0] = vec[2] = 0; break; case PART_AVE_GLOBAL_Z: - vec[2] = 1.f; + vec[2] = 1.0f; vec[0] = vec[1] = 0; break; } @@ -864,36 +864,36 @@ void psys_get_birth_coords( /* -velocity from: */ /* *reactions */ - if (dtime > 0.f) { + if (dtime > 0.0f) { sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel); } /* *emitter velocity */ - if (dtime != 0.f && part->obfac != 0.f) { + if (dtime != 0.0f && part->obfac != 0.0f) { sub_v3_v3v3(vel, loc, state->co); mul_v3_fl(vel, part->obfac / dtime); } /* *emitter normal */ - if (part->normfac != 0.f) { + if (part->normfac != 0.0f) { madd_v3_v3fl(vel, nor, part->normfac); } /* *emitter tangent */ - if (sim->psmd && part->tanfac != 0.f) { + if (sim->psmd && part->tanfac != 0.0f) { madd_v3_v3fl(vel, vtan, part->tanfac); } /* *emitter object orientation */ - if (part->ob_vel[0] != 0.f) { + if (part->ob_vel[0] != 0.0f) { normalize_v3_v3(vec, ob->obmat[0]); madd_v3_v3fl(vel, vec, part->ob_vel[0]); } - if (part->ob_vel[1] != 0.f) { + if (part->ob_vel[1] != 0.0f) { normalize_v3_v3(vec, ob->obmat[1]); madd_v3_v3fl(vel, vec, part->ob_vel[1]); } - if (part->ob_vel[2] != 0.f) { + if (part->ob_vel[2] != 0.0f) { normalize_v3_v3(vec, ob->obmat[2]); madd_v3_v3fl(vel, vec, part->ob_vel[2]); } @@ -902,12 +902,12 @@ void psys_get_birth_coords( /* TODO */ /* *random */ - if (part->randfac != 0.f) { + if (part->randfac != 0.0f) { madd_v3_v3fl(vel, r_vel, part->randfac); } /* *particle */ - if (part->partfac != 0.f) { + if (part->partfac != 0.0f) { madd_v3_v3fl(vel, p_vel, part->partfac); } @@ -1077,7 +1077,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, part = psys->part; /* get precise emitter matrix if particle is born */ - if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { + if (part->type != PART_HAIR && dtime > 0.0f && pa->time < cfra && pa->time >= sim->psys->cfra) { evaluate_emitter_anim(sim->depsgraph, sim->scene, sim->ob, pa->time); psys->flag |= PSYS_OB_ANIM_RESTORE; @@ -1165,7 +1165,7 @@ ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt) { ParticleSystem *psys = NULL; - if (pt->ob == NULL || pt->ob == ob) { + if (ELEM(pt->ob, NULL, ob)) { psys = BLI_findlink(&ob->particlesystem, pt->psys - 1); } else { @@ -1427,7 +1427,7 @@ static void integrate_particle( copy_v3_v3(oldpos, pa->state.co); /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */ - if (pa->prev_state.time < 0.f && integrator == PART_INT_VERLET) { + if (pa->prev_state.time < 0.0f && integrator == PART_INT_VERLET) { integrator = PART_INT_EULER; } @@ -1450,7 +1450,7 @@ static void integrate_particle( copy_particle_key(states + i, &pa->state, 1); } - states->time = 0.f; + states->time = 0.0f; for (i = 0; i < steps; i++) { zero_v3(force); @@ -1611,9 +1611,9 @@ static void sph_springs_modify(ParticleSystem *psys, float dtime) float yield_ratio = fluid->yield_ratio; float plasticity = fluid->plasticity_constant; /* scale things according to dtime */ - float timefix = 25.f * dtime; + float timefix = 25.0f * dtime; - if ((fluid->flag & SPH_VISCOELASTIC_SPRINGS) == 0 || fluid->spring_k == 0.f) { + if ((fluid->flag & SPH_VISCOELASTIC_SPRINGS) == 0 || fluid->spring_k == 0.0f) { return; } @@ -1636,7 +1636,7 @@ static void sph_springs_modify(ParticleSystem *psys, float dtime) spring->rest_length -= plasticity * (Lij - d - rij) * timefix; } - h = 4.f * pa1->size; + h = 4.0f * pa1->size; if (spring->rest_length > h) { spring->delete_flag = 1; @@ -1743,7 +1743,7 @@ static void sph_density_accum_cb(void *userdata, int index, const float co[3], f pfr->tot_neighbors++; dist = sqrtf(squared_dist); - q = (1.f - dist / pfr->h) * pfr->massfac; + q = (1.0f - dist / pfr->h) * pfr->massfac; if (pfr->use_size) { q *= npa->size; @@ -1799,7 +1799,7 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa float visc = fluid->viscosity_omega; float stiff_visc = fluid->viscosity_beta * - (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.f); + (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.0f); float inv_mass = 1.0f / sphdata->mass; float spring_constant = fluid->spring_k; @@ -1809,13 +1809,13 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa (fluid->flag & SPH_FAC_RADIUS ? 4.0f * pa->size : 1.0f); float h = interaction_radius * sphdata->hfac; /* 4.77 is an experimentally determined density factor */ - float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); + float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f); float rest_length = fluid->rest_length * - (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f); + (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.0f); float stiffness = fluid->stiffness_k; float stiffness_near_fac = fluid->stiffness_knear * - (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.f); + (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.0f); ParticleData *npa; float vec[3]; @@ -1849,7 +1849,7 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa sub_v3_v3v3(vec, co, state->co); rij = normalize_v3(vec); - q = (1.f - rij / h) * pfn->psys->part->mass * inv_mass; + q = (1.0f - rij / h) * pfn->psys->part->mass * inv_mass; if (pfn->psys->part->flag & PART_SIZEMASS) { q *= npa->size; @@ -1861,20 +1861,20 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa madd_v3_v3fl(force, vec, -(pressure + near_pressure * q) * q); /* Viscosity */ - if (visc > 0.f || stiff_visc > 0.f) { + if (visc > 0.0f || stiff_visc > 0.0f) { sub_v3_v3v3(dv, vel, state->vel); u = dot_v3v3(vec, dv); - if (u < 0.f && visc > 0.f) { + if (u < 0.0f && visc > 0.0f) { madd_v3_v3fl(force, vec, 0.5f * q * visc * u); } - if (u > 0.f && stiff_visc > 0.f) { + if (u > 0.0f && stiff_visc > 0.0f) { madd_v3_v3fl(force, vec, 0.5f * q * stiff_visc * u); } } - if (spring_constant > 0.f) { + if (spring_constant > 0.0f) { /* Viscoelastic spring force */ if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) { /* BLI_edgehash_lookup appears to be thread-safe. - z0r */ @@ -1883,8 +1883,9 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa if (spring_index) { spring = psys[0]->fluid_springs + spring_index - 1; - madd_v3_v3fl( - force, vec, -10.f * spring_constant * (1.f - rij / h) * (spring->rest_length - rij)); + madd_v3_v3fl(force, + vec, + -10.0f * spring_constant * (1.0f - rij / h) * (spring->rest_length - rij)); } else if (fluid->spring_frames == 0 || (pa->prev_state.time - pa->time) <= fluid->spring_frames) { @@ -1898,13 +1899,14 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa } } else { /* PART_SPRING_HOOKES - Hooke's spring force */ - madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij / h) * (rest_length - rij)); + madd_v3_v3fl( + force, vec, -10.0f * spring_constant * (1.0f - rij / h) * (rest_length - rij)); } } } /* Artificial buoyancy force in negative gravity direction */ - if (fluid->buoyancy > 0.f && gravity) { + if (fluid->buoyancy > 0.0f && gravity) { madd_v3_v3fl(force, gravity, fluid->buoyancy * (density - rest_density)); } @@ -1922,7 +1924,7 @@ static void sphclassical_density_accum_cb(void *userdata, SPHRangeData *pfr = (SPHRangeData *)userdata; ParticleData *npa = pfr->npsys->particles + index; float q; - float qfac = 21.0f / (256.f * (float)M_PI); + float qfac = 21.0f / (256.0f * (float)M_PI); float rij, rij_h; float vec[3]; @@ -2079,7 +2081,7 @@ static void sphclassical_force_cb(void *sphdata_v, } /* Artificial buoyancy force in negative gravity direction */ - if (fluid->buoyancy > 0.f && gravity) { + if (fluid->buoyancy > 0.0f && gravity) { madd_v3_v3fl(force, gravity, fluid->buoyancy * (pa->sphdensity - rest_density)); } @@ -2199,7 +2201,7 @@ static void sph_integrate(ParticleSimulationData *sim, { ParticleSettings *part = sim->psys->part; // float timestep = psys_get_timestep(sim); // UNUSED - float pa_mass = part->mass * (part->flag & PART_SIZEMASS ? pa->size : 1.f); + float pa_mass = part->mass * (part->flag & PART_SIZEMASS ? pa->size : 1.0f); float dtime = dfra * psys_get_timestep(sim); // int steps = 1; // UNUSED float effector_acceleration[3]; @@ -2211,7 +2213,7 @@ static void sph_integrate(ParticleSimulationData *sim, /* restore previous state and treat gravity & effectors as external acceleration*/ sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel); - mul_v3_fl(effector_acceleration, 1.f / dtime); + mul_v3_fl(effector_acceleration, 1.0f / dtime); copy_particle_key(&pa->state, &pa->prev_state, 0); @@ -2300,8 +2302,8 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa integrate_particle(part, pa, dtime, gravity, basic_force_cb, &efdata); /* damp affects final velocity */ - if (part->dampfac != 0.f) { - mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp * 25.f * dtime); + if (part->dampfac != 0.0f) { + mul_v3_fl(pa->state.vel, 1.0f - part->dampfac * efdata.ptex.damp * 25.0f * dtime); } // copy_v3_v3(pa->state.ave, states->ave); @@ -2406,7 +2408,7 @@ static float nr_signed_distance_to_plane(float *p, d = dot_v3v3(p0, nor); if (pce->inv_nor == -1) { - if (d < 0.f) { + if (d < 0.0f) { pce->inv_nor = 1; } else { @@ -2452,7 +2454,7 @@ static void collision_interpolate_element(ParticleCollisionElement *pce, /* fac is the starting factor for current collision iteration */ /* The col->fac's are factors for the particle subframe step start * and end during collision modifier step. */ - float f = fac + t * (1.f - fac); + float f = fac + t * (1.0f - fac); float mul = col->fac1 + f * (col->fac2 - col->fac1); if (pce->tot > 0) { madd_v3_v3v3fl(pce->x0, pce->x[0], pce->v[0], mul); @@ -2485,8 +2487,8 @@ static void collision_point_velocity(ParticleCollisionElement *pce) static float collision_point_distance_with_normal( float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor) { - if (fac >= 0.f) { - collision_interpolate_element(pce, 0.f, fac, col); + if (fac >= 0.0f) { + collision_interpolate_element(pce, 0.0f, fac, col); } switch (pce->tot) { @@ -2504,14 +2506,14 @@ static float collision_point_distance_with_normal( return normalize_v3(nor); } case 3: - return nr_signed_distance_to_plane(p, 0.f, pce, nor); + return nr_signed_distance_to_plane(p, 0.0f, pce, nor); } return 0; } static void collision_point_on_surface( const float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co) { - collision_interpolate_element(pce, 0.f, fac, col); + collision_interpolate_element(pce, 0.0f, fac, col); switch (pce->tot) { case 1: { @@ -2575,11 +2577,11 @@ static float collision_newton_rhapson(ParticleCollision *col, } /* start from the beginning */ - t0 = 0.f; + t0 = 0.0f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co1, radius, pce, n); t1 = dt_init; - d1 = 0.f; + d1 = 0.0f; for (iter = 0; iter < 10; iter++) { //, itersum++) { /* get current location */ @@ -2589,11 +2591,11 @@ static float collision_newton_rhapson(ParticleCollision *col, d1 = distance_func(pce->p, radius, pce, n); /* particle already inside face, so report collision */ - if (iter == 0 && d0 < 0.f && d0 > -radius) { + if (iter == 0 && d0 < 0.0f && d0 > -radius) { copy_v3_v3(pce->p, col->co1); copy_v3_v3(pce->nor, n); pce->inside = 1; - return 0.f; + return 0.0f; } /* Zero gradient (no movement relative to element). Can't step from @@ -2602,15 +2604,15 @@ static float collision_newton_rhapson(ParticleCollision *col, /* If first iteration, try from other end where the gradient may be * greater. Note: code duplicated below. */ if (iter == 0) { - t0 = 1.f; + t0 = 1.0f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co2, radius, pce, n); t1 = 1.0f - dt_init; - d1 = 0.f; + d1 = 0.0f; continue; } - return -1.f; + return -1.0f; } dd = (t1 - t0) / (d1 - d0); @@ -2622,30 +2624,30 @@ static float collision_newton_rhapson(ParticleCollision *col, /* Particle moving away from plane could also mean a strangely rotating * face, so check from end. Note: code duplicated above. */ - if (iter == 0 && t1 < 0.f) { - t0 = 1.f; + if (iter == 0 && t1 < 0.0f) { + t0 = 1.0f; collision_interpolate_element(pce, t0, col->f, col); d0 = distance_func(col->co2, radius, pce, n); t1 = 1.0f - dt_init; - d1 = 0.f; + d1 = 0.0f; continue; } - if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f)) { - return -1.f; + if (iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.0f)) { + return -1.0f; } if (d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) { - if (t1 >= -COLLISION_ZERO && t1 <= 1.f) { + if (t1 >= -COLLISION_ZERO && t1 <= 1.0f) { if (distance_func == nr_signed_distance_to_plane) { copy_v3_v3(pce->nor, n); } - CLAMP(t1, 0.f, 1.f); + CLAMP(t1, 0.0f, 1.0f); return t1; } - return -1.f; + return -1.0f; } } return -1.0; @@ -2663,7 +2665,7 @@ static int collision_sphere_to_tri(ParticleCollision *col, ct = collision_newton_rhapson(col, radius, pce, nr_signed_distance_to_plane); - if (ct >= 0.f && ct < *t && (result->inside == 0 || pce->inside == 1)) { + if (ct >= 0.0f && ct < *t && (result->inside == 0 || pce->inside == 1)) { float e1[3], e2[3], p0[3]; float e1e1, e1e2, e1p0, e2e2, e2p0, inv; @@ -2678,11 +2680,11 @@ static int collision_sphere_to_tri(ParticleCollision *col, e2e2 = dot_v3v3(e2, e2); e2p0 = dot_v3v3(e2, p0); - inv = 1.f / (e1e1 * e2e2 - e1e2 * e1e2); + inv = 1.0f / (e1e1 * e2e2 - e1e2 * e1e2); u = (e2e2 * e1p0 - e1e2 * e2p0) * inv; v = (e1e1 * e2p0 - e1e2 * e1p0) * inv; - if (u >= 0.f && u <= 1.f && v >= 0.f && u + v <= 1.f) { + if (u >= 0.0f && u <= 1.0f && v >= 0.0f && u + v <= 1.0f) { *result = *pce; /* normal already calculated in pce */ @@ -2718,14 +2720,14 @@ static int collision_sphere_to_edges(ParticleCollision *col, ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_edge); - if (ct >= 0.f && ct < *t) { + if (ct >= 0.0f && ct < *t) { float u, e[3], vec[3]; sub_v3_v3v3(e, cur->x1, cur->x0); sub_v3_v3v3(vec, cur->p, cur->x0); u = dot_v3v3(vec, e) / dot_v3v3(e, e); - if (u < 0.f || u > 1.f) { + if (u < 0.0f || u > 1.0f) { break; } @@ -2763,7 +2765,7 @@ static int collision_sphere_to_verts(ParticleCollision *col, ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_vert); - if (ct >= 0.f && ct < *t) { + if (ct >= 0.0f && ct < *t) { *result = *cur; sub_v3_v3v3(result->nor, cur->p, cur->x0); @@ -3019,7 +3021,7 @@ static int collision_response(ParticleSimulationData *sim, (vc_dot < 0.0f && v0_dot < 0.0f && vc_dot < v0_dot))) { mul_v3_v3fl(v0_nor, pce->nor, vc_dot); } - else if (v0_dot > 0.f) { + else if (v0_dot > 0.0f) { mul_v3_v3fl(v0_nor, pce->nor, vc_dot + v0_dot); } else { @@ -3045,25 +3047,25 @@ static int collision_response(ParticleSimulationData *sim, /* make sure particle stays on the right side of the surface */ if (!through) { - distance = collision_point_distance_with_normal(co, pce, -1.f, col, nor); + distance = collision_point_distance_with_normal(co, pce, -1.0f, col, nor); if (distance < col->radius + COLLISION_MIN_DISTANCE) { madd_v3_v3fl(co, nor, col->radius + COLLISION_MIN_DISTANCE - distance); } dot = dot_v3v3(nor, v0); - if (dot < 0.f) { + if (dot < 0.0f) { madd_v3_v3fl(v0, nor, -dot); } - distance = collision_point_distance_with_normal(pa->state.co, pce, 1.f, col, nor); + distance = collision_point_distance_with_normal(pa->state.co, pce, 1.0f, col, nor); if (distance < col->radius + COLLISION_MIN_DISTANCE) { madd_v3_v3fl(pa->state.co, nor, col->radius + COLLISION_MIN_DISTANCE - distance); } dot = dot_v3v3(nor, pa->state.vel); - if (dot < 0.f) { + if (dot < 0.0f) { madd_v3_v3fl(pa->state.vel, nor, -dot); } } @@ -3090,7 +3092,7 @@ static int collision_response(ParticleSimulationData *sim, static void collision_fail(ParticleData *pa, ParticleCollision *col) { /* final chance to prevent total failure, so stick to the surface and hope for the best */ - collision_point_on_surface(col->co1, &col->pce, 1.f, col, pa->state.co); + collision_point_on_surface(col->co1, &col->pce, 1.0f, col, pa->state.co); copy_v3_v3(pa->state.vel, col->pce.vel); mul_v3_fl(pa->state.vel, col->inv_timestep); @@ -3128,7 +3130,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa /* get acceleration (from gravity, forcefields etc. to be re-applied in collision response) */ sub_v3_v3v3(col.acc, pa->state.vel, pa->prev_state.vel); - mul_v3_fl(col.acc, 1.f / col.total_time); + mul_v3_fl(col.acc, 1.0f / col.total_time); /* set values for first iteration */ copy_v3_v3(col.co1, pa->prev_state.co); @@ -3925,7 +3927,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) if (ELEM(pa->alive, PARS_ALIVE, PARS_DYING) == 0 || (pa->flag & (PARS_UNEXIST | PARS_NO_DISP))) { - pa->state.time = -1.f; + pa->state.time = -1.0f; } } @@ -4149,20 +4151,17 @@ static bool particles_has_tracer(short parttype) static bool particles_has_spray(short parttype) { - return ((parttype == PART_FLUID_SPRAY) || (parttype == PART_FLUID_SPRAYFOAM) || - (parttype == PART_FLUID_SPRAYFOAMBUBBLE)); + return (ELEM(parttype, PART_FLUID_SPRAY, PART_FLUID_SPRAYFOAM, PART_FLUID_SPRAYFOAMBUBBLE)); } static bool particles_has_bubble(short parttype) { - return ((parttype == PART_FLUID_BUBBLE) || (parttype == PART_FLUID_FOAMBUBBLE) || - (parttype == PART_FLUID_SPRAYFOAMBUBBLE)); + return (ELEM(parttype, PART_FLUID_BUBBLE, PART_FLUID_FOAMBUBBLE, PART_FLUID_SPRAYFOAMBUBBLE)); } static bool particles_has_foam(short parttype) { - return ((parttype == PART_FLUID_FOAM) || (parttype == PART_FLUID_SPRAYFOAM) || - (parttype == PART_FLUID_SPRAYFOAMBUBBLE)); + return (ELEM(parttype, PART_FLUID_FOAM, PART_FLUID_SPRAYFOAM, PART_FLUID_SPRAYFOAMBUBBLE)); } static void particles_fluid_step(ParticleSimulationData *sim, @@ -4410,7 +4409,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, zero_v3(pa->state.ave); unit_qt(pa->state.rot); - pa->time = 1.f; + pa->time = 1.0f; pa->dietime = sim->scene->r.efra + 1; pa->lifetime = sim->scene->r.efra; pa->alive = PARS_ALIVE; @@ -4590,8 +4589,8 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ dt_frac = psys->dt_frac; for (t_frac = dt_frac; t_frac <= 1.0f; t_frac += dt_frac) { sim->courant_num = 0.0f; - dynamics_step(sim, cfra + dframe + t_frac - 1.f); - psys->cfra = cfra + dframe + t_frac - 1.f; + dynamics_step(sim, cfra + dframe + t_frac - 1.0f); + psys->cfra = cfra + dframe + t_frac - 1.0f; if (part->time_flag & PART_TIME_AUTOSF) { update_timestep(psys, sim); @@ -4692,17 +4691,17 @@ void BKE_particlesettings_fluid_default_settings(ParticleSettings *part) { SPHFluidSettings *fluid = part->fluid; - fluid->spring_k = 0.f; + fluid->spring_k = 0.0f; fluid->plasticity_constant = 0.1f; fluid->yield_ratio = 0.1f; - fluid->rest_length = 1.f; - fluid->viscosity_omega = 2.f; + fluid->rest_length = 1.0f; + fluid->viscosity_omega = 2.0f; fluid->viscosity_beta = 0.1f; - fluid->stiffness_k = 1.f; - fluid->stiffness_knear = 1.f; - fluid->rest_density = 1.f; - fluid->buoyancy = 0.f; - fluid->radius = 1.f; + fluid->stiffness_k = 1.0f; + fluid->stiffness_knear = 1.0f; + fluid->rest_density = 1.0f; + fluid->buoyancy = 0.0f; + fluid->radius = 1.0f; fluid->flag |= SPH_FAC_REPULSION | SPH_FAC_DENSITY | SPH_FAC_RADIUS | SPH_FAC_VISCOSITY | SPH_FAC_REST_LENGTH; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index d31b0d54784..09e4ad93baa 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -63,6 +63,7 @@ static void pbvh_bmesh_verify(PBVH *pbvh); #endif +/* -------------------------------------------------------------------- */ /** \name BMesh Utility API * * Use some local functions which assume triangles. diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 7c8527a8702..5c60b39e9c8 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -44,6 +44,7 @@ #include "DNA_simulation_types.h" #include "BLI_blenlib.h" +#include "BLI_endian_switch.h" #include "BLI_math.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -67,6 +68,8 @@ #include "BKE_scene.h" #include "BKE_softbody.h" +#include "BLO_read_write.h" + #include "BIK_api.h" #ifdef WITH_BULLET @@ -256,7 +259,9 @@ static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) SoftBody *soft = soft_v; return soft->totpoint; } -static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message)) +static void ptcache_softbody_error(const ID *UNUSED(owner_id), + void *UNUSED(soft_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -460,7 +465,7 @@ static void ptcache_particle_interpolate(int index, psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); - mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep)); + mul_v3_fl(pa->state.vel, 1.0f / (dfra * timestep)); pa->state.time = cfra; } @@ -471,7 +476,9 @@ static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) return psys->totpart; } -static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message)) +static void ptcache_particle_error(const ID *UNUSED(owner_id), + void *UNUSED(psys_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -642,10 +649,11 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) return clmd->clothObject ? clmd->clothObject->mvert_num : 0; } -static void ptcache_cloth_error(void *cloth_v, const char *message) +static void ptcache_cloth_error(const ID *owner_id, void *cloth_v, const char *message) { ClothModifierData *clmd = cloth_v; - BKE_modifier_set_error(&clmd->modifier, "%s", message); + BLI_assert(GS(owner_id->name) == ID_OB); + BKE_modifier_set_error((Object *)owner_id, &clmd->modifier, "%s", message); } static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) @@ -659,7 +667,9 @@ static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) return surface->data->total_points; } -static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message)) +static void ptcache_dynamicpaint_error(const ID *UNUSED(owner_id), + void *UNUSED(sd), + const char *UNUSED(message)) { /* ignored for now */ } @@ -731,8 +741,7 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { data_len = sizeof(PaintPoint); } - else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || - surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) { + else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WEIGHT)) { data_len = sizeof(float); } else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) { @@ -853,7 +862,9 @@ static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) return rbw->numbodies; } -static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message)) +static void ptcache_rigidbody_error(const struct ID *UNUSED(owner_id), + void *UNUSED(rb_v), + const char *UNUSED(message)) { /* ignored for now */ } @@ -2098,19 +2109,19 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra) } if (!ptcache_file_header_begin_read(pf)) { - pid->error(pid->calldata, "Failed to read point cache file"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file"); error = 1; } else if (pf->type != pid->type) { - pid->error(pid->calldata, "Point cache file has wrong type"); + pid->error(pid->owner_id, pid->calldata, "Point cache file has wrong type"); error = 1; } else if (!pid->read_header(pf)) { - pid->error(pid->calldata, "Failed to read point cache file header"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file header"); error = 1; } else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); error = 1; } @@ -2119,7 +2130,7 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra) /* We have stream reading here. */ if (!pid->read_stream(pf, pid->calldata)) { - pid->error(pid->calldata, "Failed to read point cache file data"); + pid->error(pid->owner_id, pid->calldata, "Failed to read point cache file data"); error = 1; } } @@ -2155,7 +2166,7 @@ static int ptcache_read(PTCacheID *pid, int cfra) int pid_totpoint = pid->totpoint(pid->calldata, cfra); if (totpoint != pid_totpoint) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); totpoint = MIN2(totpoint, pid_totpoint); } } @@ -2211,7 +2222,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra); if (totpoint != pid_totpoint) { - pid->error(pid->calldata, "Number of points in cache does not match mesh"); + pid->error(pid->owner_id, pid->calldata, "Number of points in cache does not match mesh"); totpoint = MIN2(totpoint, pid_totpoint); } } @@ -3771,3 +3782,124 @@ void BKE_ptcache_invalidate(PointCache *cache) cache->last_exact = MIN2(cache->startframe, 0); } } + +static const char *ptcache_data_struct[] = { + "", // BPHYS_DATA_INDEX + "", // BPHYS_DATA_LOCATION + "", // BPHYS_DATA_VELOCITY + "", // BPHYS_DATA_ROTATION + "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ + "", // BPHYS_DATA_SIZE: + "", // BPHYS_DATA_TIMES: + "BoidData", // case BPHYS_DATA_BOIDS: +}; +static const char *ptcache_extra_struct[] = { + "", + "ParticleSpring", + "vec3f", +}; +void BKE_ptcache_blend_write(BlendWriter *writer, ListBase *ptcaches) +{ + LISTBASE_FOREACH (PointCache *, cache, ptcaches) { + BLO_write_struct(writer, PointCache, cache); + + if ((cache->flag & PTCACHE_DISK_CACHE) == 0) { + LISTBASE_FOREACH (PTCacheMem *, pm, &cache->mem_cache) { + BLO_write_struct(writer, PTCacheMem, pm); + + for (int i = 0; i < BPHYS_TOT_DATA; i++) { + if (pm->data[i] && pm->data_types & (1 << i)) { + if (ptcache_data_struct[i][0] == '\0') { + BLO_write_raw(writer, MEM_allocN_len(pm->data[i]), pm->data[i]); + } + else { + BLO_write_struct_array_by_name( + writer, ptcache_data_struct[i], pm->totpoint, pm->data[i]); + } + } + } + + LISTBASE_FOREACH (PTCacheExtra *, extra, &pm->extradata) { + if (ptcache_extra_struct[extra->type][0] == '\0') { + continue; + } + BLO_write_struct(writer, PTCacheExtra, extra); + BLO_write_struct_array_by_name( + writer, ptcache_extra_struct[extra->type], extra->totdata, extra->data); + } + } + } + } +} + +static void direct_link_pointcache_cb(BlendDataReader *reader, void *data) +{ + PTCacheMem *pm = data; + for (int i = 0; i < BPHYS_TOT_DATA; i++) { + BLO_read_data_address(reader, &pm->data[i]); + + /* the cache saves non-struct data without DNA */ + if (pm->data[i] && ptcache_data_struct[i][0] == '\0' && + BLO_read_requires_endian_switch(reader)) { + /* data_size returns bytes. */ + int tot = (BKE_ptcache_data_size(i) * pm->totpoint) / sizeof(int); + + int *poin = pm->data[i]; + + BLI_endian_switch_int32_array(poin, tot); + } + } + + BLO_read_list(reader, &pm->extradata); + + LISTBASE_FOREACH (PTCacheExtra *, extra, &pm->extradata) { + BLO_read_data_address(reader, &extra->data); + } +} + +static void direct_link_pointcache(BlendDataReader *reader, PointCache *cache) +{ + if ((cache->flag & PTCACHE_DISK_CACHE) == 0) { + BLO_read_list_cb(reader, &cache->mem_cache, direct_link_pointcache_cb); + } + else { + BLI_listbase_clear(&cache->mem_cache); + } + + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe = 0; + cache->edit = NULL; + cache->free_edit = NULL; + cache->cached_frames = NULL; + cache->cached_frames_len = 0; +} + +void BKE_ptcache_blend_read_data(BlendDataReader *reader, + ListBase *ptcaches, + PointCache **ocache, + int force_disk) +{ + if (ptcaches->first) { + BLO_read_list(reader, ptcaches); + LISTBASE_FOREACH (PointCache *, cache, ptcaches) { + direct_link_pointcache(reader, cache); + if (force_disk) { + cache->flag |= PTCACHE_DISK_CACHE; + cache->step = 1; + } + } + + BLO_read_data_address(reader, ocache); + } + else if (*ocache) { + /* old "single" caches need to be linked too */ + BLO_read_data_address(reader, ocache); + direct_link_pointcache(reader, *ocache); + if (force_disk) { + (*ocache)->flag |= PTCACHE_DISK_CACHE; + (*ocache)->step = 1; + } + + ptcaches->first = ptcaches->last = *ocache; + } +} diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.cc index 78acf7251fa..cbfb1086e8d 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -67,7 +67,7 @@ static void pointcloud_init_data(ID *id) CustomData_add_layer_named(&pointcloud->pdata, CD_PROP_FLOAT3, CD_CALLOC, - NULL, + nullptr, pointcloud->totpoint, POINTCLOUD_ATTR_POSITION); BKE_pointcloud_update_customdata_pointers(pointcloud); @@ -77,7 +77,7 @@ static void pointcloud_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_s { PointCloud *pointcloud_dst = (PointCloud *)id_dst; const PointCloud *pointcloud_src = (const PointCloud *)id_src; - pointcloud_dst->mat = MEM_dupallocN(pointcloud_dst->mat); + pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_dst->mat)); const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE; CustomData_copy(&pointcloud_src->pdata, @@ -109,7 +109,7 @@ static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_a { PointCloud *pointcloud = (PointCloud *)id; if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) { - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE]; CustomData_blend_write_prepare( &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); @@ -164,26 +164,28 @@ static void pointcloud_blend_read_expand(BlendExpander *expander, ID *id) } IDTypeInfo IDType_ID_PT = { - .id_code = ID_PT, - .id_filter = FILTER_ID_PT, - .main_listbase_index = INDEX_ID_PT, - .struct_size = sizeof(PointCloud), - .name = "PointCloud", - .name_plural = "pointclouds", - .translation_context = BLT_I18NCONTEXT_ID_POINTCLOUD, - .flags = 0, - - .init_data = pointcloud_init_data, - .copy_data = pointcloud_copy_data, - .free_data = pointcloud_free_data, - .make_local = NULL, - .foreach_id = pointcloud_foreach_id, - .foreach_cache = NULL, - - .blend_write = pointcloud_blend_write, - .blend_read_data = pointcloud_blend_read_data, - .blend_read_lib = pointcloud_blend_read_lib, - .blend_read_expand = pointcloud_blend_read_expand, + /* id_code */ ID_PT, + /* id_filter */ FILTER_ID_PT, + /* main_listbase_index */ INDEX_ID_PT, + /* struct_size */ sizeof(PointCloud), + /* name */ "PointCloud", + /* name_plural */ "pointclouds", + /* translation_context */ BLT_I18NCONTEXT_ID_POINTCLOUD, + /* flags */ 0, + + /* init_data */ pointcloud_init_data, + /* copy_data */ pointcloud_copy_data, + /* free_data */ pointcloud_free_data, + /* make_local */ nullptr, + /* foreach_id */ pointcloud_foreach_id, + /* foreach_cache */ nullptr, + + /* blend_write */ pointcloud_blend_write, + /* blend_read_data */ pointcloud_blend_read_data, + /* blend_read_lib */ pointcloud_blend_read_lib, + /* blend_read_expand */ pointcloud_blend_read_expand, + + /* blend_read_undo_preserve */ nullptr, }; static void pointcloud_random(PointCloud *pointcloud) @@ -206,21 +208,21 @@ static void pointcloud_random(PointCloud *pointcloud) void *BKE_pointcloud_add(Main *bmain, const char *name) { - PointCloud *pointcloud = BKE_id_new(bmain, ID_PT, name); + PointCloud *pointcloud = static_cast<PointCloud *>(BKE_id_new(bmain, ID_PT, name)); return pointcloud; } void *BKE_pointcloud_add_default(Main *bmain, const char *name) { - PointCloud *pointcloud = BKE_libblock_alloc(bmain, ID_PT, name, 0); + PointCloud *pointcloud = static_cast<PointCloud *>(BKE_libblock_alloc(bmain, ID_PT, name, 0)); pointcloud_init_data(&pointcloud->id); CustomData_add_layer_named(&pointcloud->pdata, CD_PROP_FLOAT, CD_CALLOC, - NULL, + nullptr, pointcloud->totpoint, POINTCLOUD_ATTR_RADIUS); pointcloud_random(pointcloud); @@ -231,14 +233,14 @@ void *BKE_pointcloud_add_default(Main *bmain, const char *name) BoundBox *BKE_pointcloud_boundbox_get(Object *ob) { BLI_assert(ob->type == OB_POINTCLOUD); - PointCloud *pointcloud = ob->data; + PointCloud *pointcloud = static_cast<PointCloud *>(ob->data); - if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { + if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { return ob->runtime.bb; } - if (ob->runtime.bb == NULL) { - ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "pointcloud boundbox"); + if (ob->runtime.bb == nullptr) { + ob->runtime.bb = static_cast<BoundBox *>(MEM_callocN(sizeof(BoundBox), "pointcloud boundbox")); float min[3], max[3]; INIT_MINMAX(min, max); @@ -262,10 +264,10 @@ BoundBox *BKE_pointcloud_boundbox_get(Object *ob) void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) { - pointcloud->co = CustomData_get_layer_named( - &pointcloud->pdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION); - pointcloud->radius = CustomData_get_layer_named( - &pointcloud->pdata, CD_PROP_FLOAT, POINTCLOUD_ATTR_RADIUS); + pointcloud->co = static_cast<float(*)[3]>( + CustomData_get_layer_named(&pointcloud->pdata, CD_PROP_FLOAT3, POINTCLOUD_ATTR_POSITION)); + pointcloud->radius = static_cast<float *>( + CustomData_get_layer_named(&pointcloud->pdata, CD_PROP_FLOAT, POINTCLOUD_ATTR_RADIUS)); } bool BKE_pointcloud_customdata_required(PointCloud *UNUSED(pointcloud), CustomDataLayer *layer) @@ -277,11 +279,11 @@ bool BKE_pointcloud_customdata_required(PointCloud *UNUSED(pointcloud), CustomDa PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint) { - PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL); + PointCloud *pointcloud_dst = static_cast<PointCloud *>(BKE_id_new_nomain(ID_PT, nullptr)); CustomData_free(&pointcloud_dst->pdata, pointcloud_dst->totpoint); STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name); - pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat); + pointcloud_dst->mat = static_cast<Material **>(MEM_dupallocN(pointcloud_src->mat)); pointcloud_dst->totcol = pointcloud_src->totcol; pointcloud_dst->totpoint = totpoint; @@ -300,7 +302,7 @@ PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool flags |= LIB_ID_COPY_CD_REFERENCE; } - PointCloud *result = (PointCloud *)BKE_id_copy_ex(NULL, &pointcloud_src->id, NULL, flags); + PointCloud *result = (PointCloud *)BKE_id_copy_ex(nullptr, &pointcloud_src->id, nullptr, flags); return result; } @@ -324,7 +326,7 @@ static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, /* Evaluate modifiers. */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; @@ -343,7 +345,7 @@ static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, BKE_pointcloud_update_customdata_pointers(pointcloud); /* Created deformed coordinates array on demand. */ - mti->deformVerts(md, &mectx, NULL, pointcloud->co, pointcloud->totpoint); + mti->deformVerts(md, &mectx, nullptr, pointcloud->co, pointcloud->totpoint); } else if (mti->modifyPointCloud) { /* Ensure we are not modifying the input. */ @@ -356,7 +358,7 @@ static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, if (pointcloud_next && pointcloud_next != pointcloud) { /* If the modifier returned a new pointcloud, release the old one. */ if (pointcloud != pointcloud_input) { - BKE_id_free(NULL, pointcloud); + BKE_id_free(nullptr, pointcloud); } pointcloud = pointcloud_next; } @@ -372,7 +374,7 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene BKE_object_free_derived_caches(object); /* Evaluate modifiers. */ - PointCloud *pointcloud = object->data; + PointCloud *pointcloud = static_cast<PointCloud *>(object->data); PointCloud *pointcloud_eval = pointcloud_evaluate_modifiers( depsgraph, scene, object, pointcloud); @@ -382,8 +384,8 @@ void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene } /* Draw Cache */ -void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = NULL; -void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = NULL; +void (*BKE_pointcloud_batch_cache_dirty_tag_cb)(PointCloud *pointcloud, int mode) = nullptr; +void (*BKE_pointcloud_batch_cache_free_cb)(PointCloud *pointcloud) = nullptr; void BKE_pointcloud_batch_cache_dirty_tag(PointCloud *pointcloud, int mode) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 416f5aa7edd..bed10df5ace 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <stddef.h> #include <stdio.h> #include <string.h> @@ -70,6 +73,7 @@ #include "BKE_curveprofile.h" #include "BKE_duplilist.h" #include "BKE_editmesh.h" +#include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" #include "BKE_gpencil.h" @@ -87,10 +91,10 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" +#include "BKE_pointcache.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" #include "BKE_workspace.h" @@ -103,6 +107,10 @@ #include "RE_engine.h" +#include "SEQ_sequencer.h" + +#include "BLO_read_write.h" + #include "engines/eevee/eevee_lightcache.h" #include "PIL_time.h" @@ -454,53 +462,216 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE BKE_lib_query_foreachid_process(data, id_pointer, cb_flag); } -static void scene_foreach_paint(LibraryForeachIDData *data, Paint *paint) -{ - BKE_LIB_FOREACHID_PROCESS(data, paint->brush, IDWALK_CB_USER); - for (int i = 0; i < paint->tool_slots_len; i++) { - BKE_LIB_FOREACHID_PROCESS(data, paint->tool_slots[i].brush, IDWALK_CB_USER); +/** + * This code is shared by both the regular `foreach_id` looper, and the code trying to restore or + * preserve ID pointers like brushes across undoes. + */ +typedef enum eSceneForeachUndoPreserveProcess { + /* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID + * pointer from its old scene's value. */ + SCENE_FOREACH_UNDO_RESTORE, + /* Undo when preserving tool-settings from old scene, we want to keep the new value of that ID + * pointer. */ + SCENE_FOREACH_UNDO_NO_RESTORE, +} eSceneForeachUndoPreserveProcess; + +static void scene_foreach_toolsettings_id_pointer_process( + ID **id_p, + const eSceneForeachUndoPreserveProcess action, + BlendLibReader *reader, + ID **id_old_p, + const uint cb_flag) +{ + switch (action) { + case SCENE_FOREACH_UNDO_RESTORE: { + ID *id_old = *id_old_p; + /* Old data has not been remapped to new values of the pointers, if we want to keep the old + * pointer here we need its new address. */ + ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) : + NULL; + if (id_old_new != NULL) { + BLI_assert(ELEM(id_old, id_old_new, id_old_new->orig_id)); + *id_old_p = id_old_new; + if (cb_flag & IDWALK_CB_USER) { + id_us_plus_no_lib(id_old_new); + id_us_min(id_old); + } + break; + } + /* We failed to find a new valid pointer for the previous ID, just keep the current one as + * if we had been under SCENE_FOREACH_UNDO_NO_RESTORE case. */ + SWAP(ID *, *id_p, *id_old_p); + break; + } + case SCENE_FOREACH_UNDO_NO_RESTORE: + /* Counteract the swap of the whole ToolSettings container struct. */ + SWAP(ID *, *id_p, *id_old_p); + break; } - BKE_LIB_FOREACHID_PROCESS(data, paint->palette, IDWALK_CB_USER); } -static void scene_foreach_toolsettings(LibraryForeachIDData *data, ToolSettings *toolsett) -{ - BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.scene, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.object, IDWALK_CB_NOP); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.shape_object, IDWALK_CB_NOP); - - scene_foreach_paint(data, &toolsett->imapaint.paint); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.stencil, IDWALK_CB_USER); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.clone, IDWALK_CB_USER); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.canvas, IDWALK_CB_USER); +#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS( \ + __data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \ + { \ + if (__do_undo_restore) { \ + scene_foreach_toolsettings_id_pointer_process( \ + (ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \ + } \ + else { \ + BKE_LIB_FOREACHID_PROCESS(__data, __id, __cb_flag); \ + } \ + } \ + (void)0 + +static void scene_foreach_paint(LibraryForeachIDData *data, + Paint *paint, + const bool do_undo_restore, + BlendLibReader *reader, + Paint *paint_old) +{ + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + paint->brush, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->brush, + IDWALK_CB_USER); + for (int i = 0; i < paint_old->tool_slots_len; i++) { + /* This is a bit tricky. + * - In case we do not do `undo_restore`, `paint` and `paint_old` pointers are the same, so + * this is equivalent to simply looping over slots from `paint`. + * - In case we do `undo_restore`, we only want to consider the slots from the old one, since + * those are the one we keep in the end. + * + In case the new data has less valid slots, we feed in a dummy NULL pointer. + * + In case the new data has more valid slots, the extra ones are ignored. + */ + Brush *brush_tmp = NULL; + Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp; + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + *brush_p, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->brush, + IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + paint->palette, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + paint_old->palette, + IDWALK_CB_USER); +} + +static void scene_foreach_toolsettings(LibraryForeachIDData *data, + ToolSettings *toolsett, + const bool do_undo_restore, + BlendLibReader *reader, + ToolSettings *toolsett_old) +{ + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->particle.scene, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.scene, + IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->particle.object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.object, + IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->particle.shape_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->particle.shape_object, + IDWALK_CB_NOP); + + scene_foreach_paint( + data, &toolsett->imapaint.paint, do_undo_restore, reader, &toolsett_old->imapaint.paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->imapaint.stencil, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.stencil, + IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->imapaint.clone, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.clone, + IDWALK_CB_USER); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->imapaint.canvas, + do_undo_restore, + SCENE_FOREACH_UNDO_RESTORE, + reader, + toolsett_old->imapaint.canvas, + IDWALK_CB_USER); if (toolsett->vpaint) { - scene_foreach_paint(data, &toolsett->vpaint->paint); + scene_foreach_paint( + data, &toolsett->vpaint->paint, do_undo_restore, reader, &toolsett_old->vpaint->paint); } if (toolsett->wpaint) { - scene_foreach_paint(data, &toolsett->wpaint->paint); + scene_foreach_paint( + data, &toolsett->wpaint->paint, do_undo_restore, reader, &toolsett_old->wpaint->paint); } if (toolsett->sculpt) { - scene_foreach_paint(data, &toolsett->sculpt->paint); - BKE_LIB_FOREACHID_PROCESS(data, toolsett->sculpt->gravity_object, IDWALK_CB_NOP); + scene_foreach_paint( + data, &toolsett->sculpt->paint, do_undo_restore, reader, &toolsett_old->sculpt->paint); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->sculpt->gravity_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->sculpt->gravity_object, + IDWALK_CB_NOP); } if (toolsett->uvsculpt) { - scene_foreach_paint(data, &toolsett->uvsculpt->paint); + scene_foreach_paint( + data, &toolsett->uvsculpt->paint, do_undo_restore, reader, &toolsett_old->uvsculpt->paint); } if (toolsett->gp_paint) { - scene_foreach_paint(data, &toolsett->gp_paint->paint); + scene_foreach_paint( + data, &toolsett->gp_paint->paint, do_undo_restore, reader, &toolsett_old->gp_paint->paint); } if (toolsett->gp_vertexpaint) { - scene_foreach_paint(data, &toolsett->gp_vertexpaint->paint); + scene_foreach_paint(data, + &toolsett->gp_vertexpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_vertexpaint->paint); } if (toolsett->gp_sculptpaint) { - scene_foreach_paint(data, &toolsett->gp_sculptpaint->paint); + scene_foreach_paint(data, + &toolsett->gp_sculptpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_sculptpaint->paint); } if (toolsett->gp_weightpaint) { - scene_foreach_paint(data, &toolsett->gp_weightpaint->paint); + scene_foreach_paint(data, + &toolsett->gp_weightpaint->paint, + do_undo_restore, + reader, + &toolsett_old->gp_weightpaint->paint); } - BKE_LIB_FOREACHID_PROCESS(data, toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data, + toolsett->gp_sculpt.guide.reference_object, + do_undo_restore, + SCENE_FOREACH_UNDO_NO_RESTORE, + reader, + toolsett_old->gp_sculpt.guide.reference_object, + IDWALK_CB_NOP); } static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) @@ -592,7 +763,7 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) ToolSettings *toolsett = scene->toolsettings; if (toolsett) { - scene_foreach_toolsettings(data, toolsett); + scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett); } if (scene->rigidbody_world) { @@ -619,6 +790,889 @@ static void scene_foreach_cache(ID *id, user_data); } +static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Scene *sce = (Scene *)id; + + if (BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + /* XXX This UI data should not be stored in Scene at all... */ + memset(&sce->cursor, 0, sizeof(sce->cursor)); + } + + /* write LibData */ + BLO_write_id_struct(writer, Scene, id_address, &sce->id); + BKE_id_blend_write(writer, &sce->id); + + if (sce->adt) { + BKE_animdata_blend_write(writer, sce->adt); + } + BKE_keyingsets_blend_write(writer, &sce->keyingsets); + + /* direct data */ + ToolSettings *tos = sce->toolsettings; + BLO_write_struct(writer, ToolSettings, tos); + if (tos->vpaint) { + BLO_write_struct(writer, VPaint, tos->vpaint); + BKE_paint_blend_write(writer, &tos->vpaint->paint); + } + if (tos->wpaint) { + BLO_write_struct(writer, VPaint, tos->wpaint); + BKE_paint_blend_write(writer, &tos->wpaint->paint); + } + if (tos->sculpt) { + BLO_write_struct(writer, Sculpt, tos->sculpt); + BKE_paint_blend_write(writer, &tos->sculpt->paint); + } + if (tos->uvsculpt) { + BLO_write_struct(writer, UvSculpt, tos->uvsculpt); + BKE_paint_blend_write(writer, &tos->uvsculpt->paint); + } + if (tos->gp_paint) { + BLO_write_struct(writer, GpPaint, tos->gp_paint); + BKE_paint_blend_write(writer, &tos->gp_paint->paint); + } + if (tos->gp_vertexpaint) { + BLO_write_struct(writer, GpVertexPaint, tos->gp_vertexpaint); + BKE_paint_blend_write(writer, &tos->gp_vertexpaint->paint); + } + if (tos->gp_sculptpaint) { + BLO_write_struct(writer, GpSculptPaint, tos->gp_sculptpaint); + BKE_paint_blend_write(writer, &tos->gp_sculptpaint->paint); + } + if (tos->gp_weightpaint) { + BLO_write_struct(writer, GpWeightPaint, tos->gp_weightpaint); + BKE_paint_blend_write(writer, &tos->gp_weightpaint->paint); + } + /* write grease-pencil custom ipo curve to file */ + if (tos->gp_interpolate.custom_ipo) { + BKE_curvemapping_blend_write(writer, tos->gp_interpolate.custom_ipo); + } + /* write grease-pencil multiframe falloff curve to file */ + if (tos->gp_sculpt.cur_falloff) { + BKE_curvemapping_blend_write(writer, tos->gp_sculpt.cur_falloff); + } + /* write grease-pencil primitive curve to file */ + if (tos->gp_sculpt.cur_primitive) { + BKE_curvemapping_blend_write(writer, tos->gp_sculpt.cur_primitive); + } + /* Write the curve profile to the file. */ + if (tos->custom_bevel_profile_preset) { + BKE_curveprofile_blend_write(writer, tos->custom_bevel_profile_preset); + } + + BKE_paint_blend_write(writer, &tos->imapaint.paint); + + Editing *ed = sce->ed; + if (ed) { + Sequence *seq; + + BLO_write_struct(writer, Editing, ed); + + /* reset write flags too */ + + SEQ_ALL_BEGIN (ed, seq) { + if (seq->strip) { + seq->strip->done = false; + } + BLO_write_struct(writer, Sequence, seq); + } + SEQ_ALL_END; + + SEQ_ALL_BEGIN (ed, seq) { + if (seq->strip && seq->strip->done == 0) { + /* write strip with 'done' at 0 because readfile */ + + if (seq->effectdata) { + switch (seq->type) { + case SEQ_TYPE_COLOR: + BLO_write_struct(writer, SolidColorVars, seq->effectdata); + break; + case SEQ_TYPE_SPEED: + BLO_write_struct(writer, SpeedControlVars, seq->effectdata); + break; + case SEQ_TYPE_WIPE: + BLO_write_struct(writer, WipeVars, seq->effectdata); + break; + case SEQ_TYPE_GLOW: + BLO_write_struct(writer, GlowVars, seq->effectdata); + break; + case SEQ_TYPE_TRANSFORM: + BLO_write_struct(writer, TransformVars, seq->effectdata); + break; + case SEQ_TYPE_GAUSSIAN_BLUR: + BLO_write_struct(writer, GaussianBlurVars, seq->effectdata); + break; + case SEQ_TYPE_TEXT: + BLO_write_struct(writer, TextVars, seq->effectdata); + break; + case SEQ_TYPE_COLORMIX: + BLO_write_struct(writer, ColorMixVars, seq->effectdata); + break; + } + } + + BLO_write_struct(writer, Stereo3dFormat, seq->stereo3d_format); + + Strip *strip = seq->strip; + BLO_write_struct(writer, Strip, strip); + if (strip->crop) { + BLO_write_struct(writer, StripCrop, strip->crop); + } + if (strip->transform) { + BLO_write_struct(writer, StripTransform, strip->transform); + } + if (strip->proxy) { + BLO_write_struct(writer, StripProxy, strip->proxy); + } + if (seq->type == SEQ_TYPE_IMAGE) { + BLO_write_struct_array(writer, + StripElem, + MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), + strip->stripdata); + } + else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { + BLO_write_struct(writer, StripElem, strip->stripdata); + } + + strip->done = true; + } + + if (seq->prop) { + IDP_BlendWrite(writer, seq->prop); + } + + BKE_sequence_modifier_blend_write(writer, &seq->modifiers); + } + SEQ_ALL_END; + + /* new; meta stack too, even when its nasty restore code */ + LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) { + BLO_write_struct(writer, MetaStack, ms); + } + } + + if (sce->r.avicodecdata) { + BLO_write_struct(writer, AviCodecData, sce->r.avicodecdata); + if (sce->r.avicodecdata->lpFormat) { + BLO_write_raw(writer, (size_t)sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat); + } + if (sce->r.avicodecdata->lpParms) { + BLO_write_raw(writer, (size_t)sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms); + } + } + if (sce->r.ffcodecdata.properties) { + IDP_BlendWrite(writer, sce->r.ffcodecdata.properties); + } + + /* writing dynamic list of TimeMarkers to the blend file */ + LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) { + BLO_write_struct(writer, TimeMarker, marker); + + if (marker->prop != NULL) { + IDP_BlendWrite(writer, marker->prop); + } + } + + /* writing dynamic list of TransformOrientations to the blend file */ + LISTBASE_FOREACH (TransformOrientation *, ts, &sce->transform_spaces) { + BLO_write_struct(writer, TransformOrientation, ts); + } + + /* writing MultiView to the blend file */ + LISTBASE_FOREACH (SceneRenderView *, srv, &sce->r.views) { + BLO_write_struct(writer, SceneRenderView, srv); + } + + if (sce->nodetree) { + BLO_write_struct(writer, bNodeTree, sce->nodetree); + ntreeBlendWrite(writer, sce->nodetree); + } + + BKE_color_managed_view_settings_blend_write(writer, &sce->view_settings); + + /* writing RigidBodyWorld data to the blend file */ + if (sce->rigidbody_world) { + /* Set deprecated pointers to prevent crashes of older Blenders */ + sce->rigidbody_world->pointcache = sce->rigidbody_world->shared->pointcache; + sce->rigidbody_world->ptcaches = sce->rigidbody_world->shared->ptcaches; + BLO_write_struct(writer, RigidBodyWorld, sce->rigidbody_world); + + BLO_write_struct(writer, RigidBodyWorld_Shared, sce->rigidbody_world->shared); + BLO_write_struct(writer, EffectorWeights, sce->rigidbody_world->effector_weights); + BKE_ptcache_blend_write(writer, &(sce->rigidbody_world->shared->ptcaches)); + } + + BKE_previewimg_blend_write(writer, sce->preview); + BKE_curvemapping_curves_blend_write(writer, &sce->r.mblur_shutter_curve); + + LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { + BKE_view_layer_blend_write(writer, view_layer); + } + + if (sce->master_collection) { + BLO_write_struct(writer, Collection, sce->master_collection); + BKE_collection_blend_write_nolib(writer, sce->master_collection); + } + + /* Eevee Lightcache */ + if (sce->eevee.light_cache_data && !BLO_write_is_undo(writer)) { + BLO_write_struct(writer, LightCache, sce->eevee.light_cache_data); + EEVEE_lightcache_blend_write(writer, sce->eevee.light_cache_data); + } + + BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading); + + /* Freed on doversion. */ + BLI_assert(sce->layer_properties == NULL); +} + +static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint) +{ + /* TODO. is this needed */ + BLO_read_data_address(reader, paint); + + if (*paint) { + BKE_paint_blend_read_data(reader, scene, *paint); + } +} + +static void link_recurs_seq(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (Sequence *, seq, lb) { + if (seq->seqbase.first) { + link_recurs_seq(reader, &seq->seqbase); + } + } +} + +static void scene_blend_read_data(BlendDataReader *reader, ID *id) +{ + Scene *sce = (Scene *)id; + + sce->depsgraph_hash = NULL; + sce->fps_info = NULL; + + memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask)); + memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal)); + + BKE_sound_reset_scene_runtime(sce); + + /* set users to one by default, not in lib-link, this will increase it for compo nodes */ + id_us_ensure_real(&sce->id); + + BLO_read_list(reader, &(sce->base)); + + BLO_read_data_address(reader, &sce->adt); + BKE_animdata_blend_read_data(reader, sce->adt); + + BLO_read_list(reader, &sce->keyingsets); + BKE_keyingsets_blend_read_data(reader, &sce->keyingsets); + + BLO_read_data_address(reader, &sce->basact); + + BLO_read_data_address(reader, &sce->toolsettings); + if (sce->toolsettings) { + + /* Reset last_location and last_hit, so they are not remembered across sessions. In some files + * these are also NaN, which could lead to crashes in painting. */ + struct UnifiedPaintSettings *ups = &sce->toolsettings->unified_paint_settings; + zero_v3(ups->last_location); + ups->last_hit = 0; + + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->sculpt); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->vpaint); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->wpaint); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->uvsculpt); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_paint); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_vertexpaint); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_sculptpaint); + direct_link_paint_helper(reader, sce, (Paint **)&sce->toolsettings->gp_weightpaint); + + BKE_paint_blend_read_data(reader, sce, &sce->toolsettings->imapaint.paint); + + sce->toolsettings->particle.paintcursor = NULL; + sce->toolsettings->particle.scene = NULL; + sce->toolsettings->particle.object = NULL; + sce->toolsettings->gp_sculpt.paintcursor = NULL; + + /* relink grease pencil interpolation curves */ + BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo); + if (sce->toolsettings->gp_interpolate.custom_ipo) { + BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_interpolate.custom_ipo); + } + /* relink grease pencil multiframe falloff curve */ + BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_falloff); + if (sce->toolsettings->gp_sculpt.cur_falloff) { + BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_falloff); + } + /* relink grease pencil primitive curve */ + BLO_read_data_address(reader, &sce->toolsettings->gp_sculpt.cur_primitive); + if (sce->toolsettings->gp_sculpt.cur_primitive) { + BKE_curvemapping_blend_read(reader, sce->toolsettings->gp_sculpt.cur_primitive); + } + + /* Relink toolsettings curve profile */ + BLO_read_data_address(reader, &sce->toolsettings->custom_bevel_profile_preset); + if (sce->toolsettings->custom_bevel_profile_preset) { + BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset); + } + } + + if (sce->ed) { + ListBase *old_seqbasep = &sce->ed->seqbase; + + BLO_read_data_address(reader, &sce->ed); + Editing *ed = sce->ed; + + BLO_read_data_address(reader, &ed->act_seq); + ed->cache = NULL; + ed->prefetch_job = NULL; + + /* recursive link sequences, lb will be correctly initialized */ + link_recurs_seq(reader, &ed->seqbase); + + Sequence *seq; + SEQ_ALL_BEGIN (ed, seq) { + /* Do as early as possible, so that other parts of reading can rely on valid session UUID. */ + BKE_sequence_session_uuid_generate(seq); + + BLO_read_data_address(reader, &seq->seq1); + BLO_read_data_address(reader, &seq->seq2); + BLO_read_data_address(reader, &seq->seq3); + + /* a patch: after introduction of effects with 3 input strips */ + if (seq->seq3 == NULL) { + seq->seq3 = seq->seq2; + } + + BLO_read_data_address(reader, &seq->effectdata); + BLO_read_data_address(reader, &seq->stereo3d_format); + + if (seq->type & SEQ_TYPE_EFFECT) { + seq->flag |= SEQ_EFFECT_NOT_LOADED; + } + + if (seq->type == SEQ_TYPE_SPEED) { + SpeedControlVars *s = seq->effectdata; + s->frameMap = NULL; + } + + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + t->text_blf_id = SEQ_FONT_NOT_LOADED; + } + + BLO_read_data_address(reader, &seq->prop); + IDP_BlendDataRead(reader, &seq->prop); + + BLO_read_data_address(reader, &seq->strip); + if (seq->strip && seq->strip->done == 0) { + seq->strip->done = true; + + if (ELEM(seq->type, + SEQ_TYPE_IMAGE, + SEQ_TYPE_MOVIE, + SEQ_TYPE_SOUND_RAM, + SEQ_TYPE_SOUND_HD)) { + BLO_read_data_address(reader, &seq->strip->stripdata); + } + else { + seq->strip->stripdata = NULL; + } + BLO_read_data_address(reader, &seq->strip->crop); + BLO_read_data_address(reader, &seq->strip->transform); + BLO_read_data_address(reader, &seq->strip->proxy); + if (seq->strip->proxy) { + seq->strip->proxy->anim = NULL; + } + else if (seq->flag & SEQ_USE_PROXY) { + SEQ_proxy_set(seq, true); + } + + /* need to load color balance to it could be converted to modifier */ + BLO_read_data_address(reader, &seq->strip->color_balance); + } + + BKE_sequence_modifier_blend_read_data(reader, &seq->modifiers); + } + SEQ_ALL_END; + + /* link metastack, slight abuse of structs here, + * have to restore pointer to internal part in struct */ + { + Sequence temp; + void *poin; + intptr_t offset; + + offset = ((intptr_t) & (temp.seqbase)) - ((intptr_t)&temp); + + /* root pointer */ + if (ed->seqbasep == old_seqbasep) { + ed->seqbasep = &ed->seqbase; + } + else { + poin = POINTER_OFFSET(ed->seqbasep, -offset); + + poin = BLO_read_get_new_data_address(reader, poin); + + if (poin) { + ed->seqbasep = (ListBase *)POINTER_OFFSET(poin, offset); + } + else { + ed->seqbasep = &ed->seqbase; + } + } + /* stack */ + BLO_read_list(reader, &(ed->metastack)); + + LISTBASE_FOREACH (MetaStack *, ms, &ed->metastack) { + BLO_read_data_address(reader, &ms->parseq); + + if (ms->oldbasep == old_seqbasep) { + ms->oldbasep = &ed->seqbase; + } + else { + poin = POINTER_OFFSET(ms->oldbasep, -offset); + poin = BLO_read_get_new_data_address(reader, poin); + if (poin) { + ms->oldbasep = (ListBase *)POINTER_OFFSET(poin, offset); + } + else { + ms->oldbasep = &ed->seqbase; + } + } + } + } + } + +#ifdef DURIAN_CAMERA_SWITCH + /* Runtime */ + sce->r.mode &= ~R_NO_CAMERA_SWITCH; +#endif + + BLO_read_data_address(reader, &sce->r.avicodecdata); + if (sce->r.avicodecdata) { + BLO_read_data_address(reader, &sce->r.avicodecdata->lpFormat); + BLO_read_data_address(reader, &sce->r.avicodecdata->lpParms); + } + if (sce->r.ffcodecdata.properties) { + BLO_read_data_address(reader, &sce->r.ffcodecdata.properties); + IDP_BlendDataRead(reader, &sce->r.ffcodecdata.properties); + } + + BLO_read_list(reader, &(sce->markers)); + LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) { + BLO_read_data_address(reader, &marker->prop); + IDP_BlendDataRead(reader, &marker->prop); + } + + BLO_read_list(reader, &(sce->transform_spaces)); + BLO_read_list(reader, &(sce->r.layers)); + BLO_read_list(reader, &(sce->r.views)); + + LISTBASE_FOREACH (SceneRenderLayer *, srl, &sce->r.layers) { + BLO_read_data_address(reader, &srl->prop); + IDP_BlendDataRead(reader, &srl->prop); + BLO_read_list(reader, &(srl->freestyleConfig.modules)); + BLO_read_list(reader, &(srl->freestyleConfig.linesets)); + } + + BKE_color_managed_view_settings_blend_read_data(reader, &sce->view_settings); + + BLO_read_data_address(reader, &sce->rigidbody_world); + RigidBodyWorld *rbw = sce->rigidbody_world; + if (rbw) { + BLO_read_data_address(reader, &rbw->shared); + + if (rbw->shared == NULL) { + /* Link deprecated caches if they exist, so we can use them for versioning. + * We should only do this when rbw->shared == NULL, because those pointers + * are always set (for compatibility with older Blenders). We mustn't link + * the same pointcache twice. */ + BKE_ptcache_blend_read_data(reader, &rbw->ptcaches, &rbw->pointcache, false); + + /* make sure simulation starts from the beginning after loading file */ + if (rbw->pointcache) { + rbw->ltime = (float)rbw->pointcache->startframe; + } + } + else { + /* must nullify the reference to physics sim object, since it no-longer exist + * (and will need to be recalculated) + */ + rbw->shared->physics_world = NULL; + + /* link caches */ + BKE_ptcache_blend_read_data(reader, &rbw->shared->ptcaches, &rbw->shared->pointcache, false); + + /* make sure simulation starts from the beginning after loading file */ + if (rbw->shared->pointcache) { + rbw->ltime = (float)rbw->shared->pointcache->startframe; + } + } + rbw->objects = NULL; + rbw->numbodies = 0; + + /* set effector weights */ + BLO_read_data_address(reader, &rbw->effector_weights); + if (!rbw->effector_weights) { + rbw->effector_weights = BKE_effector_add_weights(NULL); + } + } + + BLO_read_data_address(reader, &sce->preview); + BKE_previewimg_blend_read(reader, sce->preview); + + BKE_curvemapping_blend_read(reader, &sce->r.mblur_shutter_curve); + +#ifdef USE_COLLECTION_COMPAT_28 + /* this runs before the very first doversion */ + if (sce->collection) { + BLO_read_data_address(reader, &sce->collection); + BKE_collection_compat_blend_read_data(reader, sce->collection); + } +#endif + + /* insert into global old-new map for reading without UI (link_global accesses it again) */ + BLO_read_glob_list(reader, &sce->view_layers); + LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { + BKE_view_layer_blend_read_data(reader, view_layer); + } + + if (BLO_read_data_is_undo(reader)) { + /* If it's undo do nothing here, caches are handled by higher-level generic calling code. */ + } + else { + /* else try to read the cache from file. */ + BLO_read_data_address(reader, &sce->eevee.light_cache_data); + if (sce->eevee.light_cache_data) { + EEVEE_lightcache_blend_read_data(reader, sce->eevee.light_cache_data); + } + } + EEVEE_lightcache_info_update(&sce->eevee); + + BKE_screen_view3d_shading_blend_read_data(reader, &sce->display.shading); + + BLO_read_data_address(reader, &sce->layer_properties); + IDP_BlendDataRead(reader, &sce->layer_properties); +} + +/* patch for missing scene IDs, can't be in do-versions */ +static void composite_patch(bNodeTree *ntree, Scene *scene) +{ + + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->id == NULL && node->type == CMP_NODE_R_LAYERS) { + node->id = &scene->id; + } + } +} + +static void scene_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Scene *sce = (Scene *)id; + + BKE_keyingsets_blend_read_lib(reader, &sce->id, &sce->keyingsets); + + BLO_read_id_address(reader, sce->id.lib, &sce->camera); + BLO_read_id_address(reader, sce->id.lib, &sce->world); + BLO_read_id_address(reader, sce->id.lib, &sce->set); + BLO_read_id_address(reader, sce->id.lib, &sce->gpd); + + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->imapaint.paint); + if (sce->toolsettings->sculpt) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->sculpt->paint); + } + if (sce->toolsettings->vpaint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->vpaint->paint); + } + if (sce->toolsettings->wpaint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->wpaint->paint); + } + if (sce->toolsettings->uvsculpt) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->uvsculpt->paint); + } + if (sce->toolsettings->gp_paint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->gp_paint->paint); + } + if (sce->toolsettings->gp_vertexpaint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->gp_vertexpaint->paint); + } + if (sce->toolsettings->gp_sculptpaint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->gp_sculptpaint->paint); + } + if (sce->toolsettings->gp_weightpaint) { + BKE_paint_blend_read_lib(reader, sce, &sce->toolsettings->gp_weightpaint->paint); + } + + if (sce->toolsettings->sculpt) { + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->sculpt->gravity_object); + } + + if (sce->toolsettings->imapaint.stencil) { + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->imapaint.stencil); + } + + if (sce->toolsettings->imapaint.clone) { + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->imapaint.clone); + } + + if (sce->toolsettings->imapaint.canvas) { + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->imapaint.canvas); + } + + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->particle.shape_object); + + BLO_read_id_address(reader, sce->id.lib, &sce->toolsettings->gp_sculpt.guide.reference_object); + + LISTBASE_FOREACH_MUTABLE (Base *, base_legacy, &sce->base) { + BLO_read_id_address(reader, sce->id.lib, &base_legacy->object); + + if (base_legacy->object == NULL) { + BLO_reportf_wrap(BLO_read_lib_reports(reader), + RPT_WARNING, + TIP_("LIB: object lost from scene: '%s'"), + sce->id.name + 2); + BLI_remlink(&sce->base, base_legacy); + if (base_legacy == sce->basact) { + sce->basact = NULL; + } + MEM_freeN(base_legacy); + } + } + + Sequence *seq; + SEQ_ALL_BEGIN (sce->ed, seq) { + IDP_BlendReadLib(reader, seq->prop); + + if (seq->ipo) { + BLO_read_id_address( + reader, sce->id.lib, &seq->ipo); /* XXX deprecated - old animation system */ + } + seq->scene_sound = NULL; + if (seq->scene) { + BLO_read_id_address(reader, sce->id.lib, &seq->scene); + seq->scene_sound = NULL; + } + if (seq->clip) { + BLO_read_id_address(reader, sce->id.lib, &seq->clip); + } + if (seq->mask) { + BLO_read_id_address(reader, sce->id.lib, &seq->mask); + } + if (seq->scene_camera) { + BLO_read_id_address(reader, sce->id.lib, &seq->scene_camera); + } + if (seq->sound) { + seq->scene_sound = NULL; + if (seq->type == SEQ_TYPE_SOUND_HD) { + seq->type = SEQ_TYPE_SOUND_RAM; + } + else { + BLO_read_id_address(reader, sce->id.lib, &seq->sound); + } + if (seq->sound) { + id_us_plus_no_lib((ID *)seq->sound); + seq->scene_sound = NULL; + } + } + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + BLO_read_id_address(reader, sce->id.lib, &t->text_font); + } + BLI_listbase_clear(&seq->anims); + + BKE_sequence_modifier_blend_read_lib(reader, sce, &seq->modifiers); + } + SEQ_ALL_END; + + LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) { + IDP_BlendReadLib(reader, marker->prop); + + if (marker->camera) { + BLO_read_id_address(reader, sce->id.lib, &marker->camera); + } + } + + /* rigidbody world relies on its linked collections */ + if (sce->rigidbody_world) { + RigidBodyWorld *rbw = sce->rigidbody_world; + if (rbw->group) { + BLO_read_id_address(reader, sce->id.lib, &rbw->group); + } + if (rbw->constraints) { + BLO_read_id_address(reader, sce->id.lib, &rbw->constraints); + } + if (rbw->effector_weights) { + BLO_read_id_address(reader, sce->id.lib, &rbw->effector_weights->group); + } + } + + if (sce->nodetree) { + composite_patch(sce->nodetree, sce); + } + + LISTBASE_FOREACH (SceneRenderLayer *, srl, &sce->r.layers) { + BLO_read_id_address(reader, sce->id.lib, &srl->mat_override); + LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &srl->freestyleConfig.modules) { + BLO_read_id_address(reader, sce->id.lib, &fmc->script); + } + LISTBASE_FOREACH (FreestyleLineSet *, fls, &srl->freestyleConfig.linesets) { + BLO_read_id_address(reader, sce->id.lib, &fls->linestyle); + BLO_read_id_address(reader, sce->id.lib, &fls->group); + } + } + /* Motion Tracking */ + BLO_read_id_address(reader, sce->id.lib, &sce->clip); + +#ifdef USE_COLLECTION_COMPAT_28 + if (sce->collection) { + BKE_collection_compat_blend_read_lib(reader, sce->id.lib, sce->collection); + } +#endif + + LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { + BKE_view_layer_blend_read_lib(reader, sce->id.lib, view_layer); + } + + if (sce->r.bake.cage_object) { + BLO_read_id_address(reader, sce->id.lib, &sce->r.bake.cage_object); + } + +#ifdef USE_SETSCENE_CHECK + if (sce->set != NULL) { + sce->flag |= SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK; + } +#endif +} + +static void scene_blend_read_expand(BlendExpander *expander, ID *id) +{ + Scene *sce = (Scene *)id; + + LISTBASE_FOREACH (Base *, base_legacy, &sce->base) { + BLO_expand(expander, base_legacy->object); + } + BLO_expand(expander, sce->camera); + BLO_expand(expander, sce->world); + + BKE_keyingsets_blend_read_expand(expander, &sce->keyingsets); + + if (sce->set) { + BLO_expand(expander, sce->set); + } + + LISTBASE_FOREACH (SceneRenderLayer *, srl, &sce->r.layers) { + BLO_expand(expander, srl->mat_override); + LISTBASE_FOREACH (FreestyleModuleConfig *, module, &srl->freestyleConfig.modules) { + if (module->script) { + BLO_expand(expander, module->script); + } + } + LISTBASE_FOREACH (FreestyleLineSet *, lineset, &srl->freestyleConfig.linesets) { + if (lineset->group) { + BLO_expand(expander, lineset->group); + } + BLO_expand(expander, lineset->linestyle); + } + } + + LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) { + IDP_BlendReadExpand(expander, view_layer->id_properties); + + LISTBASE_FOREACH (FreestyleModuleConfig *, module, &view_layer->freestyle_config.modules) { + if (module->script) { + BLO_expand(expander, module->script); + } + } + + LISTBASE_FOREACH (FreestyleLineSet *, lineset, &view_layer->freestyle_config.linesets) { + if (lineset->group) { + BLO_expand(expander, lineset->group); + } + BLO_expand(expander, lineset->linestyle); + } + } + + if (sce->gpd) { + BLO_expand(expander, sce->gpd); + } + + if (sce->ed) { + Sequence *seq; + + SEQ_ALL_BEGIN (sce->ed, seq) { + IDP_BlendReadExpand(expander, seq->prop); + + if (seq->scene) { + BLO_expand(expander, seq->scene); + } + if (seq->scene_camera) { + BLO_expand(expander, seq->scene_camera); + } + if (seq->clip) { + BLO_expand(expander, seq->clip); + } + if (seq->mask) { + BLO_expand(expander, seq->mask); + } + if (seq->sound) { + BLO_expand(expander, seq->sound); + } + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *data = seq->effectdata; + BLO_expand(expander, data->text_font); + } + } + SEQ_ALL_END; + } + + if (sce->rigidbody_world) { + BLO_expand(expander, sce->rigidbody_world->group); + BLO_expand(expander, sce->rigidbody_world->constraints); + } + + LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) { + IDP_BlendReadExpand(expander, marker->prop); + + if (marker->camera) { + BLO_expand(expander, marker->camera); + } + } + + BLO_expand(expander, sce->clip); + +#ifdef USE_COLLECTION_COMPAT_28 + if (sce->collection) { + BKE_collection_compat_blend_read_expand(expander, sce->collection); + } +#endif + + if (sce->r.bake.cage_object) { + BLO_expand(expander, sce->r.bake.cage_object); + } +} + +static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) +{ + Scene *scene_new = (Scene *)id_new; + Scene *scene_old = (Scene *)id_old; + + SWAP(View3DCursor, scene_old->cursor, scene_new->cursor); + if (scene_new->toolsettings != NULL && scene_old->toolsettings != NULL) { + /* First try to restore ID pointers that can be and should be preserved (like brushes or + * palettes), and counteract the swap of the whole ToolSettings structs below for the others + * (like object ones). */ + scene_foreach_toolsettings( + NULL, scene_new->toolsettings, true, reader, scene_old->toolsettings); + SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings); + } +} + IDTypeInfo IDType_ID_SCE = { .id_code = ID_SCE, .id_filter = FILTER_ID_SCE, @@ -638,10 +1692,12 @@ IDTypeInfo IDType_ID_SCE = { .foreach_id = scene_foreach_id, .foreach_cache = scene_foreach_cache, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = scene_blend_write, + .blend_read_data = scene_blend_read_data, + .blend_read_lib = scene_blend_read_lib, + .blend_read_expand = scene_blend_read_expand, + + .blend_read_undo_preserve = scene_undo_preserve, }; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; @@ -1971,7 +3027,7 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene } /* SCE_VIEWS_SETUP_BASIC */ - if (STREQ(srv->name, STEREO_LEFT_NAME) || STREQ(srv->name, STEREO_RIGHT_NAME)) { + if (STR_ELEM(srv->name, STEREO_LEFT_NAME, STEREO_RIGHT_NAME)) { return true; } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index d9686eba29a..568c0c6f567 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #ifdef WIN32 # include "BLI_winstuff.h" #endif @@ -49,14 +52,18 @@ #include "BLT_translation.h" +#include "BKE_gpencil.h" #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" +#include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_node.h" #include "BKE_screen.h" #include "BKE_workspace.h" +#include "BLO_read_write.h" + static void screen_free_data(ID *id) { bScreen *screen = (bScreen *)id; @@ -230,6 +237,60 @@ static void screen_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void screen_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bScreen *screen = (bScreen *)id; + /* Screens are reference counted, only saved if used by a workspace. */ + if (screen->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ + BLO_write_struct_at_address_with_filecode(writer, ID_SCRN, bScreen, id_address, screen); + BKE_id_blend_write(writer, &screen->id); + + BKE_previewimg_blend_write(writer, screen->preview); + + /* direct data */ + BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen)); + } +} + +/* Cannot use IDTypeInfo callback yet, because of the return value. */ +bool BKE_screen_blend_read_data(BlendDataReader *reader, bScreen *screen) +{ + bool success = true; + + screen->regionbase.first = screen->regionbase.last = NULL; + screen->context = NULL; + screen->active_region = NULL; + + BLO_read_data_address(reader, &screen->preview); + BKE_previewimg_blend_read(reader, screen->preview); + + if (!BKE_screen_area_map_blend_read_data(reader, AREAMAP_FROM_SCREEN(screen))) { + printf("Error reading Screen %s... removing it.\n", screen->id.name + 2); + success = false; + } + + return success; +} + +/* note: file read without screens option G_FILE_NO_UI; + * check lib pointers in call below */ +static void screen_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bScreen *screen = (bScreen *)id; + /* deprecated, but needed for versioning (will be NULL'ed then) */ + BLO_read_id_address(reader, screen->id.lib, &screen->scene); + + screen->animtimer = NULL; /* saved in rare cases */ + screen->tool_tip = NULL; + screen->scrubbing = false; + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + BKE_screen_area_blend_read_lib(reader, &screen->id, area); + } +} + IDTypeInfo IDType_ID_SCR = { .id_code = ID_SCR, .id_filter = 0, @@ -247,10 +308,13 @@ IDTypeInfo IDType_ID_SCR = { .foreach_id = screen_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, + .blend_write = screen_blend_write, + /* Cannot be used yet, because #direct_link_screen has a return value. */ .blend_read_data = NULL, - .blend_read_lib = NULL, + .blend_read_lib = screen_blend_read_lib, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /* ************ Spacetype/regiontype handling ************** */ @@ -312,7 +376,7 @@ SpaceType *BKE_spacetype_from_id(int spaceid) return NULL; } -ARegionType *BKE_regiontype_from_id_or_first(SpaceType *st, int regionid) +ARegionType *BKE_regiontype_from_id_or_first(const SpaceType *st, int regionid) { ARegionType *art; @@ -327,7 +391,7 @@ ARegionType *BKE_regiontype_from_id_or_first(SpaceType *st, int regionid) return st->regiontypes.first; } -ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) +ARegionType *BKE_regiontype_from_id(const SpaceType *st, int regionid) { ARegionType *art; @@ -404,7 +468,7 @@ static void panel_list_copy(ListBase *newlb, const ListBase *lb) } } -ARegion *BKE_area_region_copy(SpaceType *st, ARegion *region) +ARegion *BKE_area_region_copy(const SpaceType *st, const ARegion *region) { ARegion *newar = MEM_dupallocN(region); @@ -918,7 +982,7 @@ ARegion *BKE_area_find_region_xy(ScrArea *area, const int regiontype, int x, int if (area) { ARegion *region; for (region = area->regionbase.first; region; region = region->next) { - if ((regiontype == RGN_TYPE_ANY) || (region->regiontype == regiontype)) { + if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) { if (BLI_rcti_isect_pt(®ion->winrct, x, y)) { region_found = region; break; @@ -936,7 +1000,7 @@ ARegion *BKE_screen_find_region_xy(bScreen *screen, const int regiontype, int x, { ARegion *region_found = NULL; LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { - if ((regiontype == RGN_TYPE_ANY) || (region->regiontype == regiontype)) { + if (ELEM(regiontype, RGN_TYPE_ANY, region->regiontype)) { if (BLI_rcti_isect_pt(®ion->winrct, x, y)) { region_found = region; break; @@ -973,7 +1037,7 @@ ScrArea *BKE_screen_find_big_area(bScreen *screen, const int spacetype, const sh int size, maxsize = 0; for (area = screen->areabase.first; area; area = area->next) { - if ((spacetype == SPACE_TYPE_ANY) || (area->spacetype == spacetype)) { + if (ELEM(spacetype, SPACE_TYPE_ANY, area->spacetype)) { if (min <= area->winx && min <= area->winy) { size = area->winx * area->winy; if (size > maxsize) { @@ -994,7 +1058,7 @@ ScrArea *BKE_screen_area_map_find_area_xy(const ScrAreaMap *areamap, { LISTBASE_FOREACH (ScrArea *, area, &areamap->areabase) { if (BLI_rcti_isect_pt(&area->totrct, x, y)) { - if ((spacetype == SPACE_TYPE_ANY) || (area->spacetype == spacetype)) { + if (ELEM(spacetype, SPACE_TYPE_ANY, area->spacetype)) { return area; } break; @@ -1111,3 +1175,797 @@ void BKE_screen_header_alignment_reset(bScreen *screen) } screen->do_refresh = true; } + +void BKE_screen_view3d_shading_blend_write(BlendWriter *writer, View3DShading *shading) +{ + if (shading->prop) { + IDP_BlendWrite(writer, shading->prop); + } +} + +void BKE_screen_view3d_shading_blend_read_data(BlendDataReader *reader, View3DShading *shading) +{ + if (shading->prop) { + BLO_read_data_address(reader, &shading->prop); + IDP_BlendDataRead(reader, &shading->prop); + } +} + +static void write_region(BlendWriter *writer, ARegion *region, int spacetype) +{ + BLO_write_struct(writer, ARegion, region); + + if (region->regiondata) { + if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + return; + } + + switch (spacetype) { + case SPACE_VIEW3D: + if (region->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = region->regiondata; + BLO_write_struct(writer, RegionView3D, rv3d); + + if (rv3d->localvd) { + BLO_write_struct(writer, RegionView3D, rv3d->localvd); + } + if (rv3d->clipbb) { + BLO_write_struct(writer, BoundBox, rv3d->clipbb); + } + } + else { + printf("regiondata write missing!\n"); + } + break; + default: + printf("regiondata write missing!\n"); + } + } +} + +static void write_uilist(BlendWriter *writer, uiList *ui_list) +{ + BLO_write_struct(writer, uiList, ui_list); + + if (ui_list->properties) { + IDP_BlendWrite(writer, ui_list->properties); + } +} + +static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner) +{ + BLI_mempool *ts = space_outliner->treestore; + + if (ts) { + SpaceOutliner space_outliner_flat = *space_outliner; + + int elems = BLI_mempool_len(ts); + /* linearize mempool to array */ + TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; + + if (data) { + /* In this block we use the memory location of the treestore + * but _not_ its data, the addresses in this case are UUID's, + * since we can't rely on malloc giving us different values each time. + */ + TreeStore ts_flat = {0}; + + /* we know the treestore is at least as big as a pointer, + * so offsetting works to give us a UUID. */ + void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); + + ts_flat.usedelem = elems; + ts_flat.totelem = elems; + ts_flat.data = data_addr; + + BLO_write_struct(writer, SpaceOutliner, space_outliner); + + BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat); + BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data); + + MEM_freeN(data); + } + else { + space_outliner_flat.treestore = NULL; + BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat); + } + } + else { + BLO_write_struct(writer, SpaceOutliner, space_outliner); + } +} + +static void write_panel_list(BlendWriter *writer, ListBase *lb) +{ + LISTBASE_FOREACH (Panel *, panel, lb) { + BLO_write_struct(writer, Panel, panel); + write_panel_list(writer, &panel->children); + } +} + +static void write_area_regions(BlendWriter *writer, ScrArea *area) +{ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + write_region(writer, region, area->spacetype); + write_panel_list(writer, ®ion->panels); + + LISTBASE_FOREACH (PanelCategoryStack *, pc_act, ®ion->panels_category_active) { + BLO_write_struct(writer, PanelCategoryStack, pc_act); + } + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + write_uilist(writer, ui_list); + } + + LISTBASE_FOREACH (uiPreview *, ui_preview, ®ion->ui_previews) { + BLO_write_struct(writer, uiPreview, ui_preview); + } + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + write_region(writer, region, sl->spacetype); + } + + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + BLO_write_struct(writer, View3D, v3d); + + if (v3d->localvd) { + BLO_write_struct(writer, View3D, v3d->localvd); + } + + BKE_screen_view3d_shading_blend_write(writer, &v3d->shading); + } + else if (sl->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = (SpaceGraph *)sl; + ListBase tmpGhosts = sipo->runtime.ghost_curves; + + /* temporarily disable ghost curves when saving */ + BLI_listbase_clear(&sipo->runtime.ghost_curves); + + BLO_write_struct(writer, SpaceGraph, sl); + if (sipo->ads) { + BLO_write_struct(writer, bDopeSheet, sipo->ads); + } + + /* reenable ghost curves */ + sipo->runtime.ghost_curves = tmpGhosts; + } + else if (sl->spacetype == SPACE_PROPERTIES) { + BLO_write_struct(writer, SpaceProperties, sl); + } + else if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + BLO_write_struct(writer, SpaceFile, sl); + if (sfile->params) { + BLO_write_struct(writer, FileSelectParams, sfile->params); + } + } + else if (sl->spacetype == SPACE_SEQ) { + BLO_write_struct(writer, SpaceSeq, sl); + } + else if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + write_space_outliner(writer, space_outliner); + } + else if (sl->spacetype == SPACE_IMAGE) { + BLO_write_struct(writer, SpaceImage, sl); + } + else if (sl->spacetype == SPACE_TEXT) { + BLO_write_struct(writer, SpaceText, sl); + } + else if (sl->spacetype == SPACE_SCRIPT) { + SpaceScript *scr = (SpaceScript *)sl; + scr->but_refs = NULL; + BLO_write_struct(writer, SpaceScript, sl); + } + else if (sl->spacetype == SPACE_ACTION) { + BLO_write_struct(writer, SpaceAction, sl); + } + else if (sl->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)sl; + + BLO_write_struct(writer, SpaceNla, snla); + if (snla->ads) { + BLO_write_struct(writer, bDopeSheet, snla->ads); + } + } + else if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + BLO_write_struct(writer, SpaceNode, snode); + + LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) { + BLO_write_struct(writer, bNodeTreePath, path); + } + } + else if (sl->spacetype == SPACE_CONSOLE) { + SpaceConsole *con = (SpaceConsole *)sl; + + LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) { + /* 'len_alloc' is invalid on write, set from 'len' on read */ + BLO_write_struct(writer, ConsoleLine, cl); + BLO_write_raw(writer, (size_t)cl->len + 1, cl->line); + } + BLO_write_struct(writer, SpaceConsole, sl); + } + else if (sl->spacetype == SPACE_TOPBAR) { + BLO_write_struct(writer, SpaceTopBar, sl); + } + else if (sl->spacetype == SPACE_STATUSBAR) { + BLO_write_struct(writer, SpaceStatusBar, sl); + } + else if (sl->spacetype == SPACE_USERPREF) { + BLO_write_struct(writer, SpaceUserPref, sl); + } + else if (sl->spacetype == SPACE_CLIP) { + BLO_write_struct(writer, SpaceClip, sl); + } + else if (sl->spacetype == SPACE_INFO) { + BLO_write_struct(writer, SpaceInfo, sl); + } + } +} + +void BKE_screen_area_map_blend_write(BlendWriter *writer, ScrAreaMap *area_map) +{ + BLO_write_struct_list(writer, ScrVert, &area_map->vertbase); + BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */ + + BLO_write_struct(writer, ScrArea, area); + + BLO_write_struct(writer, ScrGlobalAreaData, area->global); + + write_area_regions(writer, area); + + area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */ + } +} + +static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (Panel *, panel, lb) { + panel->runtime_flag = 0; + panel->activedata = NULL; + panel->type = NULL; + panel->runtime.custom_data_ptr = NULL; + direct_link_panel_list(reader, &panel->children); + } +} + +static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype) +{ + direct_link_panel_list(reader, ®ion->panels); + + BLO_read_list(reader, ®ion->panels_category_active); + + BLO_read_list(reader, ®ion->ui_lists); + + /* The area's search filter is runtime only, so we need to clear the active flag on read. */ + region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE; + + LISTBASE_FOREACH (uiList *, ui_list, ®ion->ui_lists) { + ui_list->type = NULL; + ui_list->dyn_data = NULL; + BLO_read_data_address(reader, &ui_list->properties); + IDP_BlendDataRead(reader, &ui_list->properties); + } + + BLO_read_list(reader, ®ion->ui_previews); + + if (spacetype == SPACE_EMPTY) { + /* unknown space type, don't leak regiondata */ + region->regiondata = NULL; + } + else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) { + /* Runtime data, don't use. */ + region->regiondata = NULL; + } + else { + BLO_read_data_address(reader, ®ion->regiondata); + if (region->regiondata) { + if (spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = region->regiondata; + + BLO_read_data_address(reader, &rv3d->localvd); + BLO_read_data_address(reader, &rv3d->clipbb); + + rv3d->depths = NULL; + rv3d->render_engine = NULL; + rv3d->sms = NULL; + rv3d->smooth_timer = NULL; + + rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING); + rv3d->runtime_viewlock = 0; + } + } + } + + region->v2d.sms = NULL; + region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */ + BLI_listbase_clear(®ion->panels_category); + BLI_listbase_clear(®ion->handlers); + BLI_listbase_clear(®ion->uiblocks); + region->headerstr = NULL; + region->visible = 0; + region->type = NULL; + region->do_draw = 0; + region->gizmo_map = NULL; + region->regiontimer = NULL; + region->draw_buffer = NULL; + memset(®ion->drawrct, 0, sizeof(region->drawrct)); +} + +/* for the saved 2.50 files without regiondata */ +/* and as patch for 2.48 and older */ +void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions) +{ + LISTBASE_FOREACH (ARegion *, region, regions) { + if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) { + RegionView3D *rv3d; + + rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch"); + rv3d->persp = (char)v3d->persp; + rv3d->view = (char)v3d->view; + rv3d->dist = v3d->dist; + copy_v3_v3(rv3d->ofs, v3d->ofs); + copy_qt_qt(rv3d->viewquat, v3d->viewquat); + } + } + + /* this was not initialized correct always */ + if (v3d->gridsubdiv == 0) { + v3d->gridsubdiv = 10; + } +} + +static void direct_link_area(BlendDataReader *reader, ScrArea *area) +{ + BLO_read_list(reader, &(area->spacedata)); + BLO_read_list(reader, &(area->regionbase)); + + BLI_listbase_clear(&area->handlers); + area->type = NULL; /* spacetype callbacks */ + + /* Should always be unset so that rna_Area_type_get works correctly. */ + area->butspacetype = SPACE_EMPTY; + + area->region_active_win = -1; + + area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE; + + BLO_read_data_address(reader, &area->global); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(area->spacetype)) { + /* Hint for versioning code to replace deprecated space types. */ + area->butspacetype = area->spacetype; + + area->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + direct_link_region(reader, region, area->spacetype); + } + + /* accident can happen when read/save new file with older version */ + /* 2.50: we now always add spacedata for info */ + if (area->spacedata.first == NULL) { + SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo"); + area->spacetype = sinfo->spacetype = SPACE_INFO; + BLI_addtail(&area->spacedata, sinfo); + } + /* add local view3d too */ + else if (area->spacetype == SPACE_VIEW3D) { + BKE_screen_view3d_do_versions_250(area->spacedata.first, &area->regionbase); + } + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + BLO_read_list(reader, &(sl->regionbase)); + + /* if we do not have the spacetype registered we cannot + * free it, so don't allocate any new memory for such spacetypes. */ + if (!BKE_spacetype_exists(sl->spacetype)) { + sl->spacetype = SPACE_EMPTY; + } + + LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) { + direct_link_region(reader, region, sl->spacetype); + } + + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + + v3d->flag |= V3D_INVALID_BACKBUF; + + if (v3d->gpd) { + BLO_read_data_address(reader, &v3d->gpd); + BKE_gpencil_blend_read_data(reader, v3d->gpd); + } + BLO_read_data_address(reader, &v3d->localvd); + + /* Runtime data */ + v3d->runtime.properties_storage = NULL; + v3d->runtime.flag = 0; + + /* render can be quite heavy, set to solid on load */ + if (v3d->shading.type == OB_RENDER) { + v3d->shading.type = OB_SOLID; + } + v3d->shading.prev_type = OB_SOLID; + + BKE_screen_view3d_shading_blend_read_data(reader, &v3d->shading); + + BKE_screen_view3d_do_versions_250(v3d, &sl->regionbase); + } + else if (sl->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = (SpaceGraph *)sl; + + BLO_read_data_address(reader, &sipo->ads); + BLI_listbase_clear(&sipo->runtime.ghost_curves); + } + else if (sl->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)sl; + + BLO_read_data_address(reader, &snla->ads); + } + else if (sl->spacetype == SPACE_OUTLINER) { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + + /* use #BLO_read_get_new_data_address_no_us and do not free old memory avoiding double + * frees and use of freed memory. this could happen because of a + * bug fixed in revision 58959 where the treestore memory address + * was not unique */ + TreeStore *ts = BLO_read_get_new_data_address_no_us(reader, space_outliner->treestore); + space_outliner->treestore = NULL; + if (ts) { + TreeStoreElem *elems = BLO_read_get_new_data_address_no_us(reader, ts->data); + + space_outliner->treestore = BLI_mempool_create( + sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER); + if (ts->usedelem && elems) { + for (int i = 0; i < ts->usedelem; i++) { + TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore); + *new_elem = elems[i]; + } + } + /* we only saved what was used */ + space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */ + } + space_outliner->treehash = NULL; + space_outliner->tree.first = space_outliner->tree.last = NULL; + } + else if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + + sima->iuser.scene = NULL; + sima->iuser.ok = 1; + sima->scopes.waveform_1 = NULL; + sima->scopes.waveform_2 = NULL; + sima->scopes.waveform_3 = NULL; + sima->scopes.vecscope = NULL; + sima->scopes.ok = 0; + + /* WARNING: gpencil data is no longer stored directly in sima after 2.5 + * so sacrifice a few old files for now to avoid crashes with new files! + * committed: r28002 */ +#if 0 + sima->gpd = newdataadr(fd, sima->gpd); + if (sima->gpd) { + BKE_gpencil_blend_read_data(fd, sima->gpd); + } +#endif + } + else if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + + if (snode->gpd) { + BLO_read_data_address(reader, &snode->gpd); + BKE_gpencil_blend_read_data(reader, snode->gpd); + } + + BLO_read_list(reader, &snode->treepath); + snode->edittree = NULL; + snode->iofsd = NULL; + BLI_listbase_clear(&snode->linkdrag); + } + else if (sl->spacetype == SPACE_TEXT) { + SpaceText *st = (SpaceText *)sl; + memset(&st->runtime, 0, sizeof(st->runtime)); + } + else if (sl->spacetype == SPACE_SEQ) { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* grease pencil data is not a direct data and can't be linked from direct_link* + * functions, it should be linked from lib_link* functions instead + * + * otherwise it'll lead to lost grease data on open because it'll likely be + * read from file after all other users of grease pencil and newdataadr would + * simple return NULL here (sergey) + */ +#if 0 + if (sseq->gpd) { + sseq->gpd = newdataadr(fd, sseq->gpd); + BKE_gpencil_blend_read_data(fd, sseq->gpd); + } +#endif + sseq->scopes.reference_ibuf = NULL; + sseq->scopes.zebra_ibuf = NULL; + sseq->scopes.waveform_ibuf = NULL; + sseq->scopes.sep_waveform_ibuf = NULL; + sseq->scopes.vector_ibuf = NULL; + sseq->scopes.histogram_ibuf = NULL; + } + else if (sl->spacetype == SPACE_PROPERTIES) { + SpaceProperties *sbuts = (SpaceProperties *)sl; + + sbuts->path = NULL; + sbuts->texuser = NULL; + sbuts->mainbo = sbuts->mainb; + sbuts->mainbuser = sbuts->mainb; + sbuts->runtime = NULL; + } + else if (sl->spacetype == SPACE_CONSOLE) { + SpaceConsole *sconsole = (SpaceConsole *)sl; + + BLO_read_list(reader, &sconsole->scrollback); + BLO_read_list(reader, &sconsole->history); + + /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression, + * from left to right. the right-most expression sets the result of the comma + * expression as a whole*/ + LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) { + BLO_read_data_address(reader, &cl->line); + if (cl->line) { + /* the allocted length is not written, so reset here */ + cl->len_alloc = cl->len + 1; + } + else { + BLI_remlink(&sconsole->history, cl); + MEM_freeN(cl); + } + } + } + else if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + /* this sort of info is probably irrelevant for reloading... + * plus, it isn't saved to files yet! + */ + sfile->folders_prev = sfile->folders_next = NULL; + sfile->files = NULL; + sfile->layout = NULL; + sfile->op = NULL; + sfile->previews_timer = NULL; + BLO_read_data_address(reader, &sfile->params); + } + else if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sclip = (SpaceClip *)sl; + + sclip->scopes.track_search = NULL; + sclip->scopes.track_preview = NULL; + sclip->scopes.ok = 0; + } + } + + BLI_listbase_clear(&area->actionzones); + + BLO_read_data_address(reader, &area->v1); + BLO_read_data_address(reader, &area->v2); + BLO_read_data_address(reader, &area->v3); + BLO_read_data_address(reader, &area->v4); +} + +/** + * \return false on error. + */ +bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *area_map) +{ + BLO_read_list(reader, &area_map->vertbase); + BLO_read_list(reader, &area_map->edgebase); + BLO_read_list(reader, &area_map->areabase); + LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) { + direct_link_area(reader, area); + } + + /* edges */ + LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) { + BLO_read_data_address(reader, &se->v1); + BLO_read_data_address(reader, &se->v2); + BKE_screen_sort_scrvert(&se->v1, &se->v2); + + if (se->v1 == NULL) { + BLI_remlink(&area_map->edgebase, se); + + return false; + } + } + + return true; +} + +void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrArea *area) +{ + BLO_read_id_address(reader, parent_id->lib, &area->full); + + memset(&area->runtime, 0x0, sizeof(area->runtime)); + + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + switch (sl->spacetype) { + case SPACE_VIEW3D: { + View3D *v3d = (View3D *)sl; + + BLO_read_id_address(reader, parent_id->lib, &v3d->camera); + BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center); + + if (v3d->localvd) { + BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera); + } + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; + bDopeSheet *ads = sipo->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + break; + } + case SPACE_PROPERTIES: { + SpaceProperties *sbuts = (SpaceProperties *)sl; + BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } + break; + } + case SPACE_FILE: + break; + case SPACE_ACTION: { + SpaceAction *saction = (SpaceAction *)sl; + bDopeSheet *ads = &saction->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + + BLO_read_id_address(reader, parent_id->lib, &saction->action); + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = (SpaceImage *)sl; + + BLO_read_id_address(reader, parent_id->lib, &sima->image); + BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask); + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + BLO_read_id_address(reader, parent_id->lib, &sima->gpd); + break; + } + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + BLO_read_id_address(reader, parent_id->lib, &sseq->gpd); + break; + } + case SPACE_NLA: { + SpaceNla *snla = (SpaceNla *)sl; + bDopeSheet *ads = snla->ads; + + if (ads) { + BLO_read_id_address(reader, parent_id->lib, &ads->source); + BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp); + } + break; + } + case SPACE_TEXT: { + SpaceText *st = (SpaceText *)sl; + + BLO_read_id_address(reader, parent_id->lib, &st->text); + break; + } + case SPACE_SCRIPT: { + SpaceScript *scpt = (SpaceScript *)sl; + /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ + if (scpt->script) { + BLO_read_id_address(reader, parent_id->lib, &scpt->script); + if (scpt->script) { + SCRIPT_SET_NULL(scpt->script); + } + } + break; + } + case SPACE_OUTLINER: { + SpaceOutliner *space_outliner = (SpaceOutliner *)sl; + BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id); + + if (space_outliner->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(space_outliner->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + BLO_read_id_address(reader, NULL, &tselem->id); + } + if (space_outliner->treehash) { + /* rebuild hash table, because it depends on ids too */ + space_outliner->storeflag |= SO_TREESTORE_REBUILD; + } + } + break; + } + case SPACE_NODE: { + SpaceNode *snode = (SpaceNode *)sl; + + /* node tree can be stored locally in id too, link this first */ + BLO_read_id_address(reader, parent_id->lib, &snode->id); + BLO_read_id_address(reader, parent_id->lib, &snode->from); + + bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL; + if (ntree) { + snode->nodetree = ntree; + } + else { + BLO_read_id_address(reader, parent_id->lib, &snode->nodetree); + } + + bNodeTreePath *path; + for (path = snode->treepath.first; path; path = path->next) { + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + path->nodetree = snode->nodetree; + } + else { + BLO_read_id_address(reader, parent_id->lib, &path->nodetree); + } + + if (!path->nodetree) { + break; + } + } + + /* remaining path entries are invalid, remove */ + bNodeTreePath *path_next; + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); + } + + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; + } + else { + snode->edittree = NULL; + } + break; + } + case SPACE_CLIP: { + SpaceClip *sclip = (SpaceClip *)sl; + BLO_read_id_address(reader, parent_id->lib, &sclip->clip); + BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask); + break; + } + default: + break; + } + } +} diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index f2cdf08b415..3727ec866ca 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -36,6 +36,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "DNA_shader_fx_types.h" #include "BKE_gpencil.h" @@ -49,6 +50,8 @@ #include "FX_shader_types.h" +#include "BLO_read_write.h" + static ShaderFxTypeInfo *shader_fx_types[NUM_SHADER_FX_TYPES] = {NULL}; /* *************************************************** */ @@ -175,6 +178,11 @@ void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname) strcat(r_idname, fxi->name); } +void BKE_shaderfx_panel_expand(ShaderFxData *fx) +{ + fx->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT; +} + void BKE_shaderfx_copydata_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) { const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx_src->type); @@ -270,3 +278,45 @@ ShaderFxData *BKE_shaderfx_findby_name(Object *ob, const char *name) { return BLI_findstring(&(ob->shader_fx), name, offsetof(ShaderFxData, name)); } + +void BKE_shaderfx_blend_write(BlendWriter *writer, ListBase *fxbase) +{ + if (fxbase == NULL) { + return; + } + + LISTBASE_FOREACH (ShaderFxData *, fx, fxbase) { + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); + if (fxi == NULL) { + return; + } + + BLO_write_struct_by_name(writer, fxi->struct_name, fx); + } +} + +void BKE_shaderfx_blend_read_data(BlendDataReader *reader, ListBase *lb) +{ + BLO_read_list(reader, lb); + + LISTBASE_FOREACH (ShaderFxData *, fx, lb) { + fx->error = NULL; + + /* if shader disappear, or for upward compatibility */ + if (NULL == BKE_shaderfx_get_info(fx->type)) { + fx->type = eShaderFxType_None; + } + } +} + +void BKE_shaderfx_blend_read_lib(BlendLibReader *reader, Object *ob) +{ + BKE_shaderfx_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 (ShaderFxData *, fx, &ob->shader_fx) { + fx->flag &= ~eShaderFxFlag_OverrideLibrary_Local; + } + } +} diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 0c9ee61ca19..ae39b200b56 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -1548,8 +1548,8 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object ssmd.shrinkMode = MOD_SHRINKWRAP_ON_SURFACE; ssmd.shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR; ssmd.keepDist = 0.0f; - - /* Tolerance value to prevent artifacts on sharp edges of a mesh. + + /* Tolerance value to prevent artifacts on sharp edges of a mesh. * This constant and based on experimenting with different values. */ const float projLimitTolerance = 5.0f; ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance; diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 2e1f8bd581e..861779ec700 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -165,12 +165,14 @@ IDTypeInfo IDType_ID_SIM = { /* free_data */ simulation_free_data, /* make_local */ nullptr, /* foreach_id */ simulation_foreach_id, - /* foreach_cache */ NULL, + /* foreach_cache */ nullptr, /* blend_write */ simulation_blend_write, /* blend_read_data */ simulation_blend_read_data, /* blend_read_lib */ simulation_blend_read_lib, /* blend_read_expand */ simulation_blend_read_expand, + + /* blend_read_undo_preserve */ nullptr, }; void *BKE_simulation_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index bf61c27ee2f..efed9453003 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1063,7 +1063,7 @@ static int sb_detect_face_pointCached(const float face_v1[3], GHash *hash; GHashIterator *ihash; float nv1[3], edge1[3], edge2[3], d_nvect[3], aabbmin[3], aabbmax[3]; - float facedist, outerfacethickness, tune = 10.f; + float facedist, outerfacethickness, tune = 10.0f; int a, deflected = 0; aabbmin[0] = min_fff(face_v1[0], face_v2[0], face_v3[0]); @@ -2032,7 +2032,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, attached = 0; for (b = obp->nofsprings; b > 0; b--) { bs = sb->bspring + obp->springs[b - 1]; - if ((ilast - bb == bs->v2) || (ilast - bb == bs->v1)) { + if (ELEM(ilast - bb, bs->v2, bs->v1)) { attached = 1; continue; } @@ -2797,8 +2797,8 @@ static void reference_to_scratch(Object *ob) SoftBody *sb = ob->soft; ReferenceVert *rp; BodyPoint *bp; - float accu_pos[3] = {0.f, 0.f, 0.f}; - float accu_mass = 0.f; + float accu_pos[3] = {0.0f, 0.0f, 0.0f}; + float accu_mass = 0.0f; int a; sb->scratch->Ref.ivert = MEM_mallocN(sizeof(ReferenceVert) * sb->totpoint, "SB_Reference"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8bec9f331c5..8b66b1fc628 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -60,7 +60,6 @@ #include "BKE_main.h" #include "BKE_packedFile.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_sound.h" #include "DEG_depsgraph.h" @@ -68,6 +67,8 @@ #include "BLO_read_write.h" +#include "SEQ_sequencer.h" + static void sound_free_audio(bSound *sound); static void sound_copy_data(Main *UNUSED(bmain), @@ -211,6 +212,8 @@ IDTypeInfo IDType_ID_SO = { .blend_read_data = sound_blend_read_data, .blend_read_lib = sound_blend_read_lib, .blend_read_expand = sound_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; #ifdef WITH_AUDASPACE @@ -1320,7 +1323,10 @@ int BKE_sound_scene_playing(Scene *UNUSED(scene)) { return -1; } -void BKE_sound_read_waveform(Main *bmain, bSound *sound, short *stop) +void BKE_sound_read_waveform(Main *bmain, + bSound *sound, + /* NOLINTNEXTLINE: readability-non-const-parameter. */ + short *stop) { UNUSED_VARS(sound, stop, bmain); } diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index a98093d1893..fabf0bb8971 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -112,6 +112,8 @@ IDTypeInfo IDType_ID_SPK = { .blend_read_data = speaker_blend_read_data, .blend_read_lib = speaker_blend_read_lib, .blend_read_expand = speaker_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; void *BKE_speaker_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 93306703686..6f4ac4c44a0 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -256,6 +256,8 @@ IDTypeInfo IDType_ID_TXT = { .blend_read_data = text_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, + + .blend_read_undo_preserve = NULL, }; /** \} */ @@ -2333,7 +2335,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) if (ch == ':') { is_indent = 1; } - else if (ch != ' ' && ch != '\t') { + else if (!ELEM(ch, ' ', '\t')) { is_indent = 0; } } @@ -2459,7 +2461,7 @@ int text_check_identifier_nodigit_unicode(const unsigned int ch) bool text_check_whitespace(const char ch) { - if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') { + if (ELEM(ch, ' ', '\t', '\r', '\n')) { return true; } return false; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 90c4f71ce7a..4c2e4a82acb 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -67,7 +67,7 @@ #include "BKE_scene.h" #include "BKE_texture.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" #include "BLO_read_write.h" @@ -224,6 +224,8 @@ IDTypeInfo IDType_ID_TE = { .blend_read_data = texture_blend_read_data, .blend_read_lib = texture_blend_read_lib, .blend_read_expand = texture_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; /* Utils for all IDs using those texture slots. */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index cb33610a93f..7f927a8838e 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -338,6 +338,7 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->settings.default_weight = 1.0f; tracking->settings.dist = 1; tracking->settings.object_distance = 1; + tracking->settings.refine_camera_intrinsics = REFINE_NO_INTRINSICS; tracking->stabilization.scaleinf = 1.0f; tracking->stabilization.anchor_frame = 1; diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index 7df8bf62b16..d89d36f85ea 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -291,12 +291,12 @@ static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, flags |= LIBMV_REFINE_PRINCIPAL_POINT; } - if (refine & REFINE_RADIAL_DISTORTION_K1) { - flags |= LIBMV_REFINE_RADIAL_DISTORTION_K1; + if (refine & REFINE_RADIAL_DISTORTION) { + flags |= LIBMV_REFINE_RADIAL_DISTORTION; } - if (refine & REFINE_RADIAL_DISTORTION_K2) { - flags |= LIBMV_REFINE_RADIAL_DISTORTION_K2; + if (refine & REFINE_TANGENTIAL_DISTORTION) { + flags |= LIBMV_REFINE_TANGENTIAL_DISTORTION; } return flags; diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index bc6c94343b5..c7e4e0d5c08 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -722,7 +722,7 @@ static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf) { ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0); - BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); + BLI_assert(ELEM(ibuf->channels, 3, 4)); /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels * float buffer, so we do it manually here. @@ -880,7 +880,7 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, } /* Transform number of channels. */ if (input_mode == LIBMV_IMAGE_MODE_RGBA) { - BLI_assert(orig_ibuf->channels == 3 || orig_ibuf->channels == 4); + BLI_assert(ELEM(orig_ibuf->channels, 3, 4)); /* pass */ } else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ { diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 93f70b606dc..b687254fd69 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -95,7 +95,7 @@ static bool g_undo_callback_running = false; /** \name Public Undo Types * * Unfortunately we need this for a handful of places. - */ + * \{ */ const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL; const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL; const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL; @@ -357,7 +357,7 @@ void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain) void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C) { const UndoType *ut = BKE_undosys_type_from_context(C); - if ((ut != NULL) && (ut != BKE_UNDOSYS_TYPE_MEMFILE)) { + if (!ELEM(ut, NULL, BKE_UNDOSYS_TYPE_MEMFILE)) { BKE_undosys_step_push_with_type(ustack, C, IFACE_("Original Mode"), ut); } } @@ -549,6 +549,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, BLI_strncpy(us->name, name, sizeof(us->name)); } us->type = ut; + /* True by default, code needs to explicitely set it to false if necessary. */ + us->use_old_bmain_data = true; /* Initialized, not added yet. */ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name); @@ -897,7 +899,7 @@ void BKE_undosys_stack_group_end(UndoStack *ustack) /** \name ID Reference Utilities * * Unfortunately we need this for a handful of places. - */ + * \{ */ static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 73bf149bf2a..b55f80c6473 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -802,17 +802,12 @@ static char *find_next_negative(const char *str, const char *remaining_str) static char *find_next_op(const char *str, char *remaining_str, int len_max) { int i; - bool scientific_notation = false; for (i = 0; i < len_max; i++) { if (remaining_str[i] == '\0') { return remaining_str + i; } if (ch_is_op(remaining_str[i])) { - if (scientific_notation) { - scientific_notation = false; - } - /* Make sure we don't look backwards before the start of the string. */ if (remaining_str != str && i != 0) { /* Check for velocity or acceleration (e.g. '/' in 'ft/s' is not an op). */ @@ -822,8 +817,7 @@ static char *find_next_op(const char *str, char *remaining_str, int len_max) } /* Check for scientific notation. */ - if (remaining_str[i - 1] == 'e' || remaining_str[i - 1] == 'E') { - scientific_notation = true; + if (ELEM(remaining_str[i - 1], 'e', 'E')) { continue; } @@ -1184,7 +1178,7 @@ bool BKE_unit_replace_string( /* Any operators after this? */ for (ch = str_found + 1; *ch != '\0'; ch++) { - if (*ch == ' ' || *ch == '\t') { + if (ELEM(*ch, ' ', '\t')) { continue; } op_found = (ch_is_op(*ch) || ELEM(*ch, ',', ')')); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 87993695486..11aa9597740 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -265,12 +265,13 @@ static struct VolumeFileCache { struct VolumeGrid { VolumeGrid(const VolumeFileCache::Entry &template_entry, const int simplify_level) - : entry(NULL), simplify_level(simplify_level), is_loaded(false) + : entry(nullptr), simplify_level(simplify_level), is_loaded(false) { entry = GLOBAL_CACHE.add_metadata_user(template_entry); } - VolumeGrid(const openvdb::GridBase::Ptr &grid) : entry(NULL), local_grid(grid), is_loaded(true) + VolumeGrid(const openvdb::GridBase::Ptr &grid) + : entry(nullptr), local_grid(grid), is_loaded(true) { } @@ -295,7 +296,7 @@ struct VolumeGrid { void load(const char *volume_name, const char *filepath) { /* If already loaded or not file-backed, nothing to do. */ - if (is_loaded || entry == NULL) { + if (is_loaded || entry == nullptr) { return; } @@ -337,7 +338,7 @@ struct VolumeGrid { void unload(const char *volume_name) { /* Not loaded or not file-backed, nothing to do. */ - if (!is_loaded || entry == NULL) { + if (!is_loaded || entry == nullptr) { return; } @@ -364,7 +365,7 @@ struct VolumeGrid { local_grid = grid()->copyGridWithNewTree(); if (entry) { GLOBAL_CACHE.remove_user(*entry, is_loaded); - entry = NULL; + entry = nullptr; } is_loaded = true; } @@ -378,7 +379,7 @@ struct VolumeGrid { local_grid = grid()->deepCopyGrid(); if (entry) { GLOBAL_CACHE.remove_user(*entry, is_loaded); - entry = NULL; + entry = nullptr; } is_loaded = true; } @@ -398,7 +399,7 @@ struct VolumeGrid { return entry->error_msg.c_str(); } - return NULL; + return nullptr; } bool grid_is_loaded() const @@ -562,7 +563,7 @@ static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_addre Volume *volume = (Volume *)id; if (volume->id.us > 0 || BLO_write_is_undo(writer)) { /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - volume->runtime.grids = 0; + volume->runtime.grids = nullptr; /* write LibData */ BLO_write_id_struct(writer, Volume, id_address, &volume->id); @@ -633,12 +634,14 @@ IDTypeInfo IDType_ID_VO = { /* blend_read_data */ volume_blend_read_data, /* blend_read_lib */ volume_blend_read_lib, /* blend_read_expand */ volume_blend_read_expand, + + /* blend_read_undo_preserve */ nullptr, }; void BKE_volume_init_grids(Volume *volume) { #ifdef WITH_OPENVDB - if (volume->runtime.grids == NULL) { + if (volume->runtime.grids == nullptr) { volume->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector); } #else @@ -869,11 +872,11 @@ BoundBox *BKE_volume_boundbox_get(Object *ob) { BLI_assert(ob->type == OB_VOLUME); - if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { + if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) { return ob->runtime.bb; } - if (ob->runtime.bb == NULL) { + if (ob->runtime.bb == nullptr) { Volume *volume = (Volume *)ob->data; ob->runtime.bb = (BoundBox *)MEM_callocN(sizeof(BoundBox), "volume boundbox"); @@ -1004,7 +1007,7 @@ static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph, if (volume_next && volume_next != volume) { /* If the modifier returned a new volume, release the old one. */ if (volume != volume_input) { - BKE_id_free(NULL, volume); + BKE_id_free(nullptr, volume); } volume = volume_next; } @@ -1055,7 +1058,7 @@ void BKE_volume_grids_backup_restore(Volume *volume, VolumeGridVector *grids, co /* Restore grids after datablock was re-copied from original by depsgraph, * we don't want to load them again if possible. */ BLI_assert(volume->id.tag & LIB_TAG_COPIED_ON_WRITE); - BLI_assert(volume->runtime.grids != NULL && grids != NULL); + BLI_assert(volume->runtime.grids != nullptr && grids != nullptr); if (!grids->is_loaded()) { /* No grids loaded in CoW datablock, nothing lost by discarding. */ @@ -1078,8 +1081,8 @@ void BKE_volume_grids_backup_restore(Volume *volume, VolumeGridVector *grids, co /* Draw Cache */ -void (*BKE_volume_batch_cache_dirty_tag_cb)(Volume *volume, int mode) = NULL; -void (*BKE_volume_batch_cache_free_cb)(Volume *volume) = NULL; +void (*BKE_volume_batch_cache_dirty_tag_cb)(Volume *volume, int mode) = nullptr; +void (*BKE_volume_batch_cache_free_cb)(Volume *volume) = nullptr; void BKE_volume_batch_cache_dirty_tag(Volume *volume, int mode) { @@ -1136,10 +1139,10 @@ VolumeGrid *BKE_volume_grid_get(const Volume *volume, int grid_index) return &grid; } } - return NULL; + return nullptr; #else UNUSED_VARS(volume, grid_index); - return NULL; + return nullptr; #endif } @@ -1147,7 +1150,7 @@ VolumeGrid *BKE_volume_grid_active_get(const Volume *volume) { const int num_grids = BKE_volume_num_grids(volume); if (num_grids == 0) { - return NULL; + return nullptr; } const int index = clamp_i(volume->active_grid, 0, num_grids - 1); @@ -1165,7 +1168,7 @@ VolumeGrid *BKE_volume_grid_find(const Volume *volume, const char *name) } } - return NULL; + return nullptr; } /* Grid Loading */ @@ -1350,7 +1353,7 @@ bool BKE_volume_grid_bounds(const VolumeGrid *volume_grid, float min[3], float m Volume *BKE_volume_new_for_eval(const Volume *volume_src) { - Volume *volume_dst = (Volume *)BKE_id_new_nomain(ID_VO, NULL); + Volume *volume_dst = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); STRNCPY(volume_dst->id.name, volume_src->id.name); volume_dst->mat = (Material **)MEM_dupallocN(volume_src->mat); @@ -1370,7 +1373,7 @@ Volume *BKE_volume_copy_for_eval(Volume *volume_src, bool reference) flags |= LIB_ID_COPY_CD_REFERENCE; } - Volume *result = (Volume *)BKE_id_copy_ex(NULL, &volume_src->id, NULL, flags); + Volume *result = (Volume *)BKE_id_copy_ex(nullptr, &volume_src->id, nullptr, flags); return result; } @@ -1393,12 +1396,12 @@ VolumeGrid *BKE_volume_grid_add(Volume *volume, const char *name, VolumeGridType { #ifdef WITH_OPENVDB VolumeGridVector &grids = *volume->runtime.grids; - BLI_assert(BKE_volume_grid_find(volume, name) == NULL); + BLI_assert(BKE_volume_grid_find(volume, name) == nullptr); BLI_assert(type != VOLUME_GRID_UNKNOWN); openvdb::GridBase::Ptr vdb_grid = BKE_volume_grid_type_operation(type, CreateGridOp{}); if (!vdb_grid) { - return NULL; + return nullptr; } vdb_grid->setName(name); @@ -1406,7 +1409,7 @@ VolumeGrid *BKE_volume_grid_add(Volume *volume, const char *name, VolumeGridType return &grids.back(); #else UNUSED_VARS(volume, name, type); - return NULL; + return nullptr; #endif } diff --git a/source/blender/blenkernel/intern/volume_render.cc b/source/blender/blenkernel/intern/volume_render.cc index 37b397a9c6d..5c71f1d7eca 100644 --- a/source/blender/blenkernel/intern/volume_render.cc +++ b/source/blender/blenkernel/intern/volume_render.cc @@ -123,7 +123,7 @@ bool BKE_volume_grid_dense_floats(const Volume *volume, const int channels = BKE_volume_grid_channels(volume_grid); const int elem_size = sizeof(float) * channels; float *voxels = static_cast<float *>(MEM_malloc_arrayN(num_voxels, elem_size, __func__)); - if (voxels == NULL) { + if (voxels == nullptr) { return false; } @@ -143,7 +143,7 @@ bool BKE_volume_grid_dense_floats(const Volume *volume, void BKE_volume_dense_float_grid_clear(DenseFloatVolumeGrid *dense_grid) { - if (dense_grid->voxels != NULL) { + if (dense_grid->voxels != nullptr) { MEM_freeN(dense_grid->voxels); } } @@ -339,7 +339,7 @@ void BKE_volume_grid_wireframe(const Volume *volume, void *cb_userdata) { if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) { - cb(cb_userdata, NULL, NULL, 0, 0); + cb(cb_userdata, nullptr, nullptr, 0, 0); return; } @@ -386,7 +386,7 @@ void BKE_volume_grid_wireframe(const Volume *volume, #else UNUSED_VARS(volume, volume_grid); - cb(cb_userdata, NULL, NULL, 0, 0); + cb(cb_userdata, nullptr, nullptr, 0, 0); #endif } @@ -432,7 +432,7 @@ void BKE_volume_grid_selection_surface(const Volume *volume, cb(cb_userdata, (float(*)[3])verts.data(), (int(*)[3])tris.data(), verts.size(), tris.size()); #else UNUSED_VARS(volume, volume_grid); - cb(cb_userdata, NULL, NULL, 0, 0); + cb(cb_userdata, nullptr, nullptr, 0, 0); #endif } diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index cd163b7c8bf..291116556c3 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -48,6 +48,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_read_write.h" + /* -------------------------------------------------------------------- */ static void workspace_free_data(ID *id) @@ -75,6 +77,98 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + WorkSpace *workspace = (WorkSpace *)id; + + BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id); + BKE_id_blend_write(writer, &workspace->id); + BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts); + BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations); + BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids); + BLO_write_struct_list(writer, bToolRef, &workspace->tools); + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + if (tref->properties) { + IDP_BlendWrite(writer, tref->properties); + } + } +} + +static void workspace_blend_read_data(BlendDataReader *reader, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + + BLO_read_list(reader, &workspace->layouts); + BLO_read_list(reader, &workspace->hook_layout_relations); + BLO_read_list(reader, &workspace->owner_ids); + BLO_read_list(reader, &workspace->tools); + + LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { + /* parent pointer does not belong to workspace data and is therefore restored in lib_link step + * of window manager.*/ + BLO_read_data_address(reader, &relation->value); + } + + LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { + tref->runtime = NULL; + BLO_read_data_address(reader, &tref->properties); + IDP_BlendDataRead(reader, &tref->properties); + } + + workspace->status_text = NULL; + + id_us_ensure_real(&workspace->id); +} + +static void workspace_blend_read_lib(BlendLibReader *reader, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + Main *bmain = BLO_read_lib_get_main(reader); + + /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */ + LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) { + relation->parent = NULL; + LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + if (win->winid == relation->parentid) { + relation->parent = win->workspace_hook; + } + } + } + if (relation->parent == NULL) { + BLI_freelinkN(&workspace->hook_layout_relations, relation); + } + } + + LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) { + BLO_read_id_address(reader, id->lib, &layout->screen); + + if (layout->screen) { + if (ID_IS_LINKED(id)) { + layout->screen->winid = 0; + if (layout->screen->temp) { + /* delete temp layouts when appending */ + BKE_workspace_layout_remove(bmain, workspace, layout); + } + } + } + else { + /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it + * around. */ + BKE_workspace_layout_remove(bmain, workspace, layout); + } + } +} + +static void workspace_blend_read_expand(BlendExpander *expander, ID *id) +{ + WorkSpace *workspace = (WorkSpace *)id; + + LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { + BLO_expand(expander, BKE_workspace_layout_screen_get(layout)); + } +} + IDTypeInfo IDType_ID_WS = { .id_code = ID_WS, .id_filter = FILTER_ID_WS, @@ -92,12 +186,15 @@ IDTypeInfo IDType_ID_WS = { .foreach_id = workspace_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = workspace_blend_write, + .blend_read_data = workspace_blend_read_data, + .blend_read_lib = workspace_blend_read_lib, + .blend_read_expand = workspace_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; +/* -------------------------------------------------------------------- */ /** \name Internal Utils * \{ */ diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 094557502a3..8fe7653fc25 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -204,6 +204,8 @@ IDTypeInfo IDType_ID_WO = { .blend_read_data = world_blend_read_data, .blend_read_lib = world_blend_read_lib, .blend_read_expand = world_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; World *BKE_world_add(Main *bmain, const char *name) |